/* ═══════════════════════════════════════════════════════════════
   HAI GIAO DIỆN, MỘT BỘ BIẾN
   ---------------------------------------------------------------
   Mọi màu trong file này đều đi qua biến. Đổi giao diện = đổi bộ
   biến, không phải sửa từng chỗ.
     :root                      -> giao diện TỐI (mặc định)
     :root[data-theme="light"]  -> giao diện SÁNG kiểu Claude
   Nút đổi nằm ở thanh trên cùng, ghi nhớ lựa chọn trong máy.
   ═══════════════════════════════════════════════════════════════ */
/* ───────── GIAO DIỆN TỐI — cùng gốc tông ấm với bản sáng bên dưới, KHÔNG
   phải slate-blue lạnh chung chung (bản trước) - nền nâu-đen ấm, điểm nhấn
   vẫn đúng cam đất Claude (chỉ sáng hơn 1 chút cho đủ tương phản trên nền
   tối), 2 giao diện thấy rõ CÙNG 1 thương hiệu, chỉ đảo sáng/tối. ───────── */
:root{
  --bg-main:#262624;
  --bg-card:#30302e;
  --bg-sidebar:#1f1e1d;
  --bg-deep:#1a1918;
  --bg-soft:#2b2a28;
  --bg-raise:#3a3936;
  --bg-hover:#332f2c;
  --border:#3d3b37;
  --border-soft:#343230;
  --border-hi:#5a564f;
  --text:#f5f4ef;
  --text-1:#dedad2;
  --text-2:#a8a296;
  --text-3:#77726b;
  --blue:#d97757;
  --blue-l:#e2916f;
  --blue-hi:#c2663f;
  --blue-sub:rgba(217,119,87,.18);
  --green:#4fae82;
  --green-l:#6ec69c;
  --green-sub:rgba(79,174,130,.16);
  --amber:#d9a03c;
  --amber-l:#e6b968;
  --amber-sub:rgba(217,160,60,.16);
  --warn:#d9a03c;
  --warn-hi:#c2872a;
  --red:#d9695f;
  --red-l:#e8938b;
  --red-sub:rgba(217,105,95,.16);
  --violet:#b499e0;
  --violet-l:#c9b6ea;
  --violet-sub:rgba(180,153,224,.18);
  --vi-color:#8fb8e8;
  --lvl-a:#7fd9a0;
  --lvl-b1:#8db8e0;
  --lvl-b2:#e0b15c;
  --lvl-c1:#e08fa0;
  /* Dải màu PHÂN BIỆT các Block với nhau trong 1 Batch (không mang nghĩa
     trạng thái gì cả — trạng thái Done/Due/Chưa thi vẫn do badge + viền đỏ
     .due lo, xem .block-card bên dưới). 8 tông đá quý trầm, tách biệt hẳn
     khỏi các hue đã có nghĩa (cam đất=--blue, xanh lá=--green, đỏ=--red,
     vàng=--amber, tím=--violet, xanh dương nhạt=--vi-color) để không gây
     hiểu lầm. DÙNG CHUNG 1 bộ giá trị cho cả 2 giao diện (sáng/tối) — độ
     bão hoà/độ sáng trung bình đã chọn để đọc tốt trên cả nền tối #30302e
     lẫn nền trắng, không cần tách riêng theo theme. */
  --blk-1:#c9727b;   /* garnet       */
  --blk-2:#b8a23e;   /* mù tạt/olive vàng (lệch hẳn khỏi --amber vàng cam) */
  --blk-3:#83a85b;   /* rêu/moss     */
  --blk-4:#4fa599;   /* xanh ngọc sâu*/
  --blk-5:#5c93c4;   /* xanh thép    */
  --blk-6:#7b7fd1;   /* chàm/indigo  */
  --blk-7:#a97bc4;   /* tím mận      */
  --blk-8:#c46f9e;   /* hồng mận     */
  --on-accent:#fff;
  --scrim:rgba(0,0,0,.66);
  --shadow-lg:0 18px 44px rgba(0,0,0,.5);
  --shadow-md:0 12px 30px rgba(0,0,0,.38);
  --topbar-h:52px;
  --sidebar-w:210px;
  --sidebar-w-left:210px;
  --sidebar-w-right:210px;
  --radius:10px;
}

/* ───────── GIAO DIỆN SÁNG — tông giấy ấm, điểm nhấn đất nung (Claude) ───────── */
:root[data-theme="light"]{
  --bg-main:#faf9f7;
  --bg-card:#ffffff;
  --bg-sidebar:#f4f1ec;
  --bg-deep:#ece7df;
  --bg-soft:#faf8f5;
  --bg-raise:#f0ebe4;
  --bg-hover:#f2eee8;
  --border:#e3dbd0;
  --border-soft:#eee8e0;
  --border-hi:#c9bdae;
  --text:#2b2621;
  --text-1:#3d372f;
  --text-2:#6b6157;
  --text-3:#9a8f82;
  --blue:#c96442;
  --blue-l:#a84d30;
  --blue-hi:#b0512f;
  --blue-sub:rgba(201,100,66,.12);
  --green:#2f8f52;
  --green-l:#237a40;
  --green-sub:rgba(47,143,82,.12);
  --amber:#c8891f;
  --amber-l:#96650d;
  --amber-sub:rgba(200,137,31,.14);
  --warn:#c8891f;
  --warn-hi:#9c6a13;
  --red:#c0392b;
  --red-l:#a5342a;
  --red-sub:rgba(192,57,43,.12);
  --violet:#7c5cbf;
  --violet-l:#5b3fa0;
  --violet-sub:rgba(124,92,191,.13);
  --vi-color:#1f4e93;
  --lvl-a:#3f7d4a;
  --lvl-b1:#2e6fa8;
  --lvl-b2:#b8791f;
  --lvl-c1:#a5342a;
  --on-accent:#fff;
  --scrim:rgba(60,45,30,.42);
  --shadow-lg:0 16px 40px rgba(90,70,50,.18);
  --shadow-md:0 10px 26px rgba(90,70,50,.14);
}

*{box-sizing:border-box;}
html,body{height:100%;}
/* Cỡ chữ toàn app: đa số CSS ở đây dùng rem (ăn theo font-size của html),
   nên chỉnh 1 chỗ này là cả app to/nhỏ theo, không cần sửa từng nơi. */
html{font-size:calc(16px * var(--font-scale, 1));}
body{
  margin:0;padding:0;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  background:var(--bg-main);color:var(--text);
  display:flex;flex-direction:column;overflow:hidden;
  -webkit-tap-highlight-color:transparent;
  font-size:15px;
}
button{font-family:inherit;}
::-webkit-scrollbar{width:8px;height:8px;}
::-webkit-scrollbar-thumb{background:var(--border-hi);border-radius:8px;}
::-webkit-scrollbar-track{background:transparent;}

/* ═══════════ TOPBAR ═══════════ */
.topbar{
  height:var(--topbar-h);flex-shrink:0;
  background:var(--bg-sidebar);border-bottom:1px solid var(--border);
  display:flex;align-items:center;gap:.6rem;padding:0 .7rem;
  padding-top:env(safe-area-inset-top);
}
.brand{display:flex;align-items:center;gap:.4rem;font-weight:800;font-size:.92rem;letter-spacing:-.01em;flex-shrink:0;}
.brand-mark{font-size:1.05rem;}
.hub-tabs{display:flex;align-items:center;gap:.25rem;overflow-x:auto;flex:1;scrollbar-width:none;}
.hub-tabs::-webkit-scrollbar{display:none;}
/* ‹/› cuộn hub-tabs/section-tabs khi tràn — JS đo scrollWidth và tự hiện/
   ẩn (setupTabScroller trong app.js), mặc định [hidden] nên không tốn chỗ
   lúc tab còn đủ chỗ hiện hết, không cần cuộn. */
.tab-scroll-btn{
  flex-shrink:0;background:var(--bg-card);border:1px solid var(--border);color:var(--text-2);
  width:1.5rem;height:1.5rem;border-radius:6px;cursor:pointer;font-size:.85rem;line-height:1;
  display:flex;align-items:center;justify-content:center;padding:0;
}
.tab-scroll-btn:hover{color:var(--text);border-color:var(--text-3);}
.tab-scroll-btn[hidden]{display:none;}
.hub-tab{
  padding:.35rem .8rem;border-radius:6px;font-size:.78rem;font-weight:600;
  color:var(--text-2);cursor:pointer;white-space:nowrap;border:1px solid transparent;background:transparent;
}
.hub-tab:hover{color:var(--text);}
.hub-tab.active{background:var(--bg-card);color:var(--text);border-color:var(--border);}

.topbar-right{display:flex;align-items:center;gap:.5rem;flex-shrink:0;position:relative;}
.theme-btn{
  background:transparent;border:1px solid var(--border);color:var(--text-2);
  width:30px;height:26px;border-radius:7px;cursor:pointer;font-size:.9rem;line-height:1;
  display:flex;align-items:center;justify-content:center;flex-shrink:0;
}
.theme-btn:hover{color:var(--text);border-color:var(--border-hi);}
/* .theme-btn mặc định chỉ rộng 30px cho 1 icon — nút Journey có thêm
   chữ nên cần bỏ bề rộng cố định, để tự giãn theo nội dung. */
.btn-journey-label{width:auto;padding:0 .6rem;gap:.3rem;font-size:.78rem;font-weight:600;}
.btn-learning{
  display:flex;align-items:center;gap:.3rem;height:26px;padding:0 .55rem;border-radius:7px;
  border:1px solid var(--border);background:transparent;color:var(--text-2);cursor:pointer;
  font-size:.72rem;font-weight:700;white-space:nowrap;flex-shrink:0;
}
.btn-learning:hover{color:var(--text);border-color:var(--border-hi);}
.mode-pill{
  font-size:.62rem;font-weight:800;letter-spacing:.06em;padding:.2rem .45rem;border-radius:5px;
  border:1px solid var(--border);color:var(--text-3);background:var(--bg-deep);white-space:nowrap;
}
.mode-pill.cloud{color:var(--green-l);border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.1);}
.mode-pill.local{color:var(--amber-l);border-color:rgba(245,158,11,.35);background:rgba(245,158,11,.1);}
.word-counter{
  font-size:.68rem;font-weight:700;padding:.2rem .5rem;border-radius:5px;cursor:pointer;
  border:1px solid var(--border);color:var(--text-2);background:var(--bg-deep);white-space:nowrap;flex-shrink:0;
}
.word-counter:hover{color:var(--text);border-color:var(--border-hi);}

.user-chip{
  display:flex;align-items:center;gap:.4rem;background:var(--bg-card);border:1px solid var(--border);
  color:var(--text);padding:.25rem .5rem .25rem .3rem;border-radius:999px;cursor:pointer;font-size:.8rem;font-weight:600;
}
.user-chip:hover{border-color:var(--border-hi);}
.avatar{
  width:24px;height:24px;border-radius:50%;background:var(--blue-sub);
  display:inline-flex;align-items:center;justify-content:center;font-size:.9rem;flex-shrink:0;
}
.avatar.big{width:38px;height:38px;font-size:1.3rem;}
.uname{max-width:110px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.caret{font-size:.6rem;color:var(--text-3);}

.user-menu{
  position:absolute;top:calc(100% + 8px);right:0;width:250px;z-index:900;
  background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);
  padding:.4rem;box-shadow:var(--shadow-lg);
}
.user-menu-head{display:flex;align-items:center;gap:.6rem;padding:.5rem .5rem .6rem;}
.menu-name-row{display:flex;align-items:center;gap:.4rem;}
.menu-name{font-weight:700;font-size:.88rem;}
.menu-sub{font-size:.72rem;color:var(--text-3);margin-top:.1rem;word-break:break-all;}

/* "👑 Admin" / "User" — chỉ hiện khi đăng nhập Cloud thật (xem
   renderUserChip trong app.js), 1 cái ở #user-chip (thanh trên cùng),
   1 cái ở #user-menu (đầu menu) — cùng 1 class, 2 chỗ hiển thị. */
.role-badge{
  font-size:.62rem;font-weight:800;letter-spacing:.03em;padding:.1rem .45rem;
  border-radius:999px;white-space:nowrap;
}
.role-badge.admin{background:var(--amber-sub);color:var(--amber-l);}
.role-badge.user{background:var(--bg-soft);color:var(--text-3);border:1px solid var(--border);}
/* Admin THẬT đang bật "Xem như User" — cố tình khác hẳn màu ".user" thật,
   để không nhầm "đang xem thử" với "đã mất quyền" (đúng lo lắng user đã
   từng gặp trước khi chạy SQL is_admin). */
.role-badge.preview{background:var(--violet-sub);color:var(--violet-l);border:1px dashed var(--violet);}
.user-menu-sep{height:1px;background:var(--border-soft);margin:.25rem 0;}
.menu-item{
  width:100%;display:flex;align-items:center;gap:.55rem;background:transparent;border:none;color:var(--text-2);
  padding:.5rem .55rem;border-radius:6px;font-size:.82rem;cursor:pointer;text-align:left;
}
.menu-item:hover{background:var(--bg-deep);color:var(--text);}
.menu-item.danger:hover{color:var(--red-l);}

