/* ====================================================================
   flashcard.css · HSK-1 vocabulary trainer in the very-bad-deep-slate
   brand.  Editorial register on a parchment ground with slate-deep
   accent — adds Noto Sans SC for Chinese character display.
   ==================================================================== */

:root {
  /* Ground · warm neutrals */
  --parchment:  #f5f4ed;
  --ivory:      #faf9f5;
  --sand:       #e8e6dc;
  --border:     #c1bca6;
  --hairline:   #c9c5b4;

  /* Ink */
  --near-black: #141413;
  --dark-warm:  #2e2e2c;
  --olive:      #4a4845;
  --stone:      #6b6a64;
  --mute:       #7e7c75;

  /* Brand · slate-deep */
  --brand:      #324C62;
  --brand-soft: #5C7A92;
  --brand-pale: #B6C5D2;

  /* Severity (kept for status pills) */
  --ok:         #5d6f3f;  --ok-soft:     #e9ecdf;
  --warn:       #9c6e1e;  --warn-soft:   #f3eadb;
  --danger:     #8e3d3a;  --danger-soft: #f0dedb;
  --info:       #4d6a82;  --info-soft:   #e2eaf0;

  /* Fonts */
  --display: "Inter", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --body:    "Satoshi", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;
  --mono:    "FiraCode Nerd Font Mono", "FiraCode NFM", "Fira Code",
             "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  --cn:      "Noto Sans SC", "PingFang SC", "Hiragino Sans GB",
             "Microsoft YaHei", "Source Han Sans SC", sans-serif;

  --space-section: 36px;
  --space-block:   24px;
  --space-item:    12px;
  --radius:    5px;
  --radius-sm: 3px;
}

[data-theme="dark"] {
  --parchment:  #2e2e2c;
  --ivory:      #3e3e3b;
  --sand:       #4a4845;
  --border:     #767368;
  --hairline:   #4a4843;

  --near-black: #f0eee2;
  --dark-warm:  #d8d6c8;
  --olive:      #b8b5a8;
  --stone:      #6e6b62;
  --mute:       #9e9b91;

  --brand:      #95b3ca;
  --brand-soft: #b6c5d2;
  --brand-pale: #6e8aa3;

  --ok:         #a3b884;  --ok-soft:     #4a5b3b;
  --warn:       #d6a772;  --warn-soft:   #5e4c2c;
  --danger:     #d4928a;  --danger-soft: #5e3a37;
  --info:       #c5d4e0;  --info-soft:   #3e526a;
}

/* Reset */
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
  background: var(--parchment);
  color: var(--near-black);
  min-height: 100vh;
}
body {
  font: 18px/1.6 var(--body);
  -webkit-font-smoothing: antialiased;
  font-feature-settings: "calt" 1;
  accent-color: var(--brand);
}

/* Page frame */
.app {
  max-width: 880px;
  margin: 0 auto;
  padding: 56px 40px 48px;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

/* Screen state · only one visible at a time */
.screen { display: none; flex: 1 1 auto; flex-direction: column; }
.screen.active { display: flex; }
@media (max-width: 720px) {
  .app { padding: 28px 18px 32px; }
}
@media (max-width: 480px) {
  .app { padding: 22px 14px 24px; }
}

/* Theme toggle · top-right */
.theme-toggle {
  position: absolute;
  top: 18px; right: 18px;
  z-index: 10;
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--mute);
  padding: 5px 10px 5px 9px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--ivory);
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease, background .12s ease;
}
.theme-toggle:hover {
  color: var(--brand); border-color: var(--brand); background: var(--parchment);
}
.theme-toggle .icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 14px; height: 14px; line-height: 1;
}
.theme-toggle .icon svg { width: 14px; height: 14px; display: block; }
/* Light theme · show sun, hide moon. Dark theme inverts. */
.theme-toggle .ico-moon { display: none; }
[data-theme="dark"] .theme-toggle .ico-sun  { display: none; }
[data-theme="dark"] .theme-toggle .ico-moon { display: block; }
@media (max-width: 720px) {
  .theme-toggle .label { display: none; }
  .theme-toggle { padding: 6px 8px; top: 14px; right: 14px; }
}

/* ─── Top bar · single line: brand + user/action ─────────────────
   Replaces the older eyebrow-row + doc-id + greeting stack. */
.topbar {
  display: flex; justify-content: space-between; align-items: center;
  gap: 14px; flex-wrap: wrap;
  padding: 0 0 10px;
  margin-bottom: 22px;
  border-bottom: .5px solid var(--hairline);
}
.topbar .brand-mark {
  font-family: var(--display);
  font-size: 11.5px; font-weight: 700;
  color: var(--brand);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  display: inline-flex; align-items: center; gap: 8px;
}
.topbar .brand-mark::before {
  content: ""; display: inline-block;
  width: 22px; height: 1px; background: var(--brand);
}
.topbar .brand-mark code {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 600;
  color: var(--near-black);
  background: transparent;
  padding: 0;
  letter-spacing: 0;
  text-transform: none;
}
.topbar .switch {
  background: transparent;
  border: 0;
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  color: var(--mute);
  letter-spacing: 0.12em; text-transform: uppercase;
  cursor: pointer;
  padding: 4px 0;
  transition: color .12s ease;
}
.topbar .switch:hover { color: var(--brand); }

h1 {
  font-family: var(--display);
  font-size: 28px; font-weight: 700;
  line-height: 1.06; letter-spacing: -0.04em;
  color: var(--near-black);
  margin-bottom: 8px;
  max-width: 24ch;
}
.lead {
  font-family: var(--body);
  font-size: 16.5px; font-weight: 400;
  line-height: 1.55;
  color: var(--olive);
  max-width: 70ch;
  margin-bottom: var(--space-block);
}

