/* education-ai — two grounds, one meaning.
 *
 * 纸 (light, default) is the ground a student and a parent actually read on;
 * 夜 (dark) is for late revision. They are the SAME design: only the eleven
 * tokens below change, and every surface is built from them, so nothing has to
 * be restyled twice.
 *
 * The invariant survives the repaint: colour encodes grammatical function and
 * never anything else. The function hues keep their identity and their even
 * hue spacing across both themes — they are deepened for paper and lifted for
 * night so each clears 4.5:1 on its own ground, which scripts/validate.py now
 * computes rather than trusting.
 */

:root {
  /* ── 纸 · paper, warm and low-glare ─────────────────────────────────── */
  --bg:        #FAF7F2;
  --bg-raised: #FFFDFA;
  --rule:      #E7E2D9;
  --surface-2: #F4F1EB;   /* hover / inset */
  --surface-3: #EBE7DE;   /* active         */

  --core:      #2C313C;   /* 主干 main clause  */
  --text:      #454C5A;   /* body copy         */
  --text-2:    #646B79;   /* secondary copy    */
  --muted:     #626976;   /* labels, meta      */

  /* Function colours, matched lightness, even hue spacing, so no clause
     shouts over another. Colour means grammar here and nothing else. */
  --attributive: #0F7695;  /* 定语从句   azure  */
  --nominal:     #6A4BB8;  /* 名词性从句 violet */
  --adverbial:   #1B7A54;  /* 状语从句   mint   */
  --nonfinite:   #96620C;  /* 非谓语     amber  */
  --parenthesis: #666D7B;  /* 插入语            */
  --link:        #8F6407;  /* 指代箭头 · 依据高亮 */
  --wrong:       #BE3B58;  /* 错误选项   rose   */
  --right:       #3A752E;  /* 对了       leaf — feedback, NOT 状语从句 */

  /* Tints — the same hues at low alpha, so a highlight is the colour it
     means rather than a fourth grey invented for the purpose. */
  --tint-link:  rgba(143, 100,  7, .12);
  --tint-ok:    rgba( 58, 117, 46, .10);
  --tint-wrong: rgba(190,  59, 88, .09);
  --select:     rgba( 15, 118, 149, .16);
  --rule-faint: rgba( 44,  49, 60, .055);   /* the 作业本 line rhythm */
  --lift:       0 1px 2px rgba(44, 49, 60, .04), 0 6px 18px rgba(44, 49, 60, .045);


  /* ── chrome ────────────────────────────────────────────────────────────
     A second, separate colour family, and the rule that keeps it from
     colliding with the first:

         FUNCTION colours only ever colour TEXT.
         CHROME colours only ever colour SURFACES — washes, bars, borders.

     A colour never crosses that line. So a sage panel behind a sentence can
     never be misread as a claim about that sentence's grammar, and the four
     function hues keep sole ownership of coloured type. Every wash below is
     checked by validate.py as a ground in its own right. */
  --accent:      #9C5436;   /* clay — interactive chrome, one voice only */
  --accent-soft: rgba(156, 84, 54, .10);

  --wash-1: #F8EFE9;  --bar-1: #B87A5F;   /* clay  */
  --wash-2: #EDF3EA;  --bar-2: #75946E;   /* sage  */
  --wash-3: #EAF0F6;  --bar-3: #7290A9;   /* blue  */
  --wash-4: #F9F1E2;  --bar-4: #A6833F;   /* ochre */
  --wash-5: #F4EEF4;  --bar-5: #9C7D98;   /* plum  */
  --wash-6: #E9F2F1;  --bar-6: #65948E;   /* teal  */

  --serif: "Iowan Old Style", Charter, Georgia, "Songti SC", serif;
  --sans:  "PingFang SC", "Hiragino Sans GB", -apple-system, "Segoe UI", sans-serif;
  --mono:  ui-monospace, "SF Mono", Menlo, monospace;

  --ease: cubic-bezier(.34, .01, .2, 1);
  --dur:  480ms;
  --r:    5px;              /* one radius everywhere. Soft, never a pill. */
}

/* ── 夜 · night, milder than the old near-black ────────────────────────── */
:root[data-theme="dark"] {
  --bg:        #171A21;
  --bg-raised: #1E222B;
  --rule:      #2C323E;
  --surface-2: #232833;
  --surface-3: #2A303C;

  --core:      #EDEFF4;
  --text:      #C9CFDA;
  --text-2:    #A2AAB8;
  --muted:     #848C9B;

  --attributive: #6FCFEA;
  --nominal:     #B69AF5;
  --adverbial:   #7BD9AE;
  --nonfinite:   #F0C078;
  --parenthesis: #8B94A6;
  --link:        #F2D493;
  --wrong:       #F28FA6;
  --right:       #96D479;

  --tint-link:  rgba(242, 212, 147, .15);
  --tint-ok:    rgba(150, 212, 121, .12);
  --tint-wrong: rgba(242, 143, 166, .12);
  --select:     rgba(111, 207, 234, .24);
  --rule-faint: rgba(237, 239, 244, .05);
  --lift:       none;       /* on a dark ground, lift reads as smudge */

  --accent:      #E0A184;
  --accent-soft: rgba(224, 161, 132, .13);

  --wash-1: #251E1B;  --bar-1: #B8846A;
  --wash-2: #182219;  --bar-2: #7FA87C;
  --wash-3: #171F29;  --bar-3: #7E9EBE;
  --wash-4: #241E14;  --bar-4: #C0A05F;
  --wash-5: #211B22;  --bar-5: #A98CA5;
  --wash-6: #152220;  --bar-6: #6FA9A2;

}

