/* Chỉ những gì CSS của bài không có. Cố tình rất ít: CSS của bài sở hữu cả
   trang, thêm nhiều vào đây là đánh nhau với nó. */

/* Link quay lại, nằm trong .brand nên KHÔNG bị script gốc gắn handler
   gotoSlide như các <a> trong <nav>. */
#topbar .brand .backlink {
  color: #9FD8C9;
  text-decoration: none;
  font-weight: 400;
  margin-right: 10px;
  padding: 2px 8px;
  border: 1px solid rgba(255, 255, 255, .25);
  border-radius: 12px;
}
#topbar .brand .backlink:hover { background: rgba(255, 255, 255, .12); }

/* Bốn lối vào bài. Nằm ngoài <nav> nên script gốc không gắn gotoSlide vào —
   giống lý do .backlink phải nằm trong .brand. */
#partbar { display: flex; gap: 6px; flex-shrink: 0; }
#partbar .partlink {
  font-size: 13px;
  text-decoration: none;
  color: #9FD8C9;
  padding: 2px 10px;
  border: 1px solid rgba(255, 255, 255, .25);
  border-radius: 12px;
  white-space: nowrap;
}
#partbar .partlink:hover { background: rgba(255, 255, 255, .12); }
#partbar .partlink.on { background: #E8643C; border-color: #E8643C; color: #fff; }

/* Điều hướng sang bài khác, thêm vào #slidebar của bài. */
#slidebar .lessonjump {
  font-size: 13px;
  text-decoration: none;
  color: var(--walnut, #0F5E50);
  padding: 3px 10px;
  border: 1px solid var(--line, #BBD6CD);
  border-radius: 12px;
}
#slidebar .lessonjump:hover { background: var(--card2, #EEF7F3); }
#slidebar .lessonjump.disabled { opacity: .35; pointer-events: none; }

/* ================= MỤC LỤC BÀI =========================================

   Vì sao có khối này. CSS của bài viết cho máy chiếu: `nav{flex:1;flex-wrap:
   wrap}` bên trong `#topbar{position:fixed}`, và `.slide{padding:64px 5vw
   70px}`. Hệ quả đo được ở 1440×900 với bài 16 mục:

     · nav xuống 3 hàng → topbar cao 85px, mà slide chỉ chừa 64px
       → thanh ĐÈ LÊN tiêu đề mục;
     · `.pad` tối đa 1000px → thừa 220px mỗi bên, trống trơn.

   Tức là chiều dọc thiếu trong khi chiều ngang thừa. Nên: mục lục xuống cột
   trái (dùng đúng chỗ đang thừa), topbar còn một hàng, và `.slide` chừa đúng
   chiều cao thật của topbar thay vì một con số đoán trước.

   Sửa Ở ĐÂY chứ không sửa CSS của bài: CSS đó là nội dung bản gốc dựng lại từ
   ChineseBookToHTML mỗi lần cập nhật, đặt tên theo hash và dùng chung giữa
   nhiều bài — vá tay là lần dựng sau mất sạch (đã mất một lần, 01/09/2026).
   viewer.css nạp SAU nên vẫn thắng.

   `--tbh` là chiều cao thật của #topbar, do viewer.js đo và đặt lên :root.
   Đo chứ không đặt cứng: nhan đề bài dài ngắn khác nhau, và giáo viên có thêm
   nút Trình chiếu nên topbar của họ có thể xuống hai hàng ở màn hình hẹp.
   Giá trị dự phòng 44px dùng khi JS chưa chạy. */

:root { --rail: clamp(150px, 13vw, 184px); }

#navToggle {
  font: inherit;
  font-size: 15px;
  line-height: 1;
  flex: 0 0 auto;
  padding: 6px 9px;
  border: 1px solid rgba(255, 255, 255, .25);
  border-radius: 10px;
  background: none;
  color: #9FD8C9;
  cursor: pointer;
}
#navToggle:hover { background: rgba(255, 255, 255, .12); }

/* Nhan đề dài phải cắt bằng "…" chứ không đẩy #togglebar xuống hàng. */
#topbar .brand { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
#togglebar { flex: 0 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
#togglebar::-webkit-scrollbar { display: none; }