/* ─── Controls bar ──────────────────────────────────────────────── */
.controls {
  display: flex;
  gap: 14px;
  align-items: stretch;
  flex-wrap: wrap;
  background: var(--ivory);
  border: .5px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: var(--space-block);
}
.ctrl-group {
  display: flex; flex-direction: column; gap: 6px;
  flex: 1 1 auto; min-width: 0;
}
.ctrl-group .lbl {
  font-family: var(--display);
  font-size: 10.5px; font-weight: 700;
  color: var(--mute);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.seg {
  display: inline-flex;
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--parchment);
  overflow: hidden;
}
.seg button {
  flex: 1 1 auto;
  font-family: var(--display);
  font-size: 11.5px; font-weight: 700;
  color: var(--olive);
  letter-spacing: 0.12em; text-transform: uppercase;
  background: transparent;
  border: 0;
  padding: 8px 14px;
  cursor: pointer;
  transition: color .12s ease, background .12s ease;
}
.seg button:not(:last-child) { border-right: .5px solid var(--border); }
.seg button[aria-pressed="true"] {
  background: var(--brand); color: var(--parchment);
}
.seg button:not([aria-pressed="true"]):hover {
  color: var(--brand); background: var(--ivory);
}

/* Toggle · for pinyin show/hide */
.toggle-switch {
  display: inline-flex; align-items: center; gap: 10px;
  cursor: pointer; user-select: none;
}
.toggle-switch input { position: absolute; opacity: 0; pointer-events: none; }
.toggle-switch .track {
  width: 38px; height: 22px;
  border-radius: 11px;
  background: var(--hairline);
  border: .5px solid var(--border);
  position: relative;
  transition:
    background-color .25s cubic-bezier(0.4, 0, 0.2, 1),
    border-color .25s cubic-bezier(0.4, 0, 0.2, 1);
}
.toggle-switch .track::after {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: 16px; height: 16px;
  border-radius: 50%;
  background: var(--ivory);
  border: .5px solid var(--border);
  box-shadow: 0 1px 2px rgba(20, 20, 19, 0.08);
  transition:
    left .25s cubic-bezier(0.34, 1.56, 0.64, 1),
    border-color .25s cubic-bezier(0.4, 0, 0.2, 1);
}
.toggle-switch input:checked ~ .track { background: var(--brand); border-color: var(--brand); }
.toggle-switch input:checked ~ .track::after { left: 18px; border-color: var(--brand); }
.toggle-switch .text {
  font-family: var(--display);
  font-size: 12px; font-weight: 600;
  color: var(--olive);
  letter-spacing: 0.06em; text-transform: uppercase;
}
.toggle-switch input:checked ~ .text { color: var(--brand); }

/* ─── Flashcard ─────────────────────────────────────────────────── */
.deck {
  flex: 1 1 auto;
  display: flex; flex-direction: column;
  align-items: stretch;
}

/* The card is now the 3D perspective container — visual styling lives
   on .card-face so both front and back show the bordered ivory surface. */
.card {
  position: relative;
  min-height: 380px;
  perspective: 2000px;
  cursor: pointer;
  user-select: none;
  background: transparent;
  border: 0;
  padding: 0;
}
/* Vertical centering · push the card and nav into the middle of the
   round screen so they sit between the topbar and the page bottom
   rather than pinned to the top. */
#screen-round.active .card { margin-top: auto; }
#screen-round.active .nav  { margin-bottom: auto; }
.card-flipper {
  position: relative;
  width: 100%;
  min-height: 380px;
  transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(0.34, 1.18, 0.64, 1);
}
.card.revealed .card-flipper { transform: rotateY(180deg); }

.card-face {
  position: absolute;
  inset: 0;
  display: flex; flex-direction: column;
  align-items: stretch; justify-content: space-between;
  background: var(--ivory);
  border: .5px solid var(--border);
  border-radius: var(--radius);
  border-left: 2.6px solid var(--brand);
  padding: 28px 32px 24px;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  transition: border-color .12s ease;
}
.card-back { transform: rotateY(180deg); }

.card:hover .card-face { border-left-color: var(--brand-soft); }

/* Suppress pointer events on the hidden face so mark buttons aren't
   activated through the card while it's still front-side. */
.card:not(.revealed) .card-back  { pointer-events: none; }
.card.revealed       .card-front { pointer-events: none; }

/* No-flip · used during card-change so the rotation snaps without
   showing the next card's answer through the briefly-visible back face */
.card.no-flip .card-flipper { transition: none; }

/* Flipping-next · the card-change flip-back animation.  Overrides the
   default spring bezier with a symmetric ease-in-out so the 90° edge-on
   position lands *exactly* at the 350 ms midpoint of the .7s rotation.
   That midpoint is when nextCard() swaps the round content, hidden
   behind the invisible edge-on faces. */
.card.flipping-next .card-flipper {
  transition: transform .7s ease-in-out;
}

/* Honor reduced-motion preference — instant swap, no rotation */
@media (prefers-reduced-motion: reduce) {
  .card-flipper { transition: none; }
}

.card-top {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 12px;
  min-height: 28px;
}
.card-top .pinyin {
  font-family: var(--mono);
  font-size: 22px; font-weight: 500;
  color: var(--brand);
  letter-spacing: 0.02em;
  font-feature-settings: "calt" 1;
  opacity: 1;
  transition: opacity .15s ease;
}
.card-top .pinyin.hidden { opacity: 0; visibility: hidden; }
.card-top .progress {
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  color: var(--mute);
  letter-spacing: 0.14em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.card-body {
  flex: 1 1 auto;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  text-align: center;
  padding: 24px 8px;
  min-height: 220px;
}

.q-character {
  font-family: var(--cn);
  font-weight: 500;
  font-size: clamp(96px, 16vw, 168px);
  line-height: 1;
  color: var(--near-black);
  letter-spacing: 0;
}
.q-meaning {
  font-family: var(--body);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 38px);
  line-height: 1.25;
  color: var(--near-black);
  letter-spacing: -0.01em;
  max-width: 22ch;
}

/* Answer · always rendered on the back face; visibility comes from
   the flipper's backface-visibility, no display toggle needed. */