::selection { background: var(--select); color: var(--core); }

/* ── 字号 ─────────────────────────────────────────────────────────────────
 * Every font-size in this file is rem, so this one declaration scales the
 * entire interface as a system — nothing is left behind at its old size, and
 * ratios between heading, body and label are preserved rather than flattened.
 *
 * Default is 大 (18.5px), not the browser's 16px: the readers are a
 * thirteen-year-old and a parent reading a report, and the old 11px mono
 * labels were too small for either. Nothing anywhere is below 13px now.
 *
 * Browser zoom and OS text settings still work on top of this, because the
 * units are relative — which is the actual reason to do it this way rather
 * than by hand-raising a hundred pixel values.
 */
html                    { font-size: 18.5px; }
html[data-size="s"]     { font-size: 16px; }
html[data-size="m"]     { font-size: 18.5px; }
html[data-size="l"]     { font-size: 21px; }
html[data-size="xl"]    { font-size: 23.5px; }

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--bg);
  color: var(--core);
  font-family: var(--sans);
  line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}

.wrap { max-width: 940px; margin: 0 auto; padding: 56px 24px 96px; }

.eyebrow {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .18em;
  text-transform: uppercase; color: var(--muted);
}

h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(1.875rem, 4.6vw, 2.75rem); line-height: 1.2;
  letter-spacing: -.01em; margin: 14px 0 16px; max-width: 22ch;
}

.lede { max-width: 58ch; color: var(--text); font-size: 1.0625rem; }

/* ─── the visualiser ─────────────────────────────────────────────────────── */

.viz {
  margin: 48px 0 0; padding: 32px 28px 24px;
  background: var(--bg-raised); border: 1px solid var(--rule);
}

.viz-topic {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 22px;
}

.stage { position: relative; }

#arcs {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; overflow: visible;
}

.sentence {
  font-family: var(--serif); font-size: clamp(1.25rem, 2.9vw, 1.6875rem);
  line-height: 2.15; letter-spacing: .002em;
  padding-top: 46px;  /* headroom for the arcs */
  /* Faint rules on the sentence's own line rhythm — a workbook under lamplight. */
  background-image: linear-gradient(to bottom,
      transparent calc(2.15em - 1px), var(--rule-faint) calc(2.15em - 1px));
  background-size: 100% 2.15em;
  background-origin: content-box;
  background-clip: content-box;
}

.tok {
  display: inline-block; white-space: nowrap; overflow: hidden;
  max-width: 22em; vertical-align: baseline;
  color: var(--core); opacity: 1;
  transition: max-width var(--dur) var(--ease),
              opacity   var(--dur) var(--ease),
              color     var(--dur) var(--ease),
              margin    var(--dur) var(--ease);
}
.tok::after { content: "\00a0"; }
.tok.punct { margin-left: -.28em; }

.tok.folded { max-width: 0; opacity: 0; margin: 0; }
.tok.dim    { opacity: .26; }

.tok.attributive { color: var(--attributive); }
.tok.nominal     { color: var(--nominal); }
.tok.adverbial   { color: var(--adverbial); }
.tok.nonfinite   { color: var(--nonfinite); }
.tok.parenthesis { color: var(--parenthesis); }

.tok.connector { text-decoration: underline; text-underline-offset: .28em;
                 text-decoration-thickness: 1.5px; }
.tok.head      { box-shadow: inset 0 -2px 0 var(--link); }

.chip {
  display: inline-block; white-space: nowrap; overflow: hidden;
  font-family: var(--sans); font-size: .5em; letter-spacing: .04em;
  padding: .28em .7em; margin-right: .34em;
  border: 1px dashed currentColor; border-radius: 2px;
  max-width: 16em; opacity: 1; vertical-align: middle;
  transition: max-width var(--dur) var(--ease),
              opacity   var(--dur) var(--ease),
              padding   var(--dur) var(--ease),
              margin    var(--dur) var(--ease);
}
.chip.hidden { max-width: 0; opacity: 0; padding-left: 0; padding-right: 0; margin: 0; border-width: 0; }
.chip.attributive { color: var(--attributive); }
.chip.nominal     { color: var(--nominal); }
.chip.adverbial   { color: var(--adverbial); }
.chip.nonfinite   { color: var(--nonfinite); }
.chip.parenthesis { color: var(--parenthesis); }

/* ─── caption, card, controls ────────────────────────────────────────────── */

.caption {
  margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--rule);
  font-size: 1rem; color: var(--text); min-height: 3.4em;
}

.card {
  margin-top: 16px; padding: 16px 18px;
  border-left: 2px solid var(--link); background: var(--surface-2);
  max-height: 40em; overflow: hidden;
  transition: max-height 380ms var(--ease), opacity 300ms var(--ease),
              padding 380ms var(--ease), margin 380ms var(--ease);
}
.card.hidden { max-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0; margin-top: 0; }
.card .rewrite {
  font-family: var(--serif); font-size: 1.1875rem; color: var(--core); margin-bottom: 8px;
}
.card .why { font-size: 0.9375rem; color: var(--text-2); }

.controls {
  display: flex; align-items: center; gap: 14px; margin-top: 24px; flex-wrap: wrap;
}
button {
  font: inherit; font-size: 0.875rem; color: var(--core);
  background: transparent; border: 1px solid var(--rule);
  padding: 8px 18px; cursor: pointer;
  transition: border-color 160ms, color 160ms;
}
button:hover:not(:disabled) { border-color: var(--core); }
button:disabled { opacity: .32; cursor: default; }
button:focus-visible, a:focus-visible { outline: 2px solid var(--link); outline-offset: 2px; }

