/* HANGIL — the design system.
 *
 * This is NOT the website's design. The site is a catalogue — paper, a display
 * serif, mono metadata, 3px radii — which reads well on a desk and badly on a
 * phone held at arm's length after a shift. DESIGN.md governs the site; this
 * governs the app, the way LOGGER has its own look.
 *
 * What holds it together:
 *
 *   1. EVERY SECTION HAS A COLOUR AND AN ICON. A card sets --c and --cw and
 *      everything inside it — icon tile, progress, accents — follows. That is
 *      what makes a screen scannable without reading it. One global accent on
 *      grey was the old design's real failure: it read as unfinished.
 *   2. DEPTH COMES FROM LAYERING, NOT BORDERS. The page ground is tinted, cards
 *      sit on it in pure white with a soft shadow. A 1px hairline on white is
 *      what a wireframe looks like.
 *   3. ONE CARD IDIOM. `.card` with an optional `.card__icon`. The old design had
 *      three shapes doing the same job, which is most of why it looked unplanned.
 *   4. MOTION IS INFORMATION. Things enter in the order you should read them,
 *      progress animates so you see it move, a wrong answer shakes. All of it is
 *      off under prefers-reduced-motion, and the app must still look finished.
 *   5. SPACING IS A 4PT RHYTHM. --s1 through --s8. No arbitrary pixel values.
 */