.answer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  width: 100%;
}
.answer .a-character {
  font-family: var(--cn);
  font-weight: 500;
  font-size: clamp(40px, 6vw, 64px);
  line-height: 1;
  color: var(--brand);
}
.answer .a-meaning {
  font-family: var(--body);
  font-size: clamp(18px, 2.4vw, 24px);
  font-weight: 400;
  color: var(--dark-warm);
  letter-spacing: -0.01em;
  max-width: 32ch;
}
.answer .a-pinyin {
  font-family: var(--mono);
  font-size: 16px;
  color: var(--brand);
  font-feature-settings: "calt" 1;
}
.answer .a-meta {
  display: flex; gap: 8px; flex-wrap: wrap; justify-content: center;
  margin-top: 4px;
}

.pos-pill,
.lvl-pill {
  display: inline-flex; align-items: center;
  font-family: var(--display);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 4px 9px;
  border-radius: var(--radius-sm);
  border: .5px solid var(--hairline);
  background: var(--parchment);
  color: var(--mute);
}
.pos-pill { color: var(--brand); border-color: var(--brand-pale); }
.lvl-pill { color: var(--olive); }

.card-foot {
  display: flex; justify-content: flex-start; align-items: center;
  gap: 14px; flex-wrap: wrap;
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  color: var(--mute);
  letter-spacing: 0.12em; text-transform: uppercase;
  margin-top: 12px;
  text-align: left;
}
.card-foot .hint {
  font-family: var(--body);
  text-transform: none; letter-spacing: 0;
  font-weight: 400; font-size: 13px;
  color: var(--mute);
  margin-left: auto;   /* anchors the hint to the bottom-right corner */
  /* Always reserve the hint's line box — even when empty — so the foot
     row keeps a constant height and the centered card body doesn't shift
     up when the "Marked …" text appears. line-height and min-height must
     match exactly so the empty and filled states are pixel-identical. */
  line-height: 1.4;
  min-height: 1.4em;
  white-space: nowrap;
}
.card.revealed .hint { color: var(--brand); }

/* ─── Nav row · buttons centered, keys hint below ───────────────── */
.nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
}
.nav-buttons {
  display: flex;
  justify-content: center;
  perspective: 1400px;
}
/* Flipper · same rotateY trick as the card. Both faces share one grid
   cell (so the row sizes to the wider mark-button pair and never
   reflows) and rotate together on the card's .revealed state. */
.nav-flipper {
  display: grid;
  justify-items: center;
  align-items: center;
  transform-style: preserve-3d;
  transition: transform .7s cubic-bezier(0.34, 1.18, 0.64, 1);
}
.nav-flipper > .nav-q,
.nav-flipper > .nav-a-group {
  grid-area: 1 / 1;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
}
.nav-a-group {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  justify-content: center;
  transform: rotateY(180deg);
}
/* Lock the Reveal button width so toggling to "Hide" doesn't reflow
   the row. Mark buttons (Missed it / Got it) have their own min-width
   in the .btn.mark-wrong/.mark-correct rules. */
#reveal-btn { min-width: 110px; }
.btn {
  font-family: var(--display);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  padding: 10px 18px;
  background: var(--parchment);
  color: var(--brand);
  border: .5px solid var(--brand);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.btn:hover { background: var(--brand); color: var(--parchment); }
.btn.solid { background: var(--brand); color: var(--parchment); }
.btn.solid:hover { background: var(--brand-soft); border-color: var(--brand-soft); }
.btn.icon { padding: 9px 12px; }
.btn[disabled] { opacity: .45; cursor: not-allowed; }

.nav .keys {
  text-align: center;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--mute);
  font-feature-settings: "calt" 1;
}
.nav .keys kbd {
  display: inline-block;
  font-family: var(--mono);
  font-size: 10.5px;
  padding: 2px 6px;
  border-radius: 3px;
  border: .5px solid var(--border);
  background: var(--ivory);
  color: var(--olive);
  margin: 0 2px;
}

/* Footer */
.foot {
  margin-top: var(--space-section);
  padding-top: 14px;
  border-top: .5px solid var(--brand);
  font-family: var(--display);
  font-size: 12px; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  color: var(--stone);
}
.foot .left { color: var(--brand); font-weight: 700; }
.foot .mid  { color: var(--mute);  font-weight: 500; }
.foot a {
  color: var(--brand);
  font-weight: 700;
  text-decoration: underline;
  text-decoration-color: var(--brand-pale);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}
.foot a:hover { text-decoration-color: var(--brand); }

/* ─── Login screen ─────────────────────────────────────────────── */
#screen-login.active {
  /* Soft vertical centering for a welcome feel */
  justify-content: center;
  padding: 32px 0;
}
.login-wrap {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: 56px;
  align-items: center;
  max-width: 880px;
  width: 100%;
  margin: 0 auto;
}
.login-intro h1 {
  font-size: clamp(28px, 3.6vw, 40px);
  letter-spacing: -0.04em;
  line-height: 1.04;
  max-width: 22ch;
  margin-bottom: 14px;
  margin-top: 0;
}
.login-intro h1 .zh {
  font-family: "Noto Sans SC", var(--display);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--brand);
  display: inline-block;
  margin-right: 4px;
}
.login-intro h1 .en {
  display: block;
  font-family: var(--display);
  font-weight: 400;
  font-style: italic;
  font-size: 0.62em;
  letter-spacing: -0.02em;
  color: var(--olive);
  margin-top: 6px;
}
.login-intro .lead {
  font-size: 16.5px;
  color: var(--olive);
  max-width: 38ch;
  margin: 0;
}

.login-card {
  background: var(--ivory);
  border: .5px solid var(--border);
  border-radius: var(--radius);
  padding: 26px 28px 22px;
  position: relative;
  /* Subtle elevation for the auth card so it reads as primary */
  box-shadow: 0 1px 0 var(--hairline), 0 12px 32px rgba(20, 20, 19, 0.04);
}
.login-card::before {
  /* Brand bar — top edge, full width, a touch thicker than the callout bar */
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0; height: 3px;
  background: var(--brand);
  border-radius: var(--radius) var(--radius) 0 0;
}
.login-card .login-hint {
  font-size: 12.5px;
  color: var(--mute);
  margin: 12px 0 0;
  font-style: italic;
  text-align: center;
}