.progress { display: flex; gap: 5px; margin-left: auto; }
.pip { width: 22px; height: 3px; background: var(--rule); transition: background 240ms; }
.pip.on { background: var(--core); }

.picker { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
.picker button.active { border-color: var(--core); background: var(--surface-3); }

/* ─── legend & roadmap ───────────────────────────────────────────────────── */

.legend {
  display: flex; flex-wrap: wrap; gap: 18px; margin-top: 22px;
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em; color: var(--muted);
}
.legend span::before {
  content: ""; display: inline-block; width: 18px; height: 2px;
  margin-right: 7px; vertical-align: middle; background: currentColor;
}
.legend .l-core  { color: var(--core); }
.legend .l-attr  { color: var(--attributive); }
.legend .l-nom   { color: var(--nominal); }
.legend .l-adv   { color: var(--adverbial); }
.legend .l-nonf  { color: var(--nonfinite); }

.roadmap { margin-top: 72px; border-top: 1px solid var(--rule); padding-top: 28px; }
.roadmap h2 { font-family: var(--serif); font-weight: 400; font-size: 1.5rem; margin-bottom: 18px; }
.roadmap ol { list-style: none; counter-reset: r; }
.roadmap li {
  counter-increment: r; padding: 12px 0 12px 44px; position: relative;
  border-bottom: 1px solid var(--rule); font-size: 0.9375rem; color: var(--text);
}
.roadmap li::before {
  content: counter(r, decimal-leading-zero); position: absolute; left: 0;
  font-family: var(--mono); font-size: 0.8125rem; color: var(--muted);
}
.roadmap strong { color: var(--core); font-weight: 500; }

footer {
  margin-top: 64px; font-family: var(--mono); font-size: 0.8125rem;
  letter-spacing: .08em; color: var(--muted);
}

@media (max-width: 560px) {
  .wrap { padding: 36px 18px 72px; }
  .viz { padding: 22px 18px 18px; }
  .sentence { line-height: 2.3; }
  .progress { margin-left: 0; width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 1ms !important; }
}

/* ─── shell: masthead, tabs, panels ──────────────────────────────────────── */

.masthead { margin-bottom: 30px; }
.masthead h1 { margin-bottom: 0; }

.tabs { display: flex; gap: 0; border-bottom: 1px solid var(--rule); margin-bottom: 30px; }
.tab {
  border: none; border-bottom: 2px solid transparent; background: none;
  padding: 11px 20px 12px; font-size: 0.9375rem; color: var(--muted);
  transition: color 160ms, border-color 160ms;
}
.tab:hover { color: var(--core); }
.tab.on { color: var(--core); border-bottom-color: var(--accent); }

.panel { display: none; }
.panel.on { display: block; }

.empty { color: var(--muted); font-size: 0.875rem; padding: 10px 0; }
.hint  { color: var(--muted); font-size: 0.8125rem; margin-top: 22px; }
.note  { color: var(--muted); font-size: 0.8125rem; margin: 6px 0 12px; }

/* ─── 试卷 ───────────────────────────────────────────────────────────────── */

.papers { display: flex; flex-direction: column; gap: 22px; }
.paper { border: 1px solid var(--rule); background: var(--bg-raised); }
.paper-head {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--rule);
}
.paper-head h3 { font-family: var(--serif); font-weight: 400; font-size: 1.25rem; }
.paper .note { padding: 0 20px; }
.meta { font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em; color: var(--muted); }

.section-row {
  display: flex; align-items: baseline; gap: 14px; width: 100%;
  padding: 12px 20px; border: none; border-bottom: 1px solid var(--rule);
  background: none; text-align: left; font-size: 0.9375rem; color: var(--text);
}
.section-row:hover { background: var(--surface-2); }
.section-row.on { color: var(--core); background: var(--surface-2); }
.section-row .code {
  font-family: var(--mono); font-size: 0.8125rem; color: var(--muted);
  min-width: 46px; letter-spacing: .06em;
}
.section-row .sname { flex: 1; }

.slots { display: none; padding: 14px 20px 18px; border-bottom: 1px solid var(--rule); }
.slots.on { display: block; }
.slot {
  display: inline-block; min-width: 30px; padding: 4px 0; margin: 0 5px 5px 0;
  font-family: var(--mono); font-size: 0.8125rem; text-align: center;
  color: var(--muted); border: 1px solid var(--rule);
}
.slots .empty { padding-top: 10px; }

/* ─── 练习 ───────────────────────────────────────────────────────────────── */

.practice { display: grid; grid-template-columns: 1.05fr 1fr; gap: 34px; align-items: start; }

.passage {
  font-family: var(--serif); font-size: 1.0625rem; line-height: 1.95;
  color: var(--text); border-left: 1px solid var(--rule); padding-left: 22px;
}
.passage-title {
  font-size: 1.1875rem; font-weight: 400; color: var(--core);
  margin-bottom: 14px; display: block;
}
.sent { transition: background 300ms var(--ease), color 300ms var(--ease); }
.sent.annotated {
  border-bottom: 1px dashed var(--accent); cursor: pointer;
}
.sent.annotated:hover { color: var(--accent); }
.sent.evidence { background: var(--tint-link); color: var(--core);
                 box-shadow: 0 0 0 3px var(--tint-link); }
.licence {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em;
  color: var(--muted); margin-top: 18px;
}

.item-head { display: flex; align-items: baseline; gap: 12px; margin-bottom: 14px; }
.badge {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .08em;
  padding: 3px 9px; border: 1px solid var(--rule); color: var(--muted);
}
.stem { font-size: 1rem; color: var(--core); margin-bottom: 18px; }

