.stroke-order-practice-page {
  --stroke-order-practice-frame-width: 980px;
  /* Light-theme token overrides (theme_posture: light) — warm paper + ink */
  --color-bg: #f5f0e8;
  --color-surface: #faf7f0;
  --color-surface-2: #f5f0e8;
  --color-surface-3: #ece5d8;
  --color-text: #2c2420;
  --color-text-muted: #6f6357; /* darkened for WCAG-AA contrast on the paper surface */
  --color-border: rgba(100, 80, 60, 0.25);
  /* tool-local accents */
  --sop-ink: #2c2420;
  --sop-seal: #b23b2e;          /* 印泥紅 — current char / animation */
  --sop-grid: rgba(178, 59, 46, 0.32);
  --sop-grid-soft: rgba(178, 59, 46, 0.16);
  --sop-paper: #fbf8f2;
  --sop-outline: #d9cdba;       /* faint un-drawn stroke outline */
}

.stroke-order-practice-page .tool-frame {
  max-width: var(--stroke-order-practice-frame-width);
}

.stroke-order-practice-page .tool-header-block {
  max-width: 640px;
}

.stroke-order-practice-page .page-title {
  max-width: 16ch;
  font-size: clamp(2rem, 4vw, 2.9rem);
  line-height: 0.98;
}

.stroke-order-practice-page .page-subtitle {
  max-width: 46ch;
}

/* ── Layout: hero stage + picker aside ───────────────────────────── */
.sop {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: 22px;
  align-items: start;
}

.sop__stage {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 22px;
  border: 1px solid var(--color-border);
  border-radius: 24px;
  background: var(--color-surface);
}

/* ── The hero: big 米字格 writing square ──────────────────────────── */
/* The practice glyph is the whole point, so let it fill the stage column on
   desktop/tablet (a classroom projector needs it large), capped only so it stays
   square and never absurd on ultra-wide. Mobile width is set in the @media block. */
.sop__writer-wrap {
  position: relative;
  width: 100%;
  /* Bound by viewport HEIGHT too, so the writer + 注音 + the 示範/描寫/重來 buttons
     stay on one screen (a classroom projector is often only 720–900px tall — the
     CTA must never be pushed below the fold). Big on a 1080p projector (~518px),
     gracefully smaller on a short laptop. */
  max-width: min(560px, 48vh);
  aspect-ratio: 1 / 1;
  border-radius: 16px;
  background: var(--sop-paper);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.6) inset,
    0 8px 24px rgba(80, 60, 40, 0.1);
}

/* 米字格 guide lines drawn behind the SVG */
.sop__grid {
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--sop-grid);
  border-radius: 16px;
  background-image:
    /* outer mid cross */
    linear-gradient(to right, transparent calc(50% - 0.75px), var(--sop-grid) calc(50% - 0.75px), var(--sop-grid) calc(50% + 0.75px), transparent calc(50% + 0.75px)),
    linear-gradient(to bottom, transparent calc(50% - 0.75px), var(--sop-grid) calc(50% - 0.75px), var(--sop-grid) calc(50% + 0.75px), transparent calc(50% + 0.75px)),
    /* diagonals */
    linear-gradient(to bottom right, transparent calc(50% - 0.6px), var(--sop-grid-soft) calc(50% - 0.6px), var(--sop-grid-soft) calc(50% + 0.6px), transparent calc(50% + 0.6px)),
    linear-gradient(to bottom left, transparent calc(50% - 0.6px), var(--sop-grid-soft) calc(50% - 0.6px), var(--sop-grid-soft) calc(50% + 0.6px), transparent calc(50% + 0.6px));
}

/* 田字格 mode: keep only the centre cross (drop the 米字格 diagonals) */
.sop__writer-wrap[data-guide="tian"] .sop__grid {
  background-image:
    linear-gradient(to right, transparent calc(50% - 0.75px), var(--sop-grid) calc(50% - 0.75px), var(--sop-grid) calc(50% + 0.75px), transparent calc(50% + 0.75px)),
    linear-gradient(to bottom, transparent calc(50% - 0.75px), var(--sop-grid) calc(50% - 0.75px), var(--sop-grid) calc(50% + 0.75px), transparent calc(50% + 0.75px));
}

/* small 米/田 grid toggle, top-left corner (mirrors the 台標已核 badge) */
.sop__guide-toggle {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 3;
  width: 32px;
  height: 32px;
  font-size: 1rem;
  line-height: 1;
  color: var(--color-text-muted);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 8px;
  cursor: pointer;
}
.sop__guide-toggle:hover { color: var(--color-text); border-color: var(--sop-seal); }