/* Restore section · returning users with an existing key */
.login-restore { margin-top: 4px; }
.login-restore #restore-key {
  font-family: var(--mono);
  font-size: 15px;
  font-feature-settings: "calt" 1;
  letter-spacing: 0.02em;
  color: var(--brand);
  background: var(--parchment);
}
.login-restore #restore-key::placeholder {
  color: var(--mute);
  opacity: .5;
  letter-spacing: 0;
}
.login-restore .btn { width: 100%; }
.login-intro .intro-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  padding: 8px 14px 8px 12px;
  font-family: var(--display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--brand);
  background: transparent;
  border: 1px solid var(--brand-pale);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: color .15s ease, border-color .15s ease, background .15s ease, transform .15s ease;
}
.login-intro .intro-link svg {
  width: 14px; height: 14px;
  flex-shrink: 0;
  stroke-width: 1.9;
}
.login-intro .intro-link svg.chev {
  width: 13px; height: 13px;
  margin-left: 2px;
  transition: transform .15s ease;
}
.login-intro .intro-link:hover {
  color: var(--parchment);
  background: var(--brand);
  border-color: var(--brand);
}
.login-intro .intro-link:hover svg.chev { transform: translateX(2px); }

.field {
  display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 12px;
}
.field label,
.field > .lbl {
  font-family: var(--display);
  font-size: 10.5px; font-weight: 700;
  color: var(--mute);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.field input[type="text"],
.field input[type="number"] {
  font-family: var(--body);
  font-size: 16px;
  color: var(--near-black);
  background: var(--parchment);
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  outline: none;
  transition: border-color .12s ease, background .12s ease;
}
.field input:focus {
  border-color: var(--brand);
  background: var(--ivory);
  box-shadow: 0 0 0 3px var(--info-soft);
}
.field input::placeholder { color: var(--mute); opacity: .7; }

.login-form {
  display: flex; flex-direction: column;
}
.login-form .btn { width: 100%; padding: 12px 20px; }

/* Recovery passphrase · readonly input + copy + regenerate buttons */
.passphrase-row {
  display: flex; gap: 6px; align-items: stretch;
}
.passphrase-display {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  font-family: var(--mono);
  font-feature-settings: "calt" 1;
  letter-spacing: 0.02em;
  font-size: 15px;
  font-weight: 600;
  color: var(--brand);
  background: var(--ivory);
  border: 1px solid var(--brand-pale);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  user-select: all;
  cursor: default;
  outline: none;
  min-height: 44px;
}
.passphrase-display:focus-visible {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--info-soft);
}
.btn.pp-action,
.btn.subtle.pp-action {
  flex: 0 0 auto;
  padding: 0 14px;
  font-family: var(--display);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--brand);
  border-color: var(--border);
  background: var(--ivory);
}
.btn.pp-action:hover,
.btn.subtle.pp-action:hover {
  color: var(--parchment);
  background: var(--brand);
  border-color: var(--brand);
}
#regen-btn { width: 44px; padding: 0; font-size: 16px; font-weight: 400; letter-spacing: 0; }

/* Save-this warning · sand-tinted callout */
.passphrase-warn {
  font-size: 13px;
  color: var(--olive);
  background: var(--warn-soft);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-top: 4px;
  margin-bottom: 14px;
  line-height: 1.45;
}
.passphrase-warn strong {
  font-weight: 700;
  color: var(--warn);
}

.login-divider {
  position: relative;
  text-align: center;
  margin: 16px 0 14px;
  font-family: var(--display);
  font-size: 10px; font-weight: 700;
  color: var(--mute);
  letter-spacing: 0.18em; text-transform: uppercase;
}
.login-divider::before {
  content: "";
  position: absolute; top: 50%; left: 0; right: 0;
  height: .5px; background: var(--hairline);
}
.login-divider span {
  position: relative;
  background: var(--ivory);
  padding: 0 10px;
}

.user-list .lbl {
  font-family: var(--display);
  font-size: 10.5px; font-weight: 700;
  color: var(--mute);
  letter-spacing: 0.14em; text-transform: uppercase;
  margin-bottom: 10px;
  display: block;
}
.user-list .users {
  display: flex; flex-direction: column; gap: 6px;
}
.user-chip {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 12px;
  align-items: baseline;
  font-family: var(--display);
  font-size: 14.5px; font-weight: 600;
  color: var(--near-black);
  background: var(--parchment);
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 14px;
  cursor: pointer;
  width: 100%;
  text-align: left;
  transition: border-color .12s ease, background .12s ease, color .12s ease;
}
.user-chip:hover {
  border-color: var(--brand);
  background: var(--ivory);
  color: var(--brand);
}
.user-chip .meta {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--mute);
  font-weight: 500;
  font-feature-settings: "calt" 1;
  letter-spacing: 0;
}
.user-chip .del {
  background: transparent; border: 0;
  color: var(--mute); font-size: 18px; line-height: 1;
  padding: 0 4px; cursor: pointer; opacity: .55;
  border-radius: 3px;
  transition: color .12s ease, background .12s ease, opacity .12s ease;
}
.user-chip .del:hover {
  color: var(--danger); opacity: 1; background: var(--danger-soft);
}

/* ─── Home screen · round setup ────────────────────────────────── */

/* Single editorial setup panel · sections divided by hairlines */
.setup-panel {
  background: var(--ivory);
  border: .5px solid var(--border);
  border-radius: var(--radius);
  margin-bottom: var(--space-block);
  overflow: hidden;
}
.setup-row {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 24px;
  padding: 18px 24px;
  align-items: center;
  border-bottom: .5px solid var(--hairline);
}
.setup-row:last-child { border-bottom: 0; }
.setup-row-label .lbl {
  font-family: var(--display);
  font-size: 12px; font-weight: 700;
  color: var(--near-black);
  letter-spacing: -0.01em;
  margin-bottom: 3px;
}
.setup-row-label .hint {
  font-size: 12px;
  color: var(--mute);
  line-height: 1.45;
  font-family: var(--body);
}
.setup-row-control {
  display: flex; flex-direction: column; gap: 10px;
  align-items: flex-start;
}