.opts { display: flex; flex-direction: column; gap: 9px; }
.opt {
  display: flex; gap: 12px; align-items: baseline; text-align: left;
  padding: 11px 14px; font-size: 0.9375rem; line-height: 1.5;
  transition: border-color 160ms, background 200ms, opacity 200ms;
}
.opt .letter { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.opt .otext { flex: 1; }
.opt:disabled { opacity: 1; }
.opt.correct { border-color: var(--right); background: var(--tint-ok); }
.opt.correct .letter { color: var(--right); }
.opt.wrong { border-color: var(--wrong); background: var(--tint-wrong); }
.opt.wrong .letter { color: var(--wrong); }
.opt.faded { opacity: .38; }

.reveal { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--rule); }
.reveal.hidden { display: none; }
.verdict { font-size: 0.9375rem; color: var(--core); margin-bottom: 14px; }
.why-row {
  display: flex; gap: 11px; align-items: baseline;
  padding: 8px 0; border-top: 1px solid var(--rule); font-size: 0.875rem; color: var(--text-2);
}
.why-row.picked { color: var(--core); }
.why-row .letter { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.why-row .tag {
  font-size: 0.8125rem; padding: 2px 7px; white-space: nowrap;
  border: 1px solid var(--rule); color: var(--accent);
}
.why-row .wtext { flex: 1; }

.mastery { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 30px;
           padding-top: 16px; border-top: 1px solid var(--rule); }
.m-row { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.m-type { margin-right: 7px; font-family: var(--sans); }
.m-num { color: var(--core); }

/* ─── 21 天特训 ──────────────────────────────────────────────────────────── */

.plan-title {
  font-family: var(--serif); font-weight: 400; font-size: 1.5rem; color: var(--core);
  margin-bottom: 10px;
}
.plan-sub {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); font-weight: 400;
  margin: 34px 0 16px; padding-bottom: 10px; border-bottom: 1px solid var(--rule);
}
.plan-stats { display: flex; gap: 20px; flex-wrap: wrap; margin-top: 4px; }
.plan-start { margin-top: 22px; }

/* Twenty-one cells, so the whole run is one glance. State is carried by fill,
   never by hue alone — 漏掉的那天 also loses its border. */
.plan-grid {
  display: grid; grid-template-columns: repeat(21, 1fr); gap: 5px; margin-top: 26px;
}
.day {
  aspect-ratio: 1; display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 0.8125rem;
  border: 1px solid var(--rule); color: var(--muted);
}
.day.future  { opacity: .45; }
.day.done    { background: var(--bar-2); border-color: var(--bar-2); color: var(--bg); }
.day.partial { border-color: var(--bar-4); color: var(--text); }
.day.missed  { border-style: dashed; border-color: var(--wrong); color: var(--wrong); }
.day.today   { border-color: var(--core); color: var(--core); box-shadow: inset 0 -2px 0 var(--link); }

.plan-today { margin-top: 8px; }
.task-row {
  display: grid; grid-template-columns: max-content minmax(6em, 11em) 1fr;
  gap: 14px; align-items: baseline; width: 100%; text-align: left;
  padding: 13px 4px; font-size: 0.875rem; color: var(--text);
  border: none; border-bottom: 1px solid var(--rule);
}
.task-row:hover { background: var(--surface-2); }
.task-row .t-why {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .05em; color: var(--muted);
  white-space: nowrap;
}
.task-row.redo   .t-why { color: var(--wrong); }
.task-row.target .t-why { color: var(--accent); }
.task-row .t-title {
  font-family: var(--serif); color: var(--core);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.task-row .t-stem {
  font-family: var(--serif); color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.plan-analysis { margin-bottom: 10px; }
.weak-row {
  display: grid; grid-template-columns: minmax(5em, 7em) 1fr max-content;
  gap: 14px; align-items: center; padding: 7px 0; font-size: 0.875rem;
}
.weak-row .w-type { color: var(--text); }
.weak-row .w-bar { height: 3px; background: var(--rule); display: block; }
.weak-row .w-fill {
  display: block; height: 100%; background: var(--accent);
  transition: width var(--dur) var(--ease);
}
.plan-analysis .meta { display: block; margin-top: 16px; }

@media (max-width: 760px) {
  .plan-grid { grid-template-columns: repeat(7, 1fr); gap: 6px; }
  .task-row { grid-template-columns: 1fr; row-gap: 5px; }
  .task-row .t-title, .task-row .t-stem { white-space: normal; }
  .weak-row { grid-template-columns: minmax(5em, 6em) 1fr max-content; }
}

/* ─── 学生档案 ───────────────────────────────────────────────────────────── */

.profile-bar {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-top: 16px;
}
.profile-bar strong { font-weight: 500; color: var(--core); font-size: 0.9375rem; }
.profile-bar button { padding: 5px 13px; font-size: 0.8125rem; }

.profile-panel {
  margin-top: 14px; padding: 14px 18px 16px;
  border: 1px solid var(--rule); background: var(--bg-raised);
}
.profile-panel.hidden { display: none; }
.profile-panel .controls { margin-top: 14px; }
.profile-panel .meta { max-width: 40ch; }

.profile-list { display: flex; flex-direction: column; }
.profile-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--rule);
}
.profile-row:last-child { border-bottom: none; }
.profile-row .p-use {
  border: none; padding: 2px 0; font-size: 0.9375rem; color: var(--text); flex: 1; text-align: left;
}
.profile-row.active .p-use { color: var(--core); }
.profile-row.active .p-use::before {
  content: ""; display: inline-block; width: 14px; height: 2px;
  margin-right: 9px; vertical-align: middle; background: var(--accent);
}
.profile-row .p-del {
  border: none; padding: 2px 0; font-size: 0.8125rem; color: var(--muted);
}
.profile-row .p-del:hover { color: var(--wrong); }

/* ─── 错题本 ─────────────────────────────────────────────────────────────── */

.wrongbook { margin-top: 26px; }
#wrongbook-summary { display: block; font-size: 0.8125rem; color: var(--text-2); margin-bottom: 16px; }
#wrongbook-tags { margin-bottom: 24px; }

.wrongbook-list { display: flex; flex-direction: column; gap: 18px; }

.wrong-card {
  border: 1px solid var(--rule); background: var(--bg-raised);
  border-left: 2px solid var(--wrong); padding: 16px 20px 18px;
}
.wrong-head {
  display: flex; align-items: baseline; gap: 11px; flex-wrap: wrap; margin-bottom: 12px;
}
.wrong-head .tag {
  font-size: 0.8125rem; padding: 2px 8px; white-space: nowrap;
  border: 1px solid var(--rule); color: var(--accent);
}
.wrong-card .stem { font-size: 0.9375rem; margin-bottom: 14px; }

.wrong-line {
  display: flex; gap: 12px; align-items: baseline;
  padding: 8px 12px; margin-bottom: 6px; font-size: 0.875rem;
}
.wrong-line .letter { font-family: var(--mono); font-size: 0.8125rem; }
.wrong-line .wtext { flex: 1; font-family: var(--serif); }
.wrong-line.yours { background: var(--tint-wrong); color: var(--text); }
.wrong-line.yours .letter { color: var(--wrong); }
.wrong-line.right { background: var(--tint-ok); color: var(--text); }
.wrong-line.right .letter { color: var(--right); }

.wrong-card .why {
  font-size: 0.875rem; color: var(--text-2); margin: 12px 0 4px; max-width: 60ch;
}
.wrong-card .redo { margin-top: 14px; padding: 6px 14px; font-size: 0.8125rem; }

/* ─── 题库 ───────────────────────────────────────────────────────────────── */

.bank { margin-top: 26px; }

.bank-filters {
  border: 1px solid var(--rule); background: var(--bg-raised);
  padding: 6px 20px 14px;
}
.filter-row {
  display: flex; align-items: baseline; gap: 16px;
  padding-top: 14px; flex-wrap: wrap;
}
.filter-label {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .12em;
  color: var(--muted); min-width: 34px;
}
.picker.inline { margin-bottom: 0; gap: 8px; }
.picker.inline button { padding: 5px 13px; font-size: 0.8125rem; }
.picker.inline .empty { padding: 5px 0; }

#bank-summary { margin-left: auto; }

.bank-results { display: flex; flex-direction: column; margin-top: 24px; }

.bank-row {
  display: grid;
  grid-template-columns: max-content max-content minmax(7em, 12em) 1fr max-content;
  gap: 14px; align-items: baseline; width: 100%; text-align: left;
  padding: 13px 4px; font-size: 0.875rem; color: var(--text);
  border: none; border-bottom: 1px solid var(--rule);
}
.bank-row:first-child { border-top: 1px solid var(--rule); }
.bank-row:hover { background: var(--surface-2); }
.bank-row .badge { font-size: 0.8125rem; }
.bank-row .b-band {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em; color: var(--muted);
}
.bank-row .b-title {
  font-family: var(--serif); color: var(--core);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bank-row .b-stem {
  font-family: var(--serif); color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bank-row .b-status {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em; color: var(--muted);
}
.bank-row .b-status.s-right { color: var(--right); }
.bank-row .b-status.s-wrong { color: var(--wrong); }

@media (max-width: 760px) {
  .bank-row {
    grid-template-columns: max-content max-content 1fr;
    row-gap: 6px;
  }
  .bank-row .b-title { grid-column: 1 / -1; white-space: normal; }
  .bank-row .b-stem  { grid-column: 1 / -1; white-space: normal; }
  .bank-row .b-status { grid-column: 3; justify-self: end; }
  #bank-summary { margin-left: 0; width: 100%; }
}

@media (max-width: 760px) {
  .wrong-line { flex-wrap: wrap; row-gap: 4px; }
  .wrong-line .wtext { flex: 1 1 100%; order: 3; }
  .practice { grid-template-columns: 1fr; gap: 28px; }
  .passage { border-left: none; padding-left: 0; }
  .tabs { overflow-x: auto; }
  .tab { padding: 11px 14px 12px; white-space: nowrap; }
}

/* ═══ 学习方向 · 七上单元 · 能力画像 ═══════════════════════════════════════
   No new hues. Level is encoded as a QUANTITY — how many rungs of the ladder
   are filled — never as a colour, because colour in this product means
   grammatical function and must keep meaning only that. */

.gate.hidden, .tabs.hidden, .tab.hidden { display: none; }

/* ── the chooser ─────────────────────────────────────────────────────────── */

.gate { margin: 8px 0 40px; }
.gate-title {
  font-family: var(--serif); font-weight: 400; font-size: 1.625rem;
  margin: 12px 0 10px; color: var(--core);
}
.gate-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 26px; }
.gate-card {
  display: flex; flex-direction: column; gap: 8px; text-align: left;
  padding: 20px 18px 18px; background: var(--bg-raised);
  border: 1px solid var(--rule); color: var(--text);
  font-family: var(--sans); font-size: 0.875rem; line-height: 1.6;
  cursor: pointer; transition: border-color 200ms var(--ease), background 200ms var(--ease);
}
.gate-card:hover { border-color: var(--core); background: var(--surface-2); }
.gate-name { font-size: 1.0625rem; color: var(--core); }
.gate-blurb { color: var(--text-2); font-size: 0.8438rem; }

.track-slot { margin-left: auto; }
.track-badge {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .08em;
  color: var(--text-2); background: none; border: 1px solid var(--rule);
  padding: 4px 10px; cursor: pointer;
}
.track-badge:hover { color: var(--core); border-color: var(--core); }

/* ── unit head and the eight modules ─────────────────────────────────────── */

.unit-title {
  font-family: var(--serif); font-weight: 400; font-size: 1.75rem;
  color: var(--core); margin: 10px 0 4px;
}
.unit-zh { font-family: var(--sans); font-size: 0.9375rem; color: var(--muted); margin-left: 12px; }
.goals { margin: 16px 0 26px; display: flex; flex-direction: column; gap: 6px; }

.mod-nav {
  display: flex; gap: 0; flex-wrap: wrap;
  border-top: 1px solid var(--rule); border-bottom: 1px solid var(--rule);
  margin-bottom: 26px;
}
.mod-tab {
  display: flex; align-items: baseline; gap: 8px;
  padding: 11px 14px; background: none; border: 0; border-bottom: 2px solid transparent;
  color: var(--muted); font-family: var(--sans); font-size: 0.8438rem; cursor: pointer;
  transition: color 180ms var(--ease);
}
.mod-tab:hover { color: var(--text); }
.mod-tab.active { color: var(--core); border-bottom-color: var(--core); }
.mod-no { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.mod-tab.active .mod-no { color: var(--core); }
.mod-en {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 10px;
}
.m-body { margin: 26px 0 8px; }
.sub {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
  margin: 30px 0 12px; padding-bottom: 6px; border-bottom: 1px solid var(--rule);
}

/* ── module bodies ───────────────────────────────────────────────────────── */

.word-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(184px, 1fr)); gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.word { display: flex; align-items: baseline; gap: 7px; padding: 9px 11px; background: var(--bg-raised); }
.w-en { font-family: var(--serif); font-size: 0.9375rem; color: var(--core); }
.w-pos { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.w-zh { font-size: 0.8125rem; color: var(--text-2); margin-left: auto; }

.phrase-list, .game-list, .tag-list { display: flex; flex-direction: column; gap: 1px; background: var(--rule); border: 1px solid var(--rule); }
.phrase, .game, .tagrow { display: flex; align-items: baseline; gap: 12px; padding: 10px 12px; background: var(--bg-raised); flex-wrap: wrap; }
.p-en { font-family: var(--serif); font-size: 0.9375rem; color: var(--core); min-width: 11em; }
.p-zh { font-size: 0.8438rem; color: var(--text); min-width: 7em; }
.p-note, .t-fix { font-size: 0.8125rem; color: var(--muted); flex: 1; min-width: 14em; }
.g-name { font-size: 0.875rem; color: var(--text); min-width: 9em; }
.t-zh { font-size: 0.8125rem; color: var(--text); min-width: 6em; }

.pattern { display: flex; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--rule); }
.p-no { font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); padding-top: 4px; }
.p-sent { font-family: var(--serif); font-size: 1.0625rem; color: var(--core); line-height: 1.5; }
.p-main .p-zh { display: block; font-size: 0.8438rem; color: var(--text-2); margin-top: 3px; }
.p-main .p-note { display: block; font-size: 0.8125rem; margin-top: 5px; }

.gpoint { padding: 16px 18px; background: var(--bg-raised); border: 1px solid var(--rule); margin-bottom: 12px; }
.gpoint h4 { font-family: var(--sans); font-weight: 500; font-size: 0.9375rem; color: var(--core); margin-bottom: 10px; }
.g-row { display: flex; gap: 12px; align-items: baseline; margin-bottom: 6px; }
.g-key {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .08em; color: var(--muted);
  min-width: 5.5em; flex-shrink: 0;
}
.g-val { font-size: 0.8438rem; color: var(--text); line-height: 1.62; }

.reading, .cloze, .task { padding: 18px 0 20px; border-bottom: 1px solid var(--rule); }
.r-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.r-title { font-family: var(--serif); font-size: 1.0625rem; color: var(--core); }
.r-text { font-family: var(--serif); font-size: 1.0312rem; line-height: 1.95; color: var(--text); max-width: 62ch; }
.bank-box { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin-bottom: 12px; }
.bank-box code, .ex-support code {
  font-family: var(--mono); font-size: 0.8125rem; color: var(--text-2);
  border: 1px solid var(--rule); padding: 2px 7px; background: var(--surface-2);
}
.callout {
  font-size: 0.8438rem; color: var(--text-2); padding: 11px 14px;
  border-left: 2px solid var(--rule); background: var(--bg-raised); margin: 14px 0;
}
.prompts { list-style: none; display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.prompts li { font-size: 0.875rem; color: var(--text); padding-left: 14px; position: relative; }
.prompts li::before { content: "—"; position: absolute; left: 0; color: var(--muted); }

.steps { list-style: none; counter-reset: st; }
.steps li { counter-increment: st; display: flex; gap: 12px; align-items: baseline; padding: 10px 0; border-bottom: 1px solid var(--rule); }
.steps li::before { content: counter(st); font-family: var(--mono); font-size: 0.8125rem; color: var(--muted); }
.s-name { font-size: 0.9062rem; color: var(--core); min-width: 6em; }
.s-goal { font-size: 0.8438rem; color: var(--text-2); }

.rubric { width: 100%; border-collapse: collapse; font-size: 0.8438rem; margin: 8px 0; }
.rubric th, .rubric td { text-align: left; padding: 9px 11px; border: 1px solid var(--rule); vertical-align: top; }
.rubric th { color: var(--text-2); font-weight: 400; font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .06em; }
.rubric td { color: var(--text); }

/* ── the uniform exercise ────────────────────────────────────────────────── */

.ex-list { margin-top: 34px; }
.ex { padding: 18px 0 20px; border-bottom: 1px solid var(--rule); }
.ex-head { display: flex; align-items: center; gap: 9px; margin-bottom: 11px; }
.lv {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .1em;
  color: var(--muted); border: 1px solid var(--rule); padding: 1px 6px;
}
.ex .stem { font-size: 0.9688rem; margin-bottom: 14px; }
.ex-fill { display: flex; gap: 9px; flex-wrap: wrap; }
.fill-input {
  flex: 1; min-width: 15em; background: var(--bg-raised); border: 1px solid var(--rule);
  color: var(--core); font-family: var(--serif); font-size: 0.9375rem; padding: 9px 12px;
}
.fill-input:focus-visible { outline: 2px solid var(--core); outline-offset: 1px; }
.fill-input.correct { border-color: var(--right); }
.fill-input.wrong { border-color: var(--wrong); }
.ex-verdict { font-size: 0.8438rem; margin-top: 10px; color: var(--muted); }
.ex-verdict.ok { color: var(--right); }
.ex-verdict.no { color: var(--wrong); }
.ex-why { margin-top: 12px; padding-left: 12px; border-left: 1px solid var(--rule); }
.ex-why .why { font-size: 0.8438rem; color: var(--text-2); margin-bottom: 5px; line-height: 1.65; }
.ex-why .trap .letter { font-family: var(--mono); font-size: 0.8125rem; color: var(--wrong); margin-right: 4px; }
.ex-support { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; margin: 10px 0; }
.picker.tiny button { padding: 3px 9px; font-size: 0.8125rem; }

/* ── 能力画像 ────────────────────────────────────────────────────────────── */

.ability-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin: 26px 0 8px; }
.ab-card { padding: 16px 16px 14px; background: var(--bg-raised); border: 1px solid var(--rule); }
.ab-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 14px; }
.ab-name { font-size: 1rem; color: var(--core); }
.ladder { display: flex; gap: 4px; margin-bottom: 9px; }
.rung { flex: 1; height: 4px; background: var(--rule); transition: background 300ms var(--ease); }
.rung.on { background: var(--text-2); }
.rung.here { background: var(--core); }
.ab-level { font-family: var(--mono); font-size: 0.8125rem; color: var(--text); margin-bottom: 5px; }