:root {
  /* ---- ground and ink ---- */
  --ground:    #F6F7F9;   /* tinted, so white cards have something to sit on */
  --surface:   #FFFFFF;
  --surface-2: #FFFFFF;
  --sunk:      #EEF1F5;
  --sunk-2:    #E3E8EF;
  --ink:       #0D1117;   /* 18.9:1 on surface */
  --ink-soft:  #55606E;   /* 7.0:1 */
  --ink-faint: #8792A2;   /* 3.3:1 — large text and icons only */
  --hairline:  #E6EAF0;

  /* ---- brand ---- */
  --accent:      #C2410C;
  --accent-ink:  #FFFFFF;
  --accent-wash: #FDF0EA;

  /* Text sitting ON a section colour — the filled hero card. In light mode the
     section colours are dark enough to carry white. In dark mode they are light
     pastels chosen to be readable AS text on a dark ground, so white on them is
     about 1.9:1; the ink has to flip. Measured, not guessed. */
  --hero-ink: #FFFFFF;

  /* ---- section colours. Each is >=4.5:1 as text on --surface. ---- */
  --c-today:    #C2410C;  --cw-today:    #FDF0EA;
  --c-course:   #5B3DF5;  --cw-course:   #EFECFE;
  --c-exam:     #B45309;  --cw-exam:     #FDF3E7;
  --c-hangeul:  #0E7490;  --cw-hangeul:  #E6F4F8;
  --c-vocab:    #BE185D;  --cw-vocab:    #FCEBF2;
  --c-review:   #15803D;  --cw-review:   #E9F6ED;
  /* The trades. A true blue, sat between the hangeul cyan (hue 193) and the
     course violet (hue 250) so it is not mistaken for either: 224, 6.7:1 on
     white. Measured, like the rest. */
  --c-trade:    #1D4ED8;  --cw-trade:    #E8EEFD;

  --good:      #15803D;  --good-wash: #E9F6ED;  --good-edge: #A7DCB8;
  --bad:       #B3261E;  --bad-wash:  #FDECEA;  --bad-edge:  #F3C2BD;

  /* ---- shape ---- */
  --r-xs: 8px; --r-sm: 12px; --r-md: 18px; --r-lg: 24px; --r-pill: 999px;
  --tap: 48px;

  /* ---- 4pt rhythm ---- */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 44px; --s8: 60px;

  /* ---- elevation ---- */
  --e1: 0 1px 2px rgba(13,17,23,.04), 0 2px 8px rgba(13,17,23,.04);
  --e2: 0 2px 4px rgba(13,17,23,.05), 0 8px 24px rgba(13,17,23,.07);
  --e3: 0 8px 32px rgba(13,17,23,.12);

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --ko: "Apple SD Gothic Neo", "Noto Sans KR", Roboto, "Malgun Gothic", sans-serif;

  --ease: cubic-bezier(.22,1,.36,1);        /* settles, does not bounce */
  --ease-spring: cubic-bezier(.34,1.56,.64,1);

  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);

  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground:#0A0D12; --surface:#151A21; --surface-2:#1B212A; --sunk:#1B212A; --sunk-2:#273040;
    --ink:#EDF1F6; --ink-soft:#9FADBE; --ink-faint:#6F7C8D; --hairline:#222A35;
    --accent:#FF8154; --accent-ink:#12100D; --accent-wash:#2B1A12;
    --hero-ink: #0A0D12;
    --c-today:#FF8154;  --cw-today:#2B1A12;
    --c-course:#A395FF; --cw-course:#1E1B36;
    --c-exam:#F0A55A;   --cw-exam:#2C1F10;
    --c-hangeul:#4CC7E0;--cw-hangeul:#10272E;
    --c-vocab:#F58BB8;  --cw-vocab:#2E1522;
    --c-review:#5FD98B; --cw-review:#122A1B;
    --c-trade:#6FA8FF;  --cw-trade:#111A33;
    --good:#5FD98B; --good-wash:#122A1B; --good-edge:#1F4630;
    --bad:#FF8F84;  --bad-wash:#2A1614;  --bad-edge:#4A2420;
    --e1: 0 1px 2px rgba(0,0,0,.5);
    --e2: 0 2px 6px rgba(0,0,0,.5), 0 10px 28px rgba(0,0,0,.35);
    --e3: 0 10px 34px rgba(0,0,0,.55);
  }
}
:root[data-theme="dark"] {
  --ground:#0A0D12; --surface:#151A21; --surface-2:#1B212A; --sunk:#1B212A; --sunk-2:#273040;
  --ink:#EDF1F6; --ink-soft:#9FADBE; --ink-faint:#6F7C8D; --hairline:#222A35;
  --accent:#FF8154; --accent-ink:#12100D; --accent-wash:#2B1A12;
  --hero-ink: #0A0D12;
  --c-today:#FF8154;  --cw-today:#2B1A12;
  --c-course:#A395FF; --cw-course:#1E1B36;
  --c-exam:#F0A55A;   --cw-exam:#2C1F10;
  --c-hangeul:#4CC7E0;--cw-hangeul:#10272E;
  --c-vocab:#F58BB8;  --cw-vocab:#2E1522;
  --c-review:#5FD98B; --cw-review:#122A1B;
  --c-trade:#6FA8FF;  --cw-trade:#111A33;
  --good:#5FD98B; --good-wash:#122A1B; --good-edge:#1F4630;
  --bad:#FF8F84;  --bad-wash:#2A1614;  --bad-edge:#4A2420;
  --e1: 0 1px 2px rgba(0,0,0,.5);
  --e2: 0 2px 6px rgba(0,0,0,.5), 0 10px 28px rgba(0,0,0,.35);
  --e3: 0 10px 34px rgba(0,0,0,.55);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html, body {
  /* The floor for the section colour. head() overrides --c/--cw on #app for any
     screen that names a tone, and everything inside follows from there. */
  --c: var(--c-today); --cw: var(--cw-today);
  margin: 0; padding: 0;
}
body {
  background: var(--ground);
  color: var(--ink);
  font: 400 17px/1.55 var(--sans);
  letter-spacing: -0.011em;
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}
:lang(ko), .ko { font-family: var(--ko); letter-spacing: 0; }
button, input, select { font: inherit; color: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 2.5px solid var(--c, var(--accent)); outline-offset: 3px; border-radius: var(--r-xs); }

/* ---------- motion ---------- */
@keyframes rise { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes popIn { 0% { opacity: 0; transform: scale(.88); } 60% { transform: scale(1.03); } 100% { opacity: 1; transform: none; } }
@keyframes shake { 15%,75% { transform: translateX(-5px); } 35%,55% { transform: translateX(5px); } 100% { transform: none; } }
@keyframes drawRing { from { stroke-dashoffset: var(--dash); } }
@keyframes flicker { 0%,100% { transform: scale(1) rotate(-2deg); } 50% { transform: scale(1.12) rotate(2deg); } }

@media (prefers-reduced-motion: no-preference) {
  /* Things arrive in the order they should be read. The delay is capped so a
     long list never keeps the reader waiting on an animation. */
  .stagger > * { animation: rise .5s var(--ease) both; animation-delay: calc(min(var(--i, 0) * 42ms, 380ms)); }
  .screen { animation: fade .26s var(--ease) both; }
  .pressable { transition: transform .18s var(--ease), box-shadow .18s var(--ease); }
  .pressable:active { transform: scale(.975); box-shadow: var(--e1); }
  .ring .fill { animation: drawRing .95s var(--ease) both; }
  .streak svg { animation: flicker 2.6s ease-in-out infinite; transform-origin: 50% 70%; }
  .opt[data-state="wrong"], .picopt[data-state="wrong"] { animation: shake .42s var(--ease); }
  .opt[data-state="right"], .picopt[data-state="right"] { animation: popIn .34s var(--ease-spring); }
  .verdict { animation: rise .3s var(--ease) both; }
  .result__score { animation: popIn .5s var(--ease-spring) both; }
}

/* ---------- frame ---------- */
#app { max-width: 620px; margin: 0 auto; padding: 0 var(--s4) calc(var(--s8) + 44px + var(--sab)); }

.topbar {
  position: sticky; top: 0; z-index: 20;
  background: var(--ground);
  display: flex; align-items: center; gap: var(--s3);
  padding: calc(var(--s3) + var(--sat)) 0 var(--s3);
  min-height: 64px;
}
.topbar h1 { font: 800 20px/1 var(--sans); letter-spacing: -0.04em; margin: 0; }
.topbar .sub { font: 600 13px/1 var(--ko); color: var(--ink-faint); }
.topbar .spacer { flex: 1; }

.back {
  display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; margin-left: -2px; padding: 0;
  background: var(--surface); border: 0; border-radius: var(--r-pill);
  color: var(--ink); box-shadow: var(--e1);
}
.back svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }

.streak {
  display: inline-flex; align-items: center; gap: var(--s2);
  background: var(--cw-today); color: var(--c-today);
  font: 700 14px/1 var(--sans); padding: 10px 14px; border-radius: var(--r-pill);
  white-space: nowrap;
}
.streak svg { width: 16px; height: 16px; fill: currentColor; stroke: none; }

/* ---------- type ---------- */
h2 { font: 800 clamp(28px,7.6vw,34px)/1.14 var(--sans); letter-spacing: -0.038em; margin: var(--s2) 0 var(--s3); }
h3 {
  font: 700 13px/1 var(--sans); letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-faint); margin: var(--s6) 0 var(--s3);
}
p  { margin: 0 0 var(--s3); max-width: 36rem; }
.lead { color: var(--ink-soft); font-size: 16.5px; }
.kicker { font: 700 13px/1 var(--sans); letter-spacing: .07em; text-transform: uppercase; color: var(--ink-faint); margin: 0 0 var(--s3); }
.tiny { font-size: 14px; color: var(--ink-soft); line-height: 1.55; }
.hr { height: 1px; background: var(--hairline); border: 0; margin: var(--s6) 0; }