/* Cỡ chữ + màu nhấn — nằm ngay trong menu người dùng */
.menu-sec-title{
  font-size:.66rem;font-weight:800;color:var(--text-3);text-transform:uppercase;
  letter-spacing:.06em;padding:.3rem .55rem .1rem;
}
.menu-row{
  display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  padding:.35rem .55rem;font-size:.82rem;color:var(--text-2);
}
.font-ctl{display:flex;align-items:center;gap:.4rem;}
.font-pct{font-size:.72rem;font-weight:700;color:var(--text-3);min-width:2.6em;text-align:center;}
.accent-dots{display:flex;gap:.4rem;}
.accent-dot{
  width:20px;height:20px;border-radius:50%;border:2px solid transparent;cursor:pointer;padding:0;
  background:var(--dot-blue,#3b82f6);
}
.accent-dot[data-accent="green"]{background:#10b981;}
.accent-dot[data-accent="purple"]{background:#8b5cf6;}
.accent-dot[data-accent="orange"]{background:#f97316;}
.accent-dot[data-accent="pink"]{background:#ec4899;}
.accent-dot:hover{transform:scale(1.12);}
.accent-dot.on{border-color:var(--text);}

/* Nút tự đổi ngôn ngữ giao diện — cùng hàng "Giao diện" với màu nhấn,
   mỗi nút là 1 lá cờ, viền sáng lên khi đang chọn (giống accent-dot). */
.lang-dots{display:flex;gap:.3rem;}
.lang-dot{
  width:28px;height:24px;border-radius:6px;border:2px solid transparent;cursor:pointer;
  padding:0;background:var(--bg-soft);font-size:.95rem;line-height:1;
  display:flex;align-items:center;justify-content:center;
}
.lang-dot:hover{background:var(--bg-raise);}
.lang-dot.on{border-color:var(--blue);background:var(--bg-raise);}

/* Nút xổ xuống đổi ngôn ngữ trong topbar — sát 🌙/☀️ (TJ chốt 2026-09-13
   "chọn 3 ngôn ngữ", không phải xoay vòng). Bấm #lang-btn xổ ra đúng 3 lá
   cờ để chọn thẳng — cùng cơ chế mở/đóng với #user-menu (đóng khi bấm ra
   ngoài, xem app.js). */
.lang-picker{position:relative;}
.lang-dropdown{
  position:absolute;top:calc(100% + 6px);right:0;z-index:40;
  background:var(--bg-card);border:1px solid var(--border);border-radius:10px;
  box-shadow:0 8px 24px rgba(0,0,0,.25);padding:.3rem;
  display:flex;flex-direction:column;gap:.15rem;min-width:150px;
}
.lang-dropdown[hidden]{display:none;}
.lang-dropdown .lang-dot{
  width:auto;height:auto;border-radius:7px;justify-content:flex-start;
  padding:.45rem .6rem;font-size:.82rem;gap:.5rem;color:var(--text);
  background:none;
}
.lang-dropdown .lang-dot:hover{background:var(--bg-raise);}
.lang-dropdown .lang-dot.on{background:var(--bg-raise);color:var(--blue-l);font-weight:700;}

/* ═══════════ LAYOUT ═══════════ */
.app-container{flex:1;display:flex;overflow:hidden;min-height:0;}
.sidebar{
  flex-shrink:0;background:var(--bg-sidebar);
  display:flex;flex-direction:column;overflow:hidden;
}
.sidebar-left{width:var(--sidebar-w-left);border-right:1px solid var(--border);}
.sidebar-right{width:var(--sidebar-w-right);border-left:1px solid var(--border);}

/* Thanh kéo để chỉnh độ rộng 2 cột Notebooks / Pages. Kéo chuột ngang;
   bấm đúp để về lại độ rộng mặc định. Ẩn trên điện thoại (cột thu vào
   drawer, không có khái niệm "rộng bao nhiêu" nữa). */
.resizer{
  width:6px;flex-shrink:0;cursor:col-resize;position:relative;z-index:5;
}
.resizer::after{
  content:"";position:absolute;top:0;bottom:0;left:2px;width:2px;
  background:transparent;transition:background .12s;
}
.resizer:hover::after,.resizer.dragging::after{background:var(--blue);}
body.resizing-left,body.resizing-right{cursor:col-resize;user-select:none;}
.sidebar-scroll{padding:.5rem .25rem;overflow-y:auto;flex:1;display:flex;flex-direction:column;gap:.3rem;}
/* Riêng sidebar TRÁI: cây Notebook (.sidebar-scroll) và "🏆 RANKING"
   (.sidebar-lb-mini) chia khoảng trống còn lại theo tỉ lệ 3:1 (cây
   Notebook flex:3, Ranking flex:1 ở dưới) — từng thử chia đôi (flex:1
   mỗi bên) nhưng TJ báo Ranking vẫn to, nên hạ tiếp còn đúng 1/4. */
.sidebar-left>.sidebar-scroll{flex:3;max-height:55vh;max-height:55dvh;}
.sidebar-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:.15rem;}
.sidebar-title{
  font-size:.68rem;font-weight:800;color:var(--text-3);text-transform:uppercase;letter-spacing:.06em;
}
.mt{margin-top:1rem;}
.mini-btn{
  width:20px;height:20px;line-height:1;border-radius:5px;border:1px solid var(--border);
  background:var(--bg-card);color:var(--text-2);cursor:pointer;font-size:.9rem;
  display:flex;align-items:center;justify-content:center;padding:0;
}
.mini-btn:hover{color:var(--text);border-color:var(--border-hi);}

.nav-list{display:flex;flex-direction:column;gap:.2rem;}
/* Cây Notebook (#notebook-list, sidebar trái) — có riêng thanh trượt +
   chiều cao giới hạn, để khi có NHIỀU Notebook lồng nhau (dài), nó tự
   cuộn RIÊNG bên trong thay vì đẩy khối "🏆 RANKING"/"Chu kỳ Tony Buzan"
   xuống tuốt cuối, phải cuộn hết cây mới thấy (TJ yêu cầu). */
/* Không còn cần tự giới hạn max-height/tự cuộn riêng nữa — #notebook-list
   giờ là NỘI DUNG DUY NHẤT bên trong .sidebar-scroll (xem index.html:
   "🏆 RANKING"/"Chu kỳ Tony Buzan" đã dời RA NGOÀI .sidebar-scroll, làm
   anh em cố định của nó), nên cứ để chính .sidebar-scroll (flex:1;
   overflow-y:auto) lo việc cuộn, đơn giản hơn và không còn phụ thuộc vh
   (nguồn gây giật trên mobile trước đây khi thanh địa chỉ ẩn/hiện). */
#notebook-list{overflow-y:auto;}
/* Gọn kiểu VS Code Explorer (theo yêu cầu TJ) — hàng thấp, đệm sát trái,
   chữ nhỏ vừa đủ đọc, không còn khoảng trắng thừa như trước. */
.nav-item{
  padding:.28rem .2rem;border-radius:4px;font-size:.78rem;font-weight:500;color:var(--text-2);
  cursor:pointer;display:flex;align-items:center;gap:.25rem;border-left:2px solid transparent;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.nav-item:hover{background:var(--bg-hover);color:var(--text);}
.nav-item.active{background:var(--bg-card);color:var(--text);border-left-color:var(--blue);}
.sidebar-right .nav-item.active{border-left-color:var(--green);}
.nav-item .count{margin-left:auto;font-size:.66rem;color:var(--text-3);white-space:nowrap;flex-shrink:0;}
.nav-empty{font-size:.75rem;color:var(--text-3);padding:.4rem .2rem;font-style:italic;}

/* Đường dẫn dọc (indent guide) — 1 đường mảnh/1 cấp cha, y hệt VS Code
   Explorer, thay cho khoảng trắng rỗng trước đây. Nhân đúng "depth" span
   này ra cho mỗi hàng (xem renderLevel trong app.js) — đơn giản hơn cách
   VS Code thật (đường chỉ chạy tới sibling cuối cùng) nhưng đủ rõ, không
   cần theo dõi "có phải con cuối không" cho từng nhánh. */
.nb-indent{width:.65rem;flex-shrink:0;align-self:stretch;position:relative;}
.nb-indent::before{content:"";position:absolute;left:50%;top:0;bottom:0;width:1px;background:var(--border);}

/* Mũi tên bung/thu 1 nhánh Notebook (renderNotebooks trong app.js) — nút
   con nằm TRONG .nav-item, phải chặn click nổi lên .nav-item (đã chặn ở
   JS qua closest "[data-caret]") kẻo vừa bung/thu vừa nhảy vào Notebook
   đó luôn. .nb-caret-sp là khoảng trống thế chỗ cho Notebook lá (không
   con) để tên vẫn thẳng hàng với Notebook có mũi tên. */
.nb-caret{
  flex-shrink:0;width:.75rem;height:.75rem;display:flex;align-items:center;justify-content:center;
  background:transparent;border:none;color:var(--text-3);font-size:.6rem;cursor:pointer;border-radius:3px;padding:0;
}
.nb-caret:hover{background:var(--bg-hover);color:var(--text);}
.nb-caret-sp{flex-shrink:0;width:.75rem;}

/* Nằm NGOÀI .sidebar-scroll (xem index.html + .sidebar-scroll{flex:1} ở
   trên) nên không còn thừa hưởng padding ngang của nó -> tự khai lại
   .5rem .5rem ở đây, và flex-shrink:0 để không bị bóp nhỏ khi cây
   Notebook phía trên dài ra hết chỗ (nó tự cuộn riêng, khối này đứng
   NGUYÊN VỊ TRÍ, cố định ở đáy sidebar, TJ yêu cầu không trôi/giật nữa). */
.sidebar-foot{padding:.65rem .5rem .5rem;flex-shrink:0;border-top:1px solid var(--border-soft);}
.legend-title{font-size:.62rem;font-weight:800;color:var(--text-3);text-transform:uppercase;letter-spacing:.05em;margin-bottom:.3rem;}
.legend-row{font-size:.66rem;color:var(--text-3);display:flex;align-items:center;gap:.3rem;margin-bottom:.15rem;}
/* "🕒 Data cập nhật lần cuối" dưới khu Chu kỳ Tony Buzan (sidebar trái) —
   vàng cam + đậm nếu vừa cập nhật trong 24h, xám nhạt nếu cũ hơn. */
.legend-updated{font-size:.66rem;color:var(--text-3);margin-top:.5rem;padding-top:.5rem;border-top:1px dashed var(--border-soft);}
.legend-updated.fresh{color:var(--amber, #d97706);font-weight:700;}

/* Bảng xếp hạng thu nhỏ ở cuối sidebar trái — TJ yêu cầu để dễ thấy hơn
   là phải bấm sâu vào menu ⋯. Theo đúng Notebook đang mở, Top 5. */
/* Khối này giờ CHIẾM HẾT khoảng trống còn lại giữa cây Notebook (phía
   trên, .sidebar-scroll giờ chỉ cao vừa đủ nội dung/cuộn riêng khi dài,
   xem .sidebar-scroll bên dưới) và "Chu kỳ Tony Buzan" ghim đáy — TJ báo
   trước đó nó chỉ cao vừa đủ vài dòng, "nhỏ xíu", trong khi đúng ra phải
   to bằng cả khoảng đó. flex:1 + min-height:0 để tự cuộn riêng nếu Top 5
   + phần chừa cho message trống vẫn không lấp hết chiều cao. */
.sidebar-lb-mini{
  flex:1;min-height:4rem;display:flex;flex-direction:column;
  padding:.8rem .5rem .3rem;border-top:1px solid var(--border-soft);cursor:pointer;
}
.sidebar-lb-mini:hover .legend-title{color:var(--text-2);}
.sidebar-lb-mini .legend-title{flex-shrink:0;}
/* Nội dung (danh sách Top 5, hoặc chữ "Đang tải…"/"Chưa ai học…") được
   CĂN GIỮA theo chiều dọc trong khoảng trống lớn đó thay vì dồn lên đầu,
   trông tự nhiên hơn khi khối cao hơn hẳn số dòng thật có. */
#sidebar-lb-mini-body{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;justify-content:center;}
.sb-lb-row{display:flex;align-items:center;gap:.5rem;font-size:.76rem;color:var(--text-2);padding:.3rem 0;flex-shrink:0;}
.sb-lb-row .sb-lb-rank{width:2rem;flex-shrink:0;text-align:center;}
.sb-lb-row .sb-lb-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.sb-lb-row .sb-lb-score{font-weight:700;color:var(--text-1);flex-shrink:0;}
.sb-lb-row.sb-lb-me{color:var(--blue-l);font-weight:700;}
.sb-lb-empty{font-size:.7rem;color:var(--text-3);padding:.3rem 0;}
.sb-lb-more{font-size:.72rem;color:var(--blue-l);margin-top:.3rem;}
.dot{width:6px;height:6px;border-radius:50%;display:inline-block;flex-shrink:0;}
.dot.c1{background:var(--red);}
.dot.c2{background:var(--amber);}
.dot.c3{background:var(--blue);}
.dot.c4{background:var(--violet);}

.btn-dashed{
  background:transparent;border:1px dashed var(--border);color:var(--text-2);
  padding:.5rem;border-radius:6px;font-weight:600;font-size:.78rem;cursor:pointer;width:100%;
}
.btn-dashed:hover{border-color:var(--text-3);color:var(--text);}
/* Nút "+" đầu cột Notebooks/Pages: dính lại khi list bên dưới dài ra và
   cuộn, khỏi phải kéo lên tận đầu mỗi lần cần thêm mới. Nền đặc để chữ/
   dòng list không xuyên qua lúc dính. */
.btn-dashed.pin-top{
  position:sticky;top:0;z-index:2;background:var(--bg-sidebar);
  margin-bottom:.35rem;
}

/* ═══════════ WORKSPACE ═══════════ */
/* scroll-padding-top: chừa chỗ cho .detail-tabs dính ở trên khi
   scrollIntoView() cuộn tới 1 phần tử nào đó (vd đọc bảng từ vựng lúc
   đang MỞ RỘNG, không dùng khung cuộn riêng của #vocab-wrap nữa). */
/* KHÔNG đặt padding-top ở đây — .batches-bar giờ sticky top:0 (xem
   dưới), mà padding-top của chính CONTAINER cuộn lại tạo ra 1 dải hở
   PHÍA TRÊN vị trí dính (sticky đo "top" từ mép padding-box, không phải
   mép content đã cuộn qua) — dải hở đó vẫn nằm TRONG vùng cuộn nên chữ
   cuộn qua vẫn lộ ra ở đúng dải đó. Khoảng cách trên cùng giờ chuyển hẳn
   vào padding-top của .batches-bar (đã sticky, luôn phủ kín, không hở). */
.workspace{flex:1;display:flex;flex-direction:column;overflow-y:auto;padding:0 1.2rem 3rem;min-width:0;scroll-padding-top:3.2rem;}
/* SECTIONS — hàng ngay dưới Hub: tên cột Notebooks · tab Sections · tên cột Pages.
   Tab bo tròn hai góc trên, dính liền vào nội dung bên dưới — kiểu OneNote. */
.section-bar{
  display:flex;align-items:flex-end;gap:.3rem;flex-shrink:0;
  background:var(--bg-sidebar);border-bottom:1px solid var(--border);
  padding:.45rem .5rem 0;
}
.pane-head{
  flex-shrink:0;display:flex;align-items:center;gap:.35rem;
  padding:0 .35rem .55rem;
}
.pane-head.pane-left{width:var(--sidebar-w-left);}
.pane-head.pane-right{width:var(--sidebar-w-right);justify-content:flex-end;}
.section-bar.left-off .pane-left,
.section-bar.right-off .pane-right{width:auto;}
.pane-name{
  background:transparent;border:none;color:var(--text);font-size:.95rem;font-weight:700;
  cursor:pointer;padding:.15rem .25rem;border-radius:5px;white-space:nowrap;
}
.pane-name:hover{background:var(--bg-raise);}
.pin-btn{
  background:transparent;border:none;cursor:pointer;font-size:.85rem;line-height:1;
  padding:.25rem;border-radius:5px;opacity:.85;
}
.pin-btn:hover{background:var(--bg-raise);opacity:1;}
.pin-btn.off{opacity:.4;transform:rotate(45deg);}

.section-tabs{display:flex;gap:.15rem;overflow-x:auto;flex:1;align-items:flex-end;scrollbar-width:none;}
.section-tabs::-webkit-scrollbar{display:none;}
.section-tab{
  background:var(--bg-raise);border:1px solid var(--border);border-bottom:none;
  color:var(--text-2);padding:.5rem 1.05rem;border-radius:10px 10px 0 0;
  font-size:.82rem;font-weight:600;cursor:pointer;white-space:nowrap;
  display:flex;align-items:center;gap:.45rem;margin-bottom:-1px;position:relative;
}
.section-tab:hover{color:var(--text);}
.section-tab.active{
  background:var(--bg-main);color:var(--text);font-weight:800;
  border-color:var(--border);border-bottom:1px solid var(--bg-main);
  box-shadow:0 -2px 0 var(--blue) inset;padding-bottom:.55rem;
}
.section-tab .count{
  font-size:.66rem;color:var(--text-3);background:var(--bg-deep);
  padding:.05rem .35rem;border-radius:999px;
}
.tab-add{
  background:transparent;border:1px dashed var(--border);border-bottom:none;color:var(--text-2);
  border-radius:10px 10px 0 0;padding:.5rem .8rem;font-size:.95rem;line-height:1;
  cursor:pointer;margin-bottom:-1px;flex-shrink:0;
}
.tab-add:hover{color:var(--text);border-color:var(--text-3);}
/* Cụm nút tạo mới ở cuối hàng Section: "+" Thêm section rồi 2 nút Paste
   (dời lên từ .batches-bar cũ — xem index.html) — canh giữa theo chiều
   dọc (không dính đáy như tab) vì đây là cụm nút hành động, không phải
   thêm 1 "tab" mới vào dải section-tabs. */
.section-actions{display:flex;align-items:center;gap:.4rem;flex-shrink:0;align-self:center;}
.section-actions .tab-add{margin-bottom:0;}
.mt-s{margin-top:.5rem;}

/* Nút ⋯ và bảng thao tác (đổi tên · lên/xuống · chuyển · xoá) */
/* min-width:0 BẮT BUỘC ở đây — mặc định flex item không co dưới kích
   thước nội dung tự nhiên của nó (min-width:auto), khiến tên DÀI (vd tên
   Page) không chịu co lại nhường chỗ cho "…", đẩy nút ⋯ ra xa mép phải
   thật của cột thay vì bám sát chữ đã bị cắt — chừa khoảng trắng thừa dư
   ra bên phải dù chữ đã hiện "…" (đúng lỗi TJ chỉ ra ở cột Pages). */
.nav-item{width:100%;}
.nav-item .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;}
.dots{
  background:transparent;border:none;color:var(--text-3);cursor:pointer;
  font-size:.95rem;line-height:1;padding:.1rem .3rem;border-radius:5px;
  opacity:0;flex-shrink:0;margin-left:auto;
}
.nav-item:hover .dots,.section-tab:hover .dots,.batch-tab:hover .dots,
.nav-item.active .dots,.section-tab.active .dots,.batch-tab.active .dots{opacity:1;}
.dots:hover{background:var(--bg-raise);color:var(--text);}
.section-tab,.batch-tab{position:relative;}
/* Block card, và Hub tab: KHÔNG ẩn theo hover — trên di động không có
   hover nên nút "⋯" (đổi tên/xoá/xoá tiến trình...) sẽ vô hình vĩnh viễn
   nếu dùng chung kiểu opacity:0 như trên. Hub-tab từng bị BỎ SÓT khỏi
   danh sách hover/active phía trên -> nút "⋯" của Hub luôn opacity:0,
   không bao giờ hiện được (kể cả hover) -> user tưởng tính năng đổi
   tên/xoá Hub không tồn tại, dù code/menu đã làm đủ từ trước (đã sửa). */
.block-left .dots,.hub-tab .dots{opacity:1;}

/* ═══════════ KÉO THẢ ═══════════ */
[draggable="true"]{cursor:grab;}
[draggable="true"]:active{cursor:grabbing;}
.dragging{opacity:.4;}
.drag-over{
  outline:2px dashed var(--blue);outline-offset:-2px;
  background:var(--blue-sub) !important;
}
/* Thả Notebook vào GIỮA 1 Notebook khác = lồng vào làm Notebook con (thư
   mục mẹ/con) — viền LIỀN + bo tròn khác hẳn .drag-over (viền đứt nét,
   dùng cho "đổi thứ tự") để phân biệt rõ 2 hành vi lúc kéo, xem dropInfo
   trong app.js. */
.drag-over-nest{
  outline:2px solid var(--amber);outline-offset:-2px;border-radius:8px;
  background:var(--amber-sub) !important;
}
/* Nhãn đi theo con trỏ lúc kéo (xem showDragTip trong app.js) — nói rõ
   sắp thả vào đâu làm gì TRƯỚC khi nhả chuột. pointer-events:none để
   không chặn mất sự kiện dragover/drop của chính con trỏ đang đè lên nó. */
.drag-tip{
  position:fixed;z-index:3000;pointer-events:none;
  background:var(--bg-card);color:var(--text);border:1px solid var(--border);
  border-radius:6px;padding:.3rem .6rem;font-size:.76rem;font-weight:600;
  box-shadow:var(--shadow-md);white-space:nowrap;
}
.hub-add{padding:.35rem .7rem;font-size:.85rem;border-radius:7px;margin-left:.2rem;}
.hub-tab{
  display:inline-flex;align-items:center;gap:.35rem;position:relative;
}

.ctx-menu{
  position:fixed;z-index:1500;min-width:216px;
  background:var(--bg-card);border:1px solid var(--border);border-radius:10px;
  padding:.35rem;box-shadow:var(--shadow-lg);
}
.ctx-menu[hidden]{display:none;}
.ctx-head{
  font-size:.72rem;font-weight:800;color:var(--text-3);padding:.4rem .55rem .5rem;
  border-bottom:1px solid var(--border-soft);margin-bottom:.3rem;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.ctx-item{
  width:100%;display:flex;align-items:center;gap:.6rem;background:transparent;border:none;
  color:var(--text-2);padding:.55rem .55rem;border-radius:7px;font-size:.83rem;
  cursor:pointer;text-align:left;
}
.ctx-item:hover:not(:disabled){background:var(--bg-soft);color:var(--text);}
.ctx-item:disabled{opacity:.35;cursor:default;}
.ctx-item.danger{color:var(--red-l);}
.ctx-item.danger:hover{background:rgba(239,68,68,.12);}
.ctx-sep{height:1px;background:var(--border-soft);margin:.25rem 0;}

/* Bỏ ghim: cột thu lại; bấm tên cột thì trượt ra đè lên nội dung */
.app-container{position:relative;}
.sidebar.unpinned{width:0;border:none;overflow:hidden;}
.sidebar.unpinned.flyout{
  position:absolute;top:0;bottom:0;z-index:500;
  overflow:visible;border:1px solid var(--border);
  box-shadow:var(--shadow-md);
}
.sidebar-left.unpinned.flyout{left:0;width:var(--sidebar-w-left);}
.sidebar-right.unpinned.flyout{right:0;width:var(--sidebar-w-right);}

/* Đường dẫn ĐẦY ĐỦ, KHÔNG rút gọn/ẩn bớt bằng "…" nữa (theo yêu cầu TJ —
   "cần biết chính xác đừng hide bớt thông tin") — dài quá thì tự XUỐNG
   HÀNG (flex-wrap: wrap) thay vì cuộn ngang/ẩn khúc giữa như trước. Xem
   renderCrumb() trong app.js (đã bỏ hẳn nhánh CRUMB_MAX_CHARS). */
/* Dính lại (sticky) khi cuộn xuống (theo yêu cầu TJ — "kéo xuống đường
   dẫn cũng cố định để nhìn nhanh") — CÙNG kiểu dính chồng lớp như
   .batches-bar/.detail-tabs bên dưới (xem giải thích ở đó): --crumb-h do
   ResizeObserver đo + set trong app.js (setupStickyOffsets), TỰ ĐỘNG tăng
   khi đường dẫn dài phải xuống 2-3 hàng (flex-wrap: wrap, không rút gọn
   "…" nữa) — .batches-bar/.detail-tabs dựa vào biến này để dính LIỀN ngay
   dưới, không đè lên đường dẫn dù nó cao bao nhiêu hàng. */
.crumb{
  font-size:.72rem;color:var(--text-3);margin-bottom:.35rem;display:flex;gap:.3rem;align-items:center;
  flex-wrap:wrap;row-gap:.15rem;
  position:sticky;top:0;z-index:8;background:var(--bg-main);padding-top:.4rem;
}
.crumb b{color:var(--text-2);font-weight:600;}
.crumb .sep{opacity:.4;flex-shrink:0;}

/* Sticky luôn — trước đây chỉ .detail-tabs dính, còn hàng này (nút "Quay
   lại"/Block trước-sau/tab Batch) cuộn thường -> lúc cuộn qua đúng khoảng
   hàng này rời khỏi khung mà .detail-tabs CHƯA kịp dính, có 1 khoảng
   ngắn (~cao 1 hàng) lộ chữ bên dưới đang cuộn qua, trông như "khe hở"
   lỗi. Dính cả 2 hàng liền nhau (top:0 rồi top:var(--bbar-h)) là hết hẳn
   khoảng hở đó — không lúc nào có "vùng chuyển tiếp" nữa. --bbar-h do
   ResizeObserver đo + set trong app.js (setupStickyOffsets). */
.batches-bar{
  display:flex;gap:.5rem;align-items:center;margin-bottom:.5rem;
  position:sticky;top:var(--crumb-h,0px);z-index:7;background:var(--bg-main);
  padding-top:.5rem;   /* thay cho .workspace{padding-top} đã bỏ — đặt Ở ĐÂY (trong phần tử sticky, luôn phủ kín) thay vì ở container cuộn, để không tạo dải hở phía trên vị trí dính */
}
.batch-tabs{display:flex;gap:.45rem;overflow-x:auto;flex:1;padding-bottom:.2rem;scrollbar-width:none;}
.batch-tabs::-webkit-scrollbar{display:none;}
.batch-tab{
  background:var(--bg-card);border:1px solid var(--border);color:var(--text-2);
  padding:.4rem .9rem;border-radius:20px;font-size:.78rem;font-weight:500;cursor:pointer;white-space:nowrap;
  transition:all .15s;
}
.batch-tab:hover{border-color:var(--text-3);color:var(--text);}
.batch-tab.active{background:var(--blue-sub);color:var(--blue-l);border-color:var(--blue);font-weight:700;}
.batch-tab .n{opacity:.65;font-size:.72rem;margin-left:.2rem;}

.btn-primary{
  background:var(--blue);color:var(--on-accent);border:none;padding:.45rem 1rem;border-radius:7px;
  font-weight:700;font-size:.78rem;cursor:pointer;white-space:nowrap;flex-shrink:0;
}
.btn-primary:hover{background:var(--blue-hi);}
.btn-primary:disabled{opacity:.5;cursor:not-allowed;}
.btn-ghost{
  background:var(--bg-card);border:1px solid var(--border);color:var(--text-2);
  padding:.42rem .85rem;border-radius:7px;cursor:pointer;font-weight:600;font-size:.78rem;
}
.btn-ghost:hover{color:var(--text);border-color:var(--border-hi);}
.btn-soft{
  background:var(--bg-raise);border:1px solid var(--border-hi);color:var(--text);
  padding:.4rem .75rem;border-radius:7px;cursor:pointer;font-weight:600;font-size:.76rem;
}
.btn-soft:hover{background:var(--border-hi);}
.btn-soft.danger{color:var(--red-l);}
.btn-soft.danger:hover{background:var(--red-sub);border-color:var(--red);}
.btn-soft:disabled{opacity:.4;cursor:not-allowed;}
.btn-soft:disabled:hover{background:var(--bg-raise);border-color:var(--border-hi);}
.btn-warn{
  background:var(--warn);color:var(--on-accent);border:none;padding:.42rem .95rem;border-radius:7px;
  font-weight:700;font-size:.78rem;cursor:pointer;white-space:nowrap;
}
.btn-warn:hover{background:var(--warn-hi);}
.btn-warn:disabled{background:var(--bg-raise);color:var(--text-3);cursor:default;border:1px solid var(--border);}
.icon-btn{
  background:transparent;border:1px solid var(--border);color:var(--text-2);
  width:32px;height:30px;border-radius:7px;cursor:pointer;font-size:.95rem;flex-shrink:0;
}

.screen-head{margin-bottom:.9rem;display:flex;flex-wrap:wrap;align-items:baseline;gap:.25rem .6rem;}
.screen-head h2{margin:0;font-size:1.12rem;font-weight:700;}
.muted{font-size:.76rem;color:var(--text-2);margin-top:.2rem;}
.screen-head .muted{margin-top:0;}

/* Alert + chu kỳ */
.alert-box{
  background:var(--bg-hover);border:1px solid var(--border);border-radius:var(--radius);
  padding:.9rem 1.05rem;margin-bottom:1.2rem;display:flex;flex-direction:column;gap:.85rem;
}
.alert-header{display:flex;justify-content:space-between;align-items:center;gap:.8rem;}
.alert-title{color:var(--amber-l);font-weight:700;font-size:.88rem;}
.alert-sub{color:var(--text-2);font-size:.74rem;margin-top:.15rem;}
.cycle-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.6rem;border-top:1px solid var(--border-soft);padding-top:.85rem;}
.time-card{background:var(--bg-soft);border:1px solid var(--border-soft);border-left:3px solid var(--border-soft);border-radius:8px;padding:.6rem .7rem;display:flex;flex-direction:column;gap:.5rem;min-height:64px;transition:border-color .15s;}
/* Viền trái tô màu đúng theo mức độ khẩn — đỏ (sắp quên) nổi nhất, càng
   về sau càng dịu, để liếc 1 cái là biết nên ưu tiên ôn nhóm nào. */
.time-card:has(.dot.c1){border-left-color:var(--red);}
.time-card:has(.dot.c2){border-left-color:var(--amber);}
.time-card:has(.dot.c3){border-left-color:var(--blue);}
.time-card:has(.dot.c4){border-left-color:var(--violet);}
.time-card:hover{border-left-width:5px;}
.time-label{
  font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.02em;color:var(--text-1);
  display:flex;align-items:center;gap:.35rem;
}
.chips-row{display:flex;flex-wrap:wrap;gap:.3rem;max-height:152px;overflow-y:auto;}
.chips-more{font-size:.68rem;color:var(--text-3);align-self:center;padding-left:.15rem;font-style:italic;}
.overdue-chip{
  background:var(--bg-raise);border:1px solid var(--border-hi);color:var(--text-2);
  padding:.15rem .55rem;border-radius:12px;font-size:.7rem;font-weight:600;cursor:pointer;
}
.overdue-chip:hover{background:var(--border);color:var(--text);border-color:var(--border-hi);}
.overdue-chip.due{border-color:rgba(239,68,68,.5);color:var(--red-l);background:rgba(239,68,68,.1);}
.chips-empty{font-size:.68rem;color:var(--text-3);font-style:italic;}

/* Block cards */
.blocks-list{display:flex;flex-direction:column;gap:.75rem;}
.block-card{
  background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);
  padding:.85rem 1rem;cursor:pointer;transition:border-color .15s;display:flex;flex-direction:column;gap:.65rem;
  position:relative;overflow:hidden;   /* để ::before (dải màu) bo tròn theo góc card */
}
.block-card:hover{border-color:var(--border-hi);}
.block-card.due{border-color:rgba(239,68,68,.45);}
/* Dải màu bên trái phân biệt các Block với nhau trong 1 Batch (thuần trang
   trí/nhận diện — KHÔNG mang nghĩa trạng thái, xem khai báo --blk-1..8 ở
   :root). Cycle 8 màu theo data-bidx do app.js gán (idx % 8), lặp lại nếu
   Batch nhiều hơn 8 Block. */
.block-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--blk-1);}
.block-card[data-bidx="2"]::before{background:var(--blk-2);}
.block-card[data-bidx="3"]::before{background:var(--blk-3);}
.block-card[data-bidx="4"]::before{background:var(--blk-4);}
.block-card[data-bidx="5"]::before{background:var(--blk-5);}
.block-card[data-bidx="6"]::before{background:var(--blk-6);}
.block-card[data-bidx="7"]::before{background:var(--blk-7);}
.block-card[data-bidx="0"]::before{background:var(--blk-8);}
.block-top{display:flex;justify-content:space-between;align-items:center;gap:.6rem;flex-wrap:wrap;}
.block-left{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;}
/* Nút "Học/Ôn lại" + badge "Chưa thi"/"Done" đi CHUNG bên phải block-top
   (trước đây nút nằm riêng ở block-bottom, tách khỏi badge) - gộp lại
   thành 1 hàng để đỡ tốn thêm hàng dưới, xem app.js renderBlocks. */
.block-right{display:flex;align-items:center;gap:.6rem;flex-wrap:wrap;}
.block-title{font-size:.88rem;font-weight:800;}
.tag{font-size:.66rem;font-weight:600;padding:.14rem .5rem;border-radius:12px;background:var(--border);color:var(--text-1);border:1px solid var(--border-hi);}
.tag-time{
  background:rgba(16,185,129,.14);color:var(--green-l);font-size:.66rem;padding:.14rem .55rem;
  border-radius:12px;border:1px solid rgba(16,185,129,.3);font-weight:600;
}
.tag-time.due{background:rgba(239,68,68,.14);color:var(--red-l);border-color:rgba(239,68,68,.35);}
/* Đường dẫn thư mục lặp lại trên mỗi Block card (Notebook › Section › Page
   › Batch) — xem App.renderBlocks trong app.js. Nhỏ/mờ, KHÔNG được to hơn
   .block-title bên dưới nó — chỉ để định vị, không phải nội dung chính. */
.block-path{font-size:.66rem;color:var(--text-3);margin-bottom:.3rem;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
/* Nhãn nguồn bài đọc ("📝 Dán"/"🤖 OpenAI"/"✨ Gemini"...) trên mỗi Block
   card — xem blockSourceLabel() trong app.js. */
.tag-src{
  background:var(--bg-soft);color:var(--text-2);font-size:.66rem;padding:.14rem .55rem;
  border-radius:12px;border:1px solid var(--border);font-weight:600;
}
.done-badge{color:var(--green-l);font-weight:700;font-size:.78rem;white-space:nowrap;}
.done-badge.pending{color:var(--text-3);font-weight:600;}
.done-badge.warn{color:var(--amber-l);}
/* Bung HẾT từ trong Block (không cắt "+N từ" nữa, xem app.js) - xuống
   hàng (wrap) thay vì cuộn ngang, để thấy đủ từ ngay trên danh sách. */
.vocab-chips{display:flex;flex-wrap:wrap;gap:.35rem;}
.vchip{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-1);
  padding:.18rem .3rem .18rem .55rem;border-radius:5px;font-size:.76rem;font-weight:500;
  display:inline-flex;align-items:center;gap:.3rem;
}
.vchip.ok{border-color:rgba(16,185,129,.35);color:var(--green-l);}
/* Nút "×" xoá từ - ẩn mặc định, chỉ hiện khi rê chuột vào ĐÚNG chip đó
   (:hover), đỡ rối mắt khi nhìn cả list nhiều chip cùng lúc. Trên điện
   thoại (không có hover) luôn hiện sẵn, xem media query cuối file. */
.vchip-del{
  background:transparent;border:none;color:var(--text-3);cursor:pointer;
  font-size:.9rem;line-height:1;padding:0 .1rem;border-radius:3px;opacity:0;
}
.vchip:hover .vchip-del{opacity:1;}
.vchip-del:hover{color:var(--red-l);background:var(--red-sub);}
/* Thiết bị chạm (điện thoại/tablet) không có hover - luôn hiện sẵn, không
   thì không có cách nào bấm được nút "×" này cả. */
@media(hover:none){.vchip-del{opacity:1;}}
/* Giờ chỉ còn progress-bar (nút Học/Ôn lại đã dời lên block-top) */
.block-bottom{display:flex;align-items:center;flex-wrap:wrap;border-top:1px solid var(--border-soft);padding-top:.55rem;gap:.5rem;}
.progress-bar{height:4px;border-radius:4px;background:var(--border-soft);overflow:hidden;flex:1;}
.progress-bar > i{display:block;height:100%;background:var(--green);}

/* Hàng nút tắt 7 tab dưới thanh tiến độ mỗi Block card — bấm thẳng vào
   đúng tab của Block đó (xem quickTabsHtml/#blocks-list click trong
   app.js). flex-basis:100% ép xuống dòng riêng, dưới progress-bar. */
.block-quick-tabs{flex:0 0 100%;display:flex;gap:.3rem;flex-wrap:wrap;}
.bq-tab{
  background:var(--bg-soft);border:1px solid var(--border-soft);color:var(--text-2);
  font-size:.85rem;line-height:1;padding:.3rem .45rem;border-radius:6px;cursor:pointer;flex-shrink:0;
}
.bq-tab:hover{background:var(--bg-hover);border-color:var(--border);color:var(--text-1);}

.empty-state{
  border:1px dashed var(--border);border-radius:var(--radius);padding:2.2rem 1rem;text-align:center;color:var(--text-3);
}
.empty-state b{display:block;color:var(--text-2);font-size:.9rem;margin-bottom:.35rem;}
.empty-state span{font-size:.8rem;line-height:1.6;}
.empty-state strong{color:var(--blue-l);}

/* ═══════════ DETAIL ═══════════ */
#screen-detail{display:flex;flex-direction:column;gap:1rem;}
#screen-detail[hidden]{display:none;}
#btn-back{align-self:flex-start;}
.detail-banner{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:1.1rem;text-align:center;}
.detail-banner h2{margin:0;font-size:1.12rem;}
.detail-banner p{margin:0;font-size:.76rem;color:var(--text-2);}
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.7rem;}
.stat-box{background:var(--bg-card);border:1px solid var(--border);border-radius:8px;padding:.75rem .5rem;text-align:center;}
.stat-num{font-size:1.15rem;font-weight:800;}
.stat-num.green{color:var(--green-l);} .stat-num.blue{color:var(--blue-l);} .stat-num.amber{color:var(--amber-l);}
.stat-label{font-size:.63rem;color:var(--text-3);text-transform:uppercase;margin-top:.2rem;font-weight:700;letter-spacing:.03em;}

/* Dính lại (position:sticky) khi cuộn xuống bài đọc dài — luôn bấm được
   tab khác mà khỏi kéo lên đầu trang. Nền đặc trùng màu nền trang nên
   không lộ viền lúc dính. */
.detail-tabs{
  display:flex;align-items:center;gap:.35rem;border-bottom:1px solid var(--border);padding:.5rem 0 .4rem;
  position:sticky;top:calc(var(--crumb-h,0px) + var(--bbar-h,0px));z-index:6;background:var(--bg-main);
}
/* CHỈ dải nút tab mới cuộn ngang khi chật chỗ — #bn-pos + nút "⤒" đứng
   ngoài, KHÔNG bao giờ bị cuộn khuất (gộp 1 hàng để tiết kiệm chỗ, không
   phải để mất thông tin — xem ghi chú trong index.html). */
.dtabs-scroll{display:flex;align-items:center;gap:.35rem;overflow-x:auto;scrollbar-width:none;min-width:0;}
.dtabs-scroll::-webkit-scrollbar{display:none;}
.dtab{background:transparent;border:none;color:var(--text-2);font-weight:600;font-size:.8rem;padding:.4rem .8rem;cursor:pointer;border-radius:6px;white-space:nowrap;flex-shrink:0;}
.dtab.active{background:var(--blue-sub);color:var(--blue-l);font-weight:700;}
.tab-pane{display:none;flex-direction:column;gap:1rem;}
.tab-pane.active{display:flex;}

/* Vị trí Block hiện tại — cuối hàng tab, canh phải (trước đây là 1 hàng
   riêng bên dưới, giờ gộp lại cho gọn). margin-left:auto đẩy nó sát phải
   khi dải tab còn dư chỗ; flex-shrink:0 + đứng ngoài .dtabs-scroll đảm
   bảo KHÔNG bao giờ bị co lại hay cuộn khuất mất chữ. */
.detail-tabs .bn-pos{margin-left:auto;flex-shrink:0;font-size:.74rem;font-weight:700;color:var(--text-3);white-space:nowrap;padding-left:.5rem;}
.dtab-top{
  flex-shrink:0;background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  width:1.8rem;height:1.8rem;border-radius:6px;cursor:pointer;font-size:.85rem;line-height:1;margin-left:.4rem;
}
.dtab-top:hover{color:var(--text);border-color:var(--text-3);}

/* Nút Block trước/sau — gộp lên hàng Batch cho gọn, đứng sát nhau. */
.bn-buttons{display:flex;gap:.3rem;flex-shrink:0;}
.bn-buttons .btn-soft{padding:.4rem .6rem;}
.bn-buttons .btn-soft:disabled{opacity:.4;cursor:default;}

.card{background:var(--bg-card);border:1px solid var(--border);border-radius:var(--radius);padding:1rem;}
.card-title{font-size:.83rem;font-weight:700;color:var(--blue-l);margin-bottom:.75rem;}
.card-title-row{display:flex;justify-content:space-between;align-items:center;gap:.6rem;flex-wrap:wrap;margin-bottom:.75rem;}
.card-title-row .card-title{margin-bottom:0;}
.audio-toolbar{display:flex;gap:.4rem;align-items:center;flex-wrap:wrap;}
.mini-select{background:var(--bg-raise);border:1px solid var(--border-hi);color:var(--text);border-radius:7px;padding:.38rem .5rem;font-size:.75rem;font-weight:600;}

/* Bảng từ vựng: KHÔNG bo khung cuộn riêng (thanh cuộn lồng bên trong
   trang kéo không tối ưu) — vẫn cuộn chung theo cả trang như trước, chỉ
   giữ lại tiêu đề cột dính (position:sticky bên dưới) để bảng nào lỡ dài
   hơn 1 màn hình thì đầu cột vẫn thấy được. */
.table-wrap{overflow-x:auto;}
/* Thu gọn còn ~3 dòng để nhường chỗ cho bài đọc bên dưới — nhưng vẫn
   overflow:auto (có thanh trượt) chứ không phải hidden: (1) để kéo tay
   xem hết bảng mà không cần bấm "Mở rộng", và (2) speech.js tự dò khung
   cuộn GẦN NHẤT (overflowY auto/scroll) để cuộn theo từ đang đọc —
   overflow:hidden sẽ khiến nó bỏ qua khung này, tưởng cả trang mới là
   khung cuộn, và không "nhảy" theo từ được nữa. */
/* scroll-padding-top: chừa đúng khoảng trống bằng dòng tiêu đề dính, để
   scrollIntoView() tự canh dòng đang đọc ngay dưới tiêu đề — không cần
   tính tay trong JS nữa (cách cũ hay lệch/giật, xem speech.js). */
.table-wrap.collapsed{max-height:10.5rem;overflow-y:auto;position:relative;scroll-padding-top:2.3rem;}
.table-wrap.collapsed::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2.2rem;
  background:linear-gradient(to bottom, transparent, var(--bg-card));pointer-events:none;
}
.vocab-table{width:100%;border-collapse:collapse;font-size:.8rem;text-align:left;min-width:520px;}
.vocab-table th{background:var(--bg-soft);color:var(--text-2);padding:.5rem .55rem;font-size:.7rem;border-bottom:1px solid var(--border);font-weight:700;text-transform:uppercase;letter-spacing:.03em;position:sticky;top:0;z-index:1;}
.vocab-table td{padding:.5rem .55rem;border-bottom:1px solid var(--border-soft);color:var(--text-1);vertical-align:top;}
.vocab-table tr:last-child td{border-bottom:none;}
.term-cell{display:flex;align-items:center;gap:.4rem;}
.term-cell b{color:var(--blue-l);font-size:.85rem;}
.spk{background:transparent;border:none;color:var(--text-3);cursor:pointer;font-size:.85rem;padding:0 .1rem;line-height:1;}
.spk:hover{color:var(--blue-l);}
.ipa{color:var(--text-3);font-size:.76rem;}
.pos-badge{font-size:.66rem;padding:.1rem .4rem;border-radius:4px;background:var(--bg-raise);border:1px solid var(--border-hi);color:var(--text-2);}
.mem{font-weight:700;}
.mem.hi{color:var(--green-l);} .mem.mid{color:var(--amber-l);} .mem.lo{color:var(--text-3);}
/* dòng đang được đọc khi bấm "Đọc tất cả từ" */
.vocab-table tr.reading{background:var(--blue-sub);}
.vocab-table tr.reading b{color:var(--blue-l);}

/* Cấp độ CEFR — cùng quy ước màu với bộ tài liệu gốc, chỉnh cho nền tối */
.lvl{font-weight:800;font-size:.78rem;letter-spacing:.02em;}
.lvl-A1,.lvl-A2{color:var(--lvl-a);}
.lvl-B1{color:var(--lvl-b1);}
.lvl-B2{color:var(--lvl-b2);}
.lvl-C1,.lvl-C2{color:var(--lvl-c1);}
.def-en{color:var(--text-2);font-size:.8rem;line-height:1.5;}
.vi-cell{color:var(--vi-color);font-weight:700;}
.mem-dot{
  display:inline-block;font-size:.6rem;font-weight:800;padding:.05rem .3rem;border-radius:4px;
  background:var(--bg-raise);color:var(--text-3);border:1px solid var(--border-hi);margin-left:.3rem;vertical-align:middle;
}
.mem-dot.hi{background:rgba(16,185,129,.15);color:var(--green-l);border-color:rgba(16,185,129,.35);}
.mem-dot.mid{background:rgba(245,158,11,.13);color:var(--amber-l);border-color:rgba(245,158,11,.3);}

/* Khối bài đọc — theo đúng bố cục tài liệu gốc: nguồn · tiêu đề · đoạn văn · glossary */
.content-block{
  background:var(--bg-soft);border:1.5px dashed var(--border-hi);border-radius:12px;padding:1rem 1.2rem;
}
.src-tag{display:block;font-size:.72rem;color:var(--text-3);font-style:italic;margin-bottom:.5rem;}
.piece-row{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin:0 0 .6rem;}
.piece{font-size:1rem;font-weight:800;color:var(--amber-l);margin:0;}
/* Cho biết ngay bài đang xem là AI sinh hay bài mẫu có sẵn — trước đây
   chỉ khác ở câu chữ nhỏ trong .src-tag, rất dễ lướt qua không để ý. */
.ai-badge{font-size:.64rem;font-weight:800;padding:.1rem .5rem;border-radius:999px;border:1px solid var(--border-hi);color:var(--text-2);white-space:nowrap;}
.ai-badge:empty{display:none;}
.ai-badge.ai{color:var(--green-l);border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.1);}
.ai-badge.tpl{color:var(--amber-l);border-color:rgba(245,158,11,.35);background:rgba(245,158,11,.1);}
.word-count{font-size:.72rem;color:var(--text-3);font-weight:600;}
.word-count:empty{display:none;}
/* Chi phí ước tính OpenAI đã tốn để sinh bài đang xem — để trống (Gemini
   free/không phải AI) thì tự ẩn, xem #passage-cost trong detail.js. */
