/* grammar/grammar.css — Grammar Gym. Dựa trên biến của /theme.css. */
/* Màu nhấn của phòng gym, khai MỘT LẦN cho bộ phần tử chung — đổi ở đây là
   đổi cả nút/thẻ/mục chọn trong cột phụ, không phải đi sửa từng selector. */
body { --lg-accent: #10B981; --lg-accent-soft: rgba(16,185,129,.12);
       /* Chữ trắng trên #10B981 chỉ ~2,1:1 — dùng mực tối, giống .gym-next. */
       --lg-accent-ink: #04120c; }

.gym-wrap { max-width: var(--lg-main-w, 720px); margin: 0 auto; padding: 20px 16px calc(48px + env(safe-area-inset-bottom)); font-family: var(--font-ui-family,'Be Vietnam Pro'), system-ui, sans-serif; }

/* §R08 (QA#5 viec #6, chot D1 20/09) — tieu de app o GOC TREN TRAI cot
   giua o MOI app. Do 20/09: Grammar Gym can giua, Pron Coach/Score Sprint
   goc trai. Doi app la mat phai di tim lai tieu de.
   Chi doi VI TRI. Co chu van moi app mot kieu (1,5 / 1,6 / 2,6rem) —
   da bao chu app, cho chot rieng. */
.gym-head { text-align: left; margin: 0 0 14px; }
.gym-title { font-size: var(--lg-title); font-weight: 700; color: var(--text); margin: 0 0 8px; }
.gym-lead { font-size: var(--lg-title-sub); color: var(--dim); line-height: 1.6; margin: 0; }

/* M3/D7 — chip nhắc "gauge bắt buộc" (vocab-level-widget.js #lgGaugeChip
   dùng chung class này ở 4 app: grammar/mfi/listening/reader). */
.lg-gauge-chip {
  display: block; text-align: center;
  background: color-mix(in srgb, var(--yellow) 16%, var(--surf));
  border-bottom: 1px solid var(--yellow);
  color: var(--text); font-weight: 700; font-size: .82rem;
  padding: 8px 14px;
}
.lg-gauge-chip a { color: var(--teal-text); margin-left: 4px; }

/* gym-vocab.js — gợi ý tra-từ, hiện một lần ở màn danh sách chuyên đề */
.gym-vocab-hint { display: flex; align-items: center; gap: 8px; font-size: .8rem; color: var(--text); line-height: 1.5; background: rgba(16,185,129,.1); border: 1px solid rgba(16,185,129,.4); border-radius: 10px; padding: 8px 12px; margin: 0 0 14px; }
.gym-vocab-hint-x { margin-left: auto; flex: 0 0 auto; appearance: none; border: none; background: transparent; color: var(--dim); font-size: 1rem; line-height: 1; cursor: pointer; padding: 4px 6px; min-height: 28px; }
.gym-vocab-hint-x:hover { color: var(--text); }

/* ── Cây lý thuyết ở màn chủ ──────────────────────────────────────────
   Mỗi hàng là một đơn vị ngôn ngữ, lớn dần từ trên xuống. Một TRỤC DỌC
   liền mạch chạy suốt cây, các bậc là nút tròn đánh số trên trục đó —
   nhìn một cái là thấy mạch tiến, không phải đọc chữ mới đoán ra.
   Trục vẽ bằng ::before của .gym-tree (một đường liền), KHÔNG vẽ bằng
   ::after của từng hàng: ghép nhiều đoạn thì đúng chỗ nối luôn có khe hở
   và trên màn hẹp trông như đường đứt. */
.gym-tree-intro { font-size: .8rem; color: var(--dim); line-height: 1.6; margin: 0 0 14px; }
.gym-tree { position: relative; display: flex; flex-direction: column; gap: 26px; }
.gym-tree::before { content: ''; position: absolute; left: 13px; top: 14px; bottom: 14px; width: 2px;
  background: linear-gradient(180deg, #10B981 0%, var(--border) 100%); border-radius: 2px; }
.gym-tree-row { position: relative; }
.gym-tree-head { display: flex; align-items: flex-start; gap: 12px; margin: 0 0 10px; }
/* Nút tròn phải ĐỤC nền để trục dọc không xuyên qua số. */
.gym-tree-node { position: relative; z-index: 1; flex: 0 0 auto;
  width: 28px; height: 28px; border-radius: 999px; display: flex; align-items: center; justify-content: center;
  font-size: .8rem; font-weight: 700; color: var(--dim);
  background: var(--bg); border: 2px solid var(--border); }
.gym-tree-node-done { color: #10B981; border-color: #10B981; background: rgba(16,185,129,.12); }
.gym-tree-htxt { min-width: 0; padding-top: 2px; }
.gym-tree-lab { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.gym-tree-lab-t { font-size: .95rem; font-weight: 700; color: var(--text); }
.gym-tree-step { font-size: .68rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: #10B981; background: rgba(16,185,129,.12); border-radius: 999px; padding: 2px 8px; }
.gym-tree-lab-s { font-size: .74rem; color: var(--dim); }
.gym-tree-gain { font-size: .78rem; color: var(--dim); line-height: 1.55; margin-top: 3px; }
/* Thẻ thụt vào cho thẳng hàng với chữ của bậc, chừa chỗ cho trục. */
.gym-tree-row .gym-grid { margin-left: 40px; }
@media (max-width: 559px) { .gym-tree-row .gym-grid { margin-left: 26px; } }

.gym-card-dep { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 6px; margin-top: 6px; }
.gym-card-dep-l { font-size: .7rem; color: var(--dim); }
.gym-card-dep-p { font-size: .7rem; font-weight: 600; color: var(--dim);
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; }
.gym-card-dep-ok { color: #10B981; border-color: #10B981; background: rgba(16,185,129,.1); }

.gym-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 560px) { .gym-grid { grid-template-columns: 1fr 1fr; } }
.gym-card { display: flex; gap: 12px; align-items: flex-start; text-align: left; padding: 14px; border-radius: 14px; border: 1px solid var(--border); background: var(--surf); cursor: pointer; transition: border-color .15s, transform .15s; font-family: inherit; }
.gym-card:hover { border-color: #10B981; transform: translateY(-1px); }
.gym-card-icon { font-size: 1.5rem; line-height: 1; padding-top: 2px; }
.gym-card-name { font-weight: 700; color: var(--text); font-size: .95rem; }
.gym-card-tag { font-size: .78rem; color: var(--dim); line-height: 1.5; margin-top: 4px; }
.gym-card-stat { font-size: .74rem; color: #10B981; font-weight: 600; margin-top: 6px; min-height: 1em; }

.gym-back { background: none; border: none; color: var(--dim); font-family: inherit; font-size: .85rem; cursor: pointer; padding: 8px 0; min-height: 44px; }
.gym-back:hover { color: var(--text); }

.gym-theory { border: 1px solid var(--border); border-radius: 14px; background: var(--surf); padding: 16px; margin: 8px 0 16px; }
.gym-theory-head { font-weight: 700; font-size: 1.05rem; color: var(--text); margin-bottom: 10px; }
.gym-theory-body { font-size: .88rem; color: var(--text); line-height: 1.7; margin: 0 0 12px; }
.gym-theory-ex { border-top: 1px dashed var(--border); padding-top: 12px; }
.gym-theory-ex-label { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: #10B981; margin-bottom: 6px; }
.gym-theory-quote { margin: 0 0 8px; padding: 10px 12px; border-left: 3px solid #10B981; background: var(--surf2, rgba(16,185,129,.06)); color: var(--text); font-size: .86rem; line-height: 1.6; border-radius: 0 8px 8px 0; }
.gym-theory-note { font-size: .8rem; color: var(--dim); line-height: 1.6; }

.gym-drills { display: flex; flex-direction: column; gap: 10px; }
.gym-drill-btn { text-align: left; padding: 14px; border-radius: 12px; border: 1px solid var(--border); background: var(--surf); cursor: pointer; font-family: inherit; transition: border-color .15s; }
.gym-drill-btn:hover { border-color: #10B981; }
.gym-drill-title { font-weight: 700; color: var(--text); font-size: .95rem; }
.gym-drill-desc { font-size: .8rem; color: var(--dim); margin-top: 4px; line-height: 1.5; }

.gym-drill-top { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 6px; }
.gym-progress { font-size: .78rem; color: var(--dim); font-weight: 600; }
/* Câu hỏi phải NHÌN LÀ BIẾT là câu hỏi — trước đây cùng cỡ, cùng độ đậm với
   các đáp án bên dưới nên đọc lướt là lẫn (feedback chủ app 02/09). */
.gym-q-prompt { font-size: 1rem; font-weight: 700; color: var(--text); line-height: 1.65; background: var(--surf); border: 1px solid var(--border); border-left: 3px solid #10B981; border-radius: 12px; padding: 14px; }
.gym-q-prompt strong { font-weight: 800; }

.gym-opts { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
.gym-opt { display: flex; gap: 10px; align-items: flex-start; text-align: left; padding: 12px; min-height: 44px; border-radius: 10px; border: 1px solid var(--border); background: var(--surf); cursor: pointer; font-family: inherit; font-size: .88rem; color: var(--text); line-height: 1.5; }
.gym-opt:hover:not(:disabled) { border-color: #10B981; }
.gym-opt:disabled { cursor: default; opacity: .85; }
.gym-opt-key { font-weight: 700; color: var(--dim); flex: 0 0 auto; }
.gym-opt-right { border-color: var(--green,#4BC98A); background: rgba(34,197,94,.1); }
.gym-opt-wrong { border-color: var(--red,#F2736B); background: rgba(239,68,68,.1); }

.gym-feedback { margin-top: 12px; padding: 12px 14px; border-radius: 10px; font-size: .85rem; line-height: 1.6; }
.gym-fb-ok { background: rgba(34,197,94,.1); border: 1px solid rgba(34,197,94,.35); color: var(--text); }
.gym-fb-no { background: rgba(239,68,68,.08); border: 1px solid rgba(239,68,68,.3); color: var(--text); }
.gym-fb-head { font-weight: 700; margin-bottom: 4px; }
.gym-fb-why { color: var(--dim); }

.gym-next { display: block; width: 100%; margin-top: 14px; padding: 13px; min-height: 48px; border-radius: 12px; border: none; background: #10B981; color: #04120c; font-weight: 700; font-size: .95rem; font-family: inherit; cursor: pointer; }
.gym-next:hover { filter: brightness(1.08); }

.gym-summary { text-align: center; padding: 30px 16px; }
.gym-sum-icon { font-size: 2.6rem; margin-bottom: 10px; }
.gym-sum-score { font-size: 1.4rem; font-weight: 700; color: var(--text); margin-bottom: 8px; }
.gym-sum-note { font-size: .84rem; color: var(--dim); line-height: 1.6; max-width: 440px; margin: 0 auto 18px; }
.gym-summary .gym-back { display: block; margin: 10px auto 0; }

/* ── M0: luyện riêng từng thì ── */
.gym-tense { margin: 4px 0 14px; }
.gym-tense-intro { font-size: .82rem; color: var(--dim); line-height: 1.55; margin: 0 4px 10px; }
.gym-tense-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
@media (min-width: 520px) { .gym-tense-grid { grid-template-columns: 1fr 1fr; } }
.gym-tense-chip { display: grid; grid-template-columns: 1fr auto; column-gap: 8px; row-gap: 2px; text-align: left;
  padding: 10px 12px; min-height: 48px; border-radius: 10px; border: 1px solid var(--border); background: var(--surf);
  cursor: pointer; font-family: inherit; color: var(--text); }
.gym-tense-chip:hover { border-color: #10B981; }
.gym-tense-name { font-weight: 700; font-size: .9rem; }
.gym-tense-hint { grid-column: 1; font-size: .74rem; color: var(--dim); line-height: 1.4; }
.gym-tense-n { grid-column: 2; grid-row: 1 / span 2; align-self: center; font-size: .74rem; font-weight: 700; color: #10B981; white-space: nowrap; }
.gym-tense-title { font-size: 1.2rem; margin: 10px 4px 4px; color: var(--text); }
.gym-tense-theory { display: block; width: 100%; text-align: left; margin: 0 0 12px; padding: 11px 14px; min-height: 44px;
  border-radius: 10px; border: 1px dashed var(--border); background: transparent; color: var(--text);
  font-family: inherit; font-size: .88rem; font-weight: 600; cursor: pointer; }
.gym-tense-theory:hover { border-color: #10B981; }
.gym-tense-go { display: block; width: 100%; margin-top: 12px; padding: 11px 14px; min-height: 44px; border-radius: 10px;
  border: 1px solid #10B981; background: rgba(16,185,129,.1); color: var(--text); font-family: inherit;
  font-size: .9rem; font-weight: 700; cursor: pointer; text-align: left; }

/* ── D1 quét chọn lõi + D3 tô cụm ── */
.gym-q-sentence { font-size: .95rem; line-height: 1.7; color: var(--text); background: var(--surf); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; margin-bottom: 10px; }
.gym-q-target { background: rgba(16,185,129,.22); color: inherit; border-radius: 4px; padding: 1px 3px; font-weight: 600; }
.gym-toks { display: flex; flex-wrap: wrap; gap: 6px; background: var(--surf); border: 1px solid var(--border); border-radius: 10px; padding: 12px; line-height: 1.6; }
.gym-tok { padding: 8px 10px; min-height: 44px; border-radius: 8px; border: 1px solid transparent; background: transparent; color: var(--text); font-family: inherit; font-size: .92rem; cursor: pointer; }
.gym-tok:hover { border-color: var(--border); }
.gym-tok-on { background: rgba(16,185,129,.18); border-color: #10B981; font-weight: 600; }
.gym-tok-core { border-color: #10B981; box-shadow: inset 0 0 0 1px #10B981; font-weight: 700; }
.gym-tok-miss { border-style: dashed; border-color: #F59E0B; box-shadow: inset 0 0 0 1px #F59E0B; font-weight: 700; background: rgba(245,158,11,.14); }
.gym-tok-extra { text-decoration: line-through; border-color: rgba(239,68,68,.5); color: var(--dim); }

/* ── Bài TẠO LẬP: ghép mảnh (build) + gõ tay (gap/join) ── */
.gym-drill-sep { margin: 16px 4px 6px; font-size: .78rem; font-weight: 800; letter-spacing: .04em;
  text-transform: uppercase; color: var(--dim); }
.gym-build-answer { min-height: 52px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  background: var(--surf); border: 1px dashed var(--border); border-radius: 10px; padding: 10px; margin-bottom: 10px; }
.gym-build-ph { color: var(--dim); font-size: .9rem; font-style: italic; }
.gym-build-pool { min-height: 44px; }
.gym-typed-input { font-family: inherit; font-size: 1rem; color: var(--text); background: var(--bg, var(--surf));
  border: 1px solid var(--border); border-radius: var(--r2); padding: 8px 10px; min-height: 44px; }
.gym-typed-input:focus { outline: 2px solid #10B981; outline-offset: 1px; }
.gym-typed-full { display: block; width: 100%; box-sizing: border-box; margin-top: 10px; }
.gym-gap-line { font-size: 1.05rem; line-height: 2.1; color: var(--text); background: var(--surf);
  border: 1px solid var(--border); border-radius: 10px; padding: 14px; }
.gym-gap-txt { white-space: normal; }
.gym-gap-blank { display: inline-block; width: 11em; max-width: 60vw; vertical-align: baseline;
  text-align: center; border: none; border-bottom: 2px solid #10B981; border-radius: 0; background: transparent; padding: 2px 4px; }
.gym-gap-cue { margin-top: 8px; font-size: .85rem; color: var(--dim); }
.gym-join-src { background: var(--surf); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }
.gym-join-line { font-size: .98rem; line-height: 1.7; color: var(--text); }
.gym-fb-near { background: rgba(245,158,11,.1); border: 1px solid rgba(245,158,11,.35); color: var(--text); }
.gym-fb-note { color: var(--dim); margin-top: 6px; }

/* ── Nấc 4 — viết tự do (chấm AI) ─────────────────────────────────── */
.gym-write-task { margin-top: 10px; background: var(--surf); border: 1px solid var(--border);
  border-left: 3px solid #8B5CF6; border-radius: 10px; padding: 12px 14px; }
.gym-write-rule { font-size: .78rem; font-weight: 800; letter-spacing: .02em; text-transform: uppercase;
  color: #8B5CF6; margin-bottom: 4px; }
.gym-write-ask { font-size: 1rem; font-weight: 700; color: var(--text); line-height: 1.6; }
.gym-write-input { display: block; width: 100%; box-sizing: border-box; margin-top: 10px; resize: vertical;
  font-family: inherit; font-size: 1rem; color: var(--text); background: var(--bg, var(--surf));
  border: 1px solid var(--border); border-radius: var(--r2); padding: 10px 12px; min-height: 48px; line-height: 1.6; }
.gym-write-input:focus { outline: 2px solid #8B5CF6; outline-offset: 1px; }
.gym-write-issues { margin: 8px 0 0; padding-left: 18px; }
.gym-write-issues li { margin: 4px 0; line-height: 1.55; }
.gym-write-span { font-weight: 700; }
.gym-write-why { color: var(--dim); }
.gym-write-ex { color: var(--dim); font-style: italic; margin-top: 2px; }

/* ════════════════════════════════════════════════════════════════════
   Sơ đồ tương tác trong thẻ lý thuyết (gym-diagram.js)
   ────────────────────────────────────────────────────────────────────
   MỘT hệ màu cho cả 6 module, và ĐÚNG hệ màu mà drill D1/D3 dùng:
   S xanh dương · V cam · O vàng · bổ nghĩa xám (gạt được) · phần chen
   ngang tím · tiền ngữ xanh lá. Học lý thuyết thấy màu nào thì vào bài
   tập gặp lại màu đó — đổi màu ở đây phải đổi cả bên drill.
   Dùng nền rgba + viền đặc nên chạy được cả theme sáng lẫn tối.
   ════════════════════════════════════════════════════════════════════ */
.gym-dg { margin: 14px 0 4px; border-top: 1px dashed var(--border); padding-top: 12px; }
.gym-dg-hint { font-size: .78rem; color: var(--dim); line-height: 1.6; margin-bottom: 10px; }
.gym-dg-stage { position: relative; }
.gym-dg-ref .gym-dg-stage { padding-top: 38px; }
.gym-dg-line { margin: 0; font-size: .93rem; line-height: 2.3; color: var(--text);
  background: var(--surf); border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; }

.gym-dg-chip { font: inherit; cursor: pointer; padding: 3px 7px; border-radius: 7px;
  border: 1px solid transparent; background: transparent; color: var(--text);
  min-height: 32px; transition: opacity .18s, background .18s; }
.gym-dg-chip:focus-visible { outline: 2px solid #10B981; outline-offset: 2px; }
.gym-dg-chip.sel { box-shadow: 0 0 0 2px rgba(16,185,129,.45); }
.gym-dg-chip.grown { background: rgba(168,85,247,.22); font-weight: 600; }

.r-s     { background: rgba(59,130,246,.16); border-color: #3B82F6; }
.r-v     { background: rgba(249,115,22,.16); border-color: #F97316; font-weight: 600; }
.r-o     { background: rgba(234,179,8,.18);  border-color: #EAB308; }
.r-c     { background: rgba(20,184,166,.16); border-color: #14B8A6; }
.r-mod   { background: rgba(148,163,184,.16); border-color: var(--border); color: var(--dim); }
.r-rel,
.r-appos { background: rgba(168,85,247,.15); border-color: #A855F7; }
.r-ref   { background: rgba(168,85,247,.2);  border-color: #A855F7; font-weight: 600; }
.r-ante  { background: rgba(16,185,129,.18); border-color: #10B981; font-weight: 600; }
.r-decoy { background: transparent; border-color: rgba(239,68,68,.55); border-style: dashed; }
.r-conj  { background: rgba(168,85,247,.15); border-color: #A855F7; font-weight: 600; }
.r-perf  { background: rgba(20,184,166,.16); border-color: #14B8A6; font-weight: 600; }
.r-pass  { background: rgba(20,184,166,.16); border-color: #14B8A6; font-weight: 600; }
.r-comp  { background: rgba(234,179,8,.2); border-color: #EAB308; font-weight: 600; }
.r-modal { background: rgba(249,115,22,.16); border-color: #F97316; }
.r-bare  { background: rgba(59,130,246,.16); border-color: #3B82F6; }
.r-derived { background: rgba(234,179,8,.2); border-color: #EAB308; font-weight: 600; }

/* Gạt bổ nghĩa: mờ đi + gạch ngang, KHÔNG xoá khỏi luồng chữ — học sinh
   phải thấy phần bị gạt nằm ở đâu thì mới học được cách gạt. */
.gym-dg.stripped .r-mod,
.gym-dg.stripped .r-rel,
.gym-dg.stripped .r-appos,
.gym-dg.stripped .r-conj { opacity: .26; text-decoration: line-through; }

.gym-dg-arrow { position: absolute; inset: 0; pointer-events: none; overflow: visible; }
.gym-dg-arrow-path { fill: none; stroke: #A855F7; stroke-width: 2; stroke-linecap: round; }
.gym-dg-arrow-head { fill: #A855F7; stroke: none; }

.gym-dg-word { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 12px; }
.gym-dg-plus { color: var(--dim); font-weight: 700; }
.gym-dg-mchip { font: inherit; cursor: pointer; padding: 7px 12px; border-radius: 8px;
  min-height: 44px; border: 1px solid transparent; color: var(--text); font-weight: 600; }
.m-pre  { background: rgba(168,85,247,.16); border-color: #A855F7; }
.m-root { background: rgba(59,130,246,.16); border-color: #3B82F6; }
.m-suf  { background: rgba(234,179,8,.2);   border-color: #EAB308; }

.gym-dg-lookup { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.gym-dg-lk { font: inherit; font-size: .8rem; cursor: pointer; padding: 8px 11px; min-height: 44px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surf); color: var(--text); }
.gym-dg-lk.sel { border-color: #10B981; background: rgba(16,185,129,.14); font-weight: 600; }

.gym-dg-acts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* ══ 21/09 · QA chủ app #3 — CÔNG CỤ Ở CẠNH THỨ NÓ TÁC ĐỘNG ══
   Ở đây từng có `html[data-gym-tools="1"] .gym-dg-acts [data-gym-strip]
   {display:none}` — giấu nút gạt DƯỚI CÂU vì cột phụ đã có công tắc chung
   (§R32, QA#6 #3). Chủ app 21/09: *"phần công cụ lọc câu thì lại nằm xa so
   với câu được lọc — illogical và khó hình dung cho user"*.
   Đúng, và §R32 đã đọc sai chính yêu cầu đẻ ra nó: *"hay xuất hiện ở
   nhiều câu"* nghĩa là thao tác này LẶP LẠI qua nhiều câu, chứ không phải
   em muốn gạt NHIỀU CÂU CÙNG LÚC. Đo lại: màn lý thuyết chỉ dựng ĐÚNG MỘT
   `.gym-dg` mỗi lượt (GymDiagram.render gọi 1 lần/thẻ ở app.js:977 và :1534)
   ⇒ công tắc "bấm cho tất cả" điều khiển đúng một nút, qua một vòng gián
   tiếp, cách nó gần cả một cột màn hình. Nay nút nằm ngay dưới câu, cùng
   chỗ với dòng "Còn lại: …" mà nó in ra. ĐỪNG DỰNG LẠI CÔNG TẮC Ở CỘT PHỤ. */
.gym-dg-why { font-size: .78rem; line-height: 1.55; color: var(--dim);
  margin: 8px 0 0; max-width: 62ch; }
/* Cột phụ: hai dòng tiến độ của chuyên đề gộp thành tag (§R33 dùng .lg-tag). */
.gym-rail-tally { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.gym-dg-btn { font: inherit; font-size: .82rem; cursor: pointer; padding: 10px 14px; min-height: 44px;
  border-radius: 10px; border: 1px solid var(--border); background: var(--surf); color: var(--text); font-weight: 600; }
.gym-dg-btn:hover { border-color: #10B981; }
.gym-dg-btn[aria-pressed="true"] { border-color: #10B981; background: rgba(16,185,129,.12); }

.gym-dg-say { font-size: .82rem; line-height: 1.65; color: var(--dim); margin-top: 10px;
  min-height: 0; opacity: 0; transition: opacity .18s; }
.gym-dg-say.on { opacity: 1; min-height: 22px; }
.gym-dg-say.ok { color: var(--text); background: rgba(16,185,129,.1);
  border-left: 3px solid #10B981; border-radius: 0 8px 8px 0; padding: 8px 11px; }

.gym-dg-legend { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.gym-dg-lg { font-size: .7rem; padding: 3px 8px; border-radius: 999px; border: 1px solid transparent; color: var(--text); }

@media (max-width: 480px) {
  .gym-dg-line { font-size: .88rem; line-height: 2.4; padding: 10px 11px; }
}

/* Nút bài tập còn chờ dữ liệu: khoá lại + nhạt đi, thay vì bấm xong
   không thấy gì xảy ra (audit UX 25/8). */
.gym-drill-wait { opacity: .55; cursor: progress; }
.gym-drill-wait:hover { border-color: var(--border); }

/* ── Dẫn sang chuyên đề khác ([[M5|…]] trong lý thuyết) ──────────────── */
.gym-xref-wrap { position: relative; display: inline-block; }
.gym-xref { font: inherit; color: inherit; cursor: pointer; padding: 0 2px;
  border: 0; border-bottom: 1px dashed #6366F1; background: rgba(99,102,241,.12);
  border-radius: 3px; }
.gym-xref::after { content: ' ↗'; font-size: .75em; color: #6366F1; }
.gym-xref:hover, .gym-xref[aria-expanded="true"] { background: rgba(99,102,241,.24); }
.gym-xref-box { position: absolute; z-index: 30; left: 0; top: calc(100% + 6px);
  width: max-content; max-width: min(320px, 78vw); display: flex; flex-direction: column; gap: 5px;
  padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surf); box-shadow: 0 8px 24px rgba(0,0,0,.28); }
/* BẮT BUỘC: `display:flex` ở rule trên là style của tác giả nên nó THẮNG luật
   [hidden] mặc định của trình duyệt ⇒ thiếu dòng này là hộp luôn mở. Đúng cái
   bẫy đã mất công đo ở widget Daily Routine. */
.gym-xref-box[hidden] { display: none; }
/* Chuột: rê vào là hiện. Đặc hiệu hơn rule trên nên ghi đè được. */
.gym-xref-wrap:hover .gym-xref-box[hidden] { display: flex; }
.gym-xref-head { font-size: .8rem; font-weight: 600; color: var(--text); }
.gym-xref-tag { font-size: .75rem; color: var(--dim); }
.gym-xref-go { font-size: .78rem; font-weight: 600; color: #6366F1; text-decoration: none;
  align-self: flex-start; min-height: 44px; display: flex; align-items: center; }
@media (hover: none) { .gym-xref-wrap:hover .gym-xref-box[hidden] { display: none; } }

/* ── Phân cấp theo trình độ + gợi ý (scaffolding) ────────────────────── */
.gym-lv { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin: 0 0 12px; }
/* ── HUD R3 §1.1b (19/09) — quét lại cột phụ theo yêu cầu chủ app ──────
   "Panel bên trái UXUI element (button, rounded box) nhìn hơi out of place
   so với phần còn lại → sweep kĩ và đảm bảo tất cả các UXUI elements
   (button, box, noti…) đều chung 1 style, theme và design."

   Ba lớp .gym-lv-tag/.gym-lv-sub/.gym-lv-btn đã bị GỠ, không phải sửa:
   chúng là bản chép tay của .lg-tag/.lg-tag--muted/.lg-btn trong
   shared/chrome.css (§B2b). Cái khiến chủ app nhìn ra ngay:
     · viên bo 999px cho một cái NÚT, trong khi mọi nút khác của phòng gym
       là hộp bo 11–12px (.gym-drill-btn, .gym-next, .gym-opt);
     · màu hổ phách #F59E0B cho trạng thái bật — không có ở bất cứ đâu
       khác trong app, nên mắt đọc ra "thứ này thuộc app khác".
   Nay hình dạng do bộ chung quyết định, app chỉ khai MÀU một lần ở dưới. */
.gym-toc-item-on { color: var(--text); font-weight: 700; }

/* ── HUD R3 M3/C1 — khung .lg-shell (shared/chrome.css) ───────────────
   .lg-shell-main bọc cột chính (root/.gym-wrap) BÊN TRONG cột 1fr của
   .lg-shell — min-width:0 để grid không ép tràn khi nội dung có từ dài
   không ngắt được (bảng CEFR, mã chuyên đề…). .gym-wrap giữ nguyên
   max-width:720px của nó, chỉ được CĂN GIỮA trong phần dư của cột 1fr —
   không kéo giãn ra hết cột dù màn 1440px (spec C1: "đừng kéo chữ ra
   1200px"). */
.lg-shell-main { min-width: 0; }
/* ══ 19/09 · QA chủ app, việc #10 ══
   "Ở phần Grammar Gym có khoảng trống rất to/ rõ ở giữa right rail panel
    và main zone."
   Đo ở 1225px trước khi sửa: cột chính kết thúc ở x≈815, cột phụ bắt đầu
   ở x≈960 ⇒ 145px trống giữa hai cột, trong khi khe lưới chỉ là 24px.
   Nguyên nhân: .lg-shell được trải tới 1560px (mặc định của utility) trong khi
   .gym-wrap dừng ở 720px và tự căn giữa phần dư — tức cả phần thừa đều biến
   thành lỗ hổng ở giữa. Đây là bản sao soì gương của lỗi đã vá ở Vocab
   Vault ("REVIEW M5" trong vocab/index.css): ở đó cột phụ trái bị bỏ rơi ở
   mép, ở đây cột phụ phải bị đẩy ra mép — cùng một gốc.
   Kẹp khung bằng CHÍNH công thức bề rộng cột phụ của utility.
   ══ 20/09 · QA chủ app vòng #4, việc #1 ══
   "Composition ở các app vẫn còn khác nhau … chẳng hạn Grammar Gym khác các
    app khác." Đúng: công thức dưới đây tuy tự-nhất-quán nhưng cho ra trần
   984px, hẹp nhất trong 8 app (rộng nhất 1560px) và cột giữa 720px trong khi
   Draft Doctor 880px. Cùng một học sinh đổi app là cả khối nhảy chỗ.
   Nay CHÍNH công thức này đã lên shared/chrome.css làm hiến chương §8 cho
   mọi app, nên chỗ này chỉ còn việc: KHÔNG khai gì cả. .gym-wrap nhận
   --lg-main-w (880px mặc định) thay cho 720px chép tay ở dòng 8. */

/* Mục lục chuyên đề — cột phụ TRÁI renderHome() (spec C1 §home rail #2).
   Gọn hơn hẳn .gym-card (không mô tả, không "cần trước") vì đây là
   ĐIỀU HƯỚNG nhanh, nội dung đầy đủ vẫn ở .gym-tree cột chính — hai chỗ
   đọc CÙNG MỘT nguồn GymCore.MODULES/learnTally(), không chép tay lần hai. */
/* .gym-toc* đã nhường chỗ cho .lg-pick/.lg-pick-item/.lg-note (xem trên).
   Dấu ✓/▸/· giữ màu nhấn của app thay vì màu chữ mờ mặc định — đây là
   thông tin (đã xong / đang học dở), không phải trang trí. */
.lg-rail .lg-pick-ic { color: var(--lg-accent); }

/* 23/09 (QA mobile) — dưới 1024px cột phụ xếp chồng với cột giữa, nhưng
   khung #gymRoot > .lg-shell KHÔNG có lề (lề 16px nằm trong .gym-wrap của cột
   giữa) ⇒ thẻ cột phụ dính sát mép màn, bo góc bị cắt (đo 390px: L=0/R=375,
   thẻ cột giữa L=16). Cho khối cột phụ đúng lề của .gym-wrap. Viết mobile-first,
   trả lại ở ≥1024 (hiến chương mốc §1.3 — không dùng max-width). */
/* 24/09 (QA mobile) — rule trên đã THÔI: từ nay khung đệm 16px ở MỌI bề ngang
   (shared/chrome.css, --lg-shell-pad) nên cột phụ tự có lề. */
/* 24/09 — trong khung, mép và đỉnh cột giữa do hiến chương (--lg-shell-top,
   --lg-shell-pad) ở MỌI bề ngang. Đệm 20px/16px của .gym-wrap cộng thêm vào
   đó làm tiêu đề thụt 16px và thấp hơn app khác (đo 1280px: 20px; 390px: tiêu
   đề x=32 khi các app khác x=16). */
#gymRoot > .lg-shell .gym-wrap { padding-top: 0; padding-left: 0; padding-right: 0; }
/* .gym-wrap nhường hộp ở màn chọn chuyên đề (<1024px) ⇒ đệm đáy của nó
   (chỗ trống cuối trang) chuyển sang khung. */
@media (max-width: 1023.98px) {
  #gymRoot > .lg-shell:has(.gym-wrap.lg-lift) { padding-bottom: calc(48px + env(safe-area-inset-bottom)); }
}

.gym-hint { margin: 10px 0 0; }
.gym-hint-btn { font: inherit; font-size: .8rem; cursor: pointer; padding: 8px 12px; min-height: 44px;
  border-radius: 10px; border: 1px dashed var(--border); background: transparent; color: var(--dim); }
.gym-hint-btn:hover:not(:disabled) { border-color: #F59E0B; color: var(--text); }
.gym-hint-btn:disabled { opacity: .5; cursor: default; }
.gym-hint-step { margin: 8px 0 0; font-size: .82rem; line-height: 1.65; color: var(--text);
  background: rgba(245,158,11,.1); border-left: 3px solid #F59E0B; border-radius: 0 8px 8px 0; padding: 9px 12px; }

/* ── BTVN Grammar Gym (grammar_assignments) — banner màn chuyên đề + chip ── */
.gym-hw { margin: 0 0 18px; }
.gym-hw-head { font-size: .8rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: #10B981; margin-bottom: 8px; }
.gym-hw-note { font-size: .82rem; color: var(--dim); border: 1px dashed var(--border); border-radius: 10px; padding: 8px 12px; margin-bottom: 8px; }
.gym-hw-card { border: 1px solid var(--border); border-radius: 12px; background: var(--surf); padding: 12px 14px; margin-bottom: 8px; }
.gym-hw-overdue { border-color: #F59E0B; }
.gym-hw-done { opacity: .75; }
.gym-hw-top { display: flex; gap: 8px; align-items: baseline; flex-wrap: wrap; font-size: .92rem; color: var(--text); }
.gym-hw-due { margin-left: auto; font-size: .74rem; color: var(--dim); }
.gym-hw-overdue .gym-hw-due { color: var(--yellow); } /* 26/09: #F59E0B chữ trên nền sáng ~2,1:1 < AA; --yellow lật theo theme (#8A5A00 sáng / #E9B04A tối) */
.gym-hw-row { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
.gym-hw-bar { flex: 1; height: 8px; background: rgba(127,127,127,.18); border-radius: 99px; overflow: hidden; }
.gym-hw-fill { height: 100%; background: #10B981; border-radius: 99px; }
.gym-hw-num { font-size: .74rem; color: var(--dim); white-space: nowrap; }
.gym-hw-instr { font-size: .78rem; color: var(--dim); margin-top: 6px; }
.gym-hw-acc { font-size: .76rem; color: var(--text); margin-top: 4px; }
.gym-hw-hint { font-size: .78rem; color: var(--text); margin-top: 6px; padding-top: 6px; border-top: 1px dashed rgba(16,185,129,.4); }
.gym-hw-mods { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.gym-hw-mod { font: inherit; font-size: .78rem; color: var(--text); background: transparent; border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; min-height: 36px; cursor: pointer; }
.gym-hw-mod:hover { border-color: #10B981; }
.gym-hw-mod-done { color: #10B981; border-color: rgba(16,185,129,.5); }
.gym-hw-chip { font-size: .8rem; color: var(--text); background: rgba(16,185,129,.1); border: 1px solid rgba(16,185,129,.4); border-radius: 10px; padding: 8px 12px; margin: 0 0 12px; }

/* ── B1 v2: lý thuyết kiểu SLIDE (grammar/theory/mN.json) ───────────────
   Deck = nav (chấm tiến độ + nút Tóm tắt) + 1 slide đang xem. Mỗi slide:
   kicker/số ý → tiêu đề to → 1–4 dòng ngắn có nhấn → ví dụ tô cụm → bẫy →
   quiz → chân slide. Dùng lại gym-opt*/gym-feedback*/gym-q-prompt của
   drill để lý thuyết và bài tập trông như MỘT hệ thống.
   Mực: các khối màu chỉ là nền mờ (alpha) trên nền theme, nên chữ dùng
   var(--text) là an toàn ở cả sáng lẫn tối. */
.gym-deck { border: 1px solid var(--border); border-radius: 14px; background: var(--surf); overflow: hidden; }
.gym-deck-nav { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 14px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.gym-dots { display: flex; gap: 6px; flex-wrap: wrap; }
.gym-dot { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--border); background: transparent;
  cursor: pointer; padding: 0; }
.gym-dot-why { border-radius: 6px; }
.gym-dot-done { background: #10B981; border-color: #10B981; }
.gym-dot-cur { border-color: #10B981; box-shadow: 0 0 0 3px rgba(16,185,129,.25); }
.gym-dot-lock { opacity: .35; cursor: default; }
.gym-sum-btn { font: inherit; font-size: .78rem; font-weight: 600; color: var(--text); background: transparent;
  border: 1px solid var(--border); border-radius: 999px; padding: 6px 12px; min-height: 36px; cursor: pointer; }
.gym-sum-btn-on, .gym-sum-btn:hover { border-color: #10B981; color: #10B981; }

.gym-slide { padding: 18px 16px 16px; }
@media (min-width: 640px) { .gym-slide { padding: 24px 26px 20px; } }
.gym-slide-kicker { font-size: .72rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: #10B981; margin-bottom: 8px; }
.gym-slide-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.gym-slide-num { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: #10B981; }
.gym-slide-sec { font-size: .74rem; color: var(--dim); }
.gym-slide-title { font-size: 1.25rem; font-weight: 700; line-height: 1.3; color: var(--text); margin: 0 0 14px; }
@media (min-width: 640px) { .gym-slide-title { font-size: 1.45rem; } }

.gym-lines { list-style: none; margin: 0 0 14px; padding: 0; display: grid; gap: 8px; }
.gym-line { position: relative; padding: 9px 12px 9px 34px; font-size: .9rem; line-height: 1.6; color: var(--text);
  background: rgba(16,185,129,.06); border-radius: 10px; }
.gym-line::before { content: '▸'; position: absolute; left: 13px; top: 8px; color: #10B981; font-weight: 700; }
.gym-line strong { color: var(--text); font-weight: 700; }
.gym-line em { font-style: italic; color: var(--dim); }
.gym-code { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: .85em; background: rgba(127,127,127,.15);
  padding: 1px 5px; border-radius: 4px; }

.gym-why-list { display: grid; gap: 10px; margin: 0 0 16px; }
.gym-why-item { border-left: 3px solid #10B981; background: rgba(16,185,129,.08); border-radius: 0 10px 10px 0;
  padding: 10px 14px; }
.gym-why-head { font-weight: 700; font-size: .92rem; color: var(--text); margin-bottom: 3px; }
.gym-why-body { font-size: .86rem; color: var(--text); line-height: 1.65; }

.gym-pt-ex { border-left: 3px solid #10B981; background: rgba(16,185,129,.06); border-radius: 0 10px 10px 0;
  padding: 10px 14px; margin: 0 0 10px; }
.gym-pt-ex-label { font-size: .7rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: #10B981; margin-bottom: 4px; }
.gym-pt-ex-en { font-size: .95rem; color: var(--text); line-height: 1.6; margin: 0 0 4px; }
.gym-pt-ex-vi { font-size: .78rem; color: var(--dim); line-height: 1.5; margin: 0; }
.gym-hl { background: rgba(16,185,129,.22); color: inherit; border-radius: 4px; padding: 1px 3px; font-weight: 600; }

.gym-pt-trap { background: rgba(245,158,11,.1); border-left: 3px solid #F59E0B; border-radius: 0 10px 10px 0;
  padding: 10px 14px; margin: 0 0 14px; }
.gym-pt-trap-label { font-size: .72rem; font-weight: 700; color: var(--yellow); margin-bottom: 3px; }
.gym-pt-trap-body { font-size: .82rem; color: var(--text); line-height: 1.6; margin: 0; }

.gym-pt-quiz { margin-top: 6px; padding-top: 12px; border-top: 1px dashed var(--border); }
.gym-pt-quiz-label { font-size: .72rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--dim); margin-bottom: 8px; }
.gym-pt-quiz .gym-opt-text { font-size: .87rem; }
.gym-pt-quiz-done { font-size: .82rem; font-weight: 600; color: #10B981; }

.gym-slide-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 16px; }
.gym-prev, .gym-pt-skip { font: inherit; font-size: .8rem; color: var(--dim); background: transparent;
  border: 1px dashed var(--border); border-radius: 10px; padding: 8px 12px; min-height: 44px; cursor: pointer; }
.gym-prev:hover, .gym-pt-skip:hover { color: var(--text); border-color: var(--dim); }
.gym-next { font: inherit; font-size: .88rem; font-weight: 700; color: #fff; background: #10B981; border: none;
  border-radius: 10px; padding: 10px 16px; min-height: 44px; cursor: pointer; margin-top: 12px; }
.gym-next:hover { filter: brightness(1.08); }
.gym-slide-foot .gym-next { margin-top: 0; }

.gym-sum-intro { font-size: .86rem; color: var(--text); line-height: 1.65; margin: 0 0 12px; }
.gym-sum-scroll { overflow-x: auto; margin: 0 0 14px; }
.gym-sum-table { border-collapse: collapse; width: 100%; font-size: .82rem; line-height: 1.5; }
.gym-sum-table th, .gym-sum-table td { border: 1px solid var(--border); padding: 8px 10px; text-align: left;
  vertical-align: top; color: var(--text); }
.gym-sum-table thead th { background: rgba(16,185,129,.12); font-weight: 700; }
.gym-sum-table tbody th { background: rgba(127,127,127,.08); font-weight: 700; white-space: nowrap; }
.gym-sum-flow { display: grid; gap: 8px; margin: 0 0 12px; }
.gym-sum-step { display: flex; gap: 12px; align-items: flex-start; border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px; position: relative; }
.gym-sum-step + .gym-sum-step::before { content: '↓'; position: absolute; top: -14px; left: 16px; color: #10B981;
  font-size: .8rem; font-weight: 700; }
.gym-sum-step-n { flex: 0 0 26px; width: 26px; height: 26px; border-radius: 50%; background: #10B981; color: #fff;
  font-weight: 700; font-size: .8rem; display: flex; align-items: center; justify-content: center; }
.gym-sum-step-h { font-weight: 700; font-size: .88rem; color: var(--text); }
.gym-sum-step-b { font-size: .8rem; color: var(--dim); line-height: 1.55; margin-top: 2px; }
.gym-sum-prog { font-size: .78rem; color: var(--dim); margin: 0; }

/* Kho câu hỏi mỗi ý (v3): sai thì ra câu khác cùng ý. */
.gym-q + .gym-q { margin-top: 14px; padding-top: 14px; border-top: 1px dashed var(--border); }
.gym-q-again { font-size: .76rem; font-weight: 700; color: var(--yellow); margin-bottom: 6px; }
.gym-q-exhausted { margin-top: 10px; font-size: .8rem; color: var(--dim); }
.gym-retry { font: inherit; font-size: .85rem; font-weight: 700; color: var(--bg); background: var(--yellow); border: none;
  border-radius: 10px; padding: 10px 16px; min-height: 44px; cursor: pointer; margin-top: 12px; }
.gym-retry:hover { filter: brightness(1.08); }

/* ── Hai chế độ Học / Ôn (yêu cầu chủ app 02/09 #6) ─────────────────────
   "Ôn" khoá tới khi học hết lý thuyết — nút vẫn HIỆN kèm lý do, không ẩn:
   ẩn đi thì người học không biết là có phần đó. */
.gym-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 0 0 16px; }
.gym-mode { display: flex; flex-direction: column; gap: 3px; align-items: flex-start; text-align: left;
  font: inherit; color: var(--text); background: var(--surf); border: 1px solid var(--border);
  border-radius: 12px; padding: 12px 14px; min-height: 60px; cursor: pointer; }
.gym-mode:hover:not(:disabled) { border-color: #10B981; }
.gym-mode-on { border-color: #10B981; background: rgba(16,185,129,.08); }
.gym-mode-locked { opacity: .55; cursor: default; }
.gym-mode-t { font-weight: 700; font-size: .95rem; }
.gym-mode-s { font-size: .74rem; color: var(--dim); line-height: 1.45; }
.gym-card-stat { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.gym-card-learn { font-size: .74rem; color: var(--dim); }
.gym-card-learn-done { color: #10B981; font-weight: 600; }
.gym-card-drill { font-size: .74rem; color: var(--dim); }

/* ── Sơ đồ cụm danh từ trong slide lý thuyết (point.diagram kind:'np-map') ──
   Trục ngang: TRƯỚC danh từ chính → LÕI → SAU danh từ chính, đọc đúng thứ tự
   từ trong câu. Ở màn hẹp ba nhóm xuống dòng thành ba hàng, vẫn giữ thứ tự.
   Mọi màu lấy từ token theme.css nên tự lật theo sáng/tối — không đặt màu cứng,
   và luôn ghi CẢ background LẪN color để không bao giờ có chữ trên nền trống. */
.gym-npmap {
  margin: 12px 0 14px; padding: 12px;
  background: var(--surf2); border: 1px solid var(--border); border-radius: var(--r2);
}
.gym-npmap-band { display: flex; flex-wrap: wrap; align-items: stretch; gap: 10px; }
/* KHÔNG cho nhóm giãn: để giãn thì nhóm "trước" chiếm hết bề ngang và đẩy ô
   danh từ chính tách hẳn sang phải, mất luôn mạch trước → lõi → sau. */
.gym-npmap-group { display: flex; flex-direction: column; gap: 6px; min-width: 0; flex: 0 1 auto; }
.gym-npmap-core { flex: 0 0 auto; }
.gym-npmap-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: stretch; }
.gym-npmap-chip {
  display: flex; flex-direction: column; gap: 2px;
  padding: 6px 9px; border-radius: 8px; min-width: 0;
  background: var(--surf); border: 1px solid var(--border); color: var(--text);
}
.gym-npmap-label {
  font-size: 10px; line-height: 1.25; letter-spacing: .02em;
  text-transform: uppercase; color: var(--dim); overflow-wrap: anywhere;
}
.gym-npmap-text { font-size: 14px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
.gym-npmap-caption {
  font-size: 10px; letter-spacing: .04em; color: var(--dim); text-align: center;
}
.gym-npmap-corechip {
  border-width: 2px; border-color: var(--coral); background: var(--surf);
}
.gym-npmap-corechip .gym-npmap-text { font-size: 16px; color: var(--coral); }
.gym-npmap-vi, .gym-ladder-vi {
  margin-top: 10px; padding-top: 9px; border-top: 1px dashed var(--border);
  font-size: 13px; font-style: italic; color: var(--dim);
}

/* ── Bảng đối chiếu (point.diagram kind="ladder") ──
   Lưới N+1 cột: cột đầu là tên hàng, còn lại là các cột dữ liệu.
   grid-template-columns do app.js đặt vì số cột nằm trong dữ liệu. */
.gym-ladder {
  margin: 12px 0 14px; padding: 12px;
  background: var(--surf2); border: 1px solid var(--border); border-radius: var(--r2);
}
.gym-ladder-grid { display: grid; gap: 6px; align-items: stretch; }
.gym-ladder-colhead, .gym-ladder-rownote, .gym-ladder-sub {
  font-size: 10px; line-height: 1.3; letter-spacing: .02em; color: var(--dim);
  overflow-wrap: anywhere;
}
.gym-ladder-colhead {
  text-transform: uppercase; text-align: center; align-self: end; padding: 0 4px 2px;
}
.gym-ladder-rowhead {
  display: flex; flex-direction: column; gap: 2px; justify-content: center;
  padding: 6px 9px 6px 0; min-width: 0;
}
.gym-ladder-rowname { font-size: 13px; font-weight: 700; color: var(--text); overflow-wrap: anywhere; }
.gym-ladder-cell {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
  padding: 6px 9px; border-radius: 8px;
  background: var(--surf); border: 1px solid var(--border); color: var(--text);
}
.gym-ladder-text { font-size: 14px; font-weight: 600; color: var(--text); overflow-wrap: anywhere; }
/* Nhãn cột nhắc lại trong từng ô: CHỈ dùng ở màn hẹp, nơi hàng tiêu đề bị ẩn. */
.gym-ladder-cell::before { content: none; }

/* ── Màu viền theo vai của ô ──
   ⚠️ KHỐI NÀY PHẢI NẰM SAU mọi luật nền của ô (.gym-npmap-chip,
   .gym-ladder-cell). Hai luật đó dùng `border:` viết tắt, mà viết tắt đặt lại
   cả border-color — nên luật nền đứng SAU sẽ xoá sạch màu tone, lặng lẽ, và
   không test nào biết. Đã mắc đúng lỗi này với bảng đối chiếu 16/09/2026:
   validator xanh (luật .gym-tone-yes có thật trong file) mà trên màn hình ô
   "Được" và ô "Không bao giờ" ra y hệt một màu.
   validate.test.mjs nay canh thứ tự này. */
/* Mỗi loại thành phần một màu viền, dùng lại đúng bảng màu của theme. */
.gym-tone-quant { border-color: var(--green); }
.gym-tone-adv   { border-color: var(--teal); }
.gym-tone-adj   { border-color: var(--accent); }
.gym-tone-nmod  { border-color: var(--yellow); }
.gym-tone-prep  { border-color: var(--teal); border-style: dashed; }
.gym-tone-rel   { border-color: var(--accent); border-style: dashed; }
/* SCHEMA.md khai "core" là một tone hợp lệ nhưng trước nay CSS không có luật
   nào cho nó — ô lõi vẫn đúng màu chỉ nhờ .gym-npmap-corechip, nên đặt
   tone:"core" cho một ô pre/post sẽ ra ô KHÔNG MÀU mà build vẫn xanh. */
.gym-tone-core  { border-color: var(--coral); }
/* Hai tone dưới đây dành cho bảng đối chiếu: ô "được phép" và ô "cấm".
   Bảng màu giữ nguyên của theme nên vẫn lật đúng theo sáng/tối. */
.gym-tone-yes   { border-color: var(--green); }
.gym-tone-no    { border-color: var(--coral); }

@media (max-width: 560px) {
  .gym-npmap-band { flex-direction: column; }
  .gym-npmap-caption { text-align: left; }
}

@media (max-width: 640px) {
  /* Lưới ngang không đọc được ở bề ngang điện thoại: đổ mỗi hàng thành một
     khối dọc. Hàng tiêu đề mất đi nên từng ô tự in lại tên cột của nó. */
  .gym-ladder-grid { display: block; }
  .gym-ladder-corner, .gym-ladder-colhead { display: none; }
  .gym-ladder-rowhead { padding: 10px 0 4px; }
  .gym-ladder-rowhead-first { padding-top: 0; }
  .gym-ladder-cell { margin-bottom: 6px; }
  .gym-ladder-cell::before {
    content: attr(data-col);
    display: block; font-size: 10px; letter-spacing: .02em;
    text-transform: uppercase; color: var(--dim); overflow-wrap: anywhere;
  }
}

/* ── Nhãn "Mở rộng" cho ý ở bậc stage:'extend' (nội dung phụ, tuỳ chọn) ──
   Ý mở rộng không tính vào % hoàn thành và không khoá đường đi của người học,
   nên phải NHÌN là biết ngay nó không bắt buộc. */
.gym-ext-tag { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 2px 0 8px; }
.gym-ext-chip {
  flex: 0 0 auto; padding: 2px 9px; border-radius: 999px;
  background: var(--surf2); border: 1px dashed var(--dim); color: var(--dim);
  font-size: 11px; font-weight: 700; letter-spacing: .03em;
}
.gym-ext-note { font-size: 12px; color: var(--dim); }
.gym-dot-ext { border-style: dashed; }

/* ══ §R32 (QA#5 việc #8, chốt Đ4) — danh sách dạng câu hỏi trong cột phụ ══
   Nút drill vốn vẽ cho cột giữa 880px: tiêu đề + một câu mô tả dài. Trong
   cột phụ 288px thì câu mô tả đó là thứ làm cột phụ vượt ngân sách chiều
   cao (§R11). Kẹp còn 2 dòng — chữ đầy đủ vẫn còn trong DOM nên bộ đọc màn
   hình và tooltip của trình duyệt vẫn đọc được. */
.gym-drills--rail { display: flex; flex-direction: column; gap: 6px; }
.gym-drills--rail .gym-drill-btn { width: 100%; padding: 9px 11px; text-align: left; }
.gym-drills--rail .gym-drill-title { font-size: .84rem; }
.gym-drills--rail .gym-drill-desc {
  font-size: .72rem; line-height: 1.45;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.gym-drills--rail .gym-drill-sep { margin-top: 8px; font-size: .72rem; }

/* Hướng dẫn BTVN (24/09): trạng thái còn thiếu + luật tính câu */
.gym-hw-status { font-size: .8rem; color: var(--text); margin-top: 8px; font-weight: 600; }
.gym-hw-status-done { color: #10B981; }
.gym-hw-rules { margin-top: 8px; font-size: .78rem; color: var(--text); border: 1px dashed rgba(16,185,129,.45); border-radius: 10px; padding: 6px 10px; }
.gym-hw-rules summary { cursor: pointer; font-weight: 600; color: #10B981; min-height: 28px; display: flex; align-items: center; }
.gym-hw-rules-list { list-style: none; margin: 6px 0 2px; padding: 0; display: grid; gap: 6px; }
.gym-hw-rules-list li { display: flex; gap: 8px; line-height: 1.45; }
.gym-hw-rules-ico { flex: 0 0 auto; }