/* ---------- the one card ---------- */
.card {
  position: relative; display: flex; align-items: center; gap: var(--s4);
  width: 100%; text-align: left;
  background: var(--surface); border: 0; border-radius: var(--r-md);
  padding: var(--s4); margin: 0 0 var(--s3);
  color: inherit; text-decoration: none;
  box-shadow: var(--e1);
  min-height: 76px;
}
.card__icon {
  flex: none; width: 52px; height: 52px; border-radius: var(--r-sm);
  background: var(--cw, var(--sunk)); color: var(--c, var(--ink));
  display: flex; align-items: center; justify-content: center;
}
/* The 한글 card carries a real character instead of an icon. Sized by eye to sit
   at the same weight as the 26px icons beside it. */
.card__icon .glyph { font: 600 27px/1 var(--ko); letter-spacing: 0; }
.card__icon svg { width: 26px; height: 26px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.card__body { flex: 1; min-width: 0; }
.card__title { display: block; font: 700 17.5px/1.3 var(--sans); letter-spacing: -0.025em; margin: 0; }
.card__meta {
  display: block; font: 700 12px/1 var(--sans); letter-spacing: .06em; text-transform: uppercase;
  color: var(--c, var(--ink-faint)); margin: 0 0 var(--s1);
}
/* Two lines, so a list of cards keeps an even rhythm instead of each one being
   as tall as its longest sentence. */
.card__desc {
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; margin: 3px 0 0; color: var(--ink-soft); font-size: 14.5px; line-height: 1.45;
}
.card--hero .card__desc { -webkit-line-clamp: 3; line-clamp: 3; }
.card__sub { display: block; margin: 3px 0 0; font: 600 15px/1.35 var(--ko); color: var(--c, var(--ink-soft)); }
.card__chev { flex: none; width: 18px; height: 18px; fill: none; stroke: var(--ink-faint); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }

/* a card that is the main thing on the screen */
.card--hero {
  flex-direction: column; align-items: stretch; gap: var(--s3);
  background: linear-gradient(145deg, var(--c) 0%, color-mix(in srgb, var(--c) 78%, #000) 100%);
  color: var(--hero-ink); box-shadow: var(--e2); padding: var(--s5);
}
.card--hero .card__meta { color: color-mix(in srgb, var(--hero-ink) 78%, transparent); }
.card--hero .card__title { font-size: 23px; letter-spacing: -0.032em; }
.card--hero .card__desc { color: color-mix(in srgb, var(--hero-ink) 86%, transparent); font-size: 15px; }
.card--hero .bar { background: color-mix(in srgb, var(--hero-ink) 24%, transparent); }
.card--hero .bar i { background: var(--hero-ink); }

.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
.grid2 .card { flex-direction: column; align-items: flex-start; gap: var(--s3); min-height: 158px; margin: 0; padding: var(--s4); }
.grid2 .card__title { font-size: 16.5px; }
.grid2 .card__desc { font-size: 13.5px; line-height: 1.4; }
.grid2 .card__icon { width: 48px; height: 48px; }
.grid2 .card__chev { display: none; }
@media (max-width: 339px) { .grid2 { grid-template-columns: 1fr; } .grid2 .card { flex-direction: row; align-items: center; min-height: 76px; } }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  min-height: var(--tap); padding: 15px 24px;
  background: var(--ink); color: var(--surface);
  border: 0; border-radius: var(--r-sm);
  font: 700 16.5px/1 var(--sans); letter-spacing: -0.02em; text-decoration: none;
}
.btn--accent { background: var(--c, var(--accent)); color: #fff; box-shadow: 0 4px 14px color-mix(in srgb, var(--c, var(--accent)) 32%, transparent); }
.btn--ghost { background: var(--surface); color: var(--ink); box-shadow: var(--e1); }
.btn--wide { width: 100%; }
.btn[disabled] { opacity: .3; pointer-events: none; }
.btnrow { display: flex; gap: var(--s3); flex-wrap: wrap; margin: var(--s5) 0; }

/* ---------- bottom nav ---------- */
.nav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  display: flex; justify-content: center; gap: var(--s1);
  background: color-mix(in srgb, var(--ground) 86%, transparent);
  -webkit-backdrop-filter: saturate(180%) blur(18px);
  backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--hairline);
  padding: var(--s2) var(--s2) calc(var(--s2) + var(--sab));
}
.nav a {
  position: relative; flex: 1; max-width: 112px; min-height: 54px; padding: var(--s2) var(--s1) 7px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  text-decoration: none; color: var(--ink-faint);
  font: 700 11px/1 var(--sans); letter-spacing: 0;
  border-radius: var(--r-sm);
  transition: color .2s var(--ease);
}
.nav a[aria-current="page"] { color: var(--c); background: var(--cw); }
.nav svg { width: 24px; height: 24px; fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linecap: round; stroke-linejoin: round; }
.nav .dot {
  position: absolute; top: 5px; left: 50%; margin-left: 6px;
  min-width: 19px; height: 19px; padding: 0 5px;
  background: var(--c-review); color: #fff;
  border: 2.5px solid var(--ground);
  border-radius: var(--r-pill); font: 700 11px/15px var(--sans); text-align: center;
}

/* ---------- progress ---------- */
.bar { height: 10px; background: var(--sunk-2); border-radius: var(--r-pill); overflow: hidden; margin: var(--s3) 0; }
.bar i { display: block; height: 100%; background: var(--c, var(--accent)); border-radius: var(--r-pill); transition: width .5s var(--ease); }
@media (prefers-reduced-motion: reduce) { .bar i { transition: none; } }

.ring { display: flex; align-items: center; gap: var(--s5); }
.ring svg { flex: none; width: 96px; height: 96px; transform: rotate(-90deg); }
.ring circle { fill: none; stroke-width: 9; stroke-linecap: round; }
.ring .track { stroke: var(--sunk-2); }
.ring .fill  { stroke: var(--c, var(--accent)); }
.ring__pct { font: 800 26px/1 var(--sans); letter-spacing: -0.04em; margin: 0; }
.ring__label { font-size: 15px; color: var(--ink-soft); margin: var(--s1) 0 0; }

.stats { display: grid; grid-template-columns: repeat(3,1fr); gap: var(--s3); margin: var(--s4) 0 0; }
.stat { background: var(--surface); border-radius: var(--r-sm); padding: var(--s4) var(--s3); box-shadow: var(--e1); }
.stat b { display: block; font: 800 26px/1 var(--sans); letter-spacing: -0.04em; color: var(--c, var(--ink)); }
.stat span { display: block; margin-top: 6px; font: 600 12.5px/1.3 var(--sans); color: var(--ink-soft); }

/* ---------- letters / words ---------- */
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(78px,1fr)); gap: var(--s3); margin: var(--s3) 0 var(--s5); }
.tile {
  background: var(--surface); border: 0; border-radius: var(--r-sm);
  min-height: 84px; padding: var(--s3) var(--s1);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s1);
  box-shadow: var(--e1);
}
.tile b { font: 500 30px/1 var(--ko); }
.tile span { font: 700 12px/1 var(--sans); color: var(--c-hangeul); }