.ai-cost{font-size:.72rem;font-weight:600;}
.ai-cost:empty{display:none;}

/* Ô prompt AI cạnh nút "🔄 Tạo lại" — gấp lại mặc định (details/summary),
   mở ra mới thấy prompt gốc để sửa, đỡ chiếm chỗ màn hình lúc không cần. */
.regen-prompt-box{margin:.5rem 0;border:1px solid var(--border);border-radius:10px;padding:.4rem .7rem;background:var(--bg-raise);}
.regen-prompt-box summary{cursor:pointer;font-size:.78rem;font-weight:700;color:var(--text-2);padding:.3rem 0;}
.regen-prompt-box textarea{width:100%;min-height:120px;margin-top:.4rem;font-family:inherit;font-size:.82rem;line-height:1.4;padding:.5rem;border-radius:8px;border:1px solid var(--border);background:var(--bg);color:var(--text-1);resize:vertical;}
.regen-prompt-actions{display:flex;align-items:center;gap:.6rem;margin-top:.4rem;flex-wrap:wrap;}
.glossary{
  background:var(--bg-hover);border:1px solid var(--border-soft);border-radius:8px;
  padding:.75rem 1rem;margin-top:.7rem;font-size:.8rem;line-height:1.65;
}
.glossary .g-title-row{display:flex;justify-content:space-between;align-items:center;gap:.5rem;margin-bottom:.4rem;}
.glossary .g-title{font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--text-3);}
/* Copy kiểu code-block: nút nhỏ ở góc, copy nguyên khối glossary */
.g-copy{
  background:transparent;border:1px solid var(--border);color:var(--text-2);
  font-size:.66rem;font-weight:700;padding:.15rem .55rem;border-radius:6px;cursor:pointer;flex-shrink:0;
}
.g-copy:hover{color:var(--text);border-color:var(--border-hi);}
.g-copy.done{color:var(--green-l);border-color:rgba(16,185,129,.4);}
/* cả dòng đều bấm được để mở bảng tra từ */
.glossary div.g-row{
  margin-bottom:.15rem;color:var(--text-2);cursor:pointer;
  padding:.3rem .45rem;border-radius:6px;border:1px solid transparent;
}
.glossary div.g-row:hover{background:var(--bg-raise);border-color:var(--border);}
.vocab-table tbody tr{cursor:pointer;}
.vocab-table tbody tr:hover{background:var(--bg-raise);}
.glossary b{color:var(--amber-l);}