#lessonrail {
  position: fixed;
  left: 0;
  top: var(--tbh, 44px);
  bottom: 0;
  z-index: 59;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px 10px 18px;
  background: var(--dark, #0B4034);
  overflow-y: auto;
  overscroll-behavior: contain;
}
#lessonrail::-webkit-scrollbar { width: 6px; }
#lessonrail::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .22); border-radius: 3px; }

/* Bốn lối vào xếp 2×2: cao bằng nửa so với xếp dọc, mà vẫn đọc được nhãn. */
#lessonrail #partbar {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 5px;
  padding-bottom: 11px;
  border-bottom: 1px solid rgba(255, 255, 255, .16);
}
#lessonrail #partbar .partlink { padding: 4px 2px; text-align: center; font-size: 12.5px; }

/* nav của bài là hàng ngang co giãn (`display:flex;flex-wrap:wrap;flex:1`);
   ở đây nó là cột. */
#lessonrail nav { flex-direction: column; flex-wrap: nowrap; flex: 0 0 auto; gap: 2px; }
#lessonrail nav a { font-size: 13px; padding: 6px 10px; border-radius: 8px; }
#lessonrail nav a:hover:not(.active) { background: rgba(255, 255, 255, .10); }

/* ---------- Máy tính: cột trái cố định ---------- */
@media (min-width: 1024px) {
  #navToggle { display: none; }
  #topbar { flex-wrap: nowrap; }
  #lessonrail { width: var(--rail); }

  /* Một hàng, nên phải chọn ai chịu thiệt khi nhan đề dài: .brand co lại và
     cắt bằng "…", các nút giữ nguyên. Ngược lại là nút bị cắt mất chữ. */
  #togglebar { flex: 0 0 auto; overflow-x: visible; }

  /* #deck là khối trong luồng nên `margin-left` dịch được nó; `padding-left`
     thì KHÔNG — .slide là `position:absolute;inset:0`, mà mốc của absolute là
     hộp padding, tức slide sẽ tràn ngược vào chỗ vừa chừa ra. */
  #deck { margin-left: var(--rail); }
  #slidebar { left: var(--rail); }

  /* 5vw hai bên là để bù chỗ trống; giờ cột trái đã giữ chỗ đó nên thu lại,
     bù đúng phần chiều ngang vừa mất. */
  .slide { padding: calc(var(--tbh, 44px) + 14px) 28px 70px; }
}

/* ---------- Điện thoại & máy tính bảng: ngăn kéo ---------- */
@media (max-width: 1023.98px) {
  #topbar { gap: 8px; padding: 5px 8px; }
  #topbar .brand { font-size: 13px; }

  /* `visibility` chứ không chỉ đẩy ra ngoài màn hình: nếu chỉ dịch bằng
     transform thì 20 link vẫn nằm trong thứ tự Tab, học viên gõ Tab là con trỏ
     chạy vào một ngăn kéo không nhìn thấy. Cho vào transition để nó chỉ ẩn sau
     khi trượt xong. */
  #lessonrail {
    width: min(78vw, 268px);
    visibility: hidden;
    transform: translateX(-101%);
    transition: transform .18s ease, visibility .18s;
    box-shadow: 0 0 26px rgba(0, 0, 0, .3);
  }
  body.railopen #lessonrail { visibility: visible; transform: none; }

  #railback { display: none; position: fixed; inset: 0; z-index: 58; background: rgba(0, 0, 0, .42); }
  body.railopen #railback { display: block; }

  .slide { padding: calc(var(--tbh, 44px) + 10px) 4vw 70px; }

  /* Nhảy bài: giữ nút, bỏ chữ "trước/sau" cho khỏi xuống dòng. */
  #slidebar { gap: 10px; }
  #slidebar .lessonjump { font-size: 12px; padding: 2px 7px; white-space: nowrap; }
  #slidebar .lessonjump.disabled { display: none; }
}

/* Trình chiếu. CSS của bài chỉ ẩn #topbar, mà mục lục nay nằm ngoài nó —
   thiếu ba dòng này là cột trái nằm chình ình giữa màn chiếu. */
body.present #lessonrail,
body.present #railback { display: none; }
body.present #deck { margin-left: 0; }
body.present #slidebar { left: 0; }
body.present .slide { padding-top: 34px; }