.tagbars { display: flex; flex-direction: column; gap: 7px; }
.report { margin-top: 14px; padding: 18px 18px 16px; background: var(--bg-raised); border: 1px solid var(--rule); }
.r-line { font-size: 0.9062rem; color: var(--text); line-height: 1.75; margin-bottom: 9px; }
.report .meta { display: block; margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--rule); }

@media (max-width: 720px) {
  .gate-grid, .ability-grid { grid-template-columns: 1fr; }
  .word-grid { grid-template-columns: 1fr 1fr; }
  .mod-tab { padding: 9px 10px; font-size: 0.8125rem; }
  .rubric { display: block; overflow-x: auto; }
}
@media (max-width: 440px) {
  .word-grid { grid-template-columns: 1fr; }
  .phrase, .game, .tagrow { flex-direction: column; gap: 3px; }
}

/* ═══ polish ═══════════════════════════════════════════════════════════════
   One radius, one lift, applied to every raised surface at once. This layer
   only softens what the sections above already built — it introduces no new
   colour, and every value it uses is a token, so both themes get it free. */

button, .fill-input, input, select { border-radius: var(--r); }

.viz, .paper, .gate-card, .ab-card, .gpoint, .report, .callout,
.word-grid, .phrase-list, .game-list, .tag-list, .wrong-card,
.bank-results, .profile-panel, .rubric {
  border-radius: var(--r);
}

