/* Hanzi Hop · The Transit Network
   Characters are stations, words are the lines between them. Warm paper and enamel
   plates; colour as data (HSK level = line: red, blue, violet) plus one sky-blue accent
   for "you are here" and the primary action. Sky is the near-complement of the red
   line and the light sibling of the blue one: it is kept apart from Line 2 by lightness
   by day and by a deeper Line 2 at night, so the set reads as one palette. The
   navigation track is red, the livery of the route. Light is the daytime sign, dark is
   the backlit night sign. System faces only: the CSP forbids web fonts, and the
   signage face is the platform grotesque. */

:root {
  color-scheme: light;
  --ground: #f4f2eb;
  --plate: #ffffff;
  --plate-2: #ebe8df;
  --ink: #15171a;
  --ink-2: #4b5156;
  --ink-3: #666c72;
  --seam: #d9d6cc;
  --seam-2: #c0bdb2;
  --field: #ffffff;
  --inverse: #15171a;
  --on-inverse: #ffffff;
  --on-line: #ffffff;
  --accent: #5aa9ec;
  --on-accent: #15171a;
  --accent-ink: #0a66b4;
  --accent-plate: #dbeefb;
  --l1: #c8372d;
  --l2: #0b63a8;
  --l3: #6b3fc7;
  --nav-red: #c8372d;
  --ok: #0a7a4f;
  --warn: #9a5b00;
  --bad: #c8372d;
  --info: #0b63a8;
  --ok-plate: #e1f2e9;
  --warn-plate: #faefd8;
  --bad-plate: #fbe5e2;
  --info-plate: #e1edf8;
  --focus: #0a66b4;
  --shadow: 0 10px 28px -14px rgba(18, 20, 23, .35), 0 2px 6px -3px rgba(18, 20, 23, .25);
  --r: 6px;
  --r-l: 12px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --han: "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "Source Han Sans SC", "Hiragino Sans GB", "Heiti SC", sans-serif;
  --t: 180ms cubic-bezier(.2, .7, .2, 1);
  --bar-h: 52px;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground: #151515;
    --plate: #1c1c1c;
    --plate-2: #252525;
    --ink: #f2f2f0;
    --ink-2: #b6b6b2;
    --ink-3: #8f8f8b;
    --seam: #303030;
    --seam-2: #414141;
    --field: #181818;
    --inverse: #f2f2f0;
    --on-inverse: #151515;
    --on-line: #151515;
    --accent: #7cc1f4;
    --on-accent: #15171a;
    --accent-ink: #7cc1f4;
    --accent-plate: #0f2d45;
    --l1: #ef6b60;
    --l2: #3f84d2;
    --l3: #b094f5;
    --nav-red: #ef6b60;
    --ok: #3fbf8a;
    --warn: #e3a33a;
    --bad: #ef6b60;
    --info: #3f84d2;
    --ok-plate: #163826;
    --warn-plate: #3a2c12;
    --bad-plate: #40201d;
    --info-plate: #15304a;
    --focus: #7cc1f4;
    --shadow: 0 12px 30px -14px rgba(0, 0, 0, .7), 0 2px 6px -3px rgba(0, 0, 0, .5);
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --ground: #151515;
  --plate: #1c1c1c;
  --plate-2: #252525;
  --ink: #f2f2f0;
  --ink-2: #b6b6b2;
  --ink-3: #8f8f8b;
  --seam: #303030;
  --seam-2: #414141;
  --field: #181818;
  --inverse: #f2f2f0;
  --on-inverse: #151515;
  --on-line: #151515;
  --accent: #7cc1f4;
  --on-accent: #15171a;
  --accent-ink: #7cc1f4;
  --accent-plate: #0f2d45;
  --l1: #ef6b60;
  --l2: #3f84d2;
  --l3: #b094f5;
  --nav-red: #ef6b60;
  --ok: #3fbf8a;
  --warn: #e3a33a;
  --bad: #ef6b60;
  --info: #3f84d2;
  --ok-plate: #163826;
  --warn-plate: #3a2c12;
  --bad-plate: #40201d;
  --info-plate: #15304a;
  --focus: #7cc1f4;
  --shadow: 0 12px 30px -14px rgba(0, 0, 0, .7), 0 2px 6px -3px rgba(0, 0, 0, .5);
}

/* ---------- base ---------- */
* { box-sizing: border-box; }
html { scrollbar-color: var(--seam-2) var(--ground); }
body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 15px/1.55 var(--font);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  caret-color: var(--accent-ink);
  accent-color: var(--accent);
}
::selection { background: var(--accent); color: var(--on-accent); }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--accent-ink); text-decoration-thickness: 1px; text-underline-offset: .18em; }
h1, h2, h3 { font-weight: 700; letter-spacing: -.01em; text-wrap: balance; margin: 0; }
h2 { font-size: 22px; line-height: 1.25; }
h3 { font-size: 16px; }
p { margin: .5em 0; }
.han { font-family: var(--han); font-weight: 500; }
.hidden, [hidden] { display: none !important; }
.muted { color: var(--ink-2); font-size: 13px; }
.note { font-size: 12px; color: var(--ink-3); margin-top: 4px; max-width: 42ch; }
.empty { padding: 32px 0; color: var(--ink-2); }
.i { width: 1.1em; height: 1.1em; stroke: currentColor; fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; vertical-align: -.17em; flex: none; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: 3px; }
.skip { position: absolute; left: 12px; top: -48px; z-index: 50; background: var(--inverse); color: var(--on-inverse); padding: 8px 12px; border-radius: var(--r); text-decoration: none; }
.skip:focus-visible { top: 10px; }