/* ---------- Thanh điểm bài tập (exercise.js) ----------
   Dùng biến màu của CSS bài (--card2, --line, --walnut, --clay, --radhi) với
   giá trị dự phòng, để không phải sửa CSS của bài — CSS đó là nội dung bản
   gốc, đặt tên theo hash và dùng chung giữa các bài. */
.exbar {
  margin: 22px 0 8px;
  padding: 12px 16px;
  background: var(--card2, #EEF7F3);
  border: 1px solid var(--line, #BBD6CD);
  border-left: 4px solid var(--clay, #0F6E56);
  border-radius: 10px;
  font-size: 16px;
}
.exbar-line { color: var(--walnut, #0F5E50); margin-bottom: 8px; }
.exbar-best { font-weight: 400; color: var(--taupe, #4F6B64); }
.exbar-act { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.exbar-act button {
  font: inherit;
  font-size: 15px;
  padding: 5px 14px;
  border-radius: 14px;
  border: 1px solid var(--line, #BBD6CD);
  background: #fff;
  color: var(--walnut, #0F5E50);
  cursor: pointer;
}
.exbar-act button:hover:not(:disabled) { background: var(--card, #E3F3EE); }
.exbar-send { border-color: var(--clay, #0F6E56) !important; }
.exbar-act button:disabled { opacity: .4; cursor: default; }
.exbar-msg { font-size: 15px; font-weight: 600; }
.exbar-msg.ok { color: var(--clay, #0F6E56); }
.exbar-msg.warn { color: var(--radhi, #C0392B); }

/* Trình chiếu là để giảng, không phải để nộp bài. */
body.present .exbar { display: none; }

/* ---------- Nút Ẩn/Hiện phải với tới mục bài tập ----------
   #btnPy/#btnVi của bài chỉ toggle class `hide-py`/`hide-vi` trên <body>; CSS
   quyết định cái gì ẩn. Rule gốc chỉ phủ .exp/.dpy/.rpy (pinyin) và
   .exv/.dvi/.rvi (nghĩa), nên mục 練習 không phản ứng — bấm Ẩn nghĩa mà nghĩa
   tiếng Việt của từng câu hỏi vẫn còn.

   Hai rule này ở ĐÂY, không vá vào CSS của bài: bản gốc trong ChineseBookToHTML
   được dựng lại mỗi lần cập nhật tiếng Việt, và vá tay 27 file thì lần dựng sau
   là mất sạch (đã mất một lần, 01/09/2026). viewer.css nạp SAU CSS của bài
   (lesson.html) nên vẫn thắng.

   Chỉ ẩn `div.qsub` — `span.qsub` là gợi ý chữ Hán inline trong đề bài, ẩn nó
   là mất luôn đề. */
body.hide-vi div.qsub,
body.hide-vi .qvi,
body.hide-vi .ovi,
body.hide-vi .svi { display: none !important; }

/* Bài tập không có phần tử pinyin riêng — pinyin chỉ nằm inline trong chú thích
   và trong đáp án .reveal — nên nút Ẩn pinyin vốn ít tác dụng ở mục này. Cột
   tên trong bảng .scell là chỗ duy nhất có. */
body.hide-py .scell .sname { display: none !important; }

/* ---------- Báo lỗi nội dung (feedback.js, chỉ giáo viên) ----------
   z-index cao hơn #topbar và slide đang trình chiếu; màu lấy từ biến của CSS
   bài với giá trị dự phòng, cùng lối với .exbar. */
.fbmenu {
  position: fixed;
  z-index: 10000;
  min-width: 200px;
  padding: 6px;
  background: #fff;
  border: 1px solid var(--line, #BBD6CD);
  border-radius: 10px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .18);
  font-size: 15px;
}
.fbmenu-item {
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  padding: 8px 12px;
  border: 0;
  border-radius: 7px;
  background: none;
  color: var(--walnut, #0F5E50);
  cursor: pointer;
}
.fbmenu-item:hover { background: var(--card, #E3F3EE); }
.fbmenu-hint { padding: 4px 12px 2px; font-size: 12px; color: var(--taupe, #4F6B64); }

/* `display:flex` của class thắng `[hidden]{display:none}` của trình duyệt —
   không có dòng dưới thì hộp hiện ngay khi mở bài (đã gặp thật). */
.fbdlg[hidden] { display: none; }
.fbdlg {
  position: fixed;
  inset: 0;
  z-index: 10001;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, .35);
}
.fbdlg-box {
  width: min(520px, calc(100vw - 32px));
  padding: 18px 20px;
  background: #fff;
  border-radius: 14px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, .28);
  font-size: 16px;
  color: #222;
}
.fbdlg-head { font-weight: 600; color: var(--walnut, #0F5E50); margin-bottom: 10px; }
.fbdlg-where { font-weight: 400; color: var(--taupe, #4F6B64); font-size: 14px; }
.fbdlg-sel {
  margin: 0 0 10px;
  padding: 8px 12px;
  background: var(--card2, #EEF7F3);
  border-left: 4px solid var(--radhi, #C0392B);
  border-radius: 6px;
  max-height: 120px;
  overflow: auto;
  font-size: 16px;
}
.fbdlg-note {
  width: 100%;
  box-sizing: border-box;
  font: inherit;
  font-size: 15px;
  padding: 8px 10px;
  border: 1px solid var(--line, #BBD6CD);
  border-radius: 8px;
  resize: vertical;
}
.fbdlg-act { display: flex; align-items: center; gap: 10px; margin-top: 10px; }
.fbdlg-msg { flex: 1; font-size: 14px; }
.fbdlg-msg.ok { color: var(--clay, #0F6E56); font-weight: 600; }
.fbdlg-msg.warn { color: var(--radhi, #C0392B); font-weight: 600; }
.fbdlg-act button {
  font: inherit;
  font-size: 15px;
  padding: 6px 16px;
  border-radius: 14px;
  border: 1px solid var(--line, #BBD6CD);
  background: #fff;
  color: var(--walnut, #0F5E50);
  cursor: pointer;
}
.fbdlg-send { border-color: var(--clay, #0F6E56) !important; background: var(--card, #E3F3EE) !important; }
.fbdlg-act button:disabled { opacity: .5; cursor: default; }

/* Chỉnh sửa của quản trị (SlideEdit, lesson_edits.js). Ở đây chứ không ở CSS
   của bài: CSS bài là nội dung bản gốc, đặt tên theo hash, dùng chung nhiều bài.

   Ảnh bìa nằm DƯỚI lớp chữ: chữ tiêu đề là nội dung, ảnh là trang trí — kéo
   ảnh đè lên tiêu đề thì chữ vẫn đọc được. .cover không tự tạo stacking
   context (không z-index), nên ảnh z-index 0 vẫn nằm trên nền của .cover. */
.cover{position:relative}
/* Server chỉ kẹp GÓC TRÊN TRÁI của ảnh trong [0, 100]: x = 80, w = 30 là ảnh
   lấn tới 110% bề rộng bìa, ảnh dọc trên bìa rộng thì lấn đáy ngay lúc thêm. Mà
   `.slide{overflow-y:auto}` của cả 74 bài kéo theo overflow-x:auto, nên phần lấn
   thành thanh cuộn ngang cho người xem điện thoại. Cắt ở mép bìa. Chữ của bìa
   tràn khỏi khung (điện thoại xoay ngang) vốn là chữ sáng trên nền trang sáng,
   cắt đi không mất gì đọc được. Lúc sửa thì mở lại: xem lesson_editor.css. */
.cover{overflow:hidden}
.cover > :not(.edimg){position:relative;z-index:1}
.cover > .edimg{position:absolute;z-index:0;pointer-events:none}
.cover > .edimg > img{display:block;width:100%;height:auto;user-select:none;-webkit-user-drag:none}
.villust.hasimg{font-size:0;overflow:hidden}
.villust > .edillust{width:100%;height:100%;object-fit:contain}
/* Thẻ nhớ dùng chung ảnh của từ (④ trong lesson_edits.js). CSS bài: thẻ cao
   180px, emoji 54px — ảnh giữ đúng chỗ đó, không đẩy chữ Hán bên dưới ra khỏi
   mặt thẻ. */
.fcemoji.hasimg{font-size:0;line-height:0}
.fcemoji > .edillust{display:block;height:64px;width:auto;max-width:100%;margin:0 auto;object-fit:contain}