/* Passage + karaoke — cuộn chung theo cả trang như trước (không bo khung
   cuộn riêng, thanh cuộn lồng bên trong kéo bằng chuột không tối ưu, dễ
   bị "hất" chạy sai vùng). */
.passage{
  line-height:2;font-size:.92rem;color:var(--text-1);
}
/* Thu gọn bài đọc còn ~1 màn hình — giống hệt cách bảng từ vựng thu gọn
   (.table-wrap.collapsed) — bài dài (vd Block "full_..." dán cả bài báo)
   đỡ chiếm hết màn hình khi chỉ cần lướt qua (TJ yêu cầu 2026-09-12).
   Vẫn overflow-y:auto (không phải hidden) — lý do y hệt bảng từ vựng: (1)
   kéo tay xem hết không cần bấm "Mở rộng", (2) speech.js tự dò khung cuộn
   GẦN NHẤT để cuộn theo từ đang đọc, overflow:hidden sẽ khiến nó bỏ qua. */
.passage.collapsed{max-height:22rem;overflow-y:auto;position:relative;scroll-padding-top:1rem;}
.passage.collapsed::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:2.6rem;
  background:linear-gradient(to bottom, transparent, var(--bg-card));pointer-events:none;
}
.passage p{margin:0 0 .8rem;}
.passage p:last-child{margin-bottom:0;}
.kw{border-radius:4px;padding:.05rem .05rem;cursor:pointer;transition:background .12s,color .12s;}
.kw:hover{background:var(--bg-raise);}
.kw.vhl{color:var(--amber-l);font-weight:700;border-bottom:1px solid rgba(251,191,36,.35);}
.kw.on{background:var(--blue);color:var(--on-accent);}
.kw.vhl.on{background:var(--amber);color:var(--bg-main);}
.passage-hint{font-size:.72rem;color:var(--text-3);margin-top:.6rem;}
/* nút dẫn từ bài đọc sang bài kiểm tra, nằm cuối Glossary */
.go-exam{margin-top:1rem;}