/* ---------- plates, pills, stops: the signage vocabulary ---------- */
.plate { background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); }
.pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  min-width: 26px; height: 22px; padding: 0 7px;
  border-radius: 5px; font-size: 11px; font-weight: 750; letter-spacing: .04em;
  color: var(--on-line); background: var(--ink-2); white-space: nowrap;
}
.pill.l1 { background: var(--l1); }
.pill.l2 { background: var(--l2); }
.pill.l3 { background: var(--l3); }
.num { font-size: 12px; color: var(--ink-3); letter-spacing: .02em; }
.stop {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-width: 40px; height: 40px; padding: 0 8px;
  border: 2px solid var(--ink); border-radius: 999px;
  background: var(--plate); color: var(--ink);
  font-family: var(--han); font-size: 21px; font-weight: 500; line-height: 1;
  transition: background var(--t), color var(--t), border-color var(--t), transform var(--t);
}
.stop small { font: 600 11px/1 var(--font); color: var(--ink-3); letter-spacing: .02em; max-width: 14ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.stop:hover { background: var(--ink); color: var(--on-inverse); }
.stop:hover small { color: inherit; }
.stop[aria-current="true"], .stop.current { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.stop[aria-current="true"] small { color: inherit; }
.stop:active { transform: scale(.96); }

/* ---------- actions ---------- */
.action {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 38px; padding: 7px 14px;
  border: 1px solid var(--seam-2); border-radius: var(--r);
  background: var(--plate); color: var(--ink);
  line-height: 1.3; text-align: left;
  transition: background var(--t), border-color var(--t), color var(--t), opacity var(--t);
}
.action:hover { border-color: var(--ink); }
.action.primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); font-weight: 650; }
.action.primary:hover { opacity: .88; }
.action.quiet { background: transparent; border-color: transparent; color: var(--ink-2); }
.action.quiet:hover { border-color: var(--seam-2); color: var(--ink); }
.action.danger { color: var(--bad); border-color: var(--bad); background: transparent; }
.action.danger:hover, .action.danger:focus-visible { background: var(--bad); color: var(--on-line); }
.action:disabled, .answer-choice:disabled, .stop:disabled { opacity: .5; cursor: default; }
.action:disabled:hover { border-color: var(--seam-2); }
.action.primary:disabled:hover { opacity: .5; }
.tool {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  height: 36px; min-width: 36px; padding: 0 10px;
  border: 1px solid transparent; border-radius: var(--r);
  background: transparent; color: var(--ink);
  font-size: 13px; font-weight: 600;
  transition: background var(--t), border-color var(--t);
}
.tool:hover { background: var(--plate-2); }
.tool .i { width: 20px; height: 20px; }
.tool[aria-expanded="true"], .tool[aria-selected="true"] { background: var(--plate-2); }
.bar-tools .label { font-size: 13px; }

/* ---------- top bar ---------- */
.bar { background: var(--plate); border-bottom: 1px solid var(--seam); }
.bar-top { max-width: 1320px; margin: auto; height: var(--bar-h); padding: 0 24px; display: flex; align-items: center; gap: 12px; }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); text-decoration: none; font-weight: 750; font-size: 17px; letter-spacing: -.01em; margin-right: auto; }
.brand-mark { width: 30px; height: 30px; border: 3px solid var(--accent); border-radius: 50%; display: inline-grid; place-items: center; font-family: var(--han); font-size: 15px; font-weight: 500; line-height: 1; background: var(--accent); color: var(--on-accent); }
.bar-tools { display: flex; align-items: center; gap: 4px; }
.session-count { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px; border-radius: 999px; background: var(--accent); color: var(--on-accent); font-size: 11px; font-weight: 750; }
.session-sidebar-toggle .session-count:empty { display: none; }
.session-count.is-zero { background: var(--plate-2); color: var(--ink-2); }

/* language switcher: one flag, opens to the other seven */
.language-switcher { position: relative; display: inline-flex; align-items: center; }
.lang-button { gap: 7px; padding-right: 8px; }
.lang-button .language-flag { width: 26px; height: 16px; }
.lang-button .lang-code { text-transform: uppercase; letter-spacing: .06em; font-size: 12px; }
.lang-button .i { width: 16px; height: 16px; color: var(--ink-3); }
.lang-menu {
  position: fixed; inset: auto; margin: 0; padding: 6px; list-style: none;
  min-width: 220px; background: var(--plate); color: var(--ink);
  border: 1px solid var(--seam); border-radius: var(--r-l); box-shadow: var(--shadow);
}
.lang-menu:not(:popover-open) { display: none; }
.lang-menu a { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--r); color: var(--ink); text-decoration: none; font-size: 14px; white-space: nowrap; }
.lang-menu a:hover { background: var(--plate-2); }
.lang-menu a[aria-current="page"] { font-weight: 700; }
.lang-menu a[aria-current="page"]::after { content: ""; margin-left: auto; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.language-switcher.locked .lang-button { opacity: .45; cursor: not-allowed; }
.language-flag { flex: none; width: 24px; height: 15px; border-radius: 2px; box-shadow: 0 0 0 1px rgba(0, 0, 0, .18); }
.language-lock-note { display: none; }

/* line navigation: the five study destinations as stops on one route line.
   The label sits above the line, the stop sits on it; the current stop is the accent "you are here".
   The track is the red livery of the route and runs through the exact centre of every stop:
   every vertical measure is an integer (label line box, gap, stop, paper below the stop), so the stop
   and the track snap to the same pixel row, and the paper below the stop clears the current stop's halo
   (scale 1.3 plus a 6px ring reaches 19.5px from the centre) before the hairline seam. */
.line-nav-wrap { position: sticky; top: 0; z-index: 15; background: var(--plate); border-bottom: 1px solid var(--seam); }
.line-nav { --stop: 18px; --track: 4px; --stop-gap: 20px; max-width: 1320px; margin: auto; padding: 0 24px; display: flex; gap: 0; overflow-x: auto; scrollbar-width: none; position: relative; }
.line-nav::-webkit-scrollbar { display: none; }
.line-nav button {
  position: relative; flex: 1 1 0; min-width: max-content; display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 14px 16px var(--stop-gap); margin: 0;
  border: 0; background: none; color: var(--ink-2); font-size: 16px; line-height: 20px; font-weight: 700; letter-spacing: -.01em; white-space: nowrap; text-align: center;
  transition: color var(--t);
}
.line-nav button::before {
  content: ""; order: 2; position: relative; z-index: 1; width: var(--stop); height: var(--stop); box-sizing: border-box; flex: none; border-radius: 50%;
  border: 3px solid var(--ink); background: var(--plate);
  transition: border-color var(--t), background var(--t), transform var(--t), box-shadow var(--t);
}
.line-nav button::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: calc(var(--stop-gap) + (var(--stop) - var(--track)) / 2); height: var(--track);
  background: var(--nav-red);
}
.line-nav button:first-child::after { left: 50%; }
.line-nav button:last-child::after { right: 50%; }
.line-nav button:hover { color: var(--ink); }
.line-nav button:hover::before { background: var(--ink); }
.line-nav button[aria-selected="true"] { color: var(--accent-ink); }
.line-nav button[aria-selected="true"]::before { border-color: var(--accent); background: var(--accent); transform: scale(1.3); box-shadow: 0 0 0 3px var(--plate), 0 0 0 6px var(--accent); }
.line-nav button:disabled { opacity: .4; cursor: not-allowed; }
.line-nav button:focus-visible { outline-offset: -2px; }

