/* Shell 2 phần: nội dung chính canh TRÁI, chừa dải bên phải làm chỗ gắn các
   "side app" (hiện có Calculator guide, sẽ thêm app khác sau). Để trong luồng
   bố cục chứ không phải overlay, nên side app không bao giờ che mất đề bài —
   học sinh cần vừa đọc hướng dẫn vừa nhìn câu hỏi. */
body{display:flex; align-items:flex-start;}
/* margin auto 2 bên + margin-left:auto của panel: chỗ trống còn lại tự chia
   đều cho 3 khe (trái app, giữa app–panel, và phần đẩy panel ra mép phải), nên
   bố cục cân ở cả khi mở lẫn đóng side app mà không cần số cứng nào. */
.app{
  flex:1 1 auto; min-width:0;
  max-width:1320px; margin:0 auto; padding:20px 20px 40px;
  display:flex; flex-direction:column; gap:14px;
  min-height:100vh;
}
/* Màn hình hết hạn không có side app nên vẫn canh giữa như cũ. */
#expiredScreen{flex:1 1 auto; min-width:0;}
/* display:flex ở trên đè mất [hidden]{display:none} của trình duyệt. Không có
   dòng này thì `<div class="app" hidden>` hiện ngay khi tải trang (nháy giao
   diện trước khi xác thực xong), và showExpired() không giấu được app — user
   hết hạn gói vẫn thấy nguyên question bank kèm thông báo hết hạn. */
.app[hidden]{display:none;}

/* ---------- Top bar ---------- */
.topbar{display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;}
.topbar-left{display:flex; align-items:center; gap:22px; flex-wrap:wrap;}
.topbar .meta{font-size:.78rem; color:var(--ink-faint); font-variant-numeric:tabular-nums; display:flex; align-items:center; gap:12px;}
.topbar .who{color:var(--ink-soft);}

/* ---------- Stat cluster (question/subject counts, count-up on load) ---------- */
.stats-banner{display:flex; align-items:baseline; gap:20px; padding-left:20px; border-left:1px solid var(--line);}
.stat{display:flex; align-items:baseline; gap:6px;}
.stat-num{
  font-family:var(--font-display); font-weight:700; font-size:1.5rem; color:var(--accent-ink);
  font-variant-numeric:tabular-nums; line-height:1;
}
.stat-label{font-size:.72rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-faint);}
@media (max-width:680px){
  .stats-banner{padding-left:0; border-left:none; gap:14px;}
}

/* ---------- Account menu ---------- */
.account-menu{position:relative;}
button.who{
  background:none; border:none; padding:0; font:inherit; color:var(--ink-soft); cursor:pointer;
  text-decoration:underline dotted; text-underline-offset:3px;
}
button.who:hover{color:var(--ink);}
.account-panel{
  position:absolute; top:calc(100% + 6px); right:0; z-index:20;
  width:230px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:14px; display:none; text-align:left;
}
.account-panel.open{display:block;}
.account-panel .text-input{margin-bottom:8px; font-size:.85rem; padding:7px 10px;}
.account-panel .btn{width:100%; margin-bottom:4px; padding:7px 12px; font-size:.8rem;}
.account-panel hr{border:none; border-top:1px solid var(--line); margin:10px 0;}
.account-msg{font-size:.72rem; color:var(--accent-ink); min-height:14px; margin-top:2px;}
.account-msg.error{color:var(--danger);}
.topbar .logout-link{background:none; border:none; color:var(--ink-faint); cursor:pointer; font-size:.78rem; text-decoration:underline;}
.topbar .logout-link:hover{color:var(--ink);}
/* Khách vãng lai (chưa đăng nhập): ẩn các nút cần tài khoản — bookmark ở danh
   sách/viewer và bộ lọc "Bookmarked only" — vì chúng chỉ dẫn sang trang đăng
   nhập. Đăng nhập xong sẽ hiện lại bình thường. */
body.is-guest .bk-btn,
body.is-guest #bkFilterBtn,
body.is-guest #vBookmark{display:none;}

/* ---------- Filter bar ---------- */
.filterbar{
  position:relative;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:9px 12px;
  display:flex; flex-direction:column; gap:7px;
}
.filter-row{display:flex; gap:6px; flex-wrap:wrap; align-items:center;}
.filter-group{display:flex; flex-direction:column; gap:1px; min-width:0;}
/* An explicit display: beats the UA's [hidden]{display:none}, so single-level
   subjects (Further Mathematics HL, Mathematics SL, Mathematical Studies) would
   still show the Level filter without this. */
.filter-group[hidden]{display:none;}
.filter-group label{
  font-size:.62rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-faint);
  padding-left:2px;
}
select.field{
  appearance:none; -webkit-appearance:none;
  background:var(--surface-2) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="6"><path d="M0 0l5 6 5-6z" fill="%238592A3"/></svg>') no-repeat right 8px center;
  border:1px solid var(--line); border-radius:var(--radius); padding:4px 22px 4px 8px;
  font-size:.8rem; min-width:100px; cursor:pointer; color:var(--ink);
}
select.field:disabled{opacity:.45; cursor:not-allowed;}
select.field:hover:not(:disabled){border-color:var(--line-strong);}

.subject-btn{
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius);
  padding:4px 10px; font-size:.8rem; cursor:pointer; display:flex; align-items:center; gap:6px;
  min-width:170px; max-width:220px; text-align:left; color:var(--ink); justify-content:space-between;
}
.subject-btn:hover{border-color:var(--line-strong);}
.subject-btn span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.subject-btn::after{
  content:""; flex-shrink:0; width:10px; height:6px;
  background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="6"><path d="M0 0l5 6 5-6z" fill="%238592A3"/></svg>') no-repeat center;
}

.topic-btn{
  background:var(--surface-2); border:1px solid var(--line); border-radius:var(--radius);
  padding:4px 10px; font-size:.8rem; cursor:pointer; display:flex; align-items:center; gap:6px;
  min-width:130px; justify-content:space-between;
}
.topic-btn:hover{border-color:var(--line-strong);}
.topic-btn .count{
  background:var(--accent); color:#fff; border-radius:999px; font-size:.68rem; font-weight:700;
  padding:1px 6px; font-variant-numeric:tabular-nums;
}
.topic-btn .count.zero{display:none;}

.more-filters-btn{
  display:none; align-items:center; gap:4px; align-self:flex-end;
  background:var(--surface-2); color:var(--ink-soft); border:1px solid var(--line);
  border-radius:var(--radius); padding:4px 10px; font-size:.8rem; cursor:pointer;
}
.more-filters-btn:hover{color:var(--ink); border-color:var(--line-strong);}
.more-filters-btn .chev{font-size:.65rem; transition:transform .15s ease;}
.more-filters-btn[aria-expanded="true"] .chev{transform:rotate(180deg);}
.filter-more{display:flex; gap:6px; flex-wrap:wrap;}

.clear-btn{
  position:absolute; right:12px; bottom:9px;
  background:var(--surface-2); color:var(--ink-soft); border:1px solid var(--line);
  border-radius:var(--radius); padding:5px 14px; font-size:.8rem; font-weight:600; cursor:pointer;
}
.clear-btn:hover{color:var(--ink); border-color:var(--line-strong);}