.word { padding: var(--s4) 0; border-bottom: 1px solid var(--hairline); }
.word:last-child { border-bottom: 0; }
.word__ko { font: 700 21px/1.3 var(--ko); display: flex; align-items: center; gap: var(--s3); letter-spacing: -0.01em; }
.word__rom { font: 600 13px/1 var(--sans); color: var(--ink-faint); margin: 6px 0 3px; }
.word__en { color: var(--ink-soft); font-size: 16px; }
.word__ex { margin-top: var(--s2); font-size: 14.5px; color: var(--ink-soft); }
.word__ex b { font-family: var(--ko); font-weight: 600; color: var(--ink); }

.speak {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-pill);
  border: 0; background: var(--cw-vocab);
  display: inline-flex; align-items: center; justify-content: center; padding: 0;
  transition: transform .18s var(--ease-spring);
}
.speak:active { transform: scale(.88); }
.speak svg { width: 18px; height: 18px; fill: none; stroke: var(--c-vocab); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.speak[data-on="1"] { background: var(--c-vocab); }
.speak[data-on="1"] svg { stroke: #fff; }

/* ---------- lesson ---------- */
.lesson__form {
  display: inline-block; font: 600 20px/1 var(--ko); color: var(--c-course);
  background: var(--cw-course); padding: 12px 18px; border-radius: var(--r-pill);
  margin: 0 0 var(--s4);
}
.lesson p { font-size: 17px; line-height: 1.66; }
.tablewrap {
  overflow-x: auto; -webkit-overflow-scrolling: touch; margin: var(--s5) 0;
  background: var(--surface); border-radius: var(--r-md); padding: var(--s1) var(--s4);
  box-shadow: var(--e1);
}
table { border-collapse: collapse; width: 100%; font-size: 15px; min-width: 290px; }
th, td { text-align: left; padding: 13px var(--s4) 13px 0; border-bottom: 1px solid var(--hairline); vertical-align: top; }
tr:last-child td { border-bottom: 0; }
th { font: 700 12px/1.4 var(--sans); letter-spacing: .06em; text-transform: uppercase; color: var(--ink-faint); }
td:first-child { font-family: var(--ko); font-weight: 600; }

.ex { background: var(--surface); border-radius: var(--r-md); padding: var(--s4); margin: 0 0 var(--s3); box-shadow: var(--e1); }
.ex__ko { font: 600 19px/1.5 var(--ko); display: flex; gap: var(--s3); align-items: flex-start; }
.ex__ko span { flex: 1; }
.ex__rom { font: 500 13px/1.4 var(--sans); color: var(--ink-faint); margin: var(--s2) 0 3px; }
.ex__en { color: var(--ink-soft); font-size: 15.5px; }
.note {
  background: var(--surface); border-radius: var(--r-md); padding: var(--s4);
  margin: 0 0 var(--s3); font-size: 15.5px; line-height: 1.6; color: var(--ink-soft);
  border-left: 4px solid var(--c, var(--accent)); box-shadow: var(--e1);
}

/* ---------- quiz ---------- */
.q { margin: 0; }
.q__count { font: 700 13px/1 var(--sans); color: var(--ink-faint); }
.q__stem { font: 600 22px/1.45 var(--ko); margin: var(--s5) 0 var(--s2); white-space: pre-wrap; letter-spacing: -0.015em; }
.q__stem--en { font-family: var(--sans); font-size: 20px; font-weight: 700; letter-spacing: -0.03em; color: var(--ink); }
.q__hint { color: var(--ink-soft); font-size: 16px; margin: 0 0 var(--s5); }
.q__display {
  font: 700 clamp(28px,9vw,42px)/1.3 var(--ko); text-align: center;
  background: var(--surface); border-radius: var(--r-md);
  padding: var(--s7) var(--s4); margin: var(--s5) 0; box-shadow: var(--e1);
}
.q__passage {
  background: var(--surface); border-radius: var(--r-md);
  padding: var(--s4) var(--s5); margin: var(--s4) 0; white-space: pre-wrap;
  font: 400 16px/1.78 var(--ko); box-shadow: var(--e1);
}
.opts { display: grid; gap: var(--s3); margin: var(--s5) 0; }
.opt {
  display: flex; gap: var(--s3); align-items: center; text-align: left;
  min-height: 62px; padding: var(--s3) var(--s4);
  background: var(--surface); border: 2px solid transparent; border-radius: var(--r-sm);
  font-size: 17px; line-height: 1.4; box-shadow: var(--e1);
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.opt i {
  flex: none; width: 30px; height: 30px; border-radius: var(--r-xs);
  background: var(--sunk); color: var(--ink-soft);
  display: flex; align-items: center; justify-content: center;
  font: 800 13px/1 var(--sans); font-style: normal;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.opt span { font-family: var(--ko); flex: 1; }
.opt[data-state="right"] { border-color: var(--good); background: var(--good-wash); }
.opt[data-state="right"] i { background: var(--good); color: #fff; }
.opt[data-state="wrong"] { border-color: var(--bad); background: var(--bad-wash); }
.opt[data-state="wrong"] i { background: var(--bad); color: #fff; }
.opt[data-state="sel"] { border-color: var(--c, var(--accent)); background: var(--cw, var(--accent-wash)); }
.opt[data-state="sel"] i { background: var(--c, var(--accent)); color: #fff; }
.opt[disabled] { pointer-events: none; opacity: 1; }

/* ---------- pictures ---------- */
.q__picbox {
  display: flex; justify-content: center;
  background: var(--surface); border-radius: var(--r-md);
  padding: var(--s5); margin: var(--s5) 0; box-shadow: var(--e1);
}
.pic { width: 96px; height: 96px; color: var(--ink); }
.pic--big { width: 156px; height: 156px; }
img.pic { object-fit: contain; background: #fff; border-radius: var(--r-xs); padding: var(--s1); }

.picopts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin: var(--s5) 0; }
.picopt {
  position: relative;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--s2);
  min-height: 146px; padding: var(--s5) var(--s3) var(--s4);
  background: var(--surface); border: 2px solid transparent; border-radius: var(--r-md);
  color: var(--ink); box-shadow: var(--e1);
  transition: border-color .18s var(--ease), background .18s var(--ease);
}
.picopt i {
  position: absolute; top: 10px; left: 10px;
  width: 26px; height: 26px; border-radius: var(--r-xs);
  background: var(--sunk); color: var(--ink-soft);
  display: flex; align-items: center; justify-content: center;
  font: 800 12px/1 var(--sans); font-style: normal;
}
.picopt__name { font: 600 14px/1.2 var(--ko); color: var(--ink-soft); }
.picopt[data-state="right"] { border-color: var(--good); background: var(--good-wash); }
.picopt[data-state="right"] i { background: var(--good); color: #fff; }
.picopt[data-state="wrong"] { border-color: var(--bad); background: var(--bad-wash); }
.picopt[data-state="wrong"] i { background: var(--bad); color: #fff; }
.picopt[data-state="sel"] { border-color: var(--c, var(--accent)); background: var(--cw, var(--accent-wash)); }
.picopt[data-state="sel"] i { background: var(--c, var(--accent)); color: #fff; }
.picopt[disabled] { pointer-events: none; opacity: 1; }

/* ---------- word order / matching ---------- */
.tilerow { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s4) 0; min-height: 60px; }
.tilerow--slot { background: var(--sunk); border-radius: var(--r-md); padding: var(--s3); align-content: flex-start; }
.wtile {
  padding: 13px 18px; min-height: 50px; background: var(--surface);
  border: 0; border-radius: var(--r-sm);
  font: 600 17px/1.2 var(--ko); box-shadow: var(--e1);
  transition: transform .16s var(--ease-spring);
}
.wtile:active { transform: scale(.92); }

.pairs { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); margin: var(--s4) 0; }
.pair {
  min-height: 60px; padding: var(--s3); background: var(--surface);
  border: 2px solid transparent; border-radius: var(--r-sm);
  font-size: 15.5px; text-align: center; box-shadow: var(--e1);
  transition: transform .18s var(--ease), border-color .18s var(--ease);
}
.pair span { font-family: var(--ko); }
.pair[data-state="sel"] { border-color: var(--c, var(--accent)); background: var(--cw, var(--accent-wash)); }
.pair[data-state="done"] { opacity: .25; pointer-events: none; transform: scale(.94); }
.pair[data-state="miss"] { border-color: var(--bad); background: var(--bad-wash); }

/* ---------- verdict and result ---------- */
.verdict {
  margin: var(--s5) 0 var(--s4); padding: var(--s4) var(--s5); border-radius: var(--r-md);
  font-size: 15.5px; line-height: 1.6;
}
.verdict--right { background: var(--good-wash); border: 1.5px solid var(--good-edge); }
.verdict--wrong { background: var(--bad-wash); border: 1.5px solid var(--bad-edge); }
.verdict b { display: block; margin-bottom: var(--s1); font: 800 17px/1.3 var(--sans); letter-spacing: -0.03em; }
.verdict--right b { color: var(--good); }
.verdict--wrong b { color: var(--bad); }
.verdict .ko { font-family: var(--ko); }

.timer {
  font: 800 15px/1 var(--sans); color: var(--ink); letter-spacing: -0.03em;
  background: var(--surface); padding: 11px 15px; border-radius: var(--r-pill); box-shadow: var(--e1);
}
.timer[data-low="1"] { color: var(--bad); background: var(--bad-wash); }

.result { text-align: center; padding: var(--s6) 0 0; }
.result__ring { position: relative; width: 168px; height: 168px; margin: 0 auto; }
.result__ring svg { width: 168px; height: 168px; transform: rotate(-90deg); }
.result__ring circle { fill: none; stroke-width: 11; stroke-linecap: round; }
.result__ring .track { stroke: var(--sunk-2); }
.result__ring .fill { stroke: var(--c, var(--accent)); }
@media (prefers-reduced-motion: no-preference) { .result__ring .fill { animation: drawRing 1.1s var(--ease) both; } }
.result__inner {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
}
.result__score { font: 800 56px/1 var(--sans); letter-spacing: -0.05em; margin: 0; color: var(--c, var(--accent)); }
.result__out { font: 600 14px/1 var(--sans); color: var(--ink-soft); margin: 0; }

.sheet { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px,1fr)); gap: var(--s2); margin-top: var(--s3); }
.sheet button {
  min-height: 46px; border: 2px solid transparent; background: var(--surface);
  border-radius: var(--r-xs); font: 700 13.5px/1 var(--sans); color: var(--ink-faint); box-shadow: var(--e1);
}
.sheet button[data-done="1"] { background: var(--cw-exam); color: var(--c-exam); }
.sheet button[data-here="1"] { border-color: var(--ink); color: var(--ink); }

.empty {
  background: var(--surface); border-radius: var(--r-md); padding: var(--s5);
  color: var(--ink-soft); font-size: 15.5px; line-height: 1.6; box-shadow: var(--e1);
}
.empty p:last-child { margin-bottom: 0; }
code { font: 600 13.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; background: var(--sunk); padding: 3px 7px; border-radius: 6px; }

.field { display: block; margin: 0 0 var(--s5); }
.field span { display: block; font: 700 13px/1 var(--sans); color: var(--ink-soft); margin-bottom: var(--s2); }
.field select {
  width: 100%; min-height: var(--tap); background: var(--surface);
  border: 0; border-radius: var(--r-sm); padding: 0 var(--s4);
  font-weight: 600; appearance: none; box-shadow: var(--e1);
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-soft) 50%), linear-gradient(135deg, var(--ink-soft) 50%, transparent 50%);
  background-position: calc(100% - 21px) 21px, calc(100% - 16px) 21px;
  background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}
.field input[type=range] { width: 100%; accent-color: var(--accent); min-height: 44px; }
details summary { cursor: pointer; padding: var(--s3) 0; font-weight: 700; }
audio { width: 100%; margin-top: var(--s3); }

/* One official listening track. A plain block, deliberately not a `.card` —
   `.card` is a flex row with an icon slot, and putting a title and a player
   inside one lays them out side by side as columns of vertical text. */
.track {
  background: var(--surface); border-radius: var(--r-md);
  padding: var(--s4); margin: 0 0 var(--s3); box-shadow: var(--e1);
}
.track__name { margin: 0; font: 700 16px/1.3 var(--sans); letter-spacing: -0.02em; }
.track__file { margin: 3px 0 0; font: 500 13.5px/1.4 var(--ko); color: var(--ink-faint); }
.track audio { margin-top: var(--s3); }

/* ---- the walk-through -------------------------------------------------- */
/* One idea per card. The card is tall and mostly empty on purpose: what is on
   it is the only thing being asked of you, and the empty space is what makes
   that legible at arm's length. */
/* No --c here: head() sets it per screen from the section's tone, and the deck
   follows whatever screen it is on. The floor is on body. */
.deck__count { font: 600 12px/1 var(--sans); letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-faint); margin: var(--s3) 0 var(--s4); }
.deck__card {
  background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--e2);
  padding: var(--s5); min-height: 46vh; display: flex; align-items: flex-start;
  animation: rise .34s var(--ease) both;
}
.deck__body { width: 100%; }
.deck__body--mid { margin: auto 0; text-align: center; }
.deck__label { font: 700 11px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase;
  color: var(--c); margin: 0 0 var(--s4); }
.deck__form { font: 700 30px/1.25 var(--ko); color: var(--c); margin: 0 0 var(--s4); }
.deck__goal { font-size: 19px; line-height: 1.5; color: var(--ink); margin: 0; }
.deck__text { font-size: 17px; line-height: 1.65; color: var(--ink); margin: 0; }
.deck__note { font-size: 15px; line-height: 1.6; color: var(--ink-soft); margin: var(--s5) 0 0;
  padding-left: var(--s4); border-left: 3px solid var(--c); }
.deck__ko { display: flex; align-items: center; gap: var(--s3);
  font: 600 24px/1.45 var(--ko); color: var(--ink); }
.deck__rom { font-size: 14px; color: var(--ink-faint); margin: var(--s1) 0 0; }
.deck__nav { display: flex; gap: var(--s3); margin-top: var(--s5); }
.deck__nav .btn--wide { flex: 1; width: auto; }

/* The English, behind one tap. Sized and coloured like the answer it is, so an
   unrevealed card never looks like a card that is missing something. */
.reveal {
  display: block; width: 100%; text-align: left; margin-top: var(--s3);
  min-height: var(--tap); padding: var(--s3) var(--s4);
  border: 0; border-radius: var(--r-sm); background: var(--sunk);
  font: 400 17px/1.5 var(--sans); color: var(--ink); cursor: pointer;
}
.reveal__hint { font: 600 13px/1 var(--sans); letter-spacing: .04em; color: var(--ink-faint); }
.reveal[data-on="1"] { background: var(--cw); color: var(--ink); cursor: default; }
.reveal--sm { font-size: 15px; min-height: 40px; margin-top: var(--s2); }

/* The minimal pair: the same sentence twice, with the arrow marking the step. */
.pair { display: grid; gap: var(--s2); }
.pair__side { padding: var(--s4); border-radius: var(--r-md); background: var(--sunk); }
.pair__side--b { background: var(--cw); }
.pair__mark { display: flex; justify-content: center; color: var(--c); }
.pair__mark svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round; }