/* ---------- sessions drawer ---------- */
.session-sidebar-shade { display: none; position: fixed; inset: 0; width: 100%; height: 100%; border: 0; background: rgba(10, 12, 14, .45); z-index: 29; }
.session-sidebar {
  position: fixed; inset: 0 auto 0 0; width: min(360px, 92vw); z-index: 30;
  background: var(--plate); border-right: 1px solid var(--seam); box-shadow: var(--shadow);
  padding: 18px 18px 22px; display: flex; flex-direction: column; overflow: auto;
  transform: translateX(-100%); visibility: hidden;
  transition: transform 220ms cubic-bezier(.2, .7, .2, 1), visibility 220ms;
}
.session-sidebar-open .session-sidebar { transform: none; visibility: visible; }
.session-sidebar-open .session-sidebar-shade { display: block; }
.session-sidebar-open { overflow: hidden; }
.session-sidebar-heading { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.session-sidebar h2 { font-size: 20px; display: flex; align-items: center; gap: 8px; }
.session-sidebar-close { min-width: 36px; height: 36px; padding: 0; justify-content: center; }
.session-profile { font-weight: 650; margin: 14px 0 2px; overflow-wrap: anywhere; }
.session-profile-actions .action { font-size: 13px; padding: 4px 0; border: 0; min-height: 0; color: var(--info); text-decoration: underline; text-underline-offset: .18em; }
.session-storage, .session-lock-note { font-size: 12px; line-height: 1.5; }
.session-list { margin: 10px -6px 16px; display: grid; gap: 4px; }
.session-item {
  display: grid; gap: 3px; width: 100%; text-align: left;
  border: 1px solid transparent; border-radius: var(--r); background: transparent; color: var(--ink);
  padding: 10px 10px 10px 26px; position: relative;
  transition: background var(--t), border-color var(--t);
}
.session-item::before { content: ""; position: absolute; left: 10px; top: 16px; width: 8px; height: 8px; border-radius: 50%; border: 2px solid var(--seam-2); background: var(--plate); }
.session-item::after { content: ""; position: absolute; left: 14px; top: 26px; bottom: -6px; width: 2px; background: var(--seam); }
.session-item:last-of-type::after { display: none; }
.session-item:hover { background: var(--plate-2); }
.session-item[aria-current="true"] { background: var(--plate-2); border-color: var(--seam-2); }
.session-item[aria-current="true"]::before { background: var(--accent); border-color: var(--accent); }
.session-item strong { font-size: 13px; }
.session-item time, .session-meta { font-size: 11px; color: var(--ink-3); }
.session-score { font-size: 11px; color: var(--ok); font-weight: 650; }
.session-item:disabled { opacity: .55; cursor: default; }
.session-empty { padding: 0 6px; }
.session-answers { padding: 0; list-style: none; }
.session-answer { padding: 16px 20px; margin: 10px 0; background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); }
.session-answer-heading { display: flex; justify-content: space-between; align-items: center; gap: 15px; flex-wrap: wrap; }
.session-answer-heading strong { font-size: 20px; font-weight: 600; font-family: var(--han); }
.session-answer p { margin: 8px 0; }
.session-response { overflow-wrap: anywhere; white-space: pre-wrap; }
.session-verdict { font-size: 12px; color: var(--ink-2); font-weight: 600; }

/* ---------- main ---------- */
main { max-width: 1320px; margin: auto; padding: 0 24px 72px; }