/* Quiz */
.quiz-card{min-height:260px;}
.quiz-top{display:flex;justify-content:space-between;align-items:center;font-size:.74rem;color:var(--text-3);margin-bottom:.8rem;gap:.6rem;}
.quiz-bar{height:5px;border-radius:5px;background:var(--border-soft);overflow:hidden;flex:1;margin:0 .6rem;}
.quiz-bar > i{display:block;height:100%;background:var(--blue);transition:width .25s;}
.quiz-prompt{font-size:.78rem;color:var(--text-2);margin-bottom:.35rem;}
.quiz-meaning{font-size:1.25rem;font-weight:800;margin-bottom:.2rem;}
.quiz-extra{font-size:.78rem;color:var(--text-3);font-style:italic;margin-bottom:1rem;}
.quiz-slots{display:flex;gap:.35rem;flex-wrap:wrap;margin-bottom:.9rem;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--text-3);letter-spacing:.12em;font-size:1rem;}
.answer-input{
  width:100%;background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  padding:.75rem .9rem;border-radius:8px;font-size:1.02rem;font-weight:600;outline:none;
}
.answer-input:focus{border-color:var(--blue);}
.answer-input.right{border-color:var(--green);}
.answer-input.wrong{border-color:var(--red);}
.quiz-actions{display:flex;gap:.5rem;margin-top:.9rem;flex-wrap:wrap;}
.quiz-feedback{margin-top:.85rem;font-size:.85rem;padding:.7rem .85rem;border-radius:8px;line-height:1.55;}
.quiz-feedback.ok{background:rgba(16,185,129,.12);border:1px solid rgba(16,185,129,.3);color:var(--green-l);}
.quiz-feedback.no{background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.3);color:var(--red-l);}
.quiz-done{text-align:center;padding:1.5rem .5rem;}
.quiz-done .big{font-size:2.4rem;font-weight:800;color:var(--green-l);}

/* Đề xuất nghĩa trong bảng tra từ */
.wp-scope{padding:.35rem 1rem 0;font-size:.72rem;color:var(--blue-l);font-weight:700;}
.sg-list{display:flex;flex-direction:column;gap:.4rem;margin-bottom:.5rem;}
.sg-row{
  display:flex;flex-direction:column;gap:.15rem;text-align:left;width:100%;
  background:var(--bg-soft);border:1px solid var(--border);border-radius:9px;
  padding:.55rem .7rem;cursor:pointer;color:var(--text);
}
.sg-row:hover{border-color:var(--blue);}
.sg-row.sel{border-color:var(--blue);background:var(--blue-sub);}
.sg-vi{font-weight:700;font-size:.92rem;color:var(--vi-color);}
.sg-why{font-size:.68rem;color:var(--text-3);text-transform:uppercase;letter-spacing:.03em;}
.sg-def{font-size:.76rem;color:var(--text-2);line-height:1.45;}
.sg-empty{font-size:.8rem;color:var(--text-3);font-style:italic;margin-bottom:.5rem;}


/* ═══════════ ĐỌC KIỂU LingQ ═══════════ */
.read-modes{display:flex;gap:.4rem;margin-bottom:.7rem;flex-wrap:wrap;}
.rm-btn{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  padding:.4rem .8rem;border-radius:8px;font-size:.78rem;font-weight:700;cursor:pointer;
}
.rm-btn:hover{color:var(--text);border-color:var(--text-3);}
.rm-btn.active{background:var(--blue-sub);color:var(--blue-l);border-color:var(--blue);}

/* ═══════════ BANNER LỖI GỌI AI (in rõ lên giao diện, không chỉ toast) ═══════════
   Dùng chung cho mọi nơi gọi OpenAI/Gemini thất bại — xem App.showAiError
   trong app.js + Context.describeError trong context.js. */
.ai-error-banner{
  position:relative;background:var(--red-sub);border:1px solid var(--red);border-radius:10px;
  padding:.7rem 2.2rem .7rem .9rem;margin-bottom:.7rem;
}
.ai-error-title{font-weight:700;font-size:.85rem;color:var(--red-l);}
.ai-error-detail{font-size:.78rem;color:var(--text-1);margin-top:.25rem;line-height:1.5;}
.ai-error-close{
  position:absolute;top:.5rem;right:.5rem;background:transparent;border:none;
  color:var(--text-3);cursor:pointer;font-size:.85rem;width:24px;height:24px;border-radius:6px;
}
.ai-error-close:hover{background:var(--bg-hover);color:var(--text);}

/* ═══════════ BÀI ĐỌC TRỐNG — dán bài của bạn hoặc nhờ AI viết ═══════════ */
.passage-empty{
  border:1px dashed var(--border);border-radius:10px;padding:1rem;
  display:flex;flex-direction:column;gap:.7rem;
}
.passage-empty p{margin:0;font-size:.85rem;color:var(--text-2);}
.passage-empty textarea{
  width:100%;min-height:9rem;resize:vertical;border-radius:8px;
  border:1px solid var(--border);background:var(--bg);color:var(--text);
  padding:.6rem;font-size:.85rem;font-family:inherit;line-height:1.5;
}
.passage-empty-actions{display:flex;gap:.5rem;flex-wrap:wrap;}

.src-tabs{display:flex;gap:.4rem;flex-wrap:wrap;}
.src-tabs button{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  padding:.35rem .8rem;border-radius:8px;font-size:.78rem;font-weight:700;cursor:pointer;
}
.src-tabs button:hover{color:var(--text);border-color:var(--text-3);}
.src-tabs button.active{background:var(--blue-sub);color:var(--blue-l);border-color:var(--blue);}
.claude-preview{
  max-height:9rem;overflow-y:auto;border:1px solid var(--border);border-radius:8px;
  padding:.6rem .75rem;font-size:.82rem;line-height:1.55;color:var(--text-2);background:var(--bg);
}

.hidden-unit{display:none !important;}
.passage.mode-sentence .sent{font-size:1.25rem;line-height:2;display:block;}
.passage.mode-page p{font-size:1rem;}
.read-nav{
  display:flex;align-items:center;gap:.6rem;margin-top:.9rem;padding-top:.8rem;
  border-top:1px solid var(--border-soft);
}
.read-nav .rn-pos{flex:1;text-align:center;font-size:.8rem;font-weight:700;color:var(--text-2);}
.read-nav .btn-soft:disabled{opacity:.4;cursor:default;}

/* từ đã lưu — tô nền vàng như LingQ, đậm dần theo mức chưa thuộc */
.kw.lq{border-radius:3px;padding:.05rem .1rem;}
.kw.lq1{background:rgba(245,158,11,.34);}
.kw.lq2{background:rgba(245,158,11,.26);}
.kw.lq3{background:rgba(245,158,11,.18);}
.kw.lq4{background:rgba(245,158,11,.11);}
.kw.lq5{background:transparent;border-bottom:1px solid rgba(148,163,184,.35);}
.kw.lq-part{border-radius:0;padding-left:0;padding-right:0;}
.kw.lq-first{border-radius:3px 0 0 3px;padding-left:.1rem;}
.kw.lq-last{border-radius:0 3px 3px 0;padding-right:.1rem;}

/* ═══════════ BẢNG TRA TỪ ═══════════ */
.panel-backdrop{position:fixed;inset:0;background:var(--scrim);z-index:1100;}
.panel-backdrop[hidden]{display:none;}
.word-panel{
  position:fixed;top:0;right:0;bottom:0;width:380px;max-width:92vw;z-index:1101;
  background:var(--bg-card);border-left:1px solid var(--border);
  display:flex;flex-direction:column;
  transform:translateX(102%);transition:transform .22s ease;
  box-shadow:var(--shadow-lg);
}
.word-panel.open{transform:none;}

/* GHIM: bảng nghĩa thành một cột thật trong bố cục — đẩy khung bài đọc
   hẹp lại, nằm giữa bài đọc và cột Pages, không đè lên gì cả. */
#word-panel.pinned{
  position:relative;top:auto;right:auto;bottom:auto;left:auto;
  width:340px;flex-shrink:0;
  transform:none;transition:none;
  border-left:1px solid var(--border);box-shadow:none;
}
#word-panel.pinned:not(.open){display:none;}

.wp-grab{display:none;}
.wp-head{display:flex;align-items:flex-start;gap:.6rem;padding:1rem 1rem .5rem;}
.wp-say{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  width:38px;height:38px;border-radius:10px;cursor:pointer;font-size:1rem;flex-shrink:0;
}
.wp-say:hover{border-color:var(--blue);color:var(--blue-l);}
.wp-title{flex:1;min-width:0;}
.wp-term{font-size:1.25rem;font-weight:800;word-break:break-word;}
.wp-ipa{font-size:.85rem;color:var(--text-3);margin-top:.15rem;}
.wp-close{background:transparent;border:none;color:var(--text-3);font-size:1rem;cursor:pointer;padding:.3rem;}
.wp-close:hover{color:var(--text);}
.wp-tags{display:flex;gap:.35rem;flex-wrap:wrap;padding:0 1rem;}
.wp-status{padding:.5rem 1rem 0;font-size:.75rem;}
.wp-known{color:var(--green-l);font-weight:700;}
.wp-new{color:var(--amber-l);font-weight:700;}
.wp-body{flex:1;overflow-y:auto;padding:.8rem 1rem;}
.wp-lbl{
  font-size:.66rem;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-3);margin-bottom:.25rem;
}
.wp-lbl.mt{margin-top:1rem;}
.wp-val{font-size:.92rem;line-height:1.6;color:var(--text-2);margin-bottom:.9rem;}
.wp-val.vi{color:var(--vi-color);font-weight:700;font-size:1rem;}
.wp-val.usage{
  background:var(--bg-soft);border-left:3px solid var(--amber);border-radius:0 8px 8px 0;
  padding:.6rem .8rem;font-style:italic;color:var(--text-2);
}
.wp-foot{padding:.8rem 1rem 1rem;border-top:1px solid var(--border-soft);}
.wp-levels{display:flex;gap:.4rem;margin-top:.5rem;}
.lvl-btn{
  flex:1;height:46px;border-radius:10px;border:1px solid var(--border);
  background:var(--bg-soft);color:var(--text-2);font-size:.95rem;font-weight:800;cursor:pointer;
}
.lvl-btn:hover{border-color:var(--amber);color:var(--amber-l);}
.lvl-btn.on{background:rgba(245,158,11,.22);border-color:var(--amber);color:var(--amber-l);}
.lvl-btn.ok{color:var(--green-l);}
.lvl-btn.ok:hover,.lvl-btn.ok.on{background:rgba(16,185,129,.18);border-color:var(--green);color:var(--green-l);}
.lvl-btn.del{flex:0 0 46px;color:var(--text-3);}
.lvl-btn.del:hover{color:var(--red-l);border-color:var(--red);}

/* ═══════════ BÀI THI CUỐI BÀI ═══════════
   Dạng phiếu bài tập. Word bank DÍNH trên đầu khi cuộn để lúc nào cũng
   nhìn thấy còn từ nào chưa dùng, khỏi phải kéo lên kéo xuống. */
.final-wrap{max-width:760px;margin:0 auto;}

/* --- Màn hình chuẩn bị --- */
.prep-head{display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;margin-bottom:.9rem;}
.prep-note{font-size:.76rem;color:var(--text-3);flex:1;min-width:180px;line-height:1.5;}
.prep-list{
  background:var(--bg-soft);border:1px solid var(--border);border-radius:12px;
  padding:.5rem .9rem;margin-bottom:1rem;
}
.prep-row{
  display:flex;align-items:center;gap:.5rem;padding:.6rem 0;
  border-bottom:1px solid var(--border-soft);flex-wrap:wrap;
}
.prep-row:last-child{border-bottom:none;}
.prep-term{
  font-weight:800;font-size:.98rem;color:var(--text);
  border-bottom:1px dashed var(--text-3);cursor:pointer;
}
.prep-term:hover{color:var(--blue-l);border-bottom-color:var(--blue);}
.prep-vi{color:var(--text-2);font-size:.9rem;flex:1;min-width:140px;}
.btn-big{width:100%;padding:.9rem 1rem;font-size:.95rem;border-radius:12px;}
.best-line{font-size:.8rem;color:var(--text-3);margin-top:.9rem;text-align:center;}

/* --- Thanh đầu --- */
.exam-head{
  display:flex;align-items:center;gap:.7rem;margin-bottom:.9rem;
  padding-bottom:.8rem;border-bottom:1px solid var(--border-soft);
}
.exam-tag{font-size:.72rem;font-weight:800;letter-spacing:.14em;color:var(--text-3);text-transform:uppercase;}
.exam-meta{margin-left:auto;font-size:.8rem;color:var(--text-2);white-space:nowrap;}

/* --- WORD BANK DÍNH --- */
.wordbank{
  position:sticky;top:-1px;z-index:20;
  background:var(--bg-card);border:1px solid var(--amber);border-radius:12px;
  padding:.65rem .8rem;margin-bottom:1.1rem;
  box-shadow:var(--shadow-md);
}
.wb-head{display:flex;align-items:center;gap:.6rem;margin-bottom:.5rem;}
.wb-title{font-size:.68rem;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--amber-l);}
.wb-left{font-size:.72rem;color:var(--text-3);margin-left:auto;}
.wb-clear{
  background:transparent;border:1px solid var(--border);color:var(--text-3);
  font-size:.7rem;font-weight:700;padding:.2rem .5rem;border-radius:6px;cursor:pointer;
}
.wb-clear:hover{color:var(--text);border-color:var(--text-3);}
.wb-items{display:flex;flex-wrap:wrap;gap:.4rem;max-height:132px;overflow-y:auto;}
.wb-chip{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  padding:.4rem .7rem;border-radius:8px;font-size:.86rem;font-weight:600;cursor:pointer;
  min-height:36px;
}
.wb-chip:hover{border-color:var(--amber);color:var(--amber-l);}
.wb-chip.used{opacity:.34;border-style:dashed;}
.wb-chip.used:hover{opacity:.75;}

/* --- Chế độ TỪNG CÂU --- */
.exam-bar-row{
  display:flex;align-items:center;justify-content:space-between;gap:.8rem;
  margin:.6rem 0 .4rem;
}
.exam-idx{font-size:.68rem;font-weight:800;letter-spacing:.08em;color:var(--text-2);text-transform:uppercase;white-space:nowrap;}
.exam-score{font-size:.72rem;font-weight:700;color:var(--blue-l);white-space:nowrap;}
/* "Done x%" = đúng % đã trả lời (khớp .quiz-bar bên dưới) — sang xanh lá
   khi đạt mốc PASS_MARK 80% trở lên, để biết ngay đang trên đà đạt hay
   chưa mà khỏi phải nhìn thanh progress. */
.exam-done{font-weight:800;}
.exam-done.hi{color:var(--green-l);}
.gap-card{
  background:var(--bg-soft);border:1px solid var(--border);border-radius:14px;
  padding:.75rem .9rem;margin:.6rem 0 .7rem;
}
/* 4 đáp án bên TRÁI, giải thích bên PHẢI — chấm xong chỉ lấp vào cột
   phải, không đẩy nút "Câu tiếp" xuống dưới như kiểu xếp chồng cũ. Cột
   phải có min-height sẵn để lúc chưa trả lời cũng không đổi cao đột
   ngột khi đáp án hiện ra. Điện thoại gập về 1 cột (chật ngang).
   Thu gọn cả cụm (thẻ từ + 4 đáp án + nút Câu tiếp) để vừa trọn 1 màn
   hình, nhất là điện thoại — không phải cuộn mới thấy hết. */