/* Lift is a light-theme device: paper sits above paper. On the dark ground
   --lift resolves to none, so the same rule is simply inert there. */
.viz, .paper, .ab-card, .gpoint, .report, .wrong-card, .gate-card {
  box-shadow: var(--lift);
}
.word-grid, .phrase-list, .game-list, .tag-list { overflow: hidden; }

button {
  transition: border-color 160ms var(--ease), color 160ms var(--ease),
              background 160ms var(--ease);
}
button:hover:not(:disabled) { background: var(--surface-2); }
.picker button.active:hover { background: var(--surface-3); }

.opt { border-radius: var(--r); }
.opt:hover:not(:disabled) { background: var(--surface-2); border-color: var(--text-2); }
.opt.correct:hover, .opt.wrong:hover { background: inherit; }

/* ── rhythm ──────────────────────────────────────────────────────────────
   The page was built at one density. Giving the masthead and the section
   heads more air is most of what "nicer" means here. */

.wrap { max-width: 61.25rem; padding: 64px 28px 112px; }
.masthead { margin-bottom: 38px; }
h1 { letter-spacing: -.015em; }
.lede { line-height: 1.75; }

.tabs { gap: 2px; margin-bottom: 34px; }
.tab { padding: 11px 16px; border-radius: var(--r) var(--r) 0 0; }
.tab:hover:not(.on) { background: var(--surface-2); }