/* the station sign: the kept headline */
.sign { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 24px 40px; padding: 34px 0 22px; }
.sign h1 { font-size: 30px; line-height: 1.15; letter-spacing: -.02em; font-weight: 750; max-width: 28ch; }
.sign-sub { margin: 14px 0 0; font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
.sign-lead { margin: 10px 0 0; max-width: 66ch; color: var(--ink-2); font-size: 16px; }
.roundel-hero {
  width: 132px; height: 132px; border: 6px solid var(--accent); border-radius: 50%;
  display: grid; place-items: center; background: var(--accent);
  font-family: var(--han); font-size: 74px; font-weight: 500; line-height: 1; color: var(--on-accent);
  box-shadow: inset 0 0 0 4px var(--plate);
}
.legend { grid-column: 1 / -1; list-style: none; margin: 0; padding: 12px 0 0; border-top: 1px solid var(--seam); display: flex; flex-wrap: wrap; gap: 8px 28px; font-size: 13px; color: var(--ink-2); }
.legend li { display: inline-flex; align-items: center; gap: 8px; }
.legend strong { color: var(--ink); font-weight: 700; }
.legend .dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.legend .dot.l1 { background: var(--l1); }
.legend .dot.l2 { background: var(--l2); }
.legend .dot.l3 { background: var(--l3); }

/* status line and notices */
/* informational plates stay neutral; amber is reserved for the "review" verdict and audio warnings */
.status:not(:empty), .practice-message:not(:empty) { background: var(--plate-2); border: 1px solid var(--seam-2); color: var(--ink); border-radius: var(--r); padding: 10px 14px; margin: 0 0 16px; font-size: 14px; }
.notice { font-size: 13px; background: var(--plate-2); border: 1px solid var(--seam-2); border-radius: var(--r); padding: 10px 14px; margin: 14px 0; color: var(--ink); }
.notice:empty { display: none; }

/* toolbar */
.toolbar { display: flex; gap: 10px; flex-wrap: wrap; align-items: end; margin: 6px 0 16px; }
.toolbar label { font-size: 12px; font-weight: 650; display: block; color: var(--ink-2); }
.toolbar input, .toolbar select, .field select, .field input, .answer-form input, .hsk-audio-field input, .hsk-audio-field select, .hanzi-kb-select, .hanzi-kb-search {
  display: block; width: 100%; min-height: 40px;
  border: 1px solid var(--seam-2); background: var(--field); color: var(--ink);
  border-radius: var(--r); padding: 8px 11px; margin-top: 5px;
  transition: border-color var(--t);
}
.toolbar input:hover, .toolbar select:hover, .field select:hover, .field input:hover, .answer-form input:hover { border-color: var(--ink-3); }
.toolbar input::placeholder, .answer-form input::placeholder, .hsk-audio-field input::placeholder { color: var(--ink-3); }
.search-wrap { flex: 1 1 260px; min-width: 220px; }
.toolbar .pinyin-kb-toggle { margin: 0; min-height: 40px; border-color: var(--seam-2); background: var(--plate); color: var(--ink); }
.toolbar .pinyin-kb-toggle.active { background: var(--inverse); border-color: var(--inverse); color: var(--on-inverse); }
.toolbar .kb-toggles { display: flex; gap: 8px; }

/* search results */
.search-results { display: flex; gap: 8px; flex-wrap: wrap; background: var(--plate); border: 1px solid var(--seam); padding: 12px; border-radius: var(--r-l); margin-bottom: 18px; max-height: 340px; overflow: auto; }
.chip { display: inline-flex; align-items: center; gap: 8px; padding: 6px 8px 6px 12px; border: 1px solid var(--seam); border-radius: var(--r); background: var(--plate-2); color: var(--ink); font-size: 14px; }
.chip .stop { min-width: 32px; height: 32px; font-size: 17px; border-width: 1.5px; }
.chip .hsk-audio-button { padding: 4px 8px; }

/* route strip (the trail) */
.route { display: flex; align-items: center; gap: 0; margin: 4px 0 18px; overflow-x: auto; padding: 4px 2px 6px; scrollbar-width: none; }
.route::-webkit-scrollbar { display: none; }
.route-label { font-size: 12px; font-weight: 650; color: var(--ink-2); margin-right: 12px; white-space: nowrap; }
.route .stop { flex: none; }
.route .link { flex: none; width: 26px; height: 2.5px; background: var(--ink); }

/* the network: the current station on the left, every word a line fanning out to its next stations.
   The SVG only draws the curves; the stations and words are real HTML so they wrap, translate and focus. */
.eyebrow { display: block; font-size: 11px; font-weight: 750; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); }
/* One grid: station column, the fan gap, then the three map tracks the head row and every branch share. */
.network { position: relative; display: grid; grid-template-columns: 264px 86px minmax(0, 1fr) 36px fit-content(320px); column-gap: 12px; align-items: stretch; margin: 6px 0 14px; }
.network-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; overflow: visible; }
.network-lines path { fill: none; stroke: var(--ink); stroke-width: 3; stroke-linecap: round; }
.network-lines path.l1 { stroke: var(--l1); }
.network-lines path.l2 { stroke: var(--l2); }
.network-lines path.l3 { stroke: var(--l3); }
.network-lines path.trunk { stroke: var(--ink); }
.station { grid-column: 1; position: relative; z-index: 1; display: grid; grid-template-rows: auto 1fr; min-width: 0; }
.station > .eyebrow { padding-bottom: 10px; }
.station-body { display: flex; flex-direction: column; align-items: flex-start; justify-content: center; gap: 4px; min-width: 0; }
.station h2 { font-size: 22px; line-height: 1.2; margin-top: 6px; }
.station .notice { margin: 10px 0 0; }
.root { display: flex; align-items: center; margin: 22px 0 18px; }
.root .roundel {
  width: 88px; height: 88px; border: 4px solid var(--accent); border-radius: 50%;
  display: grid; place-items: center; font-size: 46px; line-height: 1;
  background: var(--accent); color: var(--on-accent); box-shadow: inset 0 0 0 3px var(--plate); flex: none;
}
.root .roundel.arrive { animation: arrive 220ms cubic-bezier(.2, .7, .2, 1); }
.character-audio { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 0 0 8px; }
.character-audio:empty { display: none; }
.hsk-character-audio { display: inline-flex; gap: 6px; flex-wrap: wrap; }
.family-actions { display: flex; flex-direction: column; align-items: stretch; gap: 8px; width: 100%; margin: 4px 0 0; }
.network-map { grid-column: 3 / -1; position: relative; z-index: 1; min-width: 0; display: grid; grid-template-columns: subgrid; align-content: start; }
.network-head, .network-rows, .network-row { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; }
.network-head { padding: 0 0 10px; }
.network-head .next-head { grid-column: 3; }
.network-rows { list-style: none; margin: 0; padding: 0; row-gap: 10px; }
.network-rows .empty { grid-column: 1 / -1; }
.network-row { position: relative; }
.pager { grid-column: 1 / -1; }
.network-rows .empty { padding: 24px 0; }
.net-stop {
  position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 4px 12px;
  min-height: 64px; padding: 10px 12px 10px 18px;
  background: var(--plate); border: 1px solid var(--seam); border-left: 4px solid var(--ink); border-radius: var(--r-l);
}
.net-stop .mark { position: absolute; left: -10px; top: 50%; width: 16px; height: 16px; margin-top: -8px; border-radius: 50%; border: 3px solid var(--ink); background: var(--plate); }
.net-stop .han { font-size: 27px; line-height: 1.1; }
.net-stop .net-meta { font-size: 13px; color: var(--ink-2); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.net-stop .net-tail { display: inline-flex; align-items: center; gap: 8px; }
.network-row.l1 .net-stop { border-left-color: var(--l1); }
.network-row.l2 .net-stop { border-left-color: var(--l2); }
.network-row.l3 .net-stop { border-left-color: var(--l3); }
.network-row.l1 .mark { border-color: var(--l1); }
.network-row.l2 .mark { border-color: var(--l2); }
.network-row.l3 .mark { border-color: var(--l3); }
.network-row .link { width: 100%; height: 3px; background: var(--ink); border-radius: 2px; }
.network-row .link.l1 { background: var(--l1); }
.network-row .link.l2 { background: var(--l2); }
.network-row .link.l3 { background: var(--l3); }
.net-next { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.net-next .next-dash { font-size: 13px; color: var(--ink-3); }
.pager { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding-top: 12px; }
.pager-buttons { display: inline-flex; gap: 6px; }
.pager .tool { border-color: var(--seam-2); }
.pager .tool:disabled { opacity: .35; cursor: default; }
/* the full board: always open on desktop, a disclosure on phones so it does not stack under the network */
.board-fold > summary { pointer-events: none; }
.board-fold > summary::before { display: none; }

/* the board: one vertical line with a stop per word */
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin: 26px 0 12px; }
.table-wrap { overflow: auto; border: 1px solid var(--seam); border-radius: var(--r-l); background: var(--plate); }
table { width: 100%; border-collapse: collapse; text-align: left; }
th { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; padding: 12px 14px; color: var(--ink-2); background: var(--plate-2); border-bottom: 1px solid var(--seam); font-weight: 700; white-space: nowrap; }
td { padding: 13px 14px; border-top: 1px solid var(--seam); vertical-align: middle; }
tr:first-child td { border-top: 0; }
.board { min-width: 760px; }
.board th:first-child, .board td:first-child { padding-left: 46px; position: relative; }
.board td:first-child::before { content: ""; position: absolute; left: 20px; top: -1px; bottom: 0; width: 3px; background: var(--ink); }
.board tr:first-child td:first-child::before { top: 50%; }
.board tr:last-child td:first-child::before { bottom: 50%; }
.board td:first-child::after { content: ""; position: absolute; left: 15px; top: 50%; margin-top: -7px; width: 14px; height: 14px; border-radius: 50%; border: 3px solid var(--ink); background: var(--plate); }
/* each row's rail segment and stop take the line colour of its HSK level */
.board tr.l1 td:first-child::before { background: var(--l1); }
.board tr.l2 td:first-child::before { background: var(--l2); }
.board tr.l3 td:first-child::before { background: var(--l3); }
.board tr.l1 td:first-child::after { border-color: var(--l1); }
.board tr.l2 td:first-child::after { border-color: var(--l2); }
.board tr.l3 td:first-child::after { border-color: var(--l3); }
.b-word { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.b-word .han { font-size: 26px; line-height: 1.2; }
.hsk-audio-button.compact { width: 32px; min-width: 32px; height: 32px; min-height: 32px; padding: 0; justify-content: center; color: var(--ink-2); }
.hsk-audio-button.compact .i { width: 18px; height: 18px; }
.hsk-audio-button.compact:hover { color: var(--ink); }
.b-py { color: var(--ink-2); white-space: nowrap; }
.b-id { display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.next { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.next .stop { min-width: 38px; height: 38px; font-size: 20px; }
.next-dash { color: var(--ink-3); }

/* station index (all characters): stops grouped under their theme line, no plates */
.index-group { margin: 20px 0 8px; }
.index-group h3 { display: flex; align-items: center; gap: 10px; font-size: 15px; padding-bottom: 10px; border-bottom: 1px solid var(--seam); margin-bottom: 8px; }
.index-group h3 .muted { margin-left: auto; font-weight: 600; white-space: nowrap; }
.index-stops { display: grid; grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); gap: 4px; }
.index-stop { display: grid; justify-items: center; gap: 1px; padding: 10px 6px 8px; border: 0; background: none; color: var(--ink); border-radius: var(--r); text-align: center; min-width: 0; transition: background var(--t); }
.index-stop .roundel { width: 52px; height: 52px; border: 3px solid var(--ink); border-radius: 50%; display: grid; place-items: center; font-size: 28px; line-height: 1; background: var(--plate); margin-bottom: 5px; transition: background var(--t), color var(--t); }
.index-stop b { font-size: 13px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.index-stop small { font-size: 11px; color: var(--ink-2); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.index-stop small.count { color: var(--ink-3); }
.index-stop:hover { background: var(--plate-2); }
.index-stop:hover .roundel { background: var(--ink); color: var(--on-inverse); }

/* chains: one horizontal line each */
.chain { padding: 18px 20px; background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); margin: 12px 0; }
.chain-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.chain-head h3 { display: flex; align-items: center; gap: 10px; font-size: 15px; }
.chain-line { display: flex; gap: 0; align-items: center; margin: 14px 0 4px; overflow-x: auto; padding: 6px 2px 10px; scrollbar-width: thin; }
.chain-line .stop { flex: none; }
.chain-line .link { flex: none; width: 22px; height: 2.5px; background: var(--ink); }
.chain-line .link.l1 { background: var(--l1); }
.chain-line .link.l2 { background: var(--l2); }
.chain-line .link.l3 { background: var(--l3); }
.chain-word { flex: none; text-align: center; padding: 8px 12px; border: 1px solid var(--seam); border-radius: var(--r); background: var(--plate-2); min-width: 120px; max-width: 220px; }
.chain-word strong { font-family: var(--han); font-size: 22px; font-weight: 500; display: block; line-height: 1.2; }
.chain-word span, .chain-word small { font-size: 11px; display: block; color: var(--ink-2); }
.chain-word .hsk-audio-button { margin-top: 6px; }

/* ---------- practice ---------- */
.practice-card { background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); padding: 24px; margin: 16px 0; }
.practice-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 14px; }
.field { display: block; font-size: 13px; font-weight: 650; color: var(--ink-2); }
.exercise-types { border: 0; border-top: 1px solid var(--seam); margin: 22px 0 10px; padding: 16px 0 0; display: flex; gap: 10px 22px; flex-wrap: wrap; }
.exercise-types legend { padding-right: 12px; font-weight: 650; }
.exercise-types label { display: flex; align-items: center; gap: 7px; font-size: 13px; }
.exercise-types input { width: 17px; height: 17px; }
.practice-top, .practice-actions { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
.practice-actions { justify-content: flex-start; margin-top: 14px; }
.ticket { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 13px; color: var(--ink-2); font-weight: 650; }
.ticket .pill { background: var(--accent); color: var(--on-accent); height: 24px; font-size: 12px; letter-spacing: .02em; }
.ticket .type { color: var(--ink); }
.stops { display: flex; align-items: center; gap: 0; margin: 14px 0 6px; height: 14px; }
.stops span { flex: 1; height: 2.5px; background: var(--seam-2); position: relative; }
.stops span::after { content: ""; position: absolute; right: -5px; top: 50%; width: 10px; height: 10px; margin-top: -5px; border-radius: 50%; border: 2.5px solid var(--seam-2); background: var(--plate); box-sizing: border-box; transition: background var(--t), border-color var(--t); }
.stops span.done { background: var(--accent); }
.stops span.done::after { background: var(--accent); border-color: var(--accent); }
.stops span.now::after { border-color: var(--accent); transform: scale(1.3); }
.question-card { max-width: 860px; margin: 14px auto; padding: 30px; }
.question-card h2 { margin: 0 0 16px; font-size: 20px; }
.question-display { font-size: 52px; line-height: 1.2; padding: 4px 0 18px; overflow-wrap: anywhere; }
.answer-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.answer-choice { text-align: left; border: 1px solid var(--seam-2); background: var(--plate-2); border-radius: var(--r); min-height: 60px; padding: 12px 16px; color: var(--ink); transition: border-color var(--t), background var(--t); }
.answer-choice:hover { border-color: var(--ink); background: var(--plate); }
.answer-form { display: flex; align-items: center; gap: 10px; margin: 18px 0; }
.answer-form input { font-size: 20px; min-width: 0; flex: 1; margin: 0; }
.answer-form button { flex-shrink: 0; }
.speech-panel { border-top: 1px solid var(--seam); margin-top: 20px; padding-top: 8px; }
.speech-panel audio { width: 100%; margin: 12px 0; }
.transcript { font-size: 22px; overflow-wrap: anywhere; font-family: var(--han); }
.answer-feedback:not(:empty) { margin: 20px 0 0; border-radius: var(--r-l); overflow: hidden; border: 1px solid var(--seam); background: var(--plate-2); }
.answer-feedback > strong { display: block; padding: 10px 16px; background: var(--ok); color: var(--on-line); font-size: 14px; letter-spacing: .02em; }
.answer-feedback.incorrect > strong { background: var(--bad); }
.answer-feedback.review > strong { background: var(--warn); }
.answer-feedback p { margin: 10px 16px; }
.answer-feedback > .hsk-audio-button, .answer-feedback > .action { margin: 4px 16px 14px; }
.result-total { font-size: 28px; font-weight: 800; letter-spacing: -.02em; }
.result-list { padding-left: 20px; }
.result-list li { margin: 6px 0; }
progress { display: block; width: 100%; height: 6px; border: 0; border-radius: 6px; margin: 14px 0; }
.audio-inline { margin-left: 8px; }
.practice-card input[type=file] { max-width: 100%; }
#progress-view input, #progress-view select, #audio-settings input, #audio-settings select { max-width: 100%; }
.danger { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--seam); }
.danger p { margin: 0 0 10px; }
#progress-view section, #progress-view details { margin-top: 28px; }
#progress-view details > summary { padding: 6px 0; }

/* ---------- audio buttons and settings ---------- */
.hsk-audio-button {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13px; font-weight: 600; min-height: 32px; padding: 4px 10px;
  border: 1px solid var(--seam-2); background: var(--plate); color: var(--ink);
  border-radius: 999px; cursor: pointer; max-width: 100%; white-space: normal;
  transition: border-color var(--t), background var(--t);
}
.hsk-audio-button:hover { border-color: var(--ink); }
.hsk-audio-button:disabled { opacity: .55; cursor: wait; }
.hsk-audio-settings { display: grid; gap: 14px; }
.hsk-audio-card { background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); padding: 20px 22px; }
.hsk-audio-card h2, .hsk-audio-card h3 { margin: 0 0 8px; }
.hsk-audio-card h2 { font-size: 18px; }
.hsk-audio-card p { line-height: 1.55; }
.hsk-audio-card > p, .hsk-audio-note { color: var(--ink-2); font-size: 13px; }
.hsk-audio-fields { display: flex; flex-wrap: wrap; gap: 10px; align-items: end; margin: 12px 0; }
.hsk-audio-field { display: flex; flex-direction: column; gap: 0; min-width: 180px; flex: 1; font-size: 13px; font-weight: 650; color: var(--ink-2); }
.hsk-audio-field input[type=file] { width: 100%; }
.hsk-audio-card button { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 7px 14px; border: 1px solid var(--seam-2); border-radius: var(--r); background: var(--plate); color: var(--ink); cursor: pointer; transition: border-color var(--t); }
.hsk-audio-card button:hover { border-color: var(--ink); }
.hsk-audio-card button:disabled { opacity: .5; cursor: default; }
.hsk-audio-status { min-height: 1.5em; padding: 6px 0; color: var(--ink-2); white-space: pre-wrap; overflow-wrap: anywhere; font-size: 13px; }
.hsk-audio-warning { color: var(--warn); }
.hsk-audio-review { display: flex; align-items: flex-start; gap: 8px; margin: 12px 0; line-height: 1.45; font-size: 14px; }
.hsk-audio-review input { margin-top: .25rem; }
.hsk-audio-card details { border-top: 0; margin: 0; padding: 0; }
.hsk-audio-card details > summary { font-size: 18px; font-weight: 700; }
.hsk-audio-card details[open] > summary { margin-bottom: 8px; }
.microphone-card { border: 1px solid var(--seam); background: var(--plate); border-radius: var(--r-l); padding: 20px 22px; margin: 0; }
.microphone-card h3 { margin: 0 0 6px; font-size: 18px; }
.microphone-card p { margin: 6px 0; }
.microphone-error { color: var(--bad); }
.settings-grid { display: grid; gap: 14px; }
.settings-card { background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); padding: 20px 22px; }
.settings-card h3 { font-size: 18px; margin-bottom: 6px; }
.segmented { display: inline-flex; border: 1px solid var(--seam-2); border-radius: var(--r); overflow: hidden; margin-top: 10px; }
.segmented button { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 16px; border: 0; border-right: 1px solid var(--seam-2); background: var(--plate); color: var(--ink-2); font-weight: 600; transition: background var(--t), color var(--t); }
.segmented button:last-child { border-right: 0; }
.segmented button:hover { color: var(--ink); }
.segmented button[aria-pressed="true"] { background: var(--inverse); color: var(--on-inverse); }
.segmented button:focus-visible { outline-offset: -3px; }