.chips{display:flex; gap:6px; flex-wrap:wrap; min-height:0; padding-right:96px;}
.chip{
  display:flex; align-items:center; gap:5px; background:var(--accent-soft); color:var(--accent-ink);
  border-radius:999px; padding:3px 10px 3px 11px; font-size:.74rem; font-weight:600;
}
.chip button{
  background:none; border:none; color:inherit; cursor:pointer; font-size:.85rem; line-height:1;
  opacity:.65; padding:0;
}
.chip button:hover{opacity:1;}
.chips.empty::before{content:"No filters applied — showing all questions"; color:var(--ink-faint); font-size:.78rem; padding:3px 0;}

/* ---------- Topic popover ---------- */
.popover-wrap{position:relative;}
.topic-panel{
  position:absolute; top:calc(100% + 6px); left:0; z-index:20;
  width:340px; max-height:400px; overflow-y:auto;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:10px; display:none;
}
.topic-panel.open{display:block;}

/* ---------- Subject popover (grouped tree) ---------- */
.subject-panel{
  position:absolute; top:calc(100% + 6px); left:0; z-index:20;
  width:260px; max-height:400px; overflow-y:auto;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:10px; display:none;
}
.subject-panel.open{display:block;}
.subject-group{padding:8px 2px 10px;}
.subject-group:first-child{padding-top:2px;}
.subject-group:last-child{padding-bottom:2px;}
.subject-group + .subject-group{border-top:1px solid var(--line); margin-top:2px;}
.subject-group h4{
  margin:0 0 4px; font-size:.68rem; font-weight:700; text-transform:uppercase; letter-spacing:.06em;
  color:var(--accent-ink);
}
.subject-item{
  display:block; width:100%; text-align:left; background:none; border:none; border-radius:6px;
  padding:6px 8px; font-size:.83rem; color:var(--ink); cursor:pointer; line-height:1.3;
}
.subject-item:hover{background:var(--surface-2);}
.subject-item.active{background:var(--accent-soft); color:var(--accent-ink); font-weight:600;}
.subject-item.sub{padding-left:18px; font-size:.8rem;}
.subject-bucket-label{
  padding:6px 8px 0; font-size:.68rem; font-weight:600; color:var(--ink-soft);
}
@media (max-width:480px){
  .account-panel{position:fixed; left:12px; right:12px; top:60px; width:auto; max-width:none;}
  .topic-panel{position:fixed; left:12px; right:12px; top:110px; width:auto; max-width:none; max-height:60vh;}
  .subject-panel{position:fixed; left:12px; right:12px; top:110px; width:auto; max-width:none; max-height:60vh;}
}

/* Below this width, Subject/Level/Topic + Clear stay put but Paper/Year/
   Season/Zone collapse behind a "More filters" toggle instead of wrapping
   into extra rows — keeps the bar to ~2 rows instead of 3-4 on phones. */
@media (max-width:680px){
  .more-filters-btn{display:inline-flex;}
  .filter-more{display:none;}
  .filter-row.expanded .filter-more{display:flex;}
}
.topic-panel .empty-note{color:var(--ink-faint); font-size:.82rem; padding:14px 6px;}
.topic-group{margin-bottom:10px;}
.topic-group:last-child{margin-bottom:2px;}
.topic-group h4{
  margin:0; font-size:.72rem; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-faint);
  display:flex; align-items:center; gap:6px;
}
.topic-group-head{
  display:flex; align-items:center; gap:7px; padding:5px 6px; margin:2px 0 4px; border-radius:6px; cursor:pointer;
}
.topic-group-head:hover{background:var(--surface-2);}
.topic-group-head input{accent-color:var(--accent); cursor:pointer; flex-shrink:0;}
.topic-item{
  display:flex; align-items:flex-start; gap:8px; padding:5px 6px; border-radius:6px; cursor:pointer;
  font-size:.83rem;
}
.topic-item:hover{background:var(--surface-2);}
.topic-item input{margin-top:3px; accent-color:var(--accent); cursor:pointer;}
/* Syllabus trees are 2-4 levels deep depending on subject (Math 2, Physics 3,
   Biology 4 inside each Option), so indent from the depth the renderer sets
   rather than one class per level. Depth 1 sits flush; each level adds a step
   plus a hairline rule so a sub-topic reads as belonging to the row above it. */
.topic-item[data-depth]{padding-left:calc(6px + (var(--topic-depth,1) - 1) * 14px);}
.topic-item[data-depth]:not([data-depth="1"]){
  border-left:1px solid var(--border); border-top-left-radius:0; border-bottom-left-radius:0;
  margin-left:calc((var(--topic-depth,1) - 1) * 4px);
}

/* ---------- Workspace ---------- */
.workspace{display:grid; grid-template-columns:212px 1fr; gap:10px; align-items:start;}
@media (max-width:840px){
  .workspace{grid-template-columns:1fr;}
  .qlist{height:auto; max-height:42vh; min-height:240px;}
  .viewer{min-height:50vh;}
}
.share-workspace{grid-template-columns:1fr; max-width:820px; margin:0 auto;}

.panel{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); overflow:hidden;
}

.qlist{display:flex; flex-direction:column; height:calc(100vh - 170px); min-height:360px;}
.qlist-head{
  padding:6px 10px; border-bottom:1px solid var(--line); display:flex; justify-content:space-between;
  align-items:center; font-size:.73rem; color:var(--ink-soft);
}
.qlist-head strong{color:var(--ink); font-variant-numeric:tabular-nums;}
.qlist-sort{background:none; border:none; color:var(--ink-faint); cursor:pointer; font-size:.7rem;}
.qlist-body{overflow-y:auto; flex:1;}
.qlist-body.is-loading, .viewer-body.is-loading{opacity:.5; pointer-events:none; transition:opacity .12s .1s;}
.qitem{position:relative; border-bottom:1px solid var(--line); line-height:1.3;}
.qitem:hover{background:var(--surface-2);}
.qitem.active{background:var(--accent-soft); box-shadow:inset 3px 0 0 var(--accent);}
.qitem-main{
  display:block; width:100%; text-align:left; background:none; border:none;
  padding:5px 28px 5px 10px; cursor:pointer; line-height:1.3; font:inherit; color:inherit;
}
.qitem .code{
  font-family:var(--font-mono); font-size:.65rem; color:var(--ink); font-variant-numeric:tabular-nums;
  display:block; margin-bottom:1px; word-break:break-word; padding-right:2px;
}
.qitem .qtags{display:flex; gap:3px; flex-wrap:wrap;}
.qitem .qtags .badge{font-size:.52rem; padding:0 4px;}
.qlist-empty{padding:26px 14px; text-align:center; color:var(--ink-faint); font-size:.8rem;}
.qlist-pager{display:flex; align-items:center; justify-content:space-between; padding:5px 10px; border-top:1px solid var(--line); font-size:.72rem; color:var(--ink-faint);}
.qlist-pager button{background:var(--surface-2); border:1px solid var(--line); border-radius:6px; padding:2px 7px; cursor:pointer; color:var(--ink-soft); font-size:.72rem;}
.qlist-pager button:disabled{opacity:.4; cursor:not-allowed;}

.bk-btn{
  position:absolute; top:4px; right:4px; width:19px; height:19px; border:none; background:none;
  cursor:pointer; display:flex; align-items:center; justify-content:center; color:var(--ink-faint);
  border-radius:6px;
}
.bk-btn:hover{background:var(--surface-2); color:var(--ink-soft);}
.bk-btn svg{width:12px; height:12px;}
.bk-btn.on{color:var(--gold);}
.bk-btn.on svg{fill:var(--gold);}