/* Segmented pill · sliding indicator behind the labels.
   The ::before is positioned via four CSS custom props that JS updates
   whenever the selection changes (or the layout recomputes on resize).
   Result: the brand-colored "pill" slides smoothly to the new option
   instead of snapping. Variable-width labels work because JS measures
   each label's offsetLeft / offsetWidth at runtime. */
.seg-pill {
  position: relative;
  display: inline-flex; flex-wrap: wrap;
  background: var(--parchment);
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 2px;
  gap: 2px;
  --ind-top: 2px;
  --ind-left: 2px;
  --ind-width: 0px;
  --ind-height: 0px;
}
.seg-pill::before {
  content: "";
  position: absolute;
  top: var(--ind-top);
  left: var(--ind-left);
  width: var(--ind-width);
  height: var(--ind-height);
  background: var(--brand);
  border-radius: 2px;
  box-shadow: 0 1px 2px rgba(20, 20, 19, 0.08);
  pointer-events: none;
  z-index: 0;
  /* Spring-ease transition · gives the slide a natural settle */
  transition:
    top    .32s cubic-bezier(0.34, 1.32, 0.64, 1),
    left   .32s cubic-bezier(0.34, 1.32, 0.64, 1),
    width  .32s cubic-bezier(0.34, 1.32, 0.64, 1),
    height .32s cubic-bezier(0.34, 1.32, 0.64, 1);
}
/* Hide the indicator before JS measures (width=0) so it doesn't flash
   in the corner on first paint. */
.seg-pill[data-ready="false"]::before { opacity: 0; }
.seg-pill[data-ready="true"]::before  { opacity: 1; transition: top .32s cubic-bezier(0.34, 1.32, 0.64, 1), left .32s cubic-bezier(0.34, 1.32, 0.64, 1), width .32s cubic-bezier(0.34, 1.32, 0.64, 1), height .32s cubic-bezier(0.34, 1.32, 0.64, 1), opacity .15s ease; }

.seg-pill label {
  position: relative;
  z-index: 1;          /* sit above the indicator */
  display: inline-flex; align-items: center;
  font-family: var(--display);
  font-size: 12px; font-weight: 600;
  color: var(--olive);
  letter-spacing: 0.02em;
  padding: 7px 14px;
  border-radius: 2px;
  cursor: pointer;
  transition: color .22s cubic-bezier(0.4, 0, 0.2, 1);
}
.seg-pill label:hover { color: var(--brand); }
.seg-pill input[type="radio"] {
  position: absolute; opacity: 0; pointer-events: none;
}
.seg-pill label:has(input:checked) {
  color: var(--parchment);
  /* No background — the sliding ::before indicator handles it */
}

/* Subtle bounce kept for non-sliding selectors (size chips, sub-radios) */
@keyframes pickPulse {
  0%   { transform: scale(1);    }
  45%  { transform: scale(1.06); }
  100% { transform: scale(1);    }
}
.seg-pill label span { display: inline-block; }

/* Sub-radio · refinement of "Past wrong" selection. Inline chips, hidden
   native radios, brand-soft fill on the active option to read as a
   secondary choice — not a heavy boxed form. */
.sub-radio {
  display: none;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.sub-radio.show { display: inline-flex; }
.sub-radio label {
  display: inline-flex;
  align-items: center;
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  color: var(--mute);
  letter-spacing: 0.04em;
  padding: 5px 10px;
  border: .5px solid var(--hairline);
  border-radius: var(--radius-sm);
  background: transparent;
  cursor: pointer;
  transform-origin: center;
  transition:
    color .2s cubic-bezier(0.4, 0, 0.2, 1),
    background-color .2s cubic-bezier(0.4, 0, 0.2, 1),
    border-color .2s cubic-bezier(0.4, 0, 0.2, 1);
}
.sub-radio label:hover {
  color: var(--brand);
  border-color: var(--brand-pale);
}
.sub-radio input[type="radio"] {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.sub-radio label:has(input:checked) {
  background: var(--brand-soft);
  color: var(--parchment);
  border-color: var(--brand-soft);
  animation: pickPulse .34s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Round-size chips · same subtle treatment as seg-pill */
.size-row {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
}
.size-row .size-chip,
.size-row input[type="number"] {
  height: 32px;
  box-sizing: border-box;
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--parchment);
}
.size-row .size-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--display);
  font-size: 12px; font-weight: 700;
  color: var(--olive);
  letter-spacing: 0.04em;
  padding: 0 14px;
  min-width: 44px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
  transform-origin: center;
  transition:
    color .2s cubic-bezier(0.4, 0, 0.2, 1),
    background-color .2s cubic-bezier(0.4, 0, 0.2, 1),
    border-color .2s cubic-bezier(0.4, 0, 0.2, 1);
}
.size-row .size-chip[aria-pressed="true"] {
  background: var(--brand);
  color: var(--parchment);
  border-color: var(--brand);
  animation: pickPulse .34s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.size-row .size-chip:not([aria-pressed="true"]):hover {
  color: var(--brand); border-color: var(--brand-pale);
}
.size-row input[type="number"] {
  width: 96px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1;
  padding: 0 12px;
  color: var(--near-black);
  outline: none;
  /* Hide native number-input spinners — chevrons add visual noise we don't need */
  -moz-appearance: textfield;
  appearance: textfield;
}
.size-row input[type="number"]::-webkit-inner-spin-button,
.size-row input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.size-row input[type="number"]:focus { border-color: var(--brand); background: var(--ivory); }

/* Start row · summary + primary CTA */
.start-row {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  margin-top: 8px;
  padding: 16px 20px;
  background: var(--parchment);
  border: .5px solid var(--hairline);
  border-radius: var(--radius);
}
.start-row .summary {
  font-family: var(--mono);
  font-size: 12.5px;
  color: var(--olive);
  font-feature-settings: "calt" 1;
  flex: 1 1 240px; min-width: 0;
  line-height: 1.5;
}
.start-row .summary strong {
  font-weight: 600;
  color: var(--brand);
}
.btn.lg {
  font-size: 13px;
  padding: 12px 26px;
  letter-spacing: 0.14em;
}

/* Data row · backup / restore / reset · sits between setup panel and foot */
.data-row {
  margin-top: var(--space-block);
  border-top: .5px solid var(--hairline);
}
.data-row + .foot { margin-top: 8px; }
.data-row > summary {
  list-style: none;
  cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 4px 14px 0;
  user-select: none;
  outline: none;
  transition: color 160ms ease;
}
.data-row > summary::-webkit-details-marker { display: none; }
.data-row .data-row-label {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  min-width: 0;
}
.data-row .data-row-label .lbl {
  font-family: var(--display);
  font-size: 13px; font-weight: 700;
  color: var(--near-black);
  letter-spacing: -0.01em;
}
.data-row .data-row-label .sep {
  color: var(--hairline);
  font-size: 12px;
}
.data-row .data-row-label .hint {
  font-size: 12px;
  color: var(--mute);
  line-height: 1.45;
  font-family: var(--body);
}
.data-row .data-row-chevron {
  flex: none;
  width: 8px; height: 8px;
  border-right: 1.5px solid var(--mute);
  border-bottom: 1.5px solid var(--mute);
  transform: rotate(-45deg);
  transition: transform 200ms ease, border-color 160ms ease;
  margin-right: 4px;
}
.data-row[open] .data-row-chevron {
  transform: rotate(45deg) translate(-1px, -1px);
  border-color: var(--olive);
}
.data-row-actions {
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  padding: 4px 0 14px;
  animation: data-row-reveal 220ms ease both;
}
@keyframes data-row-reveal {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: none; }
}
.data-row .btn { font-size: 11px; padding: 7px 12px; letter-spacing: 0.1em; }
.data-row .btn.danger-text {
  color: var(--danger);
  border-color: var(--danger-soft);
  margin-left: auto;
}
.data-row .btn.danger-text:hover {
  color: var(--parchment);
  background: var(--danger);
  border-color: var(--danger);
}
@media (max-width: 720px) {
  .data-row .btn.danger-text { margin-left: 0; }
}