/* ---- the 한글 chart ---------------------------------------------------- */
/* Columns line up across rows so a family reads DOWN: ㄱ, then ㅋ, then ㄲ.
   That alignment is the content, which is why the empty cells are kept rather
   than collapsed. */
.chart { display: grid; grid-template-columns: auto 1fr; gap: var(--s2) var(--s3);
  align-items: center; margin-bottom: var(--s5); }
.chart__lab { font: 600 11px/1.2 var(--sans); letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-faint); text-align: right; }
.chart__row { display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: var(--s2); }
.chart__cell {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  min-height: 52px; padding: var(--s2) 2px; border: 0; border-radius: var(--r-sm);
  background: var(--cw-hangeul); cursor: pointer;
}
.chart__cell b { font: 600 22px/1 var(--ko); color: var(--c-hangeul); }
.chart__cell span { font: 600 10px/1 var(--sans); color: var(--ink-faint); }
.chart__gap { min-height: 52px; border-radius: var(--r-sm); background: var(--sunk); opacity: .4; }

/* What a letter opens into, under the chart it was tapped in. */
.detail:empty { display: none; }
.sheetcard { background: var(--surface); border-radius: var(--r-lg); box-shadow: var(--e2);
  padding: var(--s5); margin: var(--s4) 0; animation: rise .3s var(--ease) both; }
.sheetcard__glyph { font: 600 64px/1 var(--ko); color: var(--c-hangeul); text-align: center; }
.sheetcard__rom { text-align: center; font: 600 15px/1 var(--sans); color: var(--ink-soft);
  margin: var(--s3) 0 var(--s4); }

@media (max-width: 380px) {
  .chart__cell b { font-size: 19px; }
  .chart__cell { min-height: 46px; }
}

/* ---- weak spots -------------------------------------------------------- */
/* The bar is the whole story, so it is full width and the number sits under it
   rather than competing with the title. The card's colour comes from the score
   itself — red-ish under 60, amber under 80, green above — which is the one
   place in the app a colour is a judgement rather than a section. */
.weak { display: block; }
.weak__title { font: 700 18px/1.3 var(--sans); color: var(--ink); margin: 0 0 var(--s1); }
.weak__ko { font: 600 15px/1.4 var(--ko); color: var(--c); margin: 0 0 var(--s4); }
.weak__pct { font: 700 13px/1 var(--sans); color: var(--ink-soft); margin: var(--s2) 0 0; }
.weak .bar i { background: var(--c); }