.profile-bar {
  align-items: center; gap: 12px; padding: 12px 16px;
  background: var(--bg-raised); border: 1px solid var(--rule);
  border-radius: var(--r);
}

.gate-card { padding: 24px 22px 22px; }
.gate-card:hover { background: var(--bg-raised); border-color: var(--text-2); }

.ex { padding: 22px 0 24px; }
.ex .stem { line-height: 1.7; }
.reading, .cloze, .task { padding: 22px 0 24px; }
.r-text { line-height: 2.02; }

.sub { margin: 36px 0 14px; letter-spacing: .14em; }

/* ── theme toggle ────────────────────────────────────────────────────────── */

.theme-toggle {
  font-family: var(--mono); font-size: 0.8125rem; letter-spacing: .08em;
  color: var(--text-2); background: none; border: 1px solid var(--rule);
  padding: 4px 10px; cursor: pointer;
}
.theme-toggle:hover { color: var(--core); border-color: var(--core); }

@media (max-width: 560px) {
  .wrap { padding: 36px 18px 72px; }
  .profile-bar { flex-wrap: wrap; }
  .track-slot { margin-left: 0; }
}

/* ── the 字号 control ────────────────────────────────────────────────────── */

.size-control { display: flex; align-items: center; gap: 6px; }
.size-control .meta { margin-right: 2px; }
.size-btn {
  font-family: var(--mono); font-size: 0.8125rem; line-height: 1;
  color: var(--text-2); background: none; border: 1px solid var(--rule);
  padding: 5px 9px; cursor: pointer; min-width: 2.4em;
}
.size-btn:hover { color: var(--core); border-color: var(--core); }
.size-btn.on { color: var(--core); border-color: var(--core); background: var(--surface-3); }