.sop__writer {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
}

/* Brief spinner while a freshly-opened lesson's geometry is fetching. */
.sop__writer-wrap.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: auto;
  width: 32px;
  height: 32px;
  border: 3px solid var(--sop-grid-soft);
  border-top-color: var(--sop-seal);
  border-radius: 50%;
  animation: sop-spin 0.7s linear infinite;
}

@keyframes sop-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
  .sop__writer-wrap.is-loading::after { animation: none; border-top-color: var(--sop-grid-soft); }
}

.sop__writer svg {
  display: block;
}

/* Visually hidden but available to screen readers (stroke-order description). */
.sop__sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.sop__badge {
  position: absolute;
  top: 10px;
  right: 10px;
  padding: 3px 10px;
  font-size: 0.72rem;
  font-weight: 700;
  color: #256b41;
  background: rgba(76, 175, 110, 0.14);
  border: 1px solid rgba(76, 175, 110, 0.4);
  border-radius: 999px;
}

/* Completion seal stamp — animates over the writer when a char is finished */
.sop__stamp {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 96px;
  height: 96px;
  display: grid;
  place-items: center;
  font-size: 1.4rem;
  font-weight: 800;
  color: #fff;
  background: var(--sop-seal);
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 4px 16px rgba(178, 59, 46, 0.4);
  opacity: 0;
  pointer-events: none;
  transform: scale(0.4) rotate(-18deg);
}

.sop__stamp.is-stamping {
  animation: sop-stamp 1.3s ease forwards;
}

@keyframes sop-stamp {
  0% { opacity: 0; transform: scale(1.6) rotate(-18deg); }
  18% { opacity: 1; transform: scale(0.92) rotate(-12deg); }
  28% { transform: scale(1) rotate(-12deg); }
  80% { opacity: 1; transform: scale(1) rotate(-12deg); }
  100% { opacity: 0; transform: scale(1) rotate(-12deg); }
}

@media (prefers-reduced-motion: reduce) {
  .sop__stamp.is-stamping { animation: sop-stamp-fade 1s ease forwards; }
  @keyframes sop-stamp-fade { 0%,80% { opacity: 1; transform: none; } 100% { opacity: 0; } }
}

/* ── Meta row under the hero ─────────────────────────────────────── */
.sop__meta {
  width: min(74vw, 380px);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sop__charinfo {
  display: flex;
  align-items: center;
  gap: 14px;
}

.sop__bigchar {
  /* A compact reference glyph labelling the 注音/筆畫 card — deliberately smaller
     than the writer hero so there is one unambiguous focal character. */
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1;
  color: var(--sop-seal);
}

.sop__charstats {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.sop__charstats b {
  color: var(--color-text);
  font-size: 1.05rem;
}

.sop__zhuyin {
  /* The 注音 is what young learners read first and from the back of a class, so
     it's the most prominent line in the meta card. */
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--sop-seal);
  letter-spacing: 0.04em;
}

.sop__zhuyin:empty {
  display: none;
}

/* Pinyin (learner aid, EN mode) sits just under the 注音, quieter than it. */
.sop__readings { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.sop__pinyin {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-text-muted);
  letter-spacing: 0.02em;
}
.sop__pinyin:empty { display: none; }

/* English gloss (learner aid, EN mode) — quiet, italic, hidden when empty */
.sop__gloss { font-size: var(--text-sm); font-style: italic; color: var(--color-text-muted); }
.sop__gloss:empty { display: none; }

/* Provenance line (全字庫 CNS11643) is for adults — keep it quiet vs the 注音. */
.sop__cnsorder {
  font-size: var(--text-xs, 0.78rem);
  color: var(--color-text-muted);
}

/* 念 pronounce button — sits at the trailing edge of the char-info row */
.sop__speak {
  margin-inline-start: auto;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  color: var(--sop-seal);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 50%;
  cursor: pointer;
  transition: transform 0.1s, border-color 0.12s, background 0.12s;
}

.sop__speak:hover {
  transform: translateY(-1px);
  border-color: var(--sop-seal);
  background: rgba(178, 59, 46, 0.08);
}

.sop__speak svg {
  width: 22px;
  height: 22px;
}

.sop__speak.is-speaking {
  background: var(--sop-seal);
  color: #fff;
  border-color: var(--sop-seal);
}

.sop__feedback {
  color: var(--sop-seal);
  font-weight: 600;
  text-decoration: underline;
}

.sop__picker-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: wrap;
}

.sop__print-btn {
  flex: none;
  min-height: 36px;
}