/* ─── Stats strip · sits above the controls ────────────────────── */
.stats {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr 1fr;
  border-top: .5px solid var(--hairline);
  border-bottom: .5px solid var(--hairline);
  padding: 14px 0;
  margin-bottom: var(--space-block);
  align-items: center;
}
.stat { padding: 0 16px; border-left: .5px solid var(--hairline); }
.stat:first-child { border-left: 0; padding-left: 0; }
.stat .v {
  font-family: var(--display);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  line-height: 1; letter-spacing: -0.04em;
  display: block; margin-bottom: 5px;
  color: var(--brand);
  font-size: 24px;
}
.stat.hero .v { font-size: 38px; letter-spacing: -0.06em; }
.stat .l {
  font-family: var(--display);
  font-size: 11px; font-weight: 600;
  color: var(--mute);
  letter-spacing: 0.14em; text-transform: uppercase;
}
.stat.ok .v     { color: var(--ok); }
.stat.wrong .v  { color: var(--danger); }
.stat.unseen .v { color: var(--brand-soft); }

/* Filter dropdown styled like the segmented control */
.filter-seg {
  display: inline-flex; flex-wrap: wrap;
  border: .5px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--parchment);
  overflow: hidden;
}
.filter-seg button {
  font-family: var(--display);
  font-size: 11px; font-weight: 700;
  color: var(--olive);
  letter-spacing: 0.12em; text-transform: uppercase;
  background: transparent;
  border: 0;
  padding: 8px 12px;
  cursor: pointer;
  border-right: .5px solid var(--border);
  transition: color .12s ease, background .12s ease;
}
.filter-seg button:last-child { border-right: 0; }
.filter-seg button[aria-pressed="true"] {
  background: var(--brand); color: var(--parchment);
}
.filter-seg button:not([aria-pressed="true"]):hover {
  color: var(--brand); background: var(--ivory);
}
.filter-seg button .count {
  font-family: var(--mono);
  font-size: 10px;
  margin-left: 5px;
  opacity: .75;
}

/* ─── Last-result indicator on the card top-left ───────────────── */
.card-top .result {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--display);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.card-top .result.none    { display: none; }
.card-top .result.correct { color: var(--ok); }
.card-top .result.wrong   { color: var(--danger); }
.card-top .result::before {
  content: ""; display: inline-block;
  width: 8px; height: 8px; border-radius: 50%;
}
.card-top .result.correct::before { background: var(--ok); }
.card-top .result.wrong::before   { background: var(--danger); }

.card-top {
  display: grid;
  /* 1fr · auto · 1fr · so the pinyin's auto-width middle column is
     bracketed by equal flexible side columns. The pinyin then sits at
     the true center of the card regardless of result/progress widths. */
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 12px;
}
.card-top .result   { grid-column: 1; justify-self: start; }
.card-top .pinyin   { grid-column: 2; text-align: center; }
.card-top .progress { grid-column: 3; justify-self: end; }

/* ─── Mark buttons · live in the nav row, swap in when card revealed ── */
.btn.mark-wrong,
.btn.mark-correct {
  font-size: 12px;
  padding: 10px 20px;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-width: 110px;
}
.btn.mark-wrong {
  border-color: var(--danger);
  color: var(--danger);
  background: var(--parchment);
}
.btn.mark-wrong:hover {
  background: var(--danger);
  color: var(--parchment);
}
.btn.mark-correct {
  border-color: var(--ok);
  color: var(--parchment);
  background: var(--ok);
}
.btn.mark-correct:hover {
  background: var(--ok-soft);
  color: var(--ok);
}

/* Flip the nav in lockstep with the card. Uses the adjacent-sibling
   selector — .card and .nav are siblings of the round screen, so the
   card's revealed state drives the nav rotation. */