/* ═══ chrome: colour on surfaces ═══════════════════════════════════════════
   Everything below paints BACKGROUNDS, BARS and BORDERS. Nothing below sets a
   text colour to a chrome hue — that channel belongs to grammatical function
   and is not shared. Hue here is navigational: it tells you which card you are
   on, never what a word is doing in a sentence. */

.gate-card:nth-child(1), .ab-card:nth-child(1) { background: var(--wash-1); border-color: var(--bar-1); }
.gate-card:nth-child(2), .ab-card:nth-child(2) { background: var(--wash-2); border-color: var(--bar-2); }
.gate-card:nth-child(3), .ab-card:nth-child(3) { background: var(--wash-3); border-color: var(--bar-3); }
.ab-card:nth-child(4) { background: var(--wash-4); border-color: var(--bar-4); }
.ab-card:nth-child(5) { background: var(--wash-5); border-color: var(--bar-5); }
.ab-card:nth-child(6) { background: var(--wash-6); border-color: var(--bar-6); }

/* A card announces itself with a bar along its top edge rather than a tinted
   border all round, which at this lightness reads as a smudge. */
.gate-card, .ab-card { position: relative; overflow: hidden; border-top-width: 3px; }

.gate-card:hover { background: var(--bg-raised); }
.gate-card:nth-child(1):hover { border-color: var(--bar-1); }
.gate-card:nth-child(2):hover { border-color: var(--bar-2); }
.gate-card:nth-child(3):hover { border-color: var(--bar-3); }

/* The eight modules cycle the same six hues, so a module is recognisable by
   its colour before its name is read. */
.mod-tab:nth-child(6n+1).active { border-bottom-color: var(--bar-1); }
.mod-tab:nth-child(6n+2).active { border-bottom-color: var(--bar-2); }
.mod-tab:nth-child(6n+3).active { border-bottom-color: var(--bar-3); }
.mod-tab:nth-child(6n+4).active { border-bottom-color: var(--bar-4); }
.mod-tab:nth-child(6n+5).active { border-bottom-color: var(--bar-5); }
.mod-tab:nth-child(6n+6).active { border-bottom-color: var(--bar-6); }
.mod-tab.active { border-bottom-width: 3px; }

/* ── one accent, used consistently ───────────────────────────────────────── */

.tab.on            { border-bottom-color: var(--accent); }
.picker button.active,
.size-btn.on       { border-color: var(--accent); background: var(--accent-soft); }
button:focus-visible, a:focus-visible,
.fill-input:focus-visible { outline-color: var(--accent); }
.rung.here         { background: var(--accent); }
.track-badge:hover,
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); }

/* Section heads get their rule in the accent rather than another grey line —
   the cheapest way to stop a long page reading as one undifferentiated column. */
.sub { border-bottom-color: var(--accent); color: var(--text-2); }

/* Teaching surfaces that are neither cards nor sentences: give them a wash so
   the eye can tell prose from apparatus. */
.gpoint   { background: var(--wash-3); border-color: var(--rule); }
.callout  { background: var(--wash-4); border-left-color: var(--bar-4); border-left-width: 3px; }
.report   { background: var(--wash-1); border-color: var(--bar-1); border-top-width: 3px; }
.bank-box { background: var(--wash-6); border: 1px solid var(--rule); padding: 10px 12px; border-radius: var(--r); }
.ex-support { background: var(--wash-2); border-radius: var(--r); padding: 9px 11px; }
.rubric th  { background: var(--wash-5); }
.word-grid .word:hover, .phrase:hover { background: var(--wash-1); }

/* The reading passages keep a plain ground on purpose: a wash behind English
   prose competes with the evidence highlight, which has to stay the loudest
   thing on the page. */
.reading .r-text, .cloze .r-text { background: none; }

.masthead h1 { color: var(--core); }
.profile-bar { border-top: 3px solid var(--accent); }