/* ── Printable tracing worksheet (screen-hidden; shown only in print) ── */
.sop__print-sheet { display: none; }

@media print {
  .page-shell { display: none !important; }
  body > .sop__print-sheet { display: block !important; color: #000; font-family: inherit; }

  .ps-head { display: flex; justify-content: space-between; align-items: baseline; border-bottom: 2px solid #000; padding-bottom: 6px; margin-bottom: 4px; }
  .ps-title { font-size: 18pt; font-weight: 700; }
  .ps-meta { font-size: 11pt; }
  .ps-note { margin: 2px 0 12px; font-size: 9pt; color: #555; }

  .ps-row { display: flex; align-items: center; gap: 8px; break-inside: avoid; margin-bottom: 6px; }
  .ps-label { width: 2.4cm; flex: none; text-align: center; }
  .ps-char { display: block; font-size: 20pt; font-weight: 600; }
  .ps-zhuyin { display: block; font-size: 10pt; }
  .ps-cells { display: flex; gap: 0; }

  /* 田字格 cell: square box with a faint dashed cross. Borders (not background
     gradients) are used so the guide lines reliably appear in print. */
  .ps-cell {
    position: relative;
    width: 1.8cm;
    height: 1.8cm;
    border: 1px solid #000;
    margin-left: -1px; /* shared borders */
  }
  .ps-cell::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 50%;
    border-top: 1px dashed #bbb;
  }
  .ps-cell::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 50%;
    border-left: 1px dashed #bbb;
  }
  .ps-trace {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font-size: 30pt;
    color: #ccc; /* faint 范字 to trace over */
  }

  @page { size: A4 portrait; margin: 1.2cm; }
}

/* Official Taiwan stroke-order type sequence (點 撇 撇 捺) */
.sop__order {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: stroke;
}

.sop__order li {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px 3px 7px;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--sop-ink);
  background: var(--color-surface-3);
  border: 1px solid var(--color-border);
  border-radius: 8px;
}

.sop__order li::before {
  counter-increment: stroke;
  content: counter(stroke);
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  font-size: 0.64rem;
  color: #fff;
  background: var(--sop-seal);
  border-radius: 50%;
}

.sop__order--empty {
  color: var(--color-text-muted);
  font-size: var(--text-sm);
}

/* ── Controls ────────────────────────────────────────────────────── */
.sop__controls {
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  width: min(74vw, 380px);
}