/* ---------- on-screen keyboards ---------- */
.pinyin-kb-wrap, .hanzi-kb-wrap { margin: 8px 0 14px; }
.pinyin-kb-toggle { margin: 0; white-space: nowrap; min-height: 40px; display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; border-color: var(--seam-2); background: var(--plate); color: var(--ink); }
.pinyin-kb-toggle.active { background: var(--inverse); border-color: var(--inverse); color: var(--on-inverse); }
.pinyin-kb { background: var(--plate); border: 1px solid var(--seam); border-radius: var(--r-l); padding: 14px 16px; margin-top: 8px; }
.pinyin-kb-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--seam); }
.pinyin-kb-title-wrap { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.pinyin-kb-title { font-size: 13px; font-weight: 650; }
.pinyin-kb-hint { font-size: 12px; color: var(--ink-2); }
.pinyin-kb-options { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pinyin-kb-check { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; cursor: pointer; }
.pinyin-kb-check input { width: 15px; height: 15px; margin: 0; }
.pinyin-kb-subtoggle { border: 1px solid var(--seam-2); border-radius: var(--r); background: var(--plate); color: var(--ink); font-size: 12px; font-weight: 600; padding: 5px 10px; min-height: 32px; }
.pinyin-kb-subtoggle:hover { border-color: var(--ink); }
.pinyin-kb-status { font-size: 12px; color: var(--ink); background: var(--plate-2); border: 1px solid var(--seam-2); padding: 6px 10px; border-radius: var(--r); margin-bottom: 10px; }
.pinyin-kb-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.pinyin-kb-tones, .pinyin-kb-utils { display: flex; gap: 6px; flex-wrap: wrap; }
.pinyin-key { border: 1px solid var(--seam-2); border-radius: var(--r); background: var(--plate); color: var(--ink); padding: 6px 11px; min-width: 40px; min-height: 40px; display: inline-flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1.15; transition: background var(--t), border-color var(--t), transform 60ms; user-select: none; }
.pinyin-key:hover:not(:disabled) { border-color: var(--ink); }
.pinyin-key:active:not(:disabled) { transform: translateY(1px); background: var(--plate-2); }
.pinyin-key:disabled { opacity: .45; cursor: default; }
.pinyin-key-tone { min-width: 58px; padding: 6px 10px; background: var(--plate-2); }
.pinyin-key-util { min-width: 52px; padding: 6px 10px; }
.pinyin-key-main { font-size: 16px; font-weight: 650; }
.pinyin-key-sub { font-size: 10px; color: var(--ink-3); margin-top: 2px; }
.pinyin-kb-vowels { display: grid; grid-template-columns: repeat(auto-fit, minmax(195px, 1fr)); gap: 8px; }
.pinyin-vowel-group { display: flex; align-items: center; gap: 4px; background: var(--plate-2); border: 1px solid var(--seam); border-radius: var(--r); padding: 4px 6px; }
.pinyin-vowel-label { font-size: 12px; font-weight: 750; color: var(--ink-2); min-width: 18px; text-align: center; text-transform: lowercase; }
.pinyin-key-vowel { flex: 1; min-width: 32px; min-height: 34px; padding: 4px 6px; font-size: 17px; font-weight: 550; }
.pinyin-kb-letters { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--seam-2); display: grid; gap: 8px; }
.pinyin-kb-letter-row { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.pinyin-letter-label { font-size: 11px; font-weight: 650; color: var(--ink-3); min-width: 58px; }
.pinyin-key-letter { min-width: 34px; min-height: 32px; padding: 4px 8px; font-size: 14px; font-weight: 550; }
.hanzi-kb-nav { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.hanzi-kb-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
.hanzi-kb-tab { border: 1px solid var(--seam-2); border-radius: var(--r); background: var(--plate); color: var(--ink-2); font-size: 12px; font-weight: 650; padding: 6px 11px; min-height: 32px; }
.hanzi-kb-tab:hover { border-color: var(--ink); color: var(--ink); }
.hanzi-kb-tab.active { background: var(--inverse); border-color: var(--inverse); color: var(--on-inverse); }
.hanzi-kb-filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.hanzi-kb-select, .hanzi-kb-search { width: auto; min-height: 36px; font-size: 13px; margin: 0; }
.hanzi-kb-search { flex: 1; min-width: 180px; }
.hanzi-kb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(58px, 1fr)); gap: 6px; max-height: 270px; overflow-y: auto; padding: 2px; }
.hanzi-key { min-height: 52px; padding: 6px 4px; }
.hanzi-key-char { font-family: var(--han); font-size: 24px; line-height: 1.15; }
.hanzi-key-py { font-size: 10px; color: var(--ink-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.hanzi-kb-pager { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--seam); font-size: 12px; }
.hanzi-kb-pager-btns { display: flex; gap: 6px; }
.hanzi-kb-empty { grid-column: 1 / -1; margin: 8px 0; }

/* ---------- explainer and footer ---------- */
details#study-method { margin-top: 36px; border-top: 1px solid var(--seam); padding: 16px 0 0; }
summary { cursor: pointer; font-weight: 650; list-style: none; display: flex; align-items: center; gap: 10px; }
summary::-webkit-details-marker { display: none; }
summary::before { content: ""; width: 8px; height: 8px; flex: none; border-right: 1.75px solid currentColor; border-bottom: 1.75px solid currentColor; transform: rotate(-45deg) translate(-1px, -1px); transition: transform var(--t); }
details[open] > summary::before { transform: rotate(45deg) translate(-2px, -2px); }
input[type=file] { color: var(--ink-2); font-size: 13px; }
input[type=file]::file-selector-button { font: inherit; font-size: 14px; color: var(--ink); background: var(--plate); border: 1px solid var(--seam-2); border-radius: var(--r); padding: 6px 12px; margin-right: 10px; cursor: pointer; transition: border-color var(--t); }
input[type=file]::file-selector-button:hover { border-color: var(--ink); }
details p, details li { font-size: 13px; color: var(--ink-2); max-width: 78ch; }
footer { font-size: 12px; color: var(--ink-3); margin-top: 32px; border-top: 1px solid var(--seam); padding-top: 18px; }
#session-history h2 { margin: 0 0 4px; }

/* ---------- root start page ---------- */
.start { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.start-card { width: min(560px, 100%); display: grid; gap: 14px; }
.start h1 { font-size: 34px; letter-spacing: -.03em; display: flex; align-items: center; gap: 14px; }
.start h1 .brand-mark { width: 44px; height: 44px; font-size: 22px; border-width: 4px; }
.start nav ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 8px; }
.start nav a { display: flex; align-items: center; gap: 10px; padding: 12px; border: 1px solid var(--seam); border-radius: var(--r); background: var(--plate); color: var(--ink); text-decoration: none; }
.start nav a:hover { border-color: var(--ink); }

/* ---------- state helpers and the one authored motion: the hop ---------- */
html[data-effective="dark"] .theme-moon { display: none; }
html:not([data-effective="dark"]) .theme-sun { display: none; }
.language-lock-note { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@keyframes hop { from { opacity: 0; transform: translateY(8px); } }
.board tbody.hop, .network-rows.hop, .network-lines.hop { animation: hop 220ms cubic-bezier(.2, .7, .2, 1); }
@keyframes arrive { from { opacity: 0; transform: scale(.6); } }
.route .stop[aria-current="true"] { animation: arrive 220ms cubic-bezier(.2, .7, .2, 1); }

/* ---------- responsive ---------- */
@media (max-width: 1100px) {
  .bar-top { padding: 0 16px; }
  .line-nav { padding: 0 16px; }
  .network { grid-template-columns: 224px 48px minmax(0, 1fr) 28px fit-content(260px); }
}
@media (max-width: 760px) {
  main { padding: 0 16px 56px; }
  .brand > span:last-child { display: none; }
  .bar-tools .label { display: none; }
  .line-nav { --stop-gap: 18px; }
  .line-nav button { flex: none; font-size: 14px; line-height: 18px; padding: 12px 14px var(--stop-gap); }
  .lang-button .lang-code { display: none; }
  .sign { grid-template-columns: 1fr auto; gap: 10px 16px; padding: 18px 0 14px; align-items: start; }
  .sign h1 { font-size: 22px; }
  .sign-sub { margin-top: 10px; font-size: 11px; }
  .sign-lead { font-size: 14px; }
  .roundel-hero { width: 64px; height: 64px; border-width: 3px; font-size: 36px; margin-top: 2px; box-shadow: inset 0 0 0 2px var(--plate); }
  .legend { gap: 6px 16px; padding-top: 10px; font-size: 12px; }
  .legend li { white-space: nowrap; }
  .toolbar label { flex: 1 1 140px; }
  .toolbar .search-wrap { flex: 1 1 200px; }
  .toolbar .pinyin-kb-toggle { width: 40px; padding: 0; justify-content: center; font-size: 0; gap: 0; }
  .toolbar .pinyin-kb-toggle .i { width: 20px; height: 20px; }
  /* stacked network: the station as a compact plate, the words hanging off one vertical rail */
  .network { grid-template-columns: 1fr; row-gap: 14px; }
  .network-lines { display: none; }
  .station, .network-map { grid-column: 1; }
  .station { display: block; }
  .station > .eyebrow { display: none; }
  .station-body { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 14px; align-items: center; }
  .station-body .notice, .station-body .character-audio, .station-body .family-actions { grid-column: 1 / -1; }
  .station-body .root { grid-column: 1; grid-row: 1 / span 3; margin: 6px 0; }
  .station-body h2, .station-body #root-info, .station-body #family-count { grid-column: 2; }
  .net-stop .net-meta { white-space: normal; overflow: visible; }
  .board-fold > summary { pointer-events: auto; justify-content: flex-start; align-items: center; gap: 10px; }
  .board-fold > summary::before { display: block; }
  .board-fold > summary .muted { flex-basis: 100%; }
  .station h2 { font-size: 20px; margin: 0; }
  .station .notice { margin-top: 10px; }
  .station .character-audio { margin: 10px 0 4px; }
  .root .roundel { width: 64px; height: 64px; font-size: 34px; border-width: 3px; box-shadow: inset 0 0 0 2px var(--plate); }
  .family-actions { flex-direction: row; flex-wrap: wrap; align-items: center; width: auto; }
  .network-head { display: none; }
  .network-map, .network-rows, .network-row { grid-template-columns: 1fr; }
  .network-rows { margin-left: 10px; padding-left: 22px; border-left: 3px solid var(--ink); row-gap: 12px; }
  .network-row { gap: 8px; }
  .network-row .link { display: none; }
  /* phone plate: the word on the left, pinyin and gloss at full measure, level pill and play beneath them */
  .net-stop { padding: 10px 12px 10px 14px; min-height: 0; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; }
  .net-stop .han { grid-row: 1 / span 2; }
  .net-stop .net-tail { grid-column: 2; justify-self: start; }
  .net-stop .mark { left: -36px; }
  .net-next { padding-left: 4px; }
  .pager { flex-wrap: wrap; }
  .board { min-width: 0; }
  .board thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .board tr { display: grid; grid-template-columns: 1fr; gap: 4px; padding: 12px 14px 14px 44px; border-top: 1px solid var(--seam); position: relative; }
  .board tr:first-child { border-top: 0; }
  .board td { display: block; padding: 0; border: 0; }
  .board td:first-child { padding-left: 0; position: static; }
  .board td:first-child::before { left: 18px; top: 0; bottom: 0; }
  .board tr:first-child td:first-child::before { top: 50%; }
  .board tr:last-child td:first-child::before { bottom: 50%; }
  .board td:first-child::after { left: 13px; }
  .b-py { font-size: 14px; }
  .b-id { margin-top: 4px; }
  .next { margin-top: 6px; }
  .question-card, .practice-card { padding: 18px; }
  .answer-choices { grid-template-columns: 1fr; }
  .answer-form { flex-wrap: wrap; }
  .answer-form input { flex-basis: 100%; }
  .practice-fields { grid-template-columns: 1fr; }
  .question-display { font-size: 40px; }
  .session-answer { padding: 14px; }
  .pinyin-kb { padding: 11px; }
  .pinyin-kb-vowels { grid-template-columns: 1fr; }
  .pinyin-vowel-group { flex-wrap: wrap; }
  .pinyin-key-tone, .pinyin-key-util { flex: 1; min-width: 46px; }
  .hanzi-kb-grid { grid-template-columns: repeat(auto-fill, minmax(50px, 1fr)); }
  .index-stops { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0ms !important; animation: none !important; }
}