.card.revealed + .nav .nav-flipper { transform: rotateY(180deg); }

/* Match the card-change flip-back easing so the nav and card stay in
   sync during nextCard()'s symmetric ease-in-out rotation. */
.card.flipping-next + .nav .nav-flipper { transition: transform .7s ease-in-out; }

/* Suppress pointer events on the face that's rotated away. */
.card:not(.revealed) + .nav .nav-a-group { pointer-events: none; }
.card.revealed       + .nav .nav-q       { pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .nav-flipper { transition: none; }
}

.btn .ico {
  width: 14px; height: 14px;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
  flex-shrink: 0;
}

/* Reset button · subdued */
.btn.subtle {
  border-color: var(--hairline);
  color: var(--mute);
  background: transparent;
}
.btn.subtle:hover {
  border-color: var(--mute);
  color: var(--olive);
}


/* Tertiary "browse cheatsheets" link · used on login + home foot.
   Editorial link style — brand text with a brand-pale underline that
   wraps cleanly with the text instead of a full-width box-border. */
.cheatsheet-link {
  font-family: var(--display);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--brand);
  text-decoration: underline;
  text-decoration-color: var(--brand-pale);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: text-decoration-color .15s ease;
}
.cheatsheet-link:hover { text-decoration-color: var(--brand); }


/* ─── Results screen ────────────────────────────────────────────── */
.results-hero {
  background: var(--ivory);
  border: .5px solid var(--border);
  border-left: 2.6px solid var(--brand);
  border-radius: var(--radius);
  padding: 28px 32px;
  margin-bottom: var(--space-block);
}
.results-hero .score {
  font-family: var(--display);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-size: clamp(48px, 7vw, 84px);
  letter-spacing: -0.06em;
  line-height: 1;
  color: var(--brand);
  margin-bottom: 8px;
}
.results-hero .score .of {
  color: var(--brand-pale);
  font-weight: 500;
  font-size: 0.5em;
  letter-spacing: -0.04em;
  margin-left: 4px;
}
.results-hero .score .pct {
  font-family: var(--mono);
  font-size: 0.36em;
  color: var(--olive);
  margin-left: 14px;
  vertical-align: middle;
  font-feature-settings: "calt" 1;
  font-weight: 500;
  letter-spacing: 0;
}
.results-hero h2 {
  font-family: var(--display);
  font-size: 22px; font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--near-black);
  margin-bottom: 6px;
}
.results-hero p {
  color: var(--olive);
  font-size: 15px;
}

.results-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: var(--space-block);
}
.results-list {
  background: var(--ivory);
  border: .5px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
}
.results-list .lbl {
  font-family: var(--display);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  border-bottom: 1.4px solid;
  padding-bottom: 4px;
  display: inline-block;
  margin-bottom: 12px;
}
.results-list.ok    .lbl { color: var(--ok); border-color: var(--ok); }
.results-list.wrong .lbl { color: var(--danger); border-color: var(--danger); }
.results-list .empty {
  font-family: var(--body);
  font-size: 14px;
  color: var(--mute);
  font-style: italic;
}
.results-list ul {
  list-style: none;
  margin: 0; padding: 0;
  max-height: 380px;
  overflow-y: auto;
}
.results-list li {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 8px 0;
  border-bottom: .5px solid var(--hairline);
}
.results-list li:last-child { border-bottom: 0; }
.results-list li .id {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--mute);
  font-feature-settings: "calt" 1;
}
.results-list li .word {
  font-family: var(--cn);
  font-size: 17px;
  font-weight: 500;
  color: var(--near-black);
}
.results-list li .word .py {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--brand);
  margin-left: 8px;
  font-feature-settings: "calt" 1;
}
.results-list li .meaning {
  font-family: var(--body);
  font-size: 13px;
  color: var(--olive);
  text-align: right;
  max-width: 22ch;
  line-height: 1.4;
}

.results-actions {
  display: flex; gap: 10px; flex-wrap: wrap;
  margin-bottom: var(--space-block);
}

/* ─── Toast · brief feedback after marking ─────────────────────── */
.toast {
  position: fixed;
  left: 50%; bottom: 28px;
  transform: translateX(-50%) translateY(20px);
  background: var(--ivory);
  border: .5px solid var(--border);
  border-left: 2.6px solid var(--brand);
  border-radius: var(--radius);
  padding: 10px 16px;
  font-family: var(--display);
  font-size: 12.5px; font-weight: 600;
  color: var(--dark-warm);
  letter-spacing: 0.04em;
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s ease, transform .2s ease;
  z-index: 50;
  box-shadow: 0 4px 18px rgba(20, 20, 19, 0.08);
}
.toast.ok    { border-left-color: var(--ok); }
.toast.wrong { border-left-color: var(--danger); }
.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Responsive · 900 · catches narrow tablets too. On touch viewports we
   anchor the chrome to the card corners: pinyin centered top, progress
   in the top-right, result badge top-left, card counter bottom-left. */
@media (max-width: 900px) {
  #screen-round .card-top {
    grid-template-columns: 1fr;
    gap: 0;
    text-align: center;
  }
  #screen-round .card-top .pinyin {
    grid-column: 1; grid-row: 1;
    justify-self: center;
    text-align: center;
    font-size: 18px;
  }
  /* Progress · pinned to the top-right corner of the card */
  #screen-round .card-top .progress {
    position: absolute;
    top: 16px; right: 16px;
    grid-column: auto; grid-row: auto;
    justify-self: auto;
    font-size: 11px;
  }
  /* Result · pinned to the top-left corner of the card */
  #screen-round .card-top .result {
    position: absolute;
    top: 16px; left: 16px;
    grid-column: auto; grid-row: auto;
    justify-self: auto;
    font-size: 9.5px;
  }
  /* Hint dropped on touch viewports — "press space for next" needs a
     keyboard. (The base .card-foot already left-aligns the counter.) */
  #screen-round .card-foot .hint { display: none; }
}