.sop__controls .button {
  flex: 1 1 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

/* A larger leading glyph so a young (barely-reading) child recognises the action
   at a glance — ▶ watch, ✏ write, ↻ redo — while the label stays for older
   readers. A light, balanced kid-friendliness touch (not a full icon redesign). */
.sop__act-ico {
  font-size: 1.5em;
  line-height: 1;
}

/* Scoped contrast + focus for buttons on the light paper theme (rule 27 #9):
   the shared .button-secondary is dark-theme by default, so re-assert readable
   ink-on-paper colours and a visible keyboard focus ring at this page scope. */
.stroke-order-practice-page .button-secondary {
  color: var(--color-text);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
}
.stroke-order-practice-page .button-secondary:hover {
  border-color: var(--sop-seal);
  color: var(--sop-seal);
}
.stroke-order-practice-page .button:focus-visible,
.stroke-order-practice-page .button-secondary:focus-visible,
.stroke-order-practice-page .sop__tab:focus-visible,
.stroke-order-practice-page .sop__charbtn:focus-visible {
  outline: 2px solid var(--sop-seal);
  outline-offset: 2px;
}

.sop__nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

.sop__nav .button-sm {
  min-width: 44px;
  min-height: 44px;
  font-size: 1rem;
}

.sop__progress {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-variant-numeric: tabular-nums;
  min-width: 7ch;
  text-align: center;
}

.sop__status {
  margin: 0;
  min-height: 1.4em;
  font-size: var(--text-sm);
  font-weight: 600;
  text-align: center;
}

.sop__status[data-tone="success"] { color: #256b41; }
.sop__status[data-tone="error"] { color: var(--sop-seal); }
.sop__status[data-tone="info"] { color: var(--color-text-muted); }

/* ── Picker aside ────────────────────────────────────────────────── */
.sop__picker {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  border: 1px solid var(--color-border);
  border-radius: 24px;
  background: var(--color-surface-2);
}

/* Search */
.sop__search-wrap {
  position: relative; /* anchor for the suggestion dropdown */
}

.sop__search {
  display: flex;
  gap: 8px;
}

/* 注音 search suggestions — a floating listbox under the input */
.sop__suggest {
  position: absolute;
  z-index: 20;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  margin: 0;
  padding: 4px;
  list-style: none;
  max-height: 240px;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: 4px;
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  box-shadow: 0 8px 24px rgba(44, 36, 32, 0.18);
}

.sop__suggest[hidden] { display: none; }

.sop__suggest-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 4px;
  border-radius: 8px;
  cursor: pointer;
}

.sop__suggest-item:hover,
.sop__suggest-item[aria-selected="true"] { background: var(--sop-grid-soft, rgba(178, 59, 46, 0.12)); }
.sop__suggest-char { font-size: 1.4rem; line-height: 1; color: var(--color-text); }
.sop__suggest-zy { font-size: 0.7rem; color: var(--color-text-muted); }
.sop__suggest-py { font-size: 0.62rem; color: var(--color-text-muted); opacity: 0.85; }
.sop__suggest-py:empty { display: none; }

/* Recently practised characters */
.sop__recent { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sop__recent[hidden] { display: none; }
.sop__recent-label { font-size: var(--text-xs, 0.78rem); font-weight: 600; color: var(--color-text-muted); flex: none; }
.sop__recent-list { display: flex; gap: 6px; flex-wrap: wrap; }
.sop__recent-btn {
  min-width: 38px;
  min-height: 38px;
  font-size: 1.25rem;
  line-height: 1;
  color: var(--color-text);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 10px;
  cursor: pointer;
}
.sop__recent-btn:hover { border-color: var(--sop-seal); }

/* Browse-mode switcher (主題 / 筆畫 / 部首) — a segmented control */
.sop__modes {
  display: flex;
  gap: 4px;
  padding: 3px;
  background: var(--sop-grid-soft, rgba(178, 59, 46, 0.08));
  border-radius: 12px;
}
.sop__mode {
  flex: 1 1 0;
  min-height: 38px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  background: transparent;
  border: 0;
  border-radius: 10px;
  cursor: pointer;
  transition: color 0.12s, background 0.12s;
}
.sop__mode:hover { color: var(--color-text); }
.sop__mode[aria-selected="true"] { color: var(--color-text); background: var(--sop-paper); box-shadow: 0 1px 3px rgba(44, 36, 32, 0.12); }

/* 自訂字組 paste box (shown only in 自訂 mode) */
.sop__custom { display: flex; flex-direction: column; gap: 6px; }
.sop__custom[hidden] { display: none; }
.sop__custom-label { font-size: var(--text-sm); font-weight: 600; color: var(--color-text); }
.sop__custom-input {
  width: 100%;
  min-height: 56px;
  padding: 8px 12px;
  font-size: 1.25rem;
  line-height: 1.5;
  color: var(--color-text);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  resize: vertical;
}
.sop__custom-input:focus-visible { outline: 2px solid var(--sop-seal); outline-offset: 1px; }
.sop__custom-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.sop__custom-msg { margin: 0; font-size: var(--text-xs, 0.78rem); color: var(--color-text-muted); }
.sop__custom-msg[data-tone="success"] { color: #256b41; }
.sop__custom-msg[data-tone="error"] { color: var(--sop-seal); }

/* radical chips carry a small character count (glyph stacked over count) */
.sop__tabs[data-mode="radical"] .sop__tab { display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.05; }
.sop__tab-rad { font-size: 1.05rem; }
.sop__tab-count { font-size: 0.62rem; opacity: 0.7; font-weight: 500; }
.sop__tab[aria-selected="true"] .sop__tab-count { opacity: 0.85; }

.sop__search-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 40px;
  padding: 6px 12px;
  font-size: 1rem;
  color: var(--color-text);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 12px;
}

.sop__search-input:focus-visible {
  outline: 2px solid var(--sop-seal);
  outline-offset: 1px;
}

.sop__search-btn {
  flex: none;
  min-height: 40px;
}

.sop__search-msg {
  margin: 0;
  font-size: var(--text-sm);
  font-weight: 600;
}

.sop__search-msg[data-tone="success"] { color: #256b41; }
.sop__search-msg[data-tone="error"] { color: var(--sop-seal); }

.sop__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* 筆畫 (~26) and especially 部首 (~181) modes have many group chips; cap the
     height and scroll so the character grid stays visible without a long scroll. */
  max-height: 132px;
  overflow-y: auto;
  scrollbar-width: thin;
}
/* 部首 mode: square, evenly-sized radical chips read as an index, not prose. */
.sop__tabs[data-mode="radical"] {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
  max-height: 160px;
}
.sop__tabs[data-mode="radical"] .sop__tab { padding: 6px 0; text-align: center; }
.sop__tabs[data-mode="theme"] { max-height: none; overflow: visible; } /* only 12 themes */

.sop__tab {
  padding: 6px 12px;
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  background: transparent;
  border: 1px solid var(--color-border);
  border-radius: 999px;
  cursor: pointer;
  transition: color 0.12s, background 0.12s, border-color 0.12s;
}

.sop__tab:hover { color: var(--color-text); }

.sop__tab[aria-selected="true"] {
  color: #fff;
  background: var(--sop-seal);
  border-color: var(--sop-seal);
}

.sop__chargrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(46px, 1fr));
  gap: 8px;
}