.single-grid{display:grid;grid-template-columns:1fr 1fr;gap:.8rem;align-items:start;margin-bottom:.6rem;}
.single-explain{min-height:56px;}
.single-explain:empty{min-height:0;}
@media(max-width:760px){
  .single-grid{grid-template-columns:1fr;gap:.5rem;}
  .single-explain{min-height:0;}
}
.gap-label{
  font-size:.7rem;font-weight:800;letter-spacing:.09em;text-transform:uppercase;
  color:var(--text-3);margin-bottom:.45rem;
}
.gap-sentence{font-size:1.12rem;line-height:1.8;color:var(--text);}
.gap-sentence.mc-term-big{font-size:1.2rem;font-weight:800;text-align:center;padding:.1rem 0;}
.blank{
  display:inline-block;color:var(--blue-l);font-weight:800;letter-spacing:.18em;
  padding:0 .25rem;vertical-align:baseline;
}
.blank.ok{background:rgba(16,185,129,.18);border-bottom:2px solid var(--green);color:var(--green-l);}
.blank.no{background:rgba(239,68,68,.16);border-bottom:2px solid var(--red);color:var(--red-l);}

/* Khối đáp án: nghĩa của từ + bản dịch cả câu, hiện dù đúng hay sai */
.ans-note{
  background:var(--bg-soft);border-left:3px solid var(--blue);
  border-radius:0 10px 10px 0;padding:.7rem .9rem;margin:.6rem 0 .2rem;
}
.an-word{font-size:.95rem;color:var(--text);}
.an-word b{color:var(--blue-l);}
.an-vi{color:var(--vi-color);font-weight:700;}
.an-def{font-size:.82rem;color:var(--text-2);margin-top:.25rem;line-height:1.5;}
.an-trans{
  font-size:.88rem;color:var(--text-1);margin-top:.4rem;line-height:1.6;
  padding-top:.4rem;border-top:1px dashed var(--border);
}

.blank.has{
  letter-spacing:normal;background:var(--blue-sub);border-bottom:2px solid var(--blue);
  border-radius:5px 5px 0 0;padding:.05rem .4rem;
}

/* --- Phần A: câu điền --- */
.exam-part{margin-bottom:1.5rem;}
.exam-part-title{
  font-size:.8rem;font-weight:800;color:var(--blue-l);margin-bottom:.8rem;
  padding-bottom:.35rem;border-bottom:1px solid var(--border-soft);
}
.ex-q{display:flex;gap:.55rem;align-items:baseline;margin-bottom:1rem;font-size:.95rem;line-height:2.1;color:var(--text);}
.ex-q .qn{color:var(--amber-l);font-weight:800;flex-shrink:0;min-width:1.5rem;}
.ex-q .qtext{flex:1;}
.slot{
  display:inline-flex;align-items:center;gap:.25rem;vertical-align:baseline;
  min-width:8.5rem;padding:.15rem .45rem;margin:0 .15rem;
  background:var(--bg-soft);border:1px solid var(--border);border-bottom:2px solid var(--text-3);
  border-radius:6px;cursor:pointer;font-weight:700;
}
.slot:hover{border-color:var(--text-3);}
.slot.active{border-color:var(--blue);border-bottom-color:var(--blue);background:var(--blue-sub);}
.slot.filled{color:var(--blue-l);border-bottom-color:var(--blue);}
.slot-text{white-space:nowrap;}
.slot-x{
  background:transparent;border:none;color:var(--text-3);cursor:pointer;
  font-size:.72rem;line-height:1;padding:.15rem .1rem;
}
.slot-x:hover{color:var(--red-l);}
.slot.right{color:var(--green-l);border-color:var(--green);border-bottom-color:var(--green);cursor:default;}
.slot.wrong{color:var(--red-l);border-color:var(--red);border-bottom-color:var(--red);text-decoration:line-through;cursor:default;}
.gap-fix{color:var(--green-l);font-weight:700;margin-left:.4rem;}

/* --- Phần B: trắc nghiệm --- */
.mc-q{margin-bottom:1.2rem;}
.mc-ask{font-size:.95rem;margin-bottom:.5rem;color:var(--text);}
.mc-ask .qn{color:var(--amber-l);font-weight:800;margin-right:.2rem;}
.mc-term{color:var(--blue-l);}
.opt-list{display:flex;flex-direction:column;gap:.4rem;}
.opt{
  display:block;width:100%;text-align:left;
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  padding:.55rem .8rem;border-radius:10px;font-size:.9rem;font-weight:600;
  cursor:pointer;min-height:42px;line-height:1.35;
}
.opt .mk{font-weight:800;margin-right:.4rem;color:var(--text-3);}
.opt:hover:not(:disabled){border-color:var(--text-3);background:var(--bg-raise);}
.opt:disabled{cursor:default;}
.opt.sel{border-color:var(--blue);background:var(--blue-sub);color:var(--blue-l);}
.opt.right{border-color:var(--green);background:rgba(16,185,129,.14);color:var(--green-l);}
.opt.wrong{border-color:var(--red);background:rgba(239,68,68,.12);color:var(--red-l);}
.opt.dim{opacity:.45;}

/* --- Kết quả --- */
.exam-actions{display:flex;gap:.6rem;flex-wrap:wrap;margin-top:.6rem;}
.exam-actions .btn-primary,.exam-actions .btn-soft{flex:1;padding:.8rem 1rem;font-size:.9rem;}
.exam-grading{flex:1;display:flex;align-items:center;justify-content:center;color:var(--text-3);font-size:.85rem;font-style:italic;}
.exam-result{
  border-radius:14px;padding:1.3rem 1rem;text-align:center;margin-bottom:1.1rem;border:1px solid var(--border);
}
.exam-result.pass{background:rgba(16,185,129,.1);border-color:rgba(16,185,129,.4);}
.exam-result.failed{background:rgba(239,68,68,.08);border-color:rgba(239,68,68,.35);}
.exam-result .score{font-size:2.6rem;font-weight:800;line-height:1;}
.exam-result.pass .score{color:var(--green-l);}
.exam-result.failed .score{color:var(--red-l);}
.exam-result .verdict{font-size:1rem;font-weight:800;margin-top:.5rem;}
.exam-result .detail{font-size:.82rem;color:var(--text-2);margin-top:.45rem;line-height:1.55;}
.pass-rule{
  display:block;text-align:center;background:rgba(245,158,11,.12);border:1px solid rgba(245,158,11,.35);
  color:var(--amber-l);padding:.5rem .8rem;border-radius:10px;font-size:.8rem;font-weight:700;margin-bottom:.9rem;
}