/* Responsive · 720 */
@media (max-width: 720px) {
  h1 { font-size: 26px; }
  .controls { flex-direction: column; gap: 12px; padding: 12px 14px; }
  .ctrl-group { width: 100%; }

  /* Round screen · vertically center the card between topbar and nav so
     it reads as the focal point on phones, not a top-pinned block. */
  #screen-round.active .nav-buttons .btn { flex: 0 0 auto; }

  /* Topbar · stack on mobile so the action button sits underneath the
     title instead of fighting with the floating theme toggle. */
  .topbar {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding-right: 44px;
  }
  .topbar .switch { padding: 2px 0; }
  /* Brand mark · wrap cleanly when the recovery-key code is long.
     Without this the static title and the <code> are inline-flex
     siblings that wrap awkwardly side-by-side (title wraps to two
     lines while code wraps mid-syllable next to it). */
  .topbar .brand-mark {
    flex-wrap: wrap;
    max-width: 100%;
    row-gap: 2px;
  }
  .topbar .brand-mark code {
    word-break: break-word;
    overflow-wrap: anywhere;
  }
  /* Hide the inline " · " separator when the code drops to its own
     line — otherwise the title row ends with an orphaned bullet. */
  .topbar .brand-mark .brand-mark-sep { display: none; }
  .topbar .brand-mark .brand-mark-title { white-space: nowrap; }
  /* Round-screen title carries the inline meta ("Round · N cards · scope"),
     so let it wrap instead of clipping on narrow viewports. */
  #screen-round .topbar .brand-mark .brand-mark-title { white-space: normal; }
  .topbar .brand-mark code { flex-basis: 100%; }

  /* Card top · pinyin centered, progress directly underneath. Result
     becomes a small badge top-left so it doesn't fight for room. */
  .card { min-height: 300px; padding: 0; position: relative; }
  .card-flipper { min-height: 300px; }
  .card-face { padding: 22px 22px 18px; }
  .card-body { padding: 16px 4px; min-height: 0; }

  /* Use the dynamic viewport unit so the app sizes to the *visible* area
     on iOS Safari (the address-bar chrome retracts) — keeps the round
     screen aligned to the visible viewport instead of overflowing. */
  .app { min-height: 100dvh; }

  .nav { flex-wrap: wrap; }
  .nav .keys { display: none; }
  .foot {
    font-size: 10px;
    letter-spacing: 0.06em;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    line-height: 1.5;
  }
  /* Stats · 5-column compact row on tablet/phone — everything stays
     visible without one stat dominating */
  .stats {
    grid-template-columns: repeat(5, 1fr);
    gap: 0;
    padding: 12px 0;
  }
  .stat {
    border-left: .5px solid var(--hairline);
    padding: 4px 8px;
    min-width: 0;
  }
  .stat:first-child { border-left: 0; padding-left: 0; }
  .stat:last-child  { padding-right: 0; }
  .stat.hero { padding: 4px 8px; border-left: 0; }
  .stat .v { font-size: 22px; margin-bottom: 3px; }
  .stat.hero .v { font-size: 24px; }
  .stat .l { font-size: 9.5px; letter-spacing: 0.1em; line-height: 1.2; }
  .filter-seg button { padding: 7px 10px; font-size: 10.5px; }
  .filter-seg button .count { display: none; }
  .btn.mark-wrong, .btn.mark-correct { padding: 10px 14px; font-size: 11.5px; min-width: 100px; }
}
@media (max-width: 480px) {
  .card { padding: 0; min-height: 260px; }
  .card-flipper { min-height: 260px; }
  .card-face { padding: 18px 18px 14px; }
  .card-body { padding: 12px 4px; }
  /* Inherit the centered card-top reflow from the 720 breakpoint, just smaller text */
  .card-top .pinyin { font-size: 16px; }
  .card-top .progress { font-size: 10.5px; }
  .q-character { font-size: clamp(72px, 22vw, 110px); }
  .answer .a-character { font-size: clamp(36px, 11vw, 56px); }
  .answer .a-pinyin { font-size: 14px; }
  .btn { padding: 9px 14px; font-size: 11px; letter-spacing: 0.12em; }
  .filter-seg { width: 100%; }
  .filter-seg button { flex: 1 1 0; padding: 7px 4px; }
}

/* Setup + results · stack on narrow screens */
@media (max-width: 720px) {
  .setup-row {
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 16px 18px;
  }
  /* Seg-pills become a full-width grid on mobile so 3- and 4-option pills
     don't wrap awkwardly inside their rounded container. */
  .seg-pill {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    width: 100%;
  }
  .seg-pill label {
    justify-content: center;
    text-align: center;
    padding: 8px 10px;
    font-size: 11.5px;
  }
  .results-grid { grid-template-columns: 1fr; }
  .start-row { padding: 14px 16px; }
  .login-wrap {
    grid-template-columns: 1fr;
    gap: 24px;
    text-align: left;
  }
  .login-intro h1 { font-size: 26px; max-width: 22ch; }
  .login-card { padding: 22px 22px 18px; }
}
@media (max-width: 480px) {
  #screen-login.active { padding: 12px 0; justify-content: flex-start; }
  .login-intro h1 { font-size: 24px; }
  .login-intro .lead { font-size: 15px; }
}
@media (max-width: 480px) {
  .results-list li { grid-template-columns: 1fr; gap: 4px; }
  .results-list li .meaning { text-align: left; max-width: none; }
  .size-row .size-chip { padding: 6px 9px; font-size: 11.5px; min-width: 38px; }
  .topbar { padding-bottom: 8px; margin-bottom: 16px; }
  .topbar .brand-mark { font-size: 10.5px; letter-spacing: 0.12em; }
  .topbar .brand-mark code { font-size: 11.5px; }
  /* Stats · still 5-col but tighter */
  .stats { padding: 10px 0; }
  .stat { padding: 2px 6px; }
  .stat .v { font-size: 18px; }
  .stat.hero .v { font-size: 19px; }
  .stat .l { font-size: 8.5px; letter-spacing: 0.08em; }
}