.sop__charbtn {
  position: relative;
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  font-size: 1.35rem;
  font-weight: 600;
  color: var(--color-text);
  background: var(--sop-paper);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  cursor: pointer;
  transition: transform 0.1s, border-color 0.12s, box-shadow 0.12s;
}

.sop__charbtn:hover {
  transform: translateY(-1px);
  border-color: var(--sop-seal);
}

.sop__charbtn[aria-current="true"] {
  color: #fff;
  background: var(--sop-seal);
  border-color: var(--sop-seal);
  box-shadow: 0 4px 12px rgba(178, 59, 46, 0.28);
}

/* green ✓ corner badge = the learner has completed this character */
.sop__charbtn[data-done="true"]::after {
  content: "✓";
  position: absolute;
  top: 2px;
  right: 4px;
  font-size: 0.7rem;
  font-weight: 800;
  line-height: 1;
  color: #256b41;
}

.sop__charbtn[data-done="true"][aria-current="true"]::after {
  color: #fff;
}

.sop__progress-pair {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  min-width: 0;
}

.sop__lesson-progress {
  font-size: var(--text-sm);
  font-weight: 600;
  color: #256b41;
}

.sop__total-progress {
  font-size: var(--text-xs, 0.78rem);
  font-weight: 600;
  color: var(--color-text-muted);
}

/* A thin divider so the two counts read as distinct facts, not one run-on —
   shown only when the per-lesson count precedes it (both present). */
.sop__lesson-progress:not(:empty) + .sop__total-progress {
  border-inline-start: 1px solid var(--color-border);
  padding-inline-start: 10px;
}

/* Each count hides when empty; a pair with no visible child is inert (flex with
   zero rendered children has no size/gap), so no extra collapse rule is needed. */
.sop__lesson-progress:empty,
.sop__total-progress:empty {
  display: none;
}

.sop__provenance {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--color-text-muted);
}

/* ── Responsive ──────────────────────────────────────────────────── */
@media (max-width: 760px) {
  /* Flatten both cards so their children become one reorderable column —
     the learner reaches the writer, its feedback, the controls and the
     character picker without a long scroll (review: mobile picker below fold). */
  .sop {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
  }

  .sop__stage,
  .sop__picker {
    display: contents;
  }

  /* writer → its reference meta (注音/筆畫/序列) → feedback → controls → picker.
     (review: meta is core reference, must sit right under the char, not at the
     bottom; the print/progress bar must not float above the hero.) */
  .sop__writer-wrap { order: 1; width: min(78vw, 300px); }
  .sop__meta { order: 2; }
  .sop__status { order: 3; }
  .sop__controls { order: 4; }
  .sop__nav { order: 5; }
  .sop__search-wrap { order: 6; }
  .sop__search-msg { order: 7; }
  .sop__recent { order: 8; }
  .sop__modes { order: 9; }
  .sop__custom { order: 10; }
  .sop__tabs { order: 11; }
  .sop__picker-bar { order: 12; }
  .sop__chargrid { order: 13; }
  .sop__provenance { order: 14; }

  /* re-establish the width the cards used to give these blocks */
  .sop__status,
  .sop__controls,
  .sop__search-wrap,
  .sop__search-msg,
  .sop__recent,
  .sop__modes,
  .sop__custom,
  .sop__tabs,
  .sop__picker-bar,
  .sop__chargrid,
  .sop__meta,
  .sop__provenance {
    width: min(88vw, 360px);
  }

  /* tap targets for young fingers (review: tabs were 33px < 44px) */
  .sop__tab {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
  }
  /* the 主題/筆畫/部首/自訂 switcher was 38px — give little fingers ≥44px */
  .sop__mode { min-height: 44px; }

  .stroke-order-practice-page .page-title {
    max-width: none;
    font-size: clamp(2rem, 9vw, 2.7rem);
  }
}