.qlist-filter{
  display:flex; align-items:center; gap:5px; background:none; border:1px solid var(--line); border-radius:6px;
  padding:3px 8px; font-size:.72rem; cursor:pointer; color:var(--ink-soft);
}
.qlist-filter:hover{border-color:var(--line-strong);}
.qlist-filter.on{background:var(--hl-soft); border-color:transparent; color:var(--hl); font-weight:600;}
.qlist-filter svg{width:12px; height:12px;}
.qlist-filter.on svg{fill:var(--hl);}

.viewer{display:flex; flex-direction:column; min-height:calc(100vh - 180px);}
.viewer-head{
  padding:12px 18px; border-bottom:1px solid var(--line); display:flex; align-items:center;
  justify-content:space-between; gap:12px; flex-wrap:wrap;
}
.viewer-title{display:flex; flex-direction:column; gap:2px; min-width:0;}
.viewer-title .code{font-family:var(--font-mono); font-size:.86rem; font-weight:600;}
.viewer-title .path{font-size:.74rem; color:var(--ink-faint);}
.viewer-controls{display:flex; align-items:center; gap:10px;}

.segmented{display:flex; background:var(--surface-2); border:1px solid var(--line); border-radius:999px; padding:2px;}
.segmented button{
  border:none; background:none; padding:6px 16px; font-size:.8rem; font-weight:600; border-radius:999px;
  cursor:pointer; color:var(--ink-soft);
}
.segmented button.active{background:var(--accent); color:#fff;}

.nav-btn{
  width:30px; height:30px; border-radius:8px; border:1px solid var(--line); background:var(--surface-2);
  cursor:pointer; display:flex; align-items:center; justify-content:center; color:var(--ink-soft);
}
.nav-btn:hover{border-color:var(--line-strong); color:var(--ink);}
.nav-btn:disabled{opacity:.35; cursor:not-allowed;}
.nav-btn.on{color:var(--gold); border-color:#B8860B55; background:var(--gold-soft);}

.nav-btn-wrap{position:relative; display:inline-flex;}
.share-toast{
  position:absolute; top:calc(100% + 6px); left:50%; transform:translateX(-50%) translateY(-4px);
  background:var(--ink); color:var(--bg); font-size:.7rem; font-weight:600; padding:4px 9px;
  border-radius:6px; white-space:nowrap; opacity:0; pointer-events:none; transition:opacity .15s, transform .15s;
  z-index:5;
}
.share-toast::before{
  content:""; position:absolute; bottom:100%; left:50%; transform:translateX(-50%);
  border:4px solid transparent; border-bottom-color:var(--ink);
}
.share-toast.show{opacity:1; transform:translateX(-50%) translateY(0);}

.viewer-body{padding:30px 36px 46px; flex:1; overflow-y:auto; background:var(--bg);}

/* ---- Exam-paper typesetting ---- */
math{font-family:var(--font-math); font-style:normal;}

/* KaTeX: inline formulas match body text; standalone/nested-fraction
   formulas get a roomy centered block like a real textbook equation. */
.katex-display-wrap{
  display:block; margin:16px 0; text-align:center;
  padding:4px 2px; max-width:100%;
}
.katex-display-wrap .katex-display{margin:0;}

/* ---- Wide formulas shrink to fit; they never scroll and never get clipped ----
   .sheet-body is overflow:hidden, so a formula wider than the 638px column used
   to be silently cut off mid-expression. The old workaround was a horizontal
   scroller (either this rule or a `<div style="overflow-x:auto">` baked into
   Source C bodyHtml), but a scrollbar inside a question is not acceptable — the
   student has to be able to read the formula where it stands.

   Same resolution as the wide-table fix above: make it fit instead of scroll.
   The actual scaling is done in viewer-shared.js fitFormulas(), because only
   layout knows the rendered width; these rules just stop anything from
   scrolling or spilling in the meantime. */
:is(.sheet-body, .exam-q-body) :is(mjx-container,.katex){max-width:100%;}
/* Neutralises the legacy per-formula scrollers still present in stored bodyHtml
   (48 parts). Inline styles outrank a stylesheet, hence !important. Tables do
   their own thing via .sheet-body table and are unaffected — these divs only
   ever wrapped formulas. */
:is(.sheet-body, .exam-q-body) div[style*="overflow-x"]{overflow:visible !important;}
.sheet{
  max-width:720px; margin:0 auto; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius); box-shadow:var(--shadow); position:relative;
}
.sheet-kicker{
  display:flex; align-items:center; justify-content:space-between; gap:12px;
  padding:10px 30px; background:var(--surface-2); border-bottom:1px solid var(--line);
  font-family:var(--font-ui); font-size:.68rem; text-transform:uppercase; letter-spacing:.08em;
  color:var(--ink-faint);
  border-radius:var(--radius) var(--radius) 0 0;
}
.sheet-kicker .ref{font-family:var(--font-mono); font-variant-numeric:tabular-nums; letter-spacing:0; color:var(--ink-soft);}
.sheet-body{
  padding:34px 40px 38px; font-family:var(--font-serif); color:var(--ink); font-size:1.02rem; line-height:1.68;
  border-radius:0 0 var(--radius) var(--radius); overflow:hidden;
}
.sheet-body img{max-width:100%; height:auto; display:block; margin:16px auto;}
.sheet-body p{margin:0 0 12px;}
.sheet-body p:last-child{margin-bottom:0;}

/* Áp cho CẢ trang xem câu hỏi (.sheet-body) lẫn trang in đề (.exam-q-body).
   Trang in dựng DOM riêng nên không có .sheet-body, và trước khi nối vào đây
   thì bảng trong đề in giữ nguyên `style="width:504px"` của editor IB — 133
   part có con số cứng như vậy — nên bảng đứng lệch, không canh theo khung câu
   hỏi. Nối selector thay vì chép luật sang exam-print.css: chép là hai bản sẽ
   trôi khỏi nhau, mà phần lý giải bên dưới đo được thì chỉ có một chỗ.

   Question-body tables (data tables, MCQ answer grids, etc.) come from
   scraped/transcribed HTML with no styling of their own — left bare, browser
   default table layout packs cells edge-to-edge with ~1px padding, which
   reads as illegibly cramped (reported across every subject, not just one
   scrape source, since they all funnel through the same .sheet-body render
   path in app.js/share.js).

   These used to be `display:block; overflow-x:auto; width:fit-content`, which
   turned any too-wide table into a horizontally scrolling strip — a student
   reading e.g. the 11-country expatriate table of 24N.2.AHL.TZ0.1 saw seven
   columns and had to drag the rest into view, and the exported/printed sheet
   lost them entirely. Two things were wrong with that:

     1. It hid data by default. Measured against the real 640px content column,
        8 of the bank's 321 distinct tables overflowed, the worst by 212px.
     2. `display:block` re-boxes the cells as *anonymous* table cells, so an
        oversized inline-block inside a cell (a rendered MathJax container)
        overflows its cell instead of widening the table — which is why some
        tables scrolled even though their own box was far narrower than the
        column.

   So: real table layout, shrink-to-fit, and instead of scrolling, wide tables
   get denser. The density steps below were measured, not guessed — at 11
   columns the expatriate table needs 878px at the base size but 597px at
   .76rem/3px, comfortably inside 640px, with words still wrapping whole
   rather than breaking mid-word. After this change 0 of 321 tables overflow. */
:is(.sheet-body, .exam-q-body) table{
  /* Full-bleed: every table spans the whole content column, so its right edge
     lines up with the body text and the sheet frame instead of shrink-wrapping
     to its content and leaving a ragged gap (a two-column table used to end
     a third of the way across). max-width keeps a wide one wrapping down
     rather than running off the sheet. */
  display:table; width:100%; max-width:100%;
  border-collapse:collapse; margin:16px 0; font-size:.95rem;
}
/* The scraped source HTML hard-codes its own sizing on many tables —
   style="width:359px", width="749", even margin-left:150px — and an inline
   style outranks a stylesheet, so the width rule above silently lost on 35 of
   the bank's 127 rendered tables: they sat stranded at a third of the column,
   some indented off-centre. Force the column width back (same reason the
   overflow-x neutraliser above needs !important) and drop the stray side
   margins so every table starts at the text's left edge. Height/border hints
   in that inline style are left alone — only the horizontal box is wrong. */
:is(.sheet-body, .exam-q-body) table{width:100% !important; margin-left:0 !important; margin-right:0 !important;}

:is(.sheet-body, .exam-q-body) :is(th,td){
  border:1px solid var(--line); padding:6px 12px; vertical-align:middle;
  /* Let a cell wrap inside itself before it forces the whole table wider.
     break-word (not anywhere) so ordinary words still wrap at spaces and only
     a token genuinely wider than its cell is broken. */
  overflow-wrap:break-word; hyphens:auto;
}
/* A rendered formula is an unbreakable inline-block; without this it can push
   its cell past the table's share of the column. */
:is(.sheet-body, .exam-q-body) :is(th,td) :is(mjx-container,.katex){max-width:100%;}
/* Column-count-responsive density. `:has(tr > *:nth-child(N))` is "this table
   has a row with at least N cells" — the only way to branch on column count in
   CSS. Tables of 6 columns or fewer (277 of 321) keep the comfortable size. */
:is(.sheet-body, .exam-q-body) table:has(tr > *:nth-child(7))  :is(th,td){padding:5px 8px; font-size:.88rem;}
:is(.sheet-body, .exam-q-body) table:has(tr > *:nth-child(9))  :is(th,td){padding:4px 5px; font-size:.82rem;}
:is(.sheet-body, .exam-q-body) table:has(tr > *:nth-child(11)) :is(th,td){padding:3px 4px; font-size:.76rem;}
/* Fallback for engines without :has() — there the density steps never fire, so
   keep the old scrolling behaviour rather than letting a wide table spill out
   of the sheet. */
@supports not (selector(:has(*))){
  :is(.sheet-body, .exam-q-body) table{display:block; overflow-x:auto; width:100%;}
}
/* Every cell centred, including the first column. An earlier version left-
   aligned the first column on the theory that these are always label+numbers
   tables — but checking the actual rendered tables across the bank showed
   that assumption wrong often enough (short nuclide/element/word labels read
   as misaligned sitting alone at the left of a wide cell) that a uniform
   centre reads right everywhere instead. */
:is(.sheet-body, .exam-q-body) :is(th,td){text-align:center;}
:is(.sheet-body, .exam-q-body) th{background:var(--surface-2); font-weight:600;}
/* Legacy border="1" attributes ride along in the scraped HTML; our own border
   rule already draws the grid, so stop the browser doubling it up. */
:is(.sheet-body, .exam-q-body) table[border]{border:0;}

.qpart{
  display:grid; grid-template-columns:30px 1fr; gap:2px 12px; margin:0 0 20px;
  padding-bottom:18px; border-bottom:1px dashed var(--line);
}
.qpart:last-child{border-bottom:none; margin-bottom:0; padding-bottom:0;}
.qpart.context-only{border-bottom:none; padding-bottom:0; margin-bottom:14px; display:block;}
.qpart-label{
  font-weight:400; color:var(--ink-soft); padding-top:1px; font-variant-numeric:tabular-nums;
}
.qpart-main{min-width:0;}
.qpart-row{display:flex; align-items:baseline; justify-content:space-between; gap:16px;}
/* min-width:0 is load-bearing: a flex item defaults to min-width:auto, which
   refuses to shrink below its content's intrinsic width. Without it an
   unbreakable rendered formula stretched this column to its own width (measured
   784px inside a 598px row), pushing the part past the sheet — which .sheet-body
   then clipped. .qpart-main already carries it for the same reason as a grid
   item. */
.qpart-text{margin:0; flex:1; min-width:0;}
.qpart-text p{margin:0 0 10px;}
.qpart-text p:last-child{margin-bottom:0;}
.qpart-marks{
  flex-shrink:0; font-family:var(--font-ui); font-weight:700; font-size:.74rem; color:var(--ink-soft);
  font-variant-numeric:tabular-nums; white-space:nowrap; padding-top:3px;
}

/* "(i)"/"(ii)" sub-item markers are plain inline text at the start of a
   paragraph, not a grid column of their own like the outer "(a.)" label —
   so a wrapped second line fell back to the paragraph's own left edge
   instead of lining up under the first line's own text. Classic hanging
   indent: push the whole block right by `padding-left`, then pull just the
   FIRST line back by the same amount with a matching negative `text-indent`.
   1.5em is MEASURED (2026-09-03, via Range.getBoundingClientRect on a live
   "(i)" marker), not guessed — a first attempt at 2.4em cleared even
   "(viii)" comfortably but left the wrapped line sitting ~1em right of
   where "(i)"'s own sentence text actually starts, which read as "indented
   too far" (user, on seeing it live). 1.5em matches "(i)"/"(ii)"/"(iii)" —
   the near-total majority of real sub-items — exactly; a rare wide marker
   like "(viii)" just leaves a touch less gap before its own first-line
   text, not a wrapped-line misalignment. */
.qpart-text p:has(> .qpart-sub-marker:first-child){
  padding-left:1.5em; text-indent:-1.5em;
}
.qpart-sub-marker{margin-right:.4em;}
@supports not (selector(:has(*))){
  /* Không hỗ trợ :has() — giữ hành vi cũ (dòng bọc về sát lề), không tràn. */
  .qpart-text p{padding-left:0; text-indent:0;}
}

.sheet.answer .sheet-body{background:var(--sl-soft);}
.sheet.answer .sheet-kicker{background:#DCF0E7; border-bottom-color:#C6E5D9;}
.sheet.answer .qpart{border-bottom-color:#C6E5D9;}

/* ---------- Report-issue widget ---------- */
.report-widget{position:absolute; bottom:10px; right:10px; z-index:15;}
.report-fab{
  width:26px; height:26px; border-radius:50%; background:var(--surface-2); border:1px solid var(--line);
  color:var(--ink-faint); display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:.6;
}
.report-fab:hover{opacity:1; color:var(--ink-soft); border-color:var(--line-strong);}
.report-popover{
  /* position:fixed (not absolute) — its right/bottom are set from JS in
     viewport coordinates, anchored to the fab, so it always floats above
     every ancestor (including the scrollable viewer-body) instead of being
     clipped by an ancestor's overflow. */
  position:fixed; width:260px; z-index:50;
  background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg);
  box-shadow:var(--shadow); padding:14px; font-family:var(--font-ui); text-align:left;
}
.report-title{font-size:.78rem; font-weight:700; color:var(--ink); margin-bottom:8px;}
.report-option{
  display:flex; align-items:center; gap:7px; padding:4px 2px; font-size:.8rem; color:var(--ink-soft); cursor:pointer;
}
.report-option input{accent-color:var(--accent); cursor:pointer;}
.report-note{
  width:100%; margin-top:6px; resize:vertical; min-height:44px; font:inherit; font-size:.78rem;
  border:1px solid var(--line); border-radius:6px; padding:6px 8px; color:var(--ink);
}
.report-submit{
  width:100%; margin-top:8px; background:var(--accent); color:#fff; border:none; border-radius:6px;
  padding:7px; font-size:.8rem; font-weight:600; cursor:pointer;
}
.report-submit:hover{background:var(--accent-ink);}
.report-submit:disabled{opacity:.6; cursor:not-allowed;}
.report-step-thanks{font-size:.8rem; color:var(--ink-soft); line-height:1.5;}
.report-emoji{display:inline-block; font-size:1.3rem; line-height:1; margin-right:4px; vertical-align:-3px;}
.report-emoji-pop{animation:report-emoji-pop .6s cubic-bezier(.34,1.56,.64,1);}
@keyframes report-emoji-pop{
  0%{transform:scale(0) rotate(-15deg);}
  55%{transform:scale(1.35) rotate(8deg);}
  75%{transform:scale(.92) rotate(-4deg);}
  100%{transform:scale(1) rotate(0deg);}
}

/* Rare easter egg (every 3rd report ever submitted): the thank-you text
   blows apart into flying, fading words while the emoji blooms and
   dissolves, instead of the normal calm pop-in. */
.report-thanks-exploding{position:relative;}
.report-thanks-exploding .report-thanks-text{display:inline;}
.report-word{
  display:inline-block; animation:report-word-fly 2.6s forwards;
}
@keyframes report-word-fly{
  /* burst outward/upward, quick ease-out */
  0%{transform:translate(0,0) rotate(0deg); opacity:1; animation-timing-function:cubic-bezier(.17,.67,.3,1);}
  28%{transform:translate(var(--tx-mid), var(--ty-peak)) rotate(var(--tr-mid)); opacity:1; animation-timing-function:cubic-bezier(.55,.05,.7,.2);}
  /* then fall back down past the start, accelerating like gravity */
  80%{opacity:1;}
  100%{transform:translate(var(--tx), var(--ty-fall)) rotate(var(--tr)); opacity:0;}
}
.report-emoji-explode{
  animation:report-emoji-bloom 2.4s ease-out forwards !important;
}
@keyframes report-emoji-bloom{
  0%{transform:scale(1); opacity:1;}
  40%{transform:scale(1.9) rotate(6deg); opacity:1;}
  100%{transform:scale(3.4) rotate(18deg); opacity:0;}
}

.empty-viewer{
  display:flex; flex-direction:column; align-items:center; justify-content:center; height:100%;
  color:var(--ink-faint); gap:8px; padding:60px 20px; text-align:center;
}
.empty-viewer svg{opacity:.5;}

.viewer-foot{
  padding:10px 18px; border-top:1px solid var(--line); display:flex; justify-content:space-between;
  align-items:center; font-size:.74rem; color:var(--ink-faint);
}

/* ---------- Calculator guide (tra cứu cách dùng TI-Nspire) ---------- */
/* Đây là panel ĐỌC, không phải máy tính mô phỏng — nên dựng thành drawer cao
   hết màn hình bên phải (đọc được đoạn văn dài) thay vì cửa sổ nhỏ nổi như
   bản calculator cũ đã gỡ. */
/* BẮT BUỘC: display:flex ở dưới đè mất [hidden]{display:none} của trình duyệt.
   Thiếu dòng này thì lệnh ẩn nút Guide ở môn không phải Toán không có tác dụng
   — đúng cái bẫy đã vấp ở .upgrade-backdrop và .tier-badge. */
.calcguide-launcher[hidden]{display:none;}
.calcguide-launcher{
  position:fixed; right:22px; bottom:22px; z-index:55;
  display:flex; align-items:center; gap:7px;
  padding:8px 13px 8px 11px; border:1px solid var(--line-strong); border-radius:999px;
  background:var(--surface); color:var(--ink-soft); box-shadow:var(--shadow);
  font-size:.8rem; cursor:pointer;
}
.calcguide-launcher:hover{color:var(--ink); border-color:var(--ink-faint);}
.calcguide-launcher span{font-weight:500;}
/* Chấm nhấn khi câu hỏi đang mở có hướng dẫn khớp topic */
.calcguide-launcher.has-match{border-color:var(--accent); color:var(--accent-ink); background:var(--accent-soft);}
.calcguide-launcher.has-match::after{
  content:""; position:absolute; top:-2px; right:-2px; width:9px; height:9px;
  border-radius:50%; background:var(--accent); border:2px solid var(--bg);
}

/* Side app: item flex nằm cuối shell. margin-left:auto đẩy nó bám hẳn mép phải
   để phần trống rơi vào giữa, không kẹt lại sau panel. sticky + 100vh để panel
   đứng yên khi cuộn danh sách câu hỏi. */
.calcguide-panel{
  /* Tách width ra khỏi shorthand: `flex:0 0 min(...)` không parse được ở mọi
     trình duyệt, hỏng cả khai báo và panel rơi về sizing theo nội dung.
     clamp: laptop/desktop được 430px, tablet ngang co còn ~340px để phần đọc
     đề không bị bóp quá hẹp. */
  flex:0 0 auto; width:clamp(340px, 26vw, 430px); margin-left:auto;
  position:sticky; top:0; height:100vh; z-index:40;
  display:flex; flex-direction:column;
  background:var(--surface); border-left:1px solid var(--line-strong);
  box-shadow:-14px 0 40px -22px rgba(20,30,26,.35);
}
/* BẮT BUỘC: display:flex ở trên đè mất [hidden]{display:none} của trình duyệt,
   nên không có dòng này thì panel không bao giờ ẩn được (kể cả lúc tải trang). */
.calcguide-panel[hidden]{display:none;}
.calcguide-head{
  flex:0 0 auto; display:flex; align-items:center; gap:10px;
  padding:12px 14px; border-bottom:1px solid var(--line); background:var(--surface-2);
}
.calcguide-title{display:flex; flex-direction:column; min-width:0; flex:1;}
.calcguide-title strong{font-size:.92rem; font-weight:600;}
.calcguide-title span{font-size:.68rem; color:var(--ink-faint); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
/* Cùng kích thước/bo góc với .nav-btn của viewer để header đọc thành một hệ
   thống nút. Dùng icon SVG thay glyph chữ (‹ và × lệch nhau về độ dày và tâm
   quang học nên nhìn không đều dù cùng khung). */
.calcguide-back,.calcguide-close{
  flex:0 0 auto; width:30px; height:30px; padding:0; display:grid; place-items:center;
  border:1px solid var(--line); border-radius:8px; background:var(--surface-2);
  color:var(--ink-soft); cursor:pointer;
}
.calcguide-back:hover,.calcguide-close:hover{color:var(--ink); border-color:var(--line-strong);}
/* Ẩn nhưng GIỮ CHỖ: nếu để [hidden] thu về display:none thì tiêu đề nhảy ngang
   mỗi lần chuyển giữa danh sách và trang chi tiết. visibility:hidden vẫn loại
   nút khỏi tab order và khỏi accessibility tree. */
.calcguide-back[hidden]{display:grid; visibility:hidden; pointer-events:none;}

.calcguide-body{flex:1; min-height:0; overflow-y:auto; padding:14px;}
.calcguide-body::-webkit-scrollbar{width:8px;}
.calcguide-body::-webkit-scrollbar-thumb{background:var(--line-strong); border-radius:4px;}

/* --- Danh sách: mỗi nhóm là 1 accordion thu gọn --- */
/* Dùng `>` ở mọi chỗ vì nhóm "General tips" chứa <details> lồng bên trong
   (từng mẹo), không được để style của nhóm đè lên chúng. */
.calcguide-section{
  margin-bottom:6px; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface); overflow:hidden;
}
.calcguide-section > summary{
  display:flex; align-items:center; gap:8px; padding:9px 11px; cursor:pointer;
  list-style:none; user-select:none;
}
.calcguide-section > summary::-webkit-details-marker{display:none;}
.calcguide-section > summary:hover{background:var(--surface-2);}
.calcguide-section[open] > summary{border-bottom:1px solid var(--line); background:var(--surface-2);}
.calcguide-chev{
  flex:0 0 auto; color:var(--ink-faint); font-size:.85rem; line-height:1;
  transition:transform .12s ease;
}
.calcguide-section[open] .calcguide-chev{transform:rotate(90deg);}
.calcguide-sec-title{
  flex:1; min-width:0; font-size:.72rem; font-weight:600; text-transform:uppercase;
  letter-spacing:.07em; color:var(--accent-ink);
}
.calcguide-sec-meta{flex:0 0 auto; font-size:.66rem; color:var(--ink-faint);}
.calcguide-sec-match{
  flex:0 0 auto; font-size:.62rem; padding:2px 6px; border-radius:999px;
  background:var(--accent); color:#fff; white-space:nowrap;
}
.calcguide-sec-body{padding:10px 11px 11px;}
.calcguide-blurb{margin:0 0 9px; font-size:.72rem; color:var(--ink-faint); line-height:1.45;}
.calcguide-entries{display:flex; flex-direction:column; gap:4px;}
.calcguide-entry{
  display:flex; align-items:flex-start; gap:8px; width:100%; text-align:left;
  padding:8px 10px; border:1px solid var(--line); border-radius:var(--radius);
  background:var(--surface); cursor:pointer;
}
.calcguide-entry:hover{border-color:var(--accent); background:var(--accent-soft);}
.calcguide-entry-main{flex:1; min-width:0; display:flex; flex-direction:column; gap:2px;}
.calcguide-entry-title{font-size:.82rem; font-weight:500; color:var(--ink);}
.calcguide-entry-goal{font-size:.71rem; color:var(--ink-faint); line-height:1.4;}
.calcguide-star{color:var(--accent); font-size:.5rem; vertical-align:middle; margin-left:5px;}
.calcguide-codes{display:flex; flex-wrap:wrap; gap:3px; justify-content:flex-end; max-width:96px;}
.calcguide-code{
  font-size:.6rem; font-family:var(--font-mono); white-space:nowrap;
  padding:2px 5px; border-radius:4px; background:var(--surface-3); color:var(--ink-soft);
}

/* --- Khối gợi ý theo câu hỏi đang mở --- */
.calcguide-suggest{
  margin-bottom:20px; padding:11px; border:1px solid var(--accent);
  border-radius:var(--radius-lg); background:var(--accent-soft);
}
.calcguide-suggest-head{
  display:flex; align-items:center; gap:6px; margin-bottom:8px;
  font-size:.7rem; font-weight:600; color:var(--accent-ink);
}
.calcguide-suggest-head code{font-family:var(--font-mono); font-size:.66rem; font-weight:400;}
.calcguide-dot{width:6px; height:6px; border-radius:50%; background:var(--accent); flex:0 0 auto;}
.calcguide-entry.is-suggested{border-color:transparent; background:var(--surface);}
.calcguide-entry.is-suggested:hover{border-color:var(--accent);}
.calcguide-note{
  margin:0 0 18px; padding:10px 11px; border-radius:var(--radius);
  background:var(--surface-3); color:var(--ink-soft); font-size:.73rem; line-height:1.5;
}

/* --- Mẹo dùng chung --- */
.calcguide-tips{display:flex; flex-direction:column; gap:3px;}
.calcguide-tip{border:1px solid var(--line); border-radius:var(--radius); background:var(--surface);}
.calcguide-tip summary{padding:7px 10px; cursor:pointer; font-size:.79rem; color:var(--ink-soft);}
.calcguide-tip[open] summary{color:var(--ink); font-weight:500; border-bottom:1px solid var(--line);}
.calcguide-tip p{margin:0; padding:9px 11px; font-size:.74rem; line-height:1.55; color:var(--ink-soft);}

/* --- Trang chi tiết --- */
.calcguide-detail-head{margin-bottom:14px; padding-bottom:12px; border-bottom:1px solid var(--line);}
.calcguide-crumb{font-size:.66rem; text-transform:uppercase; letter-spacing:.07em; color:var(--ink-faint);}
.calcguide-detail h2{margin:4px 0 5px; font-size:1.02rem; font-family:var(--font-serif); line-height:1.3;}
.calcguide-goal{margin:0 0 8px; font-size:.78rem; color:var(--ink-soft); line-height:1.5;}
.calcguide-detail-head .calcguide-codes{justify-content:flex-start; max-width:none;}

.calcguide-steps{margin:0 0 16px; padding-left:20px; display:flex; flex-direction:column; gap:11px;}
.calcguide-steps li{font-size:.78rem; line-height:1.5;}
.calcguide-steps li::marker{color:var(--accent-ink); font-weight:600; font-size:.72rem;}
.calcguide-keys{display:flex; flex-wrap:wrap; align-items:center; gap:3px; margin-bottom:4px;}
.calcguide-key{
  font-family:var(--font-ui); font-size:.68rem; padding:3px 7px;
  border:1px solid var(--line-strong); border-bottom-width:2px; border-radius:5px;
  background:var(--surface-2); color:var(--ink); white-space:nowrap;
}
.calcguide-key.is-menu{background:var(--accent-soft); border-color:var(--accent); color:var(--accent-ink);}
.calcguide-arrow{color:var(--ink-faint); font-size:.7rem;}
.calcguide-steptext{color:var(--ink-soft);}

.calcguide-block{margin-bottom:14px;}
.calcguide-block h4{
  margin:0 0 6px; font-size:.68rem; text-transform:uppercase; letter-spacing:.07em;
  color:var(--ink-faint);
}
.calcguide-fields{margin:0; display:grid; grid-template-columns:auto 1fr; gap:5px 10px; font-size:.75rem;}
.calcguide-fields dt{font-family:var(--font-mono); font-size:.71rem; color:var(--accent-ink); white-space:nowrap;}
.calcguide-fields dd{margin:0; color:var(--ink-soft); line-height:1.45;}
.calcguide-syntax{
  margin:0; padding:9px 11px; border-radius:var(--radius); overflow-x:auto;
  background:var(--surface-3); border:1px solid var(--line);
  font-family:var(--font-mono); font-size:.72rem; line-height:1.65; color:var(--ink);
}
.calcguide-example{padding:10px 12px; border-radius:var(--radius); background:var(--surface-2); border:1px solid var(--line);}
.calcguide-example p{margin:0 0 5px; font-size:.76rem; line-height:1.5;}
.calcguide-example p:last-child{margin-bottom:0;}
.calcguide-exlabel{
  display:inline-block; min-width:52px; font-size:.65rem; text-transform:uppercase;
  letter-spacing:.06em; color:var(--ink-faint);
}
.calcguide-example code{font-family:var(--font-mono); font-size:.72rem;}
.calcguide-notes{padding:10px 12px; border-radius:var(--radius); background:var(--gold-soft); border:1px solid #E8D9A8;}
.calcguide-notes h4{color:var(--gold);}
.calcguide-notes ul{margin:0; padding-left:16px; display:flex; flex-direction:column; gap:5px;}
.calcguide-notes li{font-size:.75rem; line-height:1.5; color:var(--ink-soft);}

/* Mục tiêu là tablet + laptop trở lên (không tối ưu cho điện thoại). Dưới 900px
   — tablet dựng đứng — không còn đủ chỗ cho dải side app nằm cạnh nội dung
   (dưới 840px .workspace đã về 1 cột), nên quay lại overlay phủ lên trên. */
@media (max-width:900px){
  body{display:block;}
  .app{margin:0 auto; max-width:1320px;}
  .calcguide-panel{
    position:fixed; top:0; right:0; bottom:0; height:auto; z-index:60;
    flex:none; width:min(430px, 92vw); margin-left:0;
  }
}

/* ---------- Subscription-expired block ---------- */
.expired-screen{
  max-width:480px; margin:80px auto; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius-lg); box-shadow:var(--shadow); padding:36px 40px; text-align:center;
}
.expired-screen h2{margin:0 0 10px; font-family:var(--font-serif);}
.expired-screen p{color:var(--ink-soft); line-height:1.6;}

/* ---------- Gói Free ----------
   Phần ngoài gói KHÔNG bị ẩn: vẫn hiện tên, làm mờ và gắn ổ khoá. Học sinh cần
   thấy mình đang bỏ lỡ gì thì mới có lý do nâng cấp. */
.tier-badge{
  display:inline-flex; align-items:center; gap:5px; padding:3px 9px;
  background:var(--surface-2); border:1px solid var(--line); border-radius:999px;
  color:var(--ink-faint); font-size:.7rem; font-weight:600; letter-spacing:.04em;
  text-transform:uppercase; cursor:pointer;
}
.tier-badge:hover{color:var(--accent-ink); border-color:var(--accent); background:var(--accent-soft);}
/* BẮT BUỘC: display:inline-flex ở trên đè mất [hidden]{display:none} của trình
   duyệt, nên không có dòng này thì tài khoản PRO cũng thấy huy hiệu "Free". */
.tier-badge[hidden]{display:none;}

.topic-item.is-locked, .topic-group.is-locked .topic-group-head{color:var(--ink-faint);}
.topic-item.is-locked span:last-child, .topic-group.is-locked h4{opacity:.55;}
.topic-item.is-locked input, .topic-group.is-locked .topic-group-all{display:none;}
.topic-lock{flex-shrink:0; margin-top:2px; color:var(--ink-faint); opacity:.7;}
.topic-group.is-locked .topic-lock{margin-top:0;}

.upgrade-backdrop{
  position:fixed; inset:0; z-index:60; display:flex; align-items:center; justify-content:center;
  padding:20px; background:rgba(27,35,32,.42);
}
/* BẮT BUỘC: display:flex ở trên đè mất [hidden]{display:none} của trình duyệt.
   Thiếu dòng này thì hộp thoại hiện ngay khi tải trang và nút "Got it" bấm
   không tắt được — `hidden = true` chạy đúng nhưng CSS thắng. */
.upgrade-backdrop[hidden]{display:none;}
.upgrade-card{
  width:100%; max-width:400px; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--radius-lg); box-shadow:var(--shadow); padding:28px 30px;
}
.upgrade-card h2{margin:0 0 8px; font-family:var(--font-serif); font-size:1.15rem;}
.upgrade-card p{margin:0 0 14px; color:var(--ink-soft); line-height:1.6; font-size:.88rem;}
.upgrade-list{margin:0 0 16px; padding-left:18px; color:var(--ink-soft); font-size:.85rem; line-height:1.8;}
.upgrade-contact{font-size:.82rem !important; color:var(--ink-faint) !important;}
.upgrade-card .btn{width:100%; display:block; text-align:center; text-decoration:none;}
/* BẮT BUỘC: cùng hộp thoại này còn dùng cho thông báo "đăng nhập đi" và "mở
   quá nhiều câu", lúc đó phải giấu bớt phần nói về gói Pro. Cả ba selector trên
   đều đặt `display:` nên đè mất [hidden]{display:none} của trình duyệt — không
   có ba dòng này thì `el.hidden = true` không giấu được gì. */
.upgrade-list[hidden]{display:none;}
.upgrade-contact[hidden]{display:none;}
.upgrade-card .btn[hidden]{display:none;}
.upgrade-card .btn.secondary{margin-top:8px;}

.calcguide-section.is-locked > summary{color:var(--ink-faint);}
.calcguide-section.is-locked .calcguide-sec-title{opacity:.6;}
.calcguide-lock{flex:0 0 auto; margin-left:auto; color:var(--ink-faint); opacity:.75;}
.calcguide-locked-body{padding:12px 14px; color:var(--ink-faint); font-size:.8rem; line-height:1.6;}
.calcguide-locked-body button{
  margin-top:10px; padding:6px 12px; background:var(--accent); color:#fff; border:none;
  border-radius:var(--radius); font:inherit; font-size:.78rem; cursor:pointer;
}

/* Lối vào trang tài khoản từ popover. Popover chỉ giữ vài thao tác nhanh;
   mọi thứ về gói, đơn hàng, xoá tài khoản nằm ở /account.html. */
.account-panel .acct-link{
  display:block; font-size:.82rem; font-weight:600; color:var(--accent-ink);
  text-decoration:none; padding:2px 0 6px;
}
.account-panel .acct-link:hover{text-decoration:underline;}

/* ============================ Exam builder ============================ */

/* Nhiều side app cùng có nút nổi ở góc phải dưới. Gom vào một cột để chúng xếp
   chồng lên nhau thay vì đè lên nhau, và để khoảng trống tự thu lại khi một nút
   bị ẩn (nút Guide ẩn ở môn không phải Toán). */
.side-dock-launchers{
  position:fixed; right:22px; bottom:22px; z-index:55;
  display:flex; flex-direction:column-reverse; align-items:flex-end; gap:8px;
}
/* Nút bên trong đã nằm trong hộp fixed rồi nên bỏ định vị riêng của chúng. */
.side-dock-launchers .calcguide-launcher{position:relative; right:auto; bottom:auto;}

.exam-launcher.has-items{border-color:var(--accent); color:var(--accent-ink); background:var(--accent-soft);}
.exam-count{
  min-width:17px; height:17px; padding:0 5px; border-radius:999px;
  background:var(--accent); color:#fff; font-size:.66rem; font-weight:600;
  display:flex; align-items:center; justify-content:center;
}
/* BẮT BUỘC: display:flex ở trên đè mất [hidden]{display:none} của trình duyệt —
   đúng cái bẫy đã vấp ở .calcguide-launcher và .tier-badge. */
.exam-count[hidden]{display:none;}

.exam-stats{
  flex:0 0 auto; display:flex; border-bottom:1px solid var(--line); background:var(--surface-2);
}
.exam-stat{flex:1; padding:9px 11px; display:flex; flex-direction:column; gap:2px;}
.exam-stat + .exam-stat{border-left:1px solid var(--line);}
.exam-stat span{font-size:.64rem; color:var(--ink-faint);}
.exam-stat strong{font-size:1.15rem; font-weight:600; line-height:1;}

/* Cảnh báo (câu thiếu điểm, trộn môn/level). Không phải lỗi nên dùng tông nhắc
   nhở, và KHÔNG chặn thao tác nào. */
.exam-note{
  margin-bottom:8px; padding:7px 9px; border-radius:var(--radius);
  background:var(--hl-soft); color:var(--hl); font-size:.68rem; line-height:1.4;
}
.exam-empty{padding:26px 8px; text-align:center; color:var(--ink-faint); font-size:.75rem; line-height:1.6;}

.exam-row{display:flex; align-items:center; gap:6px; padding:4px 0;}
.exam-row + .exam-row{border-top:1px solid var(--line);}
.exam-code{flex:1; min-width:0; font-size:.7rem; font-family:var(--font-mono); font-variant-numeric:tabular-nums; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.exam-extra{font-size:.62rem; color:var(--ink-faint);}
.exam-marks{font-size:.68rem; color:var(--ink-faint); min-width:26px; text-align:right;}
.exam-del{
  width:20px; height:20px; padding:0; display:grid; place-items:center;
  border:none; background:none; border-radius:5px; color:var(--ink-faint); cursor:pointer;
}
.exam-del:hover{background:var(--surface-2); color:var(--ink);}

.exam-share{
  width:20px; height:20px; padding:0; display:grid; place-items:center; flex-shrink:0;
  border:none; background:none; border-radius:5px; color:var(--ink-faint); cursor:pointer;
}
.exam-share:hover{background:var(--surface-2); color:var(--ink);}
.exam-share.is-on{color:var(--accent-ink); background:var(--accent-soft);}

.exam-foot{
  flex:0 0 auto; display:flex; gap:7px; padding:10px 12px;
  border-top:1px solid var(--line); background:var(--surface-2);
}
.exam-foot .btn{flex:1; font-size:.75rem; padding:6px 10px;}
.exam-foot .btn:disabled{opacity:.45; cursor:not-allowed;}

/* Nút + ở mỗi dòng danh sách, đặt bên trái ngôi sao bookmark. */
.ex-btn{
  position:absolute; top:4px; right:26px; width:19px; height:19px; border:none; background:none;
  cursor:pointer; display:flex; align-items:center; justify-content:center; color:var(--ink-faint);
  border-radius:6px;
}
.ex-btn:hover{background:var(--surface-2); color:var(--ink-soft);}
.ex-btn svg{width:12px; height:12px;}
.ex-btn.on{color:var(--accent); background:var(--accent-soft);}

/* Nút + ở viewer khi câu đang xem đã nằm trong đề. */
.nav-btn#vExamAdd.on{color:var(--accent-ink); border-color:var(--accent); background:var(--accent-soft);}

/* Nhãn "+n điểm" bay từ nút bấm về phía nút nổi. Thuần trang trí. */
.exam-fly{
  position:fixed; z-index:60; pointer-events:none;
  font-size:.78rem; font-weight:600; color:var(--accent-ink);
  transition:transform .6s cubic-bezier(.4,0,.2,1), opacity .6s ease-out;
}
@media (prefers-reduced-motion:reduce){
  .exam-fly{transition:opacity .2s linear;}
}
/* Panel mở thì giấu cụm nút nổi: nút nằm đè lên chân panel, che mất hàng nút
   Preview/Clear của exam builder (calcguide không có footer nên không lộ ra).
   Đóng panel vẫn dùng nút × trong header hoặc phím Escape. */
body.has-side-app .side-dock-launchers{display:none;}

/* ---- Lưu / mở đề trong panel soạn đề ---- */

/* Hàng đặt tên chỉ hiện lúc bấm Save, nên không chiếm chỗ thường ngày. */
.exam-namerow{display:flex; gap:6px; padding:8px 12px 0;}
.exam-namerow[hidden]{display:none;}
.exam-namerow .text-input{flex:1 1 auto; min-width:0; margin:0; padding:6px 9px; font-size:.78rem;}
.exam-namerow .btn{flex:0 0 auto; padding:6px 12px; font-size:.78rem;}

.exam-msg{margin:0; padding:6px 12px 0; font-size:.68rem; color:var(--ink-faint); line-height:1.4;}
.exam-msg:empty{display:none;}
.exam-msg.is-error{color:var(--danger);}

.exam-saved-row{display:flex; align-items:center; gap:4px;}
.exam-saved-row + .exam-saved-row{border-top:1px solid var(--line);}
.exam-saved-open{
  flex:1 1 auto; min-width:0; display:flex; align-items:baseline; gap:8px;
  background:none; border:none; padding:6px 0; cursor:pointer; text-align:left; color:var(--ink);
}
.exam-saved-open:hover .exam-saved-name{text-decoration:underline;}
.exam-saved-name{flex:1 1 auto; min-width:0; font-size:.75rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
.exam-saved-meta{flex:0 0 auto; font-size:.66rem; color:var(--ink-faint);}
/* Đề đang mở: đánh dấu để không mở nhầm lần nữa rồi tưởng không có gì xảy ra. */
.exam-saved-row.is-open .exam-saved-name{color:var(--accent-ink); font-weight:600;}
/* Xác nhận xoá ngay trên dòng, thay cho window.confirm — xem ghi chú ở
   exam-builder.js deleteSaved(). */
.exam-saved-row.is-asking{gap:6px; padding:5px 0;}
.exam-saved-row.is-asking .exam-saved-name{flex:1 1 auto; font-size:.72rem; color:var(--ink-soft);}
.exam-confirm{
  flex:0 0 auto; padding:3px 9px; font-size:.68rem; cursor:pointer;
  border:1px solid var(--danger); border-radius:5px;
  background:var(--danger); color:#fff;
}
.exam-confirm.ghost{background:none; color:var(--ink-soft); border-color:var(--line);}
.exam-confirm.ghost:hover{color:var(--ink); border-color:var(--line-strong);}

/* ---- Generate a paper (PRO) ---- */

.exam-generate-btn{margin:8px 12px 0; font-size:.78rem; padding:7px 10px;}

.practice-launcher:disabled{opacity:.5; cursor:not-allowed;}

.gen-card{max-width:440px;}
.gen-body{max-height:56vh; overflow-y:auto; margin:0 -4px; padding:0 4px;}
.gen-row{display:block; margin-top:12px;}
.gen-row:first-child{margin-top:0;}
.gen-two{display:flex; gap:10px;}
.gen-two .gen-label{flex:1 1 0; min-width:0;}
.gen-label{
  display:flex; flex-direction:column; gap:4px;
  font-size:.68rem; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint);
}
.gen-label select.field, .gen-label .text-input{
  text-transform:none; letter-spacing:normal; font-size:.85rem; width:100%;
}
.gen-label-static{
  display:block; font-size:.68rem; text-transform:uppercase; letter-spacing:.05em; color:var(--ink-faint);
}
.gen-topic-note{text-transform:none; letter-spacing:normal;}
.gen-topics{
  margin-top:6px; max-height:260px; overflow-y:auto;
  border:1px solid var(--line); border-radius:var(--radius);
}
.gen-topics .empty-note{color:var(--ink-faint); font-size:.82rem; padding:14px 10px;}
.gen-topic-row{display:flex; align-items:center; gap:8px; padding:2px 8px 2px 2px;}
.gen-topic-row + .gen-topic-row{border-top:1px solid var(--line);}
.gen-topic-row .gen-topic-check{flex:1 1 auto; min-width:0; padding:6px;}
.gen-percent{
  flex:0 0 auto; width:52px; text-align:right; padding:5px 7px; font-size:.8rem;
}
.gen-percent:disabled{opacity:.35;}
.gen-actions{display:flex; gap:8px; margin-top:16px;}
.gen-actions .btn{flex:1;}