/* SRS timeline */
.srs-timeline{display:flex;flex-direction:column;gap:.5rem;}
.srs-step{display:flex;align-items:center;gap:.8rem;padding:.65rem .8rem;border-radius:10px;background:var(--bg-soft);border:1px solid var(--border-soft);font-size:.8rem;}
.srs-step .idx{
  min-width:2rem;height:2rem;padding:0 .3rem;border-radius:999px;background:var(--bg-raise);color:var(--text-3);
  display:flex;align-items:center;justify-content:center;font-size:.72rem;font-weight:800;flex-shrink:0;
}
.srs-step.done{border-color:rgba(16,185,129,.3);}
.srs-step.done .idx{background:rgba(16,185,129,.2);color:var(--green-l);}
.srs-step.now{border-color:var(--amber);background:rgba(245,158,11,.06);}
.srs-step.now .idx{background:var(--amber);color:#1a1200;}
.srs-step-body{display:flex;flex-direction:column;gap:.15rem;min-width:0;flex:1;}
.srs-step-name{font-weight:700;color:var(--text);}
.srs-step.now .srs-step-name{color:var(--amber-l);}
.srs-step .when{color:var(--text-3);font-size:.72rem;}
.srs-step.now .when{color:var(--text-2);font-weight:600;}

/* ═══════════ MODALS ═══════════ */
/* Hộp thoại phải nằm TRÊN bảng nghĩa (z-index 1101), nếu không thì hộp
   "Xoá Notebook?" bị bảng nghĩa che mất một nửa. */
.modal-overlay{
  position:fixed;inset:0;background:var(--scrim);backdrop-filter:blur(3px);
  display:flex;justify-content:center;align-items:center;z-index:1300;padding:1rem;
}
.modal-overlay[hidden]{display:none;}
.modal-box{
  background:var(--bg-card);border:1px solid var(--border);width:100%;max-width:460px;
  padding:1.2rem;border-radius:14px;max-height:88vh;overflow-y:auto;
}
.modal-box.wide{max-width:620px;}
.modal-box.xwide{max-width:96vw;width:960px;}
.modal-box h3{margin:0 0 .4rem;font-size:1rem;font-weight:700;}
.modal-desc{font-size:.78rem;color:var(--text-2);margin:0 0 .9rem;line-height:1.55;}
.format-help{
  background:var(--bg-soft);border:1px solid var(--border-soft);border-radius:8px;padding:.6rem .7rem;
  font-size:.72rem;color:var(--text-2);line-height:1.7;margin-bottom:.7rem;
}
.format-help code{background:var(--bg-raise);padding:.1rem .35rem;border-radius:4px;color:var(--blue-l);font-size:.7rem;}
textarea{
  width:100%;height:180px;background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  padding:.7rem;border-radius:8px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  font-size:.8rem;resize:vertical;outline:none;line-height:1.6;
}
textarea:focus{border-color:var(--blue);}
/* Ô gõ lại câu Dictation — chữ thường (không monospace như textarea mặc
   định, đây là câu tiếng Anh bình thường chứ không phải code/JSON), thấp
   hơn hẳn 180px mặc định vì chỉ cần gõ 1 câu. */
.dictation-input{height:70px;font-family:inherit;font-size:.95rem;margin:.6rem 0;}
.text-input{
  width:100%;background:var(--bg-soft);border:1px solid var(--border);color:var(--text);
  padding:.65rem .8rem;border-radius:8px;font-size:.9rem;outline:none;
}
.text-input:focus{border-color:var(--blue);}
.extract-url-row{display:flex;gap:.5rem;}
.extract-url-row .text-input{flex:1;}
.extract-url-row .btn-soft{flex-shrink:0;}
/* "Dán cả sách, tự chia Chapter" — xem trước danh sách phần đã cắt */
.modal-sep{border:none;border-top:1px solid var(--border);margin:1.1rem 0;}
.book-chapters-list{max-height:260px;overflow-y:auto;display:flex;flex-direction:column;gap:.4rem;margin-top:.4rem;}
.book-chapter-row{display:flex;align-items:center;gap:.5rem;}
.book-chapter-row .book-chapter-check{flex-shrink:0;width:16px;height:16px;}
.book-chapter-row .book-chapter-name{flex:1;padding:.4rem .6rem;font-size:.85rem;}
.book-chapter-meta{flex-shrink:0;font-size:.72rem;color:var(--text-2);white-space:nowrap;}
.book-progress{margin-top:.7rem;font-size:.85rem;color:var(--text-2);}

/* Thanh điều khiển NGHE NỔI (sticky player) — nổi cố định đáy màn hình,
   tự hiện ngay khi cuộn khỏi tầm nhìn nút Dừng lúc đang nghe (xem
   detail.js). Bố cục kiểu mini-player thật: nút Play tròn bên trái,
   tiêu đề + thanh tiến độ ở giữa, nút "🎤 nhảy tới karaoke" + Đóng bên
   phải — TJ yêu cầu "thiết kế sao cho hay" (2026-09-12). */
.sticky-player{
  position:fixed;left:50%;bottom:18px;transform:translateX(-50%);
  z-index:60;display:flex;align-items:center;gap:.7rem;
  background:#232220;color:#fff;border-radius:18px;
  padding:.5rem .7rem .5rem .5rem;
  box-shadow:0 10px 30px rgba(0,0,0,.4),0 0 0 1px rgba(255,255,255,.06);
  max-width:calc(100vw - 24px);width:520px;
  animation:sp-pop-in .18s ease-out;
}
@keyframes sp-pop-in{from{opacity:0;transform:translateX(-50%) translateY(10px);}to{opacity:1;transform:translateX(-50%) translateY(0);}}
.sticky-player[hidden]{display:none;}
.sp-btn{
  flex-shrink:0;background:none;border:none;color:#fff;
  cursor:pointer;line-height:1;
  display:flex;align-items:center;justify-content:center;
  transition:opacity .15s,background .15s;
}
.sp-btn:hover{opacity:1;background:rgba(255,255,255,.08);}
.sp-play{
  width:38px;height:38px;border-radius:50%;font-size:1.05rem;
  background:var(--blue);flex-shrink:0;
}
.sp-play:hover{background:var(--blue-hi,var(--blue));opacity:1;}
.sp-mid{flex:1;min-width:0;display:flex;flex-direction:column;gap:.28rem;}
.sp-title{
  font-size:.78rem;font-weight:600;color:#fff;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.sp-track-row{display:flex;align-items:center;gap:.45rem;}
.sp-time{flex-shrink:0;font-size:.68rem;color:#9d988f;min-width:28px;font-variant-numeric:tabular-nums;}
.sp-time:last-child{text-align:right;}
.sp-bar{flex:1;height:4px;background:rgba(255,255,255,.18);border-radius:2px;overflow:hidden;min-width:50px;cursor:default;}
.sp-bar-fill{height:100%;background:var(--blue);width:0%;transition:width .25s linear;}
.sp-jump{width:32px;height:32px;border-radius:9px;font-size:.95rem;opacity:.85;}
.sp-close{width:32px;height:32px;border-radius:9px;font-size:.85rem;opacity:.6;}
@media (max-width:480px){
  .sticky-player{width:calc(100vw - 24px);padding:.45rem .55rem;gap:.5rem;}
  .sp-jump{display:none;}
}
/* Hộp xuất PDF */
.export-size-row{display:flex;gap:1rem;flex-wrap:wrap;font-size:.85rem;color:var(--text-2);}
.export-size-row label{display:flex;align-items:center;gap:.35rem;cursor:pointer;}
#export-scope-list .user-row{cursor:pointer;}
#export-scope-list .user-row input{margin-right:.2rem;}
.emoji-row{display:flex;flex-wrap:wrap;gap:.35rem;margin-top:.7rem;}
.emoji-row[hidden]{display:none;}
.emoji-pick{
  width:34px;height:34px;border-radius:8px;border:1px solid var(--border);background:var(--bg-soft);
  font-size:1.05rem;cursor:pointer;display:flex;align-items:center;justify-content:center;
}
.emoji-pick.sel{border-color:var(--blue);background:var(--blue-sub);}
.paste-preview{font-size:.74rem;color:var(--text-2);margin-top:.55rem;min-height:1.1rem;}
.paste-preview b{color:var(--blue-l);}
.modal-actions{display:flex;justify-content:flex-end;gap:.5rem;margin-top:1rem;}
.user-list{display:flex;flex-direction:column;gap:.4rem;margin-bottom:.7rem;}
.user-row{
  display:flex;align-items:center;gap:.6rem;padding:.55rem .65rem;border-radius:8px;
  border:1px solid var(--border);background:var(--bg-soft);cursor:pointer;font-size:.85rem;
  color:var(--text);width:100%;text-align:left;font-family:inherit;
  /* Đây là <button>, không đặt màu chữ thì trình duyệt tự lấy màu mặc
     định (thường gần đen) — chỗ "Đổi người học" không lộ ra vì chữ nằm
     trong span con đã có màu riêng, nhưng askPick() (Chuyển Hub/Section/
     Page khác) in chữ thẳng vào đây nên bị đen chìm trên nền tối. */
}
.user-row:hover{border-color:var(--border-hi);}
.user-row.active{border-color:var(--blue);background:var(--blue-sub);}
.user-row .del{margin-left:auto;background:transparent;border:none;color:var(--text-3);cursor:pointer;font-size:.85rem;}
.user-row .del:hover{color:var(--red-l);}
.cloud-status{font-size:.78rem;margin-top:.7rem;color:var(--text-2);line-height:1.55;}
.cloud-status.ok{color:var(--green-l);}
.cloud-status.err{color:var(--red-l);}

/* Modal Quản lý tài khoản (Admin) — xem #modal-admin trong index.html */
.admin-list{display:flex;flex-direction:column;gap:.4rem;margin:.7rem 0;max-height:50vh;overflow-y:auto;}
.admin-row{
  display:flex;align-items:center;gap:.6rem;padding:.55rem .65rem;border-radius:8px;
  border:1px solid var(--border);background:var(--bg-soft);font-size:.85rem;flex-wrap:wrap;
}
.admin-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.admin-toggle{display:flex;align-items:center;gap:.3rem;font-size:.76rem;color:var(--text-2);cursor:pointer;white-space:nowrap;}
.admin-toggle input{cursor:pointer;}
.admin-toggle input:disabled{cursor:not-allowed;opacity:.5;}
.admin-new-link{
  font-size:.78rem;color:var(--text-2);background:var(--green-sub);border:1px solid rgba(79,174,130,.35);
  border-radius:8px;padding:.6rem .7rem;margin:.6rem 0;line-height:1.6;
}
.admin-new-link code{
  display:block;word-break:break-all;font-size:.72rem;color:var(--text);background:var(--bg-deep);
  border-radius:6px;padding:.4rem .5rem;margin:.3rem 0;
}

/* Modal Báo cáo AI — xem #modal-ai-report trong index.html */
.ai-report-summary{display:flex;flex-wrap:wrap;gap:.4rem;margin:.5rem 0 .9rem;}
.ai-report-chip{
  font-size:.76rem;font-weight:600;color:var(--text-2);background:var(--bg-soft);
  border:1px solid var(--border);border-radius:999px;padding:.3rem .65rem;
}
.ai-report-body{max-height:60vh;overflow-y:auto;}
.ai-report-batch{margin-bottom:1rem;}
.ai-report-batch h4{margin:0 0 .35rem;font-size:.85rem;font-weight:700;color:var(--text-2);}
.ai-report-table{width:100%;border-collapse:collapse;font-size:.78rem;}
.ai-report-table th,.ai-report-table td{
  text-align:left;padding:.4rem .5rem;border-bottom:1px solid var(--border);
}
.ai-report-table th{color:var(--text-3);font-weight:600;}

/* Modal Chia sẻ Notebook (Mức A) — xem #modal-share/#modal-share-overview
   trong index.html, App.openShareModal/openShareOverview trong app.js. */
.share-toggle{
  display:flex;align-items:center;gap:.5rem;font-size:.82rem;font-weight:600;color:var(--text);
  background:var(--bg-soft);border:1px solid var(--border);border-radius:8px;padding:.6rem .7rem;margin:.6rem 0;
}
.share-toggle input{cursor:pointer;}
.share-user-list{display:flex;flex-direction:column;gap:.4rem;max-height:45vh;overflow-y:auto;margin-bottom:.4rem;}
.share-user-row{
  display:flex;align-items:center;justify-content:space-between;gap:.6rem;
  padding:.5rem .65rem;border-radius:8px;border:1px solid var(--border);background:var(--bg-soft);font-size:.82rem;
}
.share-user-label{display:flex;align-items:center;gap:.45rem;cursor:pointer;flex:1;min-width:0;}

/* Ma trận chia sẻ (🔐 Quản lý chia sẻ, #modal-share-overview) — hàng =
   tài khoản, cột = Notebook, xem App.renderShareMatrix trong app.js.
   Header hàng (tên Notebook) VÀ cột đầu (tên user) đều sticky — bảng
   thường rộng + cao hơn khung nhìn, cuộn ngang/dọc vẫn thấy đang ở
   đúng hàng/cột nào. */
.share-hub-filter{display:flex;flex-wrap:wrap;gap:.4rem;margin:.6rem 0;}
#btn-share-restrict-all{margin-bottom:.6rem;}
.share-matrix-wrap{max-height:60vh;overflow:auto;border:1px solid var(--border);border-radius:8px;}
.share-matrix{border-collapse:collapse;font-size:.78rem;white-space:nowrap;}
.share-matrix th,.share-matrix td{border:1px solid var(--border);padding:.4rem .5rem;}
.share-matrix thead th{
  position:sticky;top:0;background:var(--bg-card);z-index:2;text-align:center;vertical-align:top;
}
.share-mx-corner{position:sticky;left:0;top:0;z-index:3;background:var(--bg-card);}
.share-mx-nbname{font-weight:700;max-width:9rem;overflow:hidden;text-overflow:ellipsis;margin:0 auto .3rem;}
.share-mx-vis{
  display:block;width:100%;background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  font-size:.68rem;font-weight:600;padding:.15rem .4rem;border-radius:999px;cursor:pointer;margin-bottom:.25rem;
}
.share-mx-vis.pub{background:var(--green-sub);color:var(--green-l);border-color:rgba(79,174,130,.35);}
.share-mx-all{
  background:var(--blue-sub);color:var(--blue-l);border:1px solid var(--blue);
  font-size:.66rem;font-weight:700;padding:.1rem .5rem;border-radius:999px;cursor:pointer;
}
.share-mx-user{
  position:sticky;left:0;z-index:1;background:var(--bg-card);
  display:flex;align-items:center;justify-content:space-between;gap:.5rem;font-weight:600;
}
.share-mx-cell{text-align:center;}
.share-mx-cell input{width:1.05rem;height:1.05rem;cursor:pointer;}
.share-mx-cell input:disabled{cursor:not-allowed;opacity:.6;}

/* Tab Tuần/Tháng/Từ đầu — modal Bảng xếp hạng (#modal-leaderboard) */
.lb-tabs{display:flex;gap:.4rem;margin:.6rem 0;}
.lb-tab{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  font-size:.8rem;font-weight:600;padding:.4rem .9rem;border-radius:999px;cursor:pointer;
}
.lb-tab.active{background:var(--blue-sub);color:var(--blue-l);border-color:var(--blue);}
.lb-tab:hover{color:var(--text);}
/* Dòng của CHÍNH người đang xem — tô nổi bật, kể cả khi bị ghim riêng ở
   ngoài Top 10 (xem renderLeaderboardModal trong app.js). ".lb-gap" là
   hàng "⋯" ngăn cách Top 10 với dòng ghim riêng đó, giống Memrise. */
.lb-me{font-weight:700;color:var(--blue-l);background:var(--blue-sub);}
.lb-gap td{text-align:center;color:var(--text-3);padding:.25rem;}

/* Tab "Nghĩa" — chọn kiểm tra theo Nghĩa VN (mặc định) hay Meaning EN */
.meaning-lang-tabs{display:flex;gap:.4rem;margin:0 0 .6rem;}
.mn-lang-tab{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  font-size:.8rem;font-weight:600;padding:.4rem .9rem;border-radius:999px;cursor:pointer;
}
.mn-lang-tab.active{background:var(--blue-sub);color:var(--blue-l);border-color:var(--blue);}
.mn-lang-tab:hover{color:var(--text);}
.lb-more{width:100%;margin-top:.5rem;text-align:center;}

/* Toast */
.toast-wrap{position:fixed;bottom:1rem;left:50%;transform:translateX(-50%);z-index:2000;display:flex;flex-direction:column;gap:.4rem;align-items:center;pointer-events:none;}
.toast{
  background:var(--bg-card);border:1px solid var(--border);color:var(--text);padding:.55rem .95rem;
  border-radius:999px;font-size:.8rem;font-weight:600;box-shadow:var(--shadow-md);
  animation:tin .2s ease;max-width:90vw;
}
.toast.ok{border-color:rgba(16,185,129,.45);color:var(--green-l);}
.toast.err{border-color:rgba(239,68,68,.45);color:var(--red-l);}
@keyframes tin{from{opacity:0;transform:translateY(8px);}to{opacity:1;transform:none;}}

/* ═══════════ RESPONSIVE ═══════════ */
.mobile-only{display:none;}
.mobile-nav{display:none;}
.drawer-backdrop{position:fixed;inset:0;background:var(--scrim);z-index:800;}
.drawer-backdrop[hidden]{display:none;}

@media(max-width:1100px){
  .cycle-grid{grid-template-columns:repeat(2,1fr);}
}

@media(max-width:860px){
  body{font-size:15px;}
  .mobile-only{display:flex;}
  .brand-text{display:none;}
  .uname{max-width:70px;}
  .workspace{padding:.8rem .8rem 5rem;}
  .card{padding:.75rem;}   /* thẻ bài tập (Nghĩa/Từng câu...) bớt viền trắng thừa, vừa màn hình hơn */

  /* height thay vì bottom:0: bottom:0 phải TÍNH LẠI mỗi lần thanh địa chỉ
     mobile ẩn/hiện lúc cuộn (viewport đổi) -> cả sidebar (kéo theo 2 khối
     "cố định" RANKING/Tony Buzan bên trong) bị giật. 100dvh trừ phần
     topbar cho chiều cao ỔN ĐỊNH ngay từ đầu, khỏi phụ thuộc bottom. */
  .sidebar{
    position:fixed;top:calc(var(--topbar-h) + env(safe-area-inset-top));
    height:calc(100vh - var(--topbar-h) - env(safe-area-inset-top));
    height:calc(100dvh - var(--topbar-h) - env(safe-area-inset-top));
    width:78%;max-width:290px;z-index:850;
    transition:transform .22s ease;
  }
  .sidebar-left{left:0;transform:translateX(-102%);}
  .sidebar-right{right:0;transform:translateX(102%);}
  .sidebar.open{transform:none;box-shadow:var(--shadow-lg);}

  .stats-grid{grid-template-columns:repeat(2,1fr);}
  .alert-header{flex-direction:column;align-items:stretch;}
  .alert-header .btn-warn{width:100%;}

  /* 3 tab chia đều, bỏ bớt chữ cho vừa màn hình. #bn-pos vẫn phải hiện
     TRỌN VẸN — không đủ chỗ chung 1 hàng với dải tab thì xuống hàng riêng
     (flex-wrap), tuyệt đối không để bị cuộn/co khuất mất chữ. */
  .dt-long{display:none;}
  .detail-tabs{flex-wrap:wrap;}
  .dtabs-scroll{overflow-x:visible;flex:1 1 100%;}
  .dtab{flex:1;padding:.42rem .12rem;font-size:.68rem;white-space:nowrap;}
  .detail-tabs .bn-pos{margin-left:0;flex:1 1 100%;padding-left:0;padding-top:.15rem;}

  /* thanh công cụ nghe: các nút giãn đều, không rớt lộn xộn */
  .card-title-row{flex-direction:column;align-items:stretch;}
  .audio-toolbar{width:100%;}
  .audio-toolbar .btn-primary,.audio-toolbar .btn-soft{flex:1;}

  /* ── BẢNG -> THẺ ────────────────────────────────────────────────
     Trên điện thoại, bảng 5 cột bắt người học kéo ngang mới thấy
     cột "Nghĩa tiếng Việt" — đúng cột quan trọng nhất. Nên mỗi dòng
     được xếp lại thành một thẻ đứng, có nhãn ở đầu mỗi ô.          */
  .table-wrap{overflow-x:visible;}
  .vocab-table{min-width:0;display:block;}
  .vocab-table thead{display:none;}
  .vocab-table tbody{display:block;}
  .vocab-table tr{
    display:block;background:var(--bg-soft);border:1px solid var(--border-soft);
    border-radius:8px;padding:.6rem .7rem;margin-bottom:.5rem;
  }
  .vocab-table tr:last-child{margin-bottom:0;}
  .vocab-table td{
    display:flex;align-items:flex-start;gap:.6rem;
    border-bottom:none;padding:.22rem 0;
  }
  .vocab-table td::before{
    content:attr(data-label);flex:0 0 78px;color:var(--text-3);
    font-size:.63rem;font-weight:800;text-transform:uppercase;letter-spacing:.02em;padding-top:.22rem;
  }
  .vocab-table td:first-child{
    display:block;padding:0 0 .4rem;margin-bottom:.35rem;border-bottom:1px solid var(--border-soft);
  }
  .vocab-table td:first-child::before{display:none;}

  /* điện thoại: không có chỗ ghim cột hay kéo giãn, ẩn đi cho gọn */
  .pane-head,.pin-btn,.resizer{display:none;}
  .section-bar{padding:.4rem .5rem 0;}
  .section-tab{padding:.5rem .8rem;font-size:.78rem;}
  .sidebar.unpinned{width:78%;}
  .sidebar.unpinned.flyout{position:fixed;}

  /* ── BẢNG TRA TỪ TRÊN ĐIỆN THOẠI: trồi lên từ đáy, kéo được ── */
  .word-panel{
    top:auto;left:0;right:0;bottom:0;width:100%;max-width:100%;
    max-height:82vh;border-left:none;border-top:1px solid var(--border);
    border-radius:18px 18px 0 0;transform:translateY(102%);
    box-shadow:var(--shadow-lg);
    padding-bottom:env(safe-area-inset-bottom);
  }
  /* điện thoại không đủ chỗ chia cột — ghim hay không vẫn là tấm trồi từ đáy */
  #word-panel.pinned{
    position:fixed;top:auto;left:0;right:0;bottom:0;width:100%;
    border-left:none;border-top:1px solid var(--border);
    box-shadow:var(--shadow-lg);
    transform:translateY(102%);transition:transform .22s ease;
  }
  #word-panel.pinned.open{transform:none;}
  #word-panel.pinned:not(.open){display:flex;}
  .word-panel.open{transform:none;}
  .wp-grab{
    display:block;width:42px;height:4px;border-radius:4px;background:var(--border);
    margin:.55rem auto .1rem;flex-shrink:0;
  }
  .wp-head{padding:.5rem .9rem .4rem;}
  .wp-term{font-size:1.3rem;}
  .wp-body{padding:.7rem .9rem;}
  .wp-foot{padding:.7rem .9rem .9rem;}
  .lvl-btn{height:52px;font-size:1rem;}
  .wp-meaning,#wp-meaning{font-size:16px;}

  .read-modes{gap:.35rem;}
  .rm-btn{flex:1;padding:.5rem .3rem;font-size:.74rem;text-align:center;}
  .passage.mode-sentence .sent{font-size:1.15rem;}
  .read-nav .btn-soft{padding:.6rem .9rem;}

  /* ── BÀI THI TRÊN ĐIỆN THOẠI ──
     Word bank dính sát mép trên, chip và ô điền to để bấm bằng ngón tay. */
  #final-card{padding:.8rem .7rem;}
  .exam-head{gap:.5rem;}
  .exam-head .btn-soft{padding:.5rem .7rem;}
  .exam-tag{font-size:.64rem;letter-spacing:.08em;}
  .exam-meta{font-size:.72rem;}

  .wordbank{
    position:sticky;top:-1px;margin:0 -.7rem 1rem;border-radius:0 0 14px 14px;
    border-left:none;border-right:none;border-top:none;padding:.6rem .7rem;
  }
  /* đúng 2 hàng chip rồi mới cuộn — cắt lửng nửa hàng nhìn như bị lỗi */
  .wb-items{max-height:92px;}
  .wb-chip{font-size:.9rem;padding:.45rem .75rem;min-height:40px;}
  .wb-clear{padding:.3rem .6rem;font-size:.72rem;}

  .exam-bar-row{margin:.5rem 0 .35rem;}
  .exam-idx{font-size:.72rem;}
  .exam-score{font-size:.76rem;}
  /* Thu gọn thẻ từ + đáp án của Nghĩa/Từng câu để vừa trọn màn hình điện
     thoại (khỏi cuộn mới thấy hết nút "Câu tiếp") — .ex-q/.slot bên dưới
     là của Phiếu đầy đủ, giữ nguyên cỡ to (câu văn dài, cần dễ đọc hơn). */
  .gap-card{padding:.6rem .7rem;margin:.5rem 0 .6rem;}
  .gap-sentence{font-size:1.06rem;line-height:1.85;}
  .ex-q{flex-direction:column;gap:.15rem;line-height:2.3;margin-bottom:1.2rem;}
  .slot{min-width:9.5rem;padding:.3rem .55rem;font-size:1rem;}
  .opt{padding:.6rem .8rem;font-size:.88rem;min-height:44px;border-radius:10px;}
  .opt-list{gap:.4rem;}
  .prep-row{gap:.4rem;}
  .prep-vi{width:100%;flex:none;font-size:.86rem;}
  .exam-result .score{font-size:2.9rem;}

  .mobile-nav{
    display:flex;position:fixed;bottom:0;left:0;right:0;height:56px;z-index:860;
    background:var(--bg-sidebar);border-top:1px solid var(--border);
    padding-bottom:env(safe-area-inset-bottom);
  }
  .mobile-nav button{
    flex:1;background:transparent;border:none;color:var(--text-3);font-size:1.1rem;
    display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.1rem;cursor:pointer;
  }
  .mobile-nav button span{font-size:.62rem;font-weight:700;}
  .mobile-nav button.active{color:var(--blue-l);}
  .toast-wrap{bottom:4.5rem;}

  /* Vùng bấm tối thiểu ~40px trên di động (WCAG 2.5.5) cho các icon-button
     đang nhỏ hơn hẳn ngón tay — KHÔNG đổi cỡ chữ/icon bên trong, chỉ nới
     khung ngoài bằng padding/kích thước, nên bố cục desktop không đổi
     (những rule này chỉ áp dụng trong @media(max-width:860px) hiện tại). */
  .dots{padding:.55rem;}
  .jrow-open,.jrow-dots{width:36px;height:36px;}
  .home-card-go{width:2.4rem;height:2.4rem;}
  .wp-close{padding:.6rem;}
  .tab-scroll-btn{width:2rem;height:2rem;}
  .vchip-del{padding:.3rem .35rem;}
  .g-copy{padding:.4rem .65rem;}
  .jcal-nav .btn-ghost.mini{padding:.5rem .7rem;}

  /* .batches-bar (Batch trước/sau + tab Batch) từng chật khi màn quá hẹp
     và đang mở Chi tiết Block (3 cụm cùng hàng: "← Quay lại", nút Block
     trước/sau, dải tab Batch) — cho phép xuống hàng thay vì ép co lại
     (đã nêu trong README mục "Việc còn dang dở"). */
  .batches-bar{flex-wrap:wrap;row-gap:.4rem;}
  .batch-tabs{flex:1 1 100%;}
}

/* ═══════════ IN PDF (window.print, xem js/export.js) ═══════════
   #print-root ẩn lúc xem thường ([hidden] mặc định của trình duyệt).
   Lúc in: hiện nó lên, ẩn HẾT mọi thứ khác của trang — chỉ còn đúng nội
   dung sạch, chữ to, giấy trắng chữ đen (không theo theme sáng/tối đang
   chọn trên web, in giấy thì luôn cần tương phản cao). */
@media print{
  @page{margin:1.6cm;}
  html{font-size:16px;}   /* bỏ qua cỡ chữ đang chỉnh trên web, in theo cỡ chuẩn */
  body > *:not(#print-root){display:none !important;}
  #print-root{
    display:block !important;
    background:#fff;color:#111;
    font-family:Georgia,"Times New Roman",serif;
    line-height:1.65;
  }
  #print-root.print-normal{font-size:13pt;}
  #print-root.print-large{font-size:17pt;}
  #print-root.print-xl{font-size:21pt;}

  .pv-cover{text-align:center;padding:3em 0 2em;border-bottom:2px solid #333;margin-bottom:1.5em;}
  .pv-cover h1{font-size:2em;margin:0 0 .3em;}
  .pv-cover-sub{font-size:.75em;color:#555;}

  .pv-block{page-break-after:always;}
  .pv-block:last-child{page-break-after:auto;}
  .pv-block h2{font-size:1.5em;border-bottom:1px solid #999;padding-bottom:.25em;margin:0 0 .7em;}

  .pv-table{width:100%;border-collapse:collapse;margin:0 0 1.4em;font-size:.72em;}
  .pv-table th,.pv-table td{border:1px solid #999;padding:.4em .55em;text-align:left;vertical-align:top;}
  .pv-table th{background:#eee;}

  .pv-passage-title{font-size:1.2em;margin:0 0 .5em;}
  .pv-passage p{margin:0 0 1em;orphans:3;widows:3;}

  .pv-glossary{margin-top:1.2em;padding-top:.8em;border-top:1px dashed #999;font-size:.8em;}
  .pv-glossary-title{
    font-weight:800;text-transform:uppercase;letter-spacing:.05em;
    font-size:.85em;margin-bottom:.5em;color:#555;
  }
  .pv-glossary div{margin-bottom:.4em;}
}

/* ═══════════ JOURNEY — thống kê học theo ngày ═══════════
   Đã bỏ hẳn khối "Tổng quan" (3 thẻ .jstat + 4 chip .jgroup-chip) từng
   đứng trên lịch — trùng lặp với 4 tab Tony Buzan bên dưới, theo yêu cầu
   người dùng (che tiêu đề, rườm rà). */
.journey-legend{display:flex;gap:.9rem;font-size:.72rem;color:var(--text-2);flex-wrap:wrap;}
.journey-legend span{display:flex;align-items:center;gap:.3rem;}
.jdot{width:.6rem;height:.6rem;border-radius:3px;display:inline-block;}
.jdot.learn{background:var(--green);}
.jdot.due{background:var(--red);}
.jdot.both{background:linear-gradient(135deg,var(--green) 50%,var(--red) 50%);}

/* Giới hạn bề rộng để ô lịch không phình to trên màn hình rộng, và
   không bao giờ tràn khỏi khung màn hình trên điện thoại — 7 cột vuông,
   max mỗi ô ~52px là đủ đọc số, không cần to hơn. */
.journey-cal{
  display:grid;grid-template-columns:repeat(7,minmax(0,52px));gap:.3rem;
  justify-content:center;max-width:100%;margin:0 auto;
}
.jcell{
  aspect-ratio:1;border-radius:8px;background:var(--bg-soft);border:1px solid var(--border);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.05rem;
  font-size:.68rem;color:var(--text-3);position:relative;min-width:0;
}
.jcell .jd{font-weight:700;}
.jcell .jn{font-size:.56rem;font-weight:700;}
.jcell.learn{background:rgba(16,185,129,.16);border-color:rgba(16,185,129,.4);color:var(--green-l);}
.jcell.due{background:rgba(239,68,68,.16);border-color:rgba(239,68,68,.4);color:var(--red-l);}
.jcell.both{background:linear-gradient(135deg,rgba(16,185,129,.22) 50%,rgba(239,68,68,.22) 50%);border-color:var(--border);color:var(--text);}
.jcell.today{outline:2px solid var(--blue);outline-offset:1px;}
.jcell.pad{visibility:hidden;}
.jcal-dow{font-size:.62rem;color:var(--text-3);text-align:center;font-weight:700;text-transform:uppercase;}

@media(max-width:640px){
  .journey-cal{grid-template-columns:repeat(7,minmax(0,1fr));gap:.25rem;}
  .jcell{font-size:.6rem;}
  .jcell .jn{font-size:.5rem;}
}

/* ─── Journey: thanh trên + breadcrumb + cây drill-down ─── */
.journey-topbar{display:flex;align-items:center;justify-content:space-between;gap:.5rem;margin-bottom:.6rem;}
.journey-crumb{
  display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;font-size:.78rem;color:var(--text-3);
  margin-bottom:.7rem;
}
.jcrumb-item{cursor:pointer;padding:.15rem .4rem;border-radius:5px;color:var(--text-2);}
.jcrumb-item:hover{background:var(--bg-deep);color:var(--text);}
.jcrumb-item.active{color:var(--text);font-weight:700;cursor:default;}
.jcrumb-item.active:hover{background:transparent;}
.jcrumb-sep{color:var(--text-3);}

.journey-tree{display:flex;flex-direction:column;gap:.35rem;}
.jrow{
  display:flex;align-items:center;gap:.55rem;background:var(--bg-soft);border:1px solid var(--border);
  border-radius:9px;padding:.5rem .6rem;cursor:pointer;
}
.jrow:hover{border-color:var(--border-hi);background:var(--bg-card);}
.jrow-ic{font-size:1rem;flex-shrink:0;width:1.3em;text-align:center;}
.jrow-name{font-weight:600;color:var(--text);flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.jrow-bar{width:80px;height:6px;border-radius:4px;background:var(--bg-deep);overflow:hidden;flex-shrink:0;}
.jrow-bar i{display:block;height:100%;background:var(--green);border-radius:4px;}
.jrow-pct{font-size:.72rem;color:var(--text-2);width:2.8em;text-align:right;flex-shrink:0;}
.jrow-count{font-size:.7rem;color:var(--text-3);flex-shrink:0;white-space:nowrap;}
.jrow-status{font-size:.72rem;color:var(--text-2);flex-shrink:0;}
.jrow-open,.jrow-dots{
  background:transparent;border:1px solid var(--border);color:var(--text-2);border-radius:6px;
  width:26px;height:26px;flex-shrink:0;cursor:pointer;font-size:.85rem;line-height:1;
}
.jrow-open:hover,.jrow-dots:hover{color:var(--text);border-color:var(--border-hi);}
.jrow-block.done .jrow-ic{color:var(--green-l);}
.jrow-block.done .jrow-status{color:var(--green-l);font-weight:700;}
.jrow-block:not(.done) .jrow-ic{color:var(--text-3);}

@media(max-width:640px){
  .jrow-bar{display:none;}
  .jrow-count{display:none;}
}

/* ─── Journey: nút ←/→ đổi tháng cho lịch học ─── */
.jcal-nav{display:flex;align-items:center;gap:.5rem;}
.btn-ghost.mini{padding:.25rem .55rem;font-size:.8rem;line-height:1;}
.btn-ghost.mini:disabled{opacity:.35;cursor:not-allowed;}
.jcal-month-label{font-size:.78rem;font-weight:700;color:var(--text-2);min-width:6.5em;text-align:center;}

/* ─── Trang chủ: mỗi Hub 1 khối, bên trong là lưới thẻ Notebook (kiểu thẻ
   khoá học Memrise) ─── */
.home-hub-block{margin-bottom:1.4rem;}
.home-hub-title{font-size:.95rem;font-weight:800;color:var(--text);margin-bottom:.6rem;}
.home-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:.75rem;}
.home-card{
  display:flex;align-items:center;gap:.75rem;background:var(--bg-card);border:1px solid var(--border);
  border-radius:var(--radius);padding:.85rem;cursor:pointer;text-align:left;
}
.home-card:hover{border-color:var(--blue);}
.home-card-ic{font-size:1.6rem;flex-shrink:0;}
.home-card-body{flex:1;min-width:0;}
.home-card-name{font-weight:700;font-size:.88rem;color:var(--text);margin-bottom:.35rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.home-card-bar{width:100%;height:6px;border-radius:4px;background:var(--bg-deep);overflow:hidden;margin-bottom:.3rem;}
.home-card-bar i{display:block;height:100%;background:var(--green);border-radius:4px;}
.home-card-meta{font-size:.72rem;color:var(--text-3);}
.home-card-go{
  flex-shrink:0;background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  width:2rem;height:2rem;border-radius:999px;font-size:.9rem;cursor:pointer;
}
.home-card:hover .home-card-go{background:var(--blue);border-color:var(--blue);color:#fff;}
/* Notebook lồng nhau (thư mục mẹ/con) — thẻ mẹ + dải thẻ con nhỏ hơn nằm
   NGAY BÊN TRONG cùng 1 khối, không rải phẳng ngang hàng với thẻ mẹ khác
   nữa (xem notebookGroupHtml trong home.js). Khối nào có con thì item
   grid đó cao hơn — CSS Grid các hàng auto-fill có thể để hở khoảng
   trắng ở ô lân cận thấp hơn cùng hàng, chấp nhận được (đánh đổi lấy gọn
   gàng, ít Notebook có nhiều con trong thực tế). */
.home-group{display:flex;flex-direction:column;gap:.5rem;}
.home-subcards{
  display:flex;flex-wrap:wrap;gap:.5rem;margin-left:1.1rem;padding-left:.7rem;
  border-left:2px solid var(--border);
}
.home-subcards .home-card{flex:1 1 200px;}
.home-card.sub{padding:.6rem .7rem;background:var(--bg-soft);}
.home-card.sub .home-card-ic{font-size:1.25rem;}
.home-card.sub .home-card-name{font-size:.8rem;}
.home-card-subcount{font-weight:600;color:var(--text-3);font-size:.76rem;}
@media(max-width:640px){ .home-cards{grid-template-columns:1fr;} }

/* ─── Journey: 2 khung song song (trạng thái | cây thư mục) ─── */
.journey-body{display:grid;grid-template-columns:1fr 1fr;gap:.9rem;align-items:start;}
@media(max-width:980px){ .journey-body{grid-template-columns:1fr;} }

/* ─── Journey: 4 tab Tony Buzan + 2 danh sách Block trong mỗi tab ─── */
.jtabs{display:flex;gap:.35rem;flex-wrap:wrap;margin-bottom:.7rem;}
.jtab-btn{
  background:var(--bg-soft);border:1px solid var(--border);color:var(--text-2);
  border-radius:999px;padding:.35rem .75rem;font-size:.76rem;font-weight:700;cursor:pointer;
}
.jtab-btn:hover{border-color:var(--border-hi);color:var(--text);}
.jtab-btn.active{background:var(--blue);border-color:var(--blue);color:#fff;}
.jtab-sub{font-size:.72rem;color:var(--text-3);margin:0 0 .8rem;}
.jtab-group-title{font-size:.76rem;font-weight:700;color:var(--text-2);margin:.9rem 0 .4rem;display:flex;align-items:center;gap:.35rem;}
.jtab-group-title:first-child{margin-top:0;}
.jtab-empty{font-size:.74rem;color:var(--text-3);padding:.3rem 0 .6rem;}

/* ═══════════ FOCUS BÀN PHÍM + TRANSITION MƯỢT (toàn app) ═══════════
   1) Nhiều nút/thẻ chỉ có hiệu ứng hover đổi màu tức thì (không transition)
      — nhìn "giật", khác hẳn cảm giác SaaS thương mại. Bổ sung transition
      mượt cho các thẻ CHƯA có transition riêng (những chỗ đã tự khai báo
      transition tinh chỉnh riêng — .block-card/.time-card/.batch-tab/.kw —
      giữ nguyên, không đụng vào để khỏi lặp/ghi đè lý do đã ghi chú tại đó).
   2) .block-card/.jrow/.home-card/.g-row giờ bấm được bằng bàn phím
      (tabindex+role="button", xem app.js/journey.js/detail.js) nên cần
      con trỏ + transition khớp các thẻ nút khác. */
button,a,input,select,textarea,.jrow,.home-card,.g-row,[role="button"]{
  transition:background-color .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease;
}
.block-card,.jrow,.home-card,.g-row{cursor:pointer;}

/* Vòng focus khi điều hướng bằng bàn phím (Tab) — :focus-visible chỉ hiện
   khi dùng bàn phím, không hiện khi bấm chuột/chạm, nên không đổi cảm
   giác dùng chuột bình thường. Trước đây nhiều input/textarea tự đặt
   outline:none mà không thay bằng gì khác -> bấm Tab không biết đang
   đứng ở đâu, người dùng bàn phím/trình đọc màn hình rất khó dùng app.
   Đặt khối này Ở CUỐI file để thắng các rule outline:none cùng độ đặc
   hiệu (class-level) đã khai báo trước đó (.text-input, textarea…). */
:focus-visible{outline:2px solid var(--blue);outline-offset:2px;border-radius:4px;}
.block-card:focus-visible,.jrow:focus-visible,.home-card:focus-visible,
.nav-item:focus-visible,.g-row:focus-visible,.opt:focus-visible,.slot:focus-visible,
.wb-chip:focus-visible,.section-tab:focus-visible,.batch-tab:focus-visible,
.hub-tab:focus-visible,.dtab:focus-visible,.vchip:focus-visible{outline-offset:-2px;}

/* ═══════════ THANH LOADING MẢNH LÚC boot() ĐANG TẢI ═══════════
   Trước đây mở app ở chế độ Cloud/mạng chậm không có gì báo đang tải —
   topbar hiện sẵn "…"/"Khách" tĩnh, dễ tưởng app đứng hình. Vệt màu chạy
   ngang kiểu YouTube/GitHub, KHÔNG che nội dung bên dưới (chỉ cao 3px,
   đứng trên cùng) nên an toàn dù boot() có lỗi nửa chừng — id="boot-bar"
   được ẩn trong finally của boot() (app.js) nên không bao giờ kẹt mãi. */
.boot-bar{
  position:fixed;top:0;left:0;width:100%;height:3px;z-index:3000;
  overflow:hidden;pointer-events:none;background:transparent;
}
.boot-bar::after{
  content:"";position:absolute;top:0;left:-35%;width:35%;height:100%;
  background:var(--blue);border-radius:0 4px 4px 0;
  animation:boot-bar-sweep 1.1s ease-in-out infinite;
}
.boot-bar[hidden]{display:none;}
@keyframes boot-bar-sweep{
  0%{left:-35%;}
  60%{left:100%;}
  100%{left:100%;}
}
