:root {
  /* Themes (step 7): Light (high contrast, for outdoors) is the base; Auto follows the system; Dark and Calm below.
     look.js sets <html data-theme> (the inline script in index.html does it before the first paint).
     Every text/background pair is at least 4.5:1, main text in Light at least 7:1 (shades checked, a few nudged). */
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #eceef2;
  --ink: #0f1115;
  --ink-2: #3e4350;
  --ink-3: #646a7a;
  --line: #d9dde5;
  --accent: #2b4acb;
  --accent-ink: #ffffff;
  --accent-soft: #e6ebff;
  --good: #127a47;
  --good-soft: #e2f2e9;
  --bad: #c1332b;
  --bad-soft: #fbe7e5;
  --warn: #945700;
  --shadow: 0 1px 2px rgba(15, 17, 21, 0.06), 0 6px 20px rgba(15, 17, 21, 0.06);
  --card-shadow: 0 2px 4px rgba(15, 17, 21, 0.05), 0 20px 50px rgba(15, 17, 21, 0.1);
  --seg-shadow: 0 1px 3px rgba(15, 17, 21, 0.14);
  --overlay: rgba(15, 17, 21, 0.45);
  --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Apple SD Gothic Neo', 'Noto Sans KR', 'Malgun Gothic', Roboto, sans-serif;
  color-scheme: light;
}

/* Dark: dark grey rather than black, soft white text. Same values twice: Auto on a dark system, and chosen. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) {
    --bg: #111317;
    --surface: #1a1d23;
    --surface-2: #242831;
    --ink: #e7e9ee;
    --ink-2: #a9aeb9;
    --ink-3: #8a909c;
    --line: #2c313a;
    --accent: #8ea2ff;
    --accent-ink: #0b0f24;
    --accent-soft: #252b4f;
    --good: #47c98e;
    --good-soft: #173328;
    --bad: #ff7a6e;
    --bad-soft: #3a1f1c;
    --warn: #f2b84b;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.2);
    --card-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 20px 50px rgba(0, 0, 0, 0.35);
    --seg-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
    --overlay: rgba(0, 0, 0, 0.6);
    color-scheme: dark;
  }
}
:root[data-theme='dark'] {
  --bg: #111317;
  --surface: #1a1d23;
  --surface-2: #242831;
  --ink: #e7e9ee;
  --ink-2: #a9aeb9;
  --ink-3: #8a909c;
  --line: #2c313a;
  --accent: #8ea2ff;
  --accent-ink: #0b0f24;
  --accent-soft: #252b4f;
  --good: #47c98e;
  --good-soft: #173328;
  --bad: #ff7a6e;
  --bad-soft: #3a1f1c;
  --warn: #f2b84b;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.2);
  --card-shadow: 0 2px 4px rgba(0, 0, 0, 0.3), 0 20px 50px rgba(0, 0, 0, 0.35);
  --seg-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
  --overlay: rgba(0, 0, 0, 0.6);
  color-scheme: dark;
}

/* Calm: warm paper, brown text, muted teal accent, for eye comfort. */
:root[data-theme='calm'] {
  --bg: #f3ebdd;
  --surface: #fbf6ec;
  --surface-2: #eae0ce;
  --ink: #3a3128;
  --ink-2: #66594a;
  --ink-3: #6f604e;
  --line: #ddd0ba;
  --accent: #286c64;
  --accent-ink: #fbf6ec;
  --accent-soft: #dcebe6;
  --good: #387134;
  --good-soft: #dfe9d3;
  --bad: #a8402f;
  --bad-soft: #f2ddd6;
  --warn: #825712;
  --shadow: 0 1px 2px rgba(58, 49, 40, 0.06), 0 6px 20px rgba(58, 49, 40, 0.07);
  --card-shadow: 0 2px 4px rgba(58, 49, 40, 0.05), 0 20px 50px rgba(58, 49, 40, 0.1);
  --seg-shadow: 0 1px 3px rgba(58, 49, 40, 0.16);
  --overlay: rgba(58, 49, 40, 0.45);
  color-scheme: light;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100dvh;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
button, input, select, textarea { font: inherit; color: inherit; }
a { color: inherit; text-decoration: none; }
h1, h2, h3 { line-height: 1.25; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
[hidden] { display: none !important; }
.i { width: 20px; height: 20px; flex: none; }
.muted { color: var(--ink-2); }
.small { font-size: 13px; }
code { background: var(--surface-2); padding: 2px 6px; border-radius: 6px; font-size: 13px; font-family: ui-monospace, Menlo, monospace; }
kbd { font: 600 11px var(--font); background: var(--surface); border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 5px; padding: 1px 5px; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 44px; padding: 0 16px; border-radius: 12px;
  border: 1px solid var(--line); background: var(--surface);
  font-weight: 600; font-size: 15px; white-space: nowrap; cursor: pointer;
  transition: transform 0.12s, background 0.15s, border-color 0.15s, color 0.15s, filter 0.15s;
}
.btn:hover { border-color: var(--ink-3); }
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.45; cursor: not-allowed; transform: none; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { border-color: var(--accent); filter: brightness(1.07); }
.btn-lg { height: 56px; padding: 0 22px; font-size: 17px; border-radius: 16px; }
.btn-sm { height: 36px; padding: 0 12px; font-size: 14px; border-radius: 10px; }
.btn-sm .i { width: 16px; height: 16px; }
.btn-block { width: 100%; }
.btn-ghost { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--surface-2); border-color: transparent; }
.btn-danger { background: var(--bad); border-color: var(--bad); color: var(--surface); }
.btn-danger-ghost { background: transparent; border-color: transparent; color: var(--bad); padding: 0 10px; }
.btn-danger-ghost:hover { background: var(--bad-soft); border-color: transparent; }
.icon-btn {
  width: 44px; height: 44px; flex: none; display: grid; place-items: center;
  border: 0; border-radius: 12px; background: transparent; cursor: pointer;
}
.icon-btn:hover { background: var(--surface-2); }
.link { border: 0; background: none; padding: 0; color: var(--accent); font-weight: 600; font-size: 13px; cursor: pointer; }

/* ---------- layout ---------- */
.topbar {
  position: sticky; top: 0; z-index: 10;
  padding-top: env(safe-area-inset-top);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.topbar-in {
  max-width: 1100px; margin: 0 auto; min-height: 64px;
  display: flex; align-items: center; gap: 8px;
  padding: 10px max(16px, env(safe-area-inset-right)) 10px max(16px, env(safe-area-inset-left));
}
.topbar-title { flex: 1; min-width: 0; margin: 0; font-size: 19px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brand { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; white-space: nowrap; }
.brand-logo { flex: none; width: auto; height: 27px; color: var(--accent); }
.brand-mark { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; color: var(--ink); }
.brand-sub { font-weight: 600; color: var(--ink-2); }
.wrap {
  max-width: 1100px; margin: 0 auto;
  padding: 8px max(16px, env(safe-area-inset-right)) calc(40px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
}
.panel { background: var(--surface); border-radius: 20px; padding: 18px; box-shadow: var(--shadow); margin-bottom: 16px; }
.panel-title { margin: 0 0 14px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.section-title { margin: 8px 0 12px; font-size: 13px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }

/* ---------- home ---------- */
.folder-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); }
.folder { position: relative; }
.tile {
  display: block; height: 100%; padding: 18px 18px 66px;
  background: var(--surface); border: 1px solid transparent; border-radius: 20px; box-shadow: var(--shadow);
  transition: transform 0.15s, border-color 0.15s;
}
.tile:hover { transform: translateY(-2px); border-color: var(--line); }
.tile h3 { margin: 0 0 2px; font-size: 18px; overflow-wrap: anywhere; }
.tile .meta { margin: 0; font-size: 14px; color: var(--ink-2); }
.tile .last { position: absolute; left: 18px; bottom: 22px; margin: 0; font-size: 13px; color: var(--ink-3); }
.quick { position: absolute; right: 14px; bottom: 14px; }
.pbar { display: flex; height: 8px; margin: 14px 0 10px; border-radius: 99px; overflow: hidden; background: var(--surface-2); }
.pbar i { display: block; height: 100%; transition: width 0.4s; }
.pbar .m { background: var(--good); }
.pbar .l { background: var(--warn); }
.empty { max-width: 440px; margin: 0 auto; padding: 72px 16px; text-align: center; }
.empty-mark {
  width: 88px; height: 88px; margin: 0 auto 20px; display: grid; place-items: center;
  font-size: 44px; font-weight: 800; color: var(--accent); background: var(--accent-soft); border-radius: 26px;
}
.empty h2 { margin: 0 0 8px; }

/* ---------- sign in ---------- */
.login { max-width: 400px; margin: 0 auto; padding: calc(56px + env(safe-area-inset-top)) 16px 40px; text-align: center; }
.login .empty-mark { width: auto; height: 64px; padding: 0 18px; display: inline-grid; font-size: 30px; border-radius: 20px; }
.login h1 { margin: 0 0 6px; font-size: 26px; }
.login .panel { margin: 24px 0 16px; padding: 22px 18px 18px; text-align: left; }
.login-msg { min-height: 20px; margin: -4px 0 12px; font-size: 14px; color: var(--bad); }

/* ---------- folder ---------- */
/* Lesson page (G5). Phone: stacked, the Start button in a bar that stays at the bottom of the screen (it comes after
   the options in the page's tab order, before the word list). Wide: two columns that scroll on their own, the
   settings with Start under them on the left, the words on the right; the page itself doesn't scroll. */
.folder-page { display: flex; flex-direction: column; padding-bottom: 0; }
.folder-page > .col-left { order: 0; }
.folder-page > .word-panel { order: 1; }
.start-dock {
  order: 2; position: sticky; bottom: 0; z-index: 5;
  margin: 0 calc(-1 * max(16px, env(safe-area-inset-right))) 0 calc(-1 * max(16px, env(safe-area-inset-left)));
  padding: 10px max(16px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
  background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}
.start-dock .btn { max-width: 760px; margin: 0 auto; }
@media (min-width: 900px) {
  .folder-page {
    display: grid; gap: 0 20px; overflow: hidden;
    grid-template-columns: 410px minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas: 'left list' 'dock list';
    height: calc(100vh - 64px - env(safe-area-inset-top)); height: calc(100dvh - 64px - env(safe-area-inset-top));
    padding-bottom: 16px;
  }
  /* the inner padding leaves room for the panels' shadows, which a scrolling box would cut off */
  .folder-page > .col-left { grid-area: left; min-height: 0; overflow-y: auto; overscroll-behavior: contain; margin: 0 -8px; padding: 2px 8px 0; }
  .folder-page > .col-left > .panel:last-child { margin-bottom: 4px; }
  .folder-page > .word-panel { grid-area: list; min-height: 0; overflow-y: auto; overscroll-behavior: contain; margin: 2px 0 4px; padding-top: 0; }
  .word-panel > .list-head { position: sticky; top: 0; z-index: 1; margin: 0 -18px 4px; padding: 14px 18px 6px; background: var(--surface); }
  .word-panel > .search { position: sticky; top: 56px; z-index: 1; box-shadow: 0 0 0 6px var(--surface); }
  .start-dock { grid-area: dock; position: static; margin: 0; padding: 12px 0 0; background: none; border: 0; backdrop-filter: none; -webkit-backdrop-filter: none; }
  .start-dock .btn { max-width: none; }
}
.mode-hint { margin: -6px 2px 16px; font-size: 14px; color: var(--ink-2); }
.stats-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.stat b { display: block; font-size: 26px; font-weight: 750; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.stat span { font-size: 13px; color: var(--ink-2); }
.stat.good b { color: var(--good); }
.stat.warn b { color: var(--warn); }
.stats-meta { display: flex; flex-wrap: wrap; gap: 4px 18px; font-size: 14px; color: var(--ink-2); }
.stats-meta b { color: var(--ink); }

.seg-group { margin-bottom: 14px; }
.seg-label { display: block; margin-bottom: 6px; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.seg { display: flex; gap: 3px; padding: 3px; background: var(--surface-2); border-radius: 12px; }
.seg button {
  flex: 1; min-width: 0; min-height: 40px; padding: 4px 6px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  border: 0; border-radius: 9px; background: transparent; cursor: pointer;
  font-size: 14px; font-weight: 600; color: var(--ink-2); line-height: 1.2;
  transition: background 0.15s, color 0.15s;
}
.seg button span { max-width: 100%; text-align: center; overflow-wrap: anywhere; }
.mode-tabs .seg-label { display: none; }
.mode-tabs .seg { margin-bottom: 18px; }
.mode-tabs .seg { flex-wrap: wrap; }
.mode-tabs .seg button { flex: 1 1 30%; min-height: 46px; font-size: 15px; }
.mode-tabs .seg button[aria-checked='true'] { background: var(--accent); color: var(--accent-ink); }
.opt-note { margin: -2px 0 18px; font-size: 13px; color: var(--ink-3); }
.seg button small { font-size: 12px; font-weight: 500; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.seg button[aria-checked='true'] { background: var(--surface); color: var(--ink); box-shadow: var(--seg-shadow); }

.switch { display: flex; align-items: center; gap: 12px; margin: 4px 0 18px; font-size: 14px; color: var(--ink-2); cursor: pointer; }
.switch input { position: absolute; opacity: 0; pointer-events: none; }
.track { position: relative; flex: none; width: 44px; height: 26px; border-radius: 99px; background: var(--ink-3); transition: background 0.2s; }
.track::after {
  content: ''; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: 50%;
  background: var(--surface); box-shadow: var(--seg-shadow); transition: transform 0.2s;
}
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::after { transform: translateX(18px); }
.switch input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }

.list-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.list-head .panel-title { margin: 0; }
/* lesson word list: translations show common meanings (app.js trNote) */
.trnote-btn { margin: -8px 0; }
.trnote-btn[aria-expanded='true'] { color: var(--accent); }
.trnote { display: flex; align-items: flex-start; gap: 8px; margin: 0 0 12px; padding: 9px 11px; border-radius: 12px;
  background: var(--surface-2); font-size: 13.5px; line-height: 1.45; color: var(--ink-2); }
.trnote[hidden] { display: none; }
.trnote .i { flex: none; width: 16px; height: 16px; margin-top: 2px; color: var(--ink-3); }
.search { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; padding: 0 12px; background: var(--surface-2); border-radius: 12px; color: var(--ink-3); }
.search input { flex: 1; min-width: 0; height: 42px; border: 0; background: transparent; outline: none; font-size: 16px; color: var(--ink); }
.word-list { list-style: none; margin: 0; padding: 0; }
/* A row: the word (opens its card, wordcard.js) and its sound button, two separate thumb-sized targets. */
.word-list li { display: flex; align-items: center; gap: 2px; border-top: 1px solid var(--line); }
.word-list li:first-child { border-top: 0; }
.word {
  flex: 1; min-width: 0; min-height: 52px; display: flex; align-items: center; gap: 12px; padding: 10px 8px;
  border: 0; background: none; text-align: left; cursor: pointer; border-radius: 10px; color: inherit; font: inherit;
}
.word:hover { background: var(--surface-2); }
.word-say { width: 48px; height: 48px; color: var(--ink-3); }
.word-say:hover { color: var(--accent); }
.word-say .i { width: 20px; height: 20px; }
.word-ko { min-width: 0; display: flex; flex-direction: column; }
.word-ko b { font-size: 17px; word-break: keep-all; overflow-wrap: anywhere; }
.rom { font-size: 13px; color: var(--ink-3); }
.rom em { font-style: normal; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--warn); }
.word-tr { margin-left: auto; max-width: 55%; text-align: right; color: var(--ink-2); overflow-wrap: anywhere; }
.dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.dot.learning { background: var(--warn); }
.dot.mastered { background: var(--good); }
.empty-list { padding: 16px 8px; }

/* ---------- modal ---------- */
.overlay {
  position: fixed; inset: 0; z-index: 50; display: flex; align-items: flex-end; justify-content: center;
  background: var(--overlay); opacity: 0; transition: opacity 0.2s;
}
.overlay.open { opacity: 1; }
.sheet {
  width: 100%; max-height: 92dvh; overflow: auto; overscroll-behavior: contain;
  padding: 22px max(18px, env(safe-area-inset-right)) calc(18px + env(safe-area-inset-bottom)) max(18px, env(safe-area-inset-left));
  background: var(--surface); border-radius: 24px 24px 0 0;
  transform: translateY(30px); transition: transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.overlay.open .sheet { transform: none; }
@media (min-width: 640px) {
  .overlay { align-items: center; padding: 24px; }
  .sheet { max-width: 580px; padding: 26px; border-radius: 24px; }
}
.sheet:focus { outline: none; }
.modal-title { margin: 0 0 16px; font-size: 20px; }

/* ---------- word card (wordcard.js) ---------- */
.word-card { position: relative; padding-top: 26px; }
.wc-grab { display: none; }
@media (max-width: 639.98px) {
  /* the handle that says "pull me down" */
  .wc-grab { display: block; position: absolute; top: 8px; left: 50%; width: 40px; height: 5px; margin-left: -20px; border-radius: 3px; background: var(--line); }
}
.wc-close { position: absolute; top: 10px; right: max(10px, env(safe-area-inset-right)); color: var(--ink-3); }
.wc-head { display: flex; align-items: center; gap: 10px; padding-right: 44px; }
.wc-ko { margin: 0; min-width: 0; font-size: clamp(30px, 9vw, 42px); font-weight: 750; line-height: 1.2; overflow-wrap: anywhere; }
.wc-say { flex: none; width: 48px; height: 48px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent); cursor: pointer; }
.wc-say:hover { background: var(--accent); color: var(--accent-ink); }
.wc-say .i { width: 22px; height: 22px; }
.wc-rom { margin: 4px 0 0; font-size: 16px; color: var(--ink-3); overflow-wrap: anywhere; }
.wc-tr { margin: 12px 0 0; font-size: 19px; font-weight: 600; line-height: 1.35; overflow-wrap: anywhere; }
.wc-label { margin: 18px 0 8px; font-size: 12px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); }
.word-card .extras { max-width: none; margin: 0; }
.word-card [lang='ko'] { word-break: keep-all; } /* Korean wraps between words; overflow-wrap still breaks a too-long one */
.word-card .ex-speak { width: 36px; height: 36px; }
.wc-stats { margin-top: 18px; padding: 12px 14px; border-radius: 14px; background: var(--surface-2); font-size: 14px; color: var(--ink-2); line-height: 1.45; }
.wc-stats p { margin: 0; overflow-wrap: anywhere; }
.wc-stats p + p { margin-top: 4px; }
.wc-stats b { color: var(--ink); font-weight: 650; }
.wc-stats .dot { display: inline-block; margin-right: 7px; vertical-align: 1px; }
.wc-where { display: flex; align-items: center; gap: 10px; min-height: 48px; margin-top: 12px; padding: 8px 12px;
  border: 1px solid var(--line); border-radius: 14px; color: var(--accent); font-weight: 650; }
.wc-where:hover { border-color: var(--accent); }
.wc-where span { flex: 1; min-width: 0; overflow-wrap: anywhere; }
.wc-where .i { flex: none; width: 19px; height: 19px; }
.modal-actions { display: flex; align-items: center; gap: 10px; justify-content: flex-end; margin-top: 20px; }
.spacer { flex: 1; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field > span { display: flex; justify-content: space-between; font-size: 14px; font-weight: 600; color: var(--ink-2); }
.field input, .field select, .paste textarea {
  width: 100%; height: 46px; padding: 0 12px; font-size: 16px;
  border: 1px solid var(--line); border-radius: 12px; background: var(--bg); outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.field input:focus, .field select:focus, .paste textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.field-row { display: grid; gap: 0 12px; }
@media (min-width: 640px) { .field-row { grid-template-columns: 1fr 1fr; } }
.drop {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 26px 16px; text-align: center; cursor: pointer;
  border: 2px dashed var(--line); border-radius: 18px; transition: border-color 0.15s, background 0.15s;
}
.drop:hover, .drop.over { border-color: var(--accent); background: var(--accent-soft); }
.drop.has-file { border-style: solid; border-color: var(--accent); }
.drop .i { width: 30px; height: 30px; margin-bottom: 6px; color: var(--accent); }
.drop b { overflow-wrap: anywhere; }
.drop input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.paste { margin: 12px 0 0; }
.paste summary { cursor: pointer; font-size: 14px; font-weight: 600; color: var(--accent); }
.paste textarea { height: auto; margin-top: 8px; padding: 10px 12px; resize: vertical; line-height: 1.5; }
.hint { margin: 10px 0 16px; font-size: 13px; color: var(--ink-3); }
.preview { margin-bottom: 16px; border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.preview-head { padding: 10px 14px; font-size: 14px; background: var(--surface-2); }
.warn-text { color: var(--warn); font-weight: 600; }
.preview-list { list-style: none; margin: 0; padding: 0; max-height: 280px; overflow: auto; }
.preview-list li { display: grid; grid-template-columns: 1fr 1fr auto; align-items: center; gap: 10px; padding: 7px 6px 7px 14px; border-top: 1px solid var(--line); font-size: 15px; }
.preview-list li:first-child { border-top: 0; }
.preview-list li > span:first-child { display: flex; flex-direction: column; }
.x-btn { width: 32px; height: 32px; display: grid; place-items: center; border: 0; border-radius: 8px; background: transparent; color: var(--ink-3); cursor: pointer; }
.x-btn:hover { background: var(--bad-soft); color: var(--bad); }
.x-btn .i { width: 16px; height: 16px; }
.skipped { padding: 8px 14px; border-top: 1px solid var(--line); font-size: 13px; color: var(--ink-2); }
.skipped summary { cursor: pointer; font-weight: 600; }
.skipped ul { margin: 6px 0 0; padding-left: 18px; }
.menu-list { display: flex; flex-direction: column; gap: 4px; }
.menu-list button {
  display: flex; align-items: center; gap: 12px; height: 52px; padding: 0 14px;
  border: 0; border-radius: 12px; background: transparent; font-size: 16px; font-weight: 600; text-align: left; cursor: pointer;
}
.menu-list button:hover { background: var(--surface-2); }
.menu-list .danger { color: var(--bad); }

/* ---------- practice ---------- */
.practice {
  max-width: 640px; min-height: 100dvh; margin: 0 auto;
  display: grid; grid-template-rows: auto 1fr auto auto;
  padding: env(safe-area-inset-top) max(16px, env(safe-area-inset-right)) calc(16px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
}
.practice > * { min-width: 0; }
.p-top { display: flex; align-items: center; gap: 12px; padding: 10px 0; }
.bar { flex: 1; height: 6px; border-radius: 99px; overflow: hidden; background: var(--surface-2); }
.bar i { display: block; height: 100%; width: 0; background: var(--accent); border-radius: 99px; transition: width 0.3s; }
.p-count { min-width: 56px; text-align: right; font-size: 14px; font-weight: 600; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.p-stage { min-height: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 12px 0 18px; }
.swipe {
  width: 100%; height: min(56dvh, 440px); min-height: 280px;
  perspective: 1400px; touch-action: none; cursor: pointer; /* the card takes vertical swipes too (app.js) */
  user-select: none; -webkit-user-select: none;
  transition: transform 0.25s ease, opacity 0.22s ease;
}
/* Chrome doesn't pass the card's touch-action on to the faces inside its 3D context, so each part says it too:
   otherwise the browser takes the drag as a scroll and cancels the swipe. */
.swipe * { touch-action: none; }
.swipe.enter { animation: card-in 0.28s ease; }
.swipe.out-right { transform: translateX(110%) rotate(10deg); opacity: 0; }
.swipe.out-down { transform: translateY(40%) scale(0.92); opacity: 0; }
@keyframes card-in { from { opacity: 0; transform: translateY(14px) scale(0.98); } }
.card-3d { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 0.5s cubic-bezier(0.3, 0.7, 0.2, 1); }
.card-3d.flipped { transform: rotateY(180deg); }
.face {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 48px 24px; text-align: center;
  background: var(--surface); border: 2px solid transparent; border-radius: 28px; box-shadow: var(--card-shadow);
  backface-visibility: hidden; -webkit-backface-visibility: hidden;
  transition: border-color 0.15s;
}
.face.back { transform: rotateY(180deg); }
.swipe[data-dir='good'] .face { border-color: var(--good); }
.swipe[data-dir='bad'] .face { border-color: var(--bad); }
.swipe.missed .face.back { border-color: var(--bad); }
.face-label { position: absolute; top: 20px; left: 0; right: 0; font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.f-ko { font-size: clamp(44px, 13vw, 84px); font-weight: 700; line-height: 1.15; overflow-wrap: anywhere; }
.f-rom { margin-top: 10px; font-size: clamp(17px, 4.6vw, 22px); color: var(--ink-2); }
.f-tr { font-size: clamp(28px, 7.5vw, 46px); font-weight: 650; line-height: 1.2; overflow-wrap: anywhere; }
.speak {
  position: absolute; right: 16px; bottom: 16px; width: 46px; height: 46px; display: grid; place-items: center;
  border: 0; border-radius: 50%; background: var(--surface-2); color: var(--ink-2); cursor: pointer;
}
.speak:hover { color: var(--accent); }
.again-tag { position: absolute; top: 16px; right: 16px; padding: 3px 9px; border-radius: 99px; font-size: 12px; font-weight: 700; color: var(--bad); background: var(--bad-soft); }
.p-hint { min-height: 20px; margin: 0; font-size: 13px; color: var(--ink-3); text-align: center; }
.p-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.p-actions .btn-block { grid-column: 1 / -1; }
.ans { border-color: transparent; }
.ans.bad { background: var(--bad-soft); color: var(--bad); }
.ans.good { background: var(--good-soft); color: var(--good); }
.ans:hover { border-color: transparent; }
@media (hover: hover) {
  .ans.bad:hover { background: var(--bad); color: var(--surface); }
  .ans.good:hover { background: var(--good); color: var(--surface); }
}
.p-sound { display: none; } /* phones only, see below */
.p-keys { margin: 14px 0 0; text-align: center; font-size: 12px; color: var(--ink-3); }
@media (hover: none) { .p-keys { display: none; } }

/* ---------- match ---------- */
.match-game { grid-template-rows: auto auto 1fr; }
.match-meta { display: flex; justify-content: space-between; gap: 12px; padding: 2px 2px 12px; font-size: 14px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.match-meta span:last-child { color: var(--bad); font-weight: 600; }
.match-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; align-content: center; padding-bottom: 16px; }
.match-grid.many { grid-template-columns: repeat(4, 1fr); gap: 8px; }
.match-grid.many .tile-m { min-height: 76px; padding: 8px 4px; font-size: 14px; }
.match-grid.many .tile-m.ko b { font-size: 19px; }
@media (min-width: 560px) {
  .match-grid, .match-grid.many { grid-template-columns: repeat(4, 1fr); gap: 12px; }
  .match-grid.many .tile-m { min-height: 88px; font-size: 15px; }
  .match-grid.many .tile-m.ko b { font-size: 22px; }
}
.tile-m {
  min-height: 88px; padding: 10px 8px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  border: 2px solid transparent; border-radius: 16px; background: var(--surface); box-shadow: var(--shadow);
  font-size: 15px; font-weight: 600; line-height: 1.25; text-align: center; overflow-wrap: anywhere;
  cursor: pointer; touch-action: manipulation; user-select: none; -webkit-user-select: none;
  transition: transform 0.12s, border-color 0.12s, background 0.12s;
}
.tile-m.ko b { font-size: 22px; }
.tile-m.tr.long, .match-grid.many .tile-m.tr.long { padding: 8px 3px; font-size: 12.5px; font-weight: 550; letter-spacing: -0.01em; } /* long translations (upper books) */
.tile-m small { font-size: 12px; font-weight: 500; color: var(--ink-3); }
.tile-m:active { transform: scale(0.96); }
@media (hover: hover) { .tile-m:hover { border-color: var(--line); } }
.tile-m.sel { border-color: var(--accent); background: var(--accent-soft); transform: translateY(-2px); }
.tile-m.wrong { border-color: var(--bad); background: var(--bad-soft); color: var(--bad); animation: shake 0.4s; }
.tile-m.wrong small { color: var(--bad); }
.tile-m.hit { border-color: var(--good); background: var(--good-soft); color: var(--good); pointer-events: none; animation: vanish 0.45s ease forwards; }
@keyframes shake { 20%, 60% { transform: translateX(-5px); } 40%, 80% { transform: translateX(5px); } }
@keyframes vanish { 40% { transform: scale(1.05); opacity: 1; } 100% { transform: scale(0.6); opacity: 0; visibility: hidden; } }

/* ---------- test ---------- */
.t-body { display: flex; flex-direction: column; justify-content: center; gap: 14px; padding: 8px 0 16px; }
.t-prompt {
  position: relative; min-height: 210px; padding: 52px 20px 40px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center;
  background: var(--surface); border-radius: 24px; box-shadow: var(--card-shadow);
}
.t-prompt.enter { animation: card-in 0.25s ease; }
.t-prompt .f-ko { font-size: clamp(40px, 11vw, 68px); }
.t-prompt .f-tr { font-size: clamp(26px, 7vw, 40px); }
.tf-claim { display: flex; flex-direction: column; align-items: center; gap: 4px; margin-top: 18px; padding-top: 16px; border-top: 1px dashed var(--line); font-size: 24px; font-weight: 650; }
.tf-claim .eq { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.options { display: grid; gap: 10px; }
@media (min-width: 560px) { .options { grid-template-columns: 1fr 1fr; } }
.opt {
  min-height: 60px; padding: 10px 16px; display: flex; align-items: center; gap: 12px;
  border: 2px solid var(--line); border-radius: 16px; background: var(--surface);
  font-size: 17px; font-weight: 600; text-align: left; cursor: pointer;
  transition: border-color 0.15s, background 0.15s, color 0.15s, transform 0.12s;
}
.opt:active:not(:disabled) { transform: scale(0.98); }
@media (hover: hover) { .opt:hover:not(:disabled) { border-color: var(--accent); } }
.opt:disabled { cursor: default; }
.opt kbd { flex: none; }
.a-ko { display: flex; flex-direction: column; }
.a-ko small, .tf-claim small { font-size: 12px; font-weight: 500; color: var(--ink-3); }
.tf-claim .a-ko { align-items: center; }
.opt.right { border-color: var(--good); background: var(--good-soft); color: var(--good); }
.opt.wrong { border-color: var(--bad); background: var(--bad-soft); color: var(--bad); }
.opt.chosen { border-color: var(--accent); background: var(--accent-soft); }
.tf-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.opt.tf { justify-content: center; min-height: 64px; }
.t-feedback { min-height: 24px; margin: 0; text-align: center; font-size: 16px; font-weight: 650; }
.t-feedback.ok { color: var(--good); }
.t-feedback.no { color: var(--bad); }
@media (hover: none) { .opt kbd { display: none; } }
.review-list { list-style: none; margin: 0; padding: 0; }
.review { display: flex; gap: 12px; padding: 12px 4px; border-top: 1px solid var(--line); }
.review:first-child { border-top: 0; }
.review .mark { flex: none; width: 28px; height: 28px; display: grid; place-items: center; border-radius: 50%; }
.review .mark .i { width: 16px; height: 16px; }
.review.ok .mark { background: var(--good-soft); color: var(--good); }
.review.no .mark { background: var(--bad-soft); color: var(--bad); }
.review-body { min-width: 0; }
.review .your { margin-top: 2px; font-size: 14px; color: var(--bad); }
.review .your .a-ko { display: inline; }

/* ---------- review (spaced repetition) ---------- */
.review-panel .list-head { margin-bottom: 8px; }
.review-counts { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
.review-counts div { padding: 10px 14px; border-radius: 14px; background: var(--surface-2); }
.review-counts b { display: block; font-size: 26px; font-weight: 750; font-variant-numeric: tabular-nums; }
.review-counts span { font-size: 13px; color: var(--ink-2); }
.review-done { display: flex; align-items: center; gap: 8px; margin: 4px 0 2px; font-weight: 650; color: var(--good); }
.review-card .f-ko, .review-card .f-tr { margin: 4px 0; }
.review-answer { width: 100%; margin-top: 16px; padding-top: 16px; border-top: 1px dashed var(--line); animation: card-in 0.2s ease; }
.new-tag { position: absolute; top: 16px; right: 16px; padding: 3px 9px; border-radius: 99px; font-size: 12px; font-weight: 700; color: var(--accent); background: var(--accent-soft); }
.grades { grid-column: 1 / -1; display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.grade { height: auto; min-height: 60px; padding: 8px 4px; flex-direction: column; gap: 2px; border-color: transparent; }
.grade b { font-size: 15px; }
.grade small { font-size: 12px; font-weight: 500; opacity: 0.8; }
.grade.g1 { background: var(--bad-soft); color: var(--bad); }
.grade.g2 { background: color-mix(in srgb, var(--warn) 10%, var(--bg)); color: var(--warn); }
.grade.g3 { background: var(--good-soft); color: var(--good); }
.grade.g4 { background: var(--accent-soft); color: var(--accent); }
.grade:hover { border-color: currentColor; }

/* ---------- write ---------- */
.write-form { display: flex; gap: 10px; }
.write-form input {
  flex: 1; width: 0; min-width: 0; /* width: 0 drops the input's built-in minimum width so it fits phones */ height: 56px; padding: 0 16px; font-size: 20px; font-weight: 600;
  border: 2px solid var(--line); border-radius: 16px; background: var(--surface); outline: none;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
}
.write-form input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.write-form input.ok { border-color: var(--good); background: var(--good-soft); }
.write-form input.no { border-color: var(--bad); background: var(--bad-soft); }
.write-form input.shake { animation: shake 0.4s; border-color: var(--bad); }
.w-feedback { min-height: 24px; text-align: center; font-size: 16px; font-weight: 600; }
.w-feedback.ok { color: var(--good); }
.w-feedback.hint { color: var(--warn); }
.w-feedback.no { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.w-answer { display: flex; flex-direction: column; align-items: center; padding: 10px 20px; border-radius: 14px; background: var(--bad-soft); color: var(--bad); }
.w-answer b { font-size: 26px; }
.w-answer small { font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.8; }
.w-answer small:last-child { text-transform: none; letter-spacing: 0; }
.w-copy-hint { font-size: 14px; color: var(--ink-2); }
.review.typo .mark { background: color-mix(in srgb, var(--warn) 10%, var(--surface)); color: var(--warn); }
.review .your { color: var(--ink-2); }
.review.no .your { color: var(--bad); }

/* ---------- mix ---------- */
.section-head { margin: 8px 0 12px; }
.section-head .section-title { margin: 0; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; height: 38px; padding: 0 14px;
  border: 1px solid var(--line); border-radius: 99px; background: transparent; font-size: 14px; font-weight: 600; color: var(--ink-2); cursor: pointer;
}
.chip small { font-size: 12px; color: var(--ink-3); font-weight: 500; }
.chip[aria-pressed='true'] { background: var(--accent-soft); border-color: var(--accent); color: var(--ink); }

/* ---------- examples and hints ---------- */
.extras { display: flex; flex-direction: column; gap: 6px; width: 100%; max-width: 420px; margin: 14px auto 0; text-align: left; }
.extra { display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; border-radius: 12px; background: var(--surface-2); font-size: 15px; font-weight: 500; color: var(--ink); }
.extra > span { display: flex; flex-direction: column; min-width: 0; overflow-wrap: anywhere; }
.extra small { font-size: 13px; color: var(--ink-2); }
.extra .i { width: 18px; height: 18px; margin-top: 1px; color: var(--warn); }
.ex-speak { flex: none; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 50%; background: var(--surface); color: var(--ink-2); cursor: pointer; }
.ex-speak .i { width: 15px; height: 15px; margin: 0; color: inherit; }
.face .extras { font-size: 14px; }
.face { overflow-y: auto; }
.hint-btn { display: inline-flex; align-items: center; gap: 6px; margin-top: 14px; padding: 6px 12px; border: 1px dashed var(--line); border-radius: 99px; background: transparent; font-size: 13px; font-weight: 600; color: var(--ink-2); cursor: pointer; }
.hint-btn .i { width: 15px; height: 15px; color: var(--warn); }
.hint-text { margin-top: 12px; padding: 8px 12px; border-radius: 12px; background: var(--surface-2); font-size: 14px; color: var(--ink-2); }
.ex-prev { display: block; font-size: 12px; color: var(--ink-3); }
.field > span small { font-weight: 500; color: var(--ink-3); }
.w-feedback .extras, .t-feedback .extras { margin: 10px auto 0; font-weight: 500; }

/* ---------- listen ---------- */
.listen-btns { display: flex; align-items: center; gap: 14px; margin: 6px 0; }
.listen-play {
  width: 88px; height: 88px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink); cursor: pointer; box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 35%, transparent);
  transition: transform 0.12s;
}
.listen-play:active { transform: scale(0.95); }
.listen-play .i { width: 38px; height: 38px; }
.listen-reveal { width: 100%; margin-top: 16px; padding-top: 16px; border-top: 1px dashed var(--line); display: flex; flex-direction: column; align-items: center; animation: card-in 0.2s ease; }
.listen-meaning { margin-top: 6px; font-size: 20px; font-weight: 650; color: var(--ink-2); }
.t-feedback.hint { color: var(--warn); }
.review-body .link .i { width: 16px; height: 16px; vertical-align: -3px; }

/* ---------- sentence builder, speak ---------- */
.t-prompt.compact { min-height: 0; padding: 44px 18px 24px; }
.b-sentence { font-size: clamp(21px, 5.6vw, 28px); font-weight: 650; line-height: 1.35; overflow-wrap: anywhere; }
.b-answer {
  min-height: 64px; padding: 10px; display: flex; flex-wrap: wrap; align-content: flex-start; gap: 8px;
  border-bottom: 2px solid var(--line); transition: border-color 0.15s, background 0.15s;
}
.b-answer.ok { border-color: var(--good); background: var(--good-soft); border-radius: 14px 14px 0 0; }
.b-answer.no { border-color: var(--bad); background: var(--bad-soft); border-radius: 14px 14px 0 0; }
.b-placeholder { align-self: center; font-size: 14px; color: var(--ink-3); }
.b-bank { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; }
.b-tile {
  min-height: 46px; padding: 8px 14px; border: 2px solid var(--line); border-bottom-width: 4px; border-radius: 14px;
  background: var(--surface); color: var(--ink); font: 600 18px/1.2 var(--font); cursor: pointer; transition: transform 0.1s;
}
.b-tile:active:not(:disabled) { transform: translateY(2px); }
@media (hover: hover) { .b-tile:hover:not(:disabled) { border-color: var(--accent); } }
.b-tile:disabled { cursor: default; }
.b-tile.ghost { color: transparent; background: var(--surface-2); border-color: var(--surface-2); user-select: none; }
.b-full { display: flex; flex-direction: column; align-items: center; gap: 2px; margin-top: 8px; font-size: 20px; color: var(--ink); }
.b-full small { font-size: 14px; font-weight: 500; color: var(--ink-2); }
.b-full .link .i, .say-heard .i { width: 18px; height: 18px; vertical-align: -3px; }
.b-word { margin-top: 8px; font-size: 14px; font-weight: 500; color: var(--ink-2); }
.b-word .f-rom { display: inline; font-size: 14px; margin: 0; }
.p-tr { margin-top: 10px; font-size: 15px; color: var(--ink-2); }
.w-feedback.no .btn-sm, .w-feedback.ok .btn-sm { margin-top: 4px; }
.say-controls { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.say-mic {
  width: 88px; height: 88px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: var(--accent); color: var(--accent-ink); cursor: pointer; box-shadow: 0 8px 24px color-mix(in srgb, var(--accent) 35%, transparent);
  transition: transform 0.12s, background 0.15s;
}
.say-mic .i { width: 38px; height: 38px; }
.say-mic:active:not(:disabled) { transform: scale(0.95); }
.say-mic:disabled { opacity: 0.4; cursor: default; box-shadow: none; }
.say-mic.on { background: var(--bad); animation: mic-pulse 1.2s ease-in-out infinite; }
@keyframes mic-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--bad) 45%, transparent); } 50% { box-shadow: 0 0 0 14px transparent; } }
.say-status { min-height: 20px; font-size: 14px; font-weight: 600; color: var(--ink-3); }
.say-heard { margin-top: 4px; font-weight: 500; color: var(--ink-2); }
.say-reveal { width: 100%; margin-top: 16px; padding-top: 16px; border-top: 1px dashed var(--line); display: flex; flex-direction: column; align-items: center; animation: card-in 0.2s ease; }
.say-reveal[hidden] { display: none; }

/* ---------- results ---------- */
.results { max-width: 560px; padding-top: calc(48px + env(safe-area-inset-top)); text-align: center; }
.results h1 { margin: 0 0 6px; font-size: 28px; }
.ring {
  width: 156px; height: 156px; margin: 0 auto 22px; display: grid; place-items: center; border-radius: 50%;
  background: conic-gradient(var(--good) calc(var(--p) * 1%), var(--surface-2) 0);
}
.ring span { width: 128px; height: 128px; display: grid; place-content: center; border-radius: 50%; background: var(--bg); }
.ring b { font-size: 36px; font-weight: 750; letter-spacing: -0.02em; }
.ring small { font-size: 13px; color: var(--ink-2); }
.result-actions { display: grid; gap: 10px; margin: 26px 0; }
.results .panel { text-align: left; }

/* ---------- toast ---------- */
#toast {
  position: fixed; left: 50%; bottom: calc(24px + env(safe-area-inset-bottom)); z-index: 100;
  max-width: calc(100% - 32px); padding: 11px 16px; border-radius: 12px;
  background: var(--ink); color: var(--bg); font-size: 14px; font-weight: 600;
  opacity: 0; pointer-events: none; transform: translate(-50%, 16px); transition: opacity 0.25s, transform 0.25s;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* ---------- public app: language, books, chapters ---------- */
.lang-pick { max-width: 420px; margin: 0 auto; padding: calc(56px + env(safe-area-inset-top)) 16px 40px; text-align: center; }
.lang-brand { display: flex; flex-direction: column; align-items: center; gap: 10px; margin: 0 0 22px; }
.lang-logo { width: auto; height: 64px; color: var(--accent); }
.lang-name { font-size: 32px; font-weight: 800; letter-spacing: -0.02em; line-height: 1; }
.lang-pick h1 { display: flex; flex-direction: column; gap: 2px; margin: 0 0 24px; font-size: 22px; }
.lang-pick h1 span + span { font-size: 16px; font-weight: 600; color: var(--ink-2); }
.lang-list { display: grid; gap: 10px; margin-bottom: 20px; }
.lang-list button {
  min-height: 60px; padding: 0 18px; display: flex; align-items: center; justify-content: center;
  border: 2px solid var(--line); border-radius: 16px; background: var(--surface); cursor: pointer;
  font-size: 18px; font-weight: 650; transition: border-color 0.15s, background 0.15s;
}
@media (hover: hover) { .lang-list button:hover { border-color: var(--accent); } }
.lang-list button[aria-checked='true'] { border-color: var(--accent); background: var(--accent-soft); }
.lang-chip {
  height: 40px; padding: 0 10px; flex: none; display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--line); border-radius: 12px; background: transparent; cursor: pointer;
  font-size: 13px; font-weight: 700; letter-spacing: 0.04em; color: var(--ink-2);
}
.lang-chip .i { width: 17px; height: 17px; }
.lang-chip:hover { background: var(--surface-2); }
.banner {
  display: flex; align-items: flex-start; gap: 10px; margin: 4px 0 16px; padding: 12px 14px;
  border-radius: 14px; background: color-mix(in srgb, var(--warn) 14%, var(--surface)); font-size: 14px; color: var(--ink);
}
.banner .i { margin-top: 1px; color: var(--warn); }
.book-grid { grid-template-columns: repeat(auto-fill, minmax(min(100%, 220px), 1fr)); }
.book-tile { padding: 18px; }
.book-tile .book-id { display: inline-block; margin-bottom: 8px; padding: 2px 10px; border-radius: 99px; background: var(--accent-soft); color: var(--accent); font-size: 14px; font-weight: 800; }
.book-tile h3 { font-size: 17px; }
.book-tile .last { position: static; }
.book-page { max-width: 760px; }
.book-page.has-bar { padding-bottom: calc(110px + env(safe-area-inset-bottom)); }
.pick-note { margin: 4px 4px 12px; }
.ch-list { list-style: none; padding: 6px; }
.ch-row { display: flex; align-items: stretch; border-top: 1px solid var(--line); }
.ch-row:first-child { border-top: 0; }
.ch-check { flex: none; width: 52px; display: grid; place-items: center; cursor: pointer; }
.ch-check input { position: absolute; opacity: 0; pointer-events: none; }
.ch-check .box {
  width: 24px; height: 24px; display: grid; place-items: center; border: 2px solid var(--ink-3); border-radius: 7px;
  color: transparent; transition: background 0.15s, border-color 0.15s;
}
.ch-check .box .i { width: 16px; height: 16px; }
.ch-check input:checked + .box { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.ch-check input:focus-visible + .box { outline: 2px solid var(--accent); outline-offset: 2px; }
.ch-check input:disabled + .box { opacity: 0.35; }
.ch-link { flex: 1; min-width: 0; display: flex; align-items: center; gap: 12px; padding: 12px 10px 12px 2px; border-radius: 12px; }
.ch-link:hover { background: var(--surface-2); }
.ch-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.ch-main b { font-size: 16px; }
.ch-sub { font-size: 14px; color: var(--ink-2); overflow-wrap: anywhere; }
.ch-main .pbar { height: 6px; margin: 8px 0 0; }
.ch-meta { flex: none; display: flex; flex-direction: column; align-items: flex-end; font-size: 14px; color: var(--ink-2); text-align: right; }
.ch-meta small { font-size: 12px; color: var(--ink-3); }
.pick-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  padding: 10px max(12px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(12px, env(safe-area-inset-left));
  background: color-mix(in srgb, var(--surface) 92%, transparent); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}
.pick-in { max-width: 760px; margin: 0 auto; display: flex; align-items: center; gap: 8px; }
.pick-info { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.pick-info span { font-size: 13px; color: var(--ink-2); }
/* levels (step 12): a level page lists its two parts, each with its lessons */
.crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 2px 8px; margin: 0 4px 6px; font-size: 14px; color: var(--ink-3); }
.crumbs a { padding: 2px 0; color: var(--accent); font-weight: 650; overflow-wrap: anywhere; }
.crumbs a:hover { text-decoration: underline; }
.set-sub { margin: 0 4px 12px; font-size: 15px; font-weight: 600; color: var(--ink-2); overflow-wrap: anywhere; }
.loading { min-height: 60dvh; display: grid; place-items: center; }
.spinner { width: 34px; height: 34px; border: 3px solid var(--surface-2); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
.extra small { font-weight: 500; }
.review-card { padding-bottom: 76px; } /* room for the speaker button under the examples */

@media (max-width: 420px) {
  .brand-sub { display: none; }
  .stat b { font-size: 24px; }
}

/* Also without JavaScript's data-motion; a person who switched Animations on in Settings (data-motion="on") gets them. */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion='on']) *, :root:not([data-motion='on']) *::before, :root:not([data-motion='on']) *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ---------- accounts and own folders (account.js) ---------- */
.section-head { margin: 8px 0 12px; }
.own-tile .book-id { display: inline-grid; place-items: center; padding: 4px 9px; }
.own-tile .book-id .i { width: 16px; height: 16px; }
.book-grid + .section-head, .book-grid + .section-title { margin-top: 24px; }
.own-tools { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; }
.own-tools .btn-danger-ghost { margin-left: auto; }
.own-tools + .muted { margin: 0 0 12px; }
.icon-btn.sm { width: 36px; height: 36px; flex: none; color: var(--ink-3); }
.icon-btn.sm .i { width: 17px; height: 17px; }
.auth-tabs { margin-bottom: 14px; }
.form-error { margin: 0 0 12px; padding: 10px 12px; border-radius: 12px; background: var(--bad-soft); color: var(--bad); font-size: 14px; }
.form-ok { margin: 0 0 12px; padding: 10px 12px; border-radius: 12px; background: var(--good-soft); color: var(--good); font-size: 14px; }
.link-btn { padding: 0 6px; color: var(--accent); }
.btn.busy { position: relative; color: transparent !important; }
.btn.busy::after { content: ''; position: absolute; width: 18px; height: 18px; border: 2px solid var(--accent-ink); border-right-color: transparent; border-radius: 50%; animation: spin 0.7s linear infinite; }
.btn:not(.btn-primary).busy::after { border-color: var(--ink-2); border-right-color: transparent; }
.account-email { display: flex; align-items: center; gap: 8px; margin: 0 0 6px; font-weight: 600; overflow-wrap: anywhere; }
.account-email .i { color: var(--accent); }
.sync-line { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.sync-dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--warn); }
.sync-dot.ok { background: var(--good); }
.sync-dot.busy { background: var(--accent); }
.account-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }

/* ---------- Korean voice: install guide, Settings (voice.js) ---------- */
.vg-status { display: flex; align-items: flex-start; gap: 10px; margin: 0 0 12px; padding: 12px 14px; border-radius: 14px; font-size: 15px; font-weight: 600; }
.vg-status .i { flex: none; margin-top: 1px; }
.vg-status.ok { background: var(--good-soft); color: var(--good); }
.vg-status.no { background: color-mix(in srgb, var(--warn) 14%, var(--surface)); color: var(--ink); }
.vg-status.no .i { color: var(--warn); }
.vg-intro { margin: 0 0 14px; }
.vg-tabs { flex-wrap: wrap; margin-bottom: 14px; }
.vg-tabs button { flex: 1 1 30%; }
.vg-tabs button[aria-selected='true'] { background: var(--surface); color: var(--ink); box-shadow: var(--seg-shadow); }
.vg-steps { margin: 0 0 14px; padding-left: 22px; line-height: 1.5; }
.vg-steps li { margin-bottom: 8px; padding-left: 2px; }
.vg-steps li::marker { font-weight: 700; color: var(--accent); }
.vg-open { margin-bottom: 6px; text-decoration: none; }
.vg-tip { margin-top: 0; }
.vg-check-msg { margin: 0; font-size: 14px; color: var(--bad); }
.vg-check-msg:empty { display: none; }
.vg-actions {
  position: sticky; bottom: calc(-18px - env(safe-area-inset-bottom)); flex-wrap: wrap;
  margin: 14px calc(-1 * max(18px, env(safe-area-inset-left))) calc(-18px - env(safe-area-inset-bottom));
  padding: 12px max(18px, env(safe-area-inset-left)) calc(18px + env(safe-area-inset-bottom));
  background: var(--surface); border-top: 1px solid var(--line);
}
@media (min-width: 640px) { .vg-actions { bottom: -26px; margin: 14px -26px -26px; padding: 12px 26px 26px; } }
.voice-line { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; font-size: 15px; }
.voice-line .i { flex: none; width: 18px; height: 18px; }
.voice-line.ok .i { color: var(--good); }
.voice-line.no .i { color: var(--warn); }
.voice-pick { margin-bottom: 10px; }
.voice-pick select { appearance: auto; color: var(--ink); }
.voice-box .seg-group { margin-bottom: 0; }
.voice-box .account-actions { margin-bottom: 12px; }
.voice-warn { margin: -2px 0 18px; }
.voice-warn .link { font-size: 14px; margin-left: 4px; }

/* ======================================================================================================
   Step 7: themes (tokens at the top), right/wrong marks, Large text, phone layout for practice screens.
   ====================================================================================================== */

/* ---------- theme button in the header (look.js) ---------- */
.theme-btn .i { width: 21px; height: 21px; }
@media (max-width: 380px) { .topbar-in { gap: 4px; } .theme-btn, .topbar .icon-btn { width: 40px; } }

/* ---------- right / wrong are never shown by colour alone: a ✓ or ✗ goes with them ---------- */
:root {
  --i-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12.5l4.5 4.5L19 7'/%3E%3C/svg%3E");
  --i-cross: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.5 6.5l11 11M17.5 6.5l-11 11'/%3E%3C/svg%3E");
}
.opt.right, .tile-m.hit, .t-feedback.ok, .w-feedback.ok { --mark: var(--i-check); }
.opt.wrong, .tile-m.wrong, .swipe.missed .face.back, .t-feedback.no { --mark: var(--i-cross); }
.opt.right::after, .opt.wrong::after, .tile-m.hit::after, .tile-m.wrong::after, .swipe.missed .face.back::after,
.t-feedback.ok::before, .t-feedback.no::before, .w-feedback.ok::before {
  content: ''; display: inline-block; flex: none; width: 1.1em; height: 1.1em; background: currentColor;
  -webkit-mask: var(--mark) center / contain no-repeat; mask: var(--mark) center / contain no-repeat;
}
.opt.right::after, .opt.wrong::after { width: 22px; height: 22px; margin-left: auto; }
.opt.tf.right::after, .opt.tf.wrong::after { margin-left: 4px; }
.tile-m { position: relative; }
.tile-m.hit::after, .tile-m.wrong::after { position: absolute; top: 6px; right: 6px; width: 15px; height: 15px; }
.swipe.missed .face.back::after { position: absolute; top: 16px; left: 18px; width: 24px; height: 24px; background: var(--bad); }
.t-feedback.ok::before, .t-feedback.no::before, .w-feedback.ok::before { margin-right: 6px; vertical-align: -0.17em; }

/* ---------- Large text (Settings → Text size; <html data-text="large">) ---------- */
:root[data-text='large'] body { font-size: 18px; }
:root[data-text='large'] .btn { font-size: 16.5px; }
:root[data-text='large'] .btn-lg { font-size: 19px; }
:root[data-text='large'] .btn-sm { font-size: 15.5px; }
:root[data-text='large'] .small, :root[data-text='large'] .opt-note, :root[data-text='large'] .p-hint,
:root[data-text='large'] .hint, :root[data-text='large'] .rom,
:root[data-text='large'] .stat span, :root[data-text='large'] .ch-meta, :root[data-text='large'] .pick-info span { font-size: 15px; }
:root[data-text='large'] .crumbs { font-size: 15.5px; }
:root[data-text='large'] .trnote { font-size: 15.5px; }
:root[data-text='large'] .seg button, :root[data-text='large'] .seg-label, :root[data-text='large'] .field > span,
:root[data-text='large'] .chip, :root[data-text='large'] .stats-meta, :root[data-text='large'] .ch-sub,
:root[data-text='large'] .tile .meta, :root[data-text='large'] .match-meta, :root[data-text='large'] .p-count { font-size: 16px; }
:root[data-text='large'] .panel-title, :root[data-text='large'] .section-title, :root[data-text='large'] .face-label { font-size: 13.5px; }
:root[data-text='large'] .topbar-title { font-size: 21px; }
:root[data-text='large'] .tile h3, :root[data-text='large'] .book-tile h3 { font-size: 20px; }
:root[data-text='large'] .ch-main b, :root[data-text='large'] .menu-list button { font-size: 18px; }
:root[data-text='large'] .word-ko b { font-size: 20px; }
:root[data-text='large'] .wc-ko { font-size: clamp(34px, 10.5vw, 48px); }
:root[data-text='large'] .wc-rom { font-size: 18px; }
:root[data-text='large'] .wc-tr { font-size: 22px; }
:root[data-text='large'] .wc-stats { font-size: 16px; }
:root[data-text='large'] .wc-label { font-size: 13.5px; }
:root[data-text='large'] .f-ko { font-size: clamp(50px, 15vw, 96px); }
:root[data-text='large'] .f-tr { font-size: clamp(31px, 8.6vw, 52px); }
:root[data-text='large'] .f-rom { font-size: clamp(19px, 5.2vw, 25px); }
:root[data-text='large'] .t-prompt .f-ko { font-size: clamp(44px, 12.5vw, 76px); }
:root[data-text='large'] .t-prompt .f-tr { font-size: clamp(29px, 8vw, 46px); }
:root[data-text='large'] .opt { font-size: 19.5px; }
:root[data-text='large'] .a-ko small, :root[data-text='large'] .tf-claim small, :root[data-text='large'] .tile-m small { font-size: 14px; }
:root[data-text='large'] .tf-claim { font-size: 27px; }
:root[data-text='large'] .extra { font-size: 17px; }
:root[data-text='large'] .extra small, :root[data-text='large'] .face .extras, :root[data-text='large'] .hint-text { font-size: 15.5px; }
:root[data-text='large'] .t-feedback, :root[data-text='large'] .w-feedback { font-size: 18px; }
:root[data-text='large'] .write-form input { font-size: 22px; }
:root[data-text='large'] .w-answer b { font-size: 29px; }
:root[data-text='large'] .listen-meaning { font-size: 22px; }
:root[data-text='large'] .b-sentence { font-size: clamp(24px, 6.4vw, 32px); }
:root[data-text='large'] .b-tile { font-size: 20.5px; }
:root[data-text='large'] .b-full { font-size: 22px; }
:root[data-text='large'] .b-full small, :root[data-text='large'] .b-word, :root[data-text='large'] .p-tr { font-size: 16.5px; }
:root[data-text='large'] .tile-m { font-size: 17px; }
:root[data-text='large'] .tile-m.ko b { font-size: 25px; }
:root[data-text='large'] .tile-m.tr.long { font-size: 14px; }
:root[data-text='large'] .grade b { font-size: 17px; }
:root[data-text='large'] .grade small { font-size: 13.5px; }
:root[data-text='large'] .review .your { font-size: 15.5px; }
:root[data-text='large'] #toast { font-size: 16px; }

/* ---------- phones: a question, its answers, the feedback and Next fit one screen ----------
   The practice screen is exactly the screen's height: the top bar, a body that only scrolls as a last resort
   (very long sentences with Large text), and the actions in a bar fixed at the bottom (above the home indicator,
   and above the keyboard on Android, see the viewport meta). The bar keeps its space even while empty, so nothing
   jumps when Next appears. Desktop keeps the layout above. */
@media (max-width: 640px), (max-height: 560px) {
  .practice {
    height: 100vh; height: 100dvh; min-height: 0;
    display: flex; flex-direction: column; overflow: hidden;
    padding-bottom: 0;
  }
  .practice > .p-top { flex: none; padding: 6px 0; }
  .practice > .p-stage, .practice > .t-body, .practice > .match-grid {
    flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
    /* full width, so card shadows aren't cut at the sides */
    margin: 0 calc(-1 * max(16px, env(safe-area-inset-right))) 0 calc(-1 * max(16px, env(safe-area-inset-left)));
    padding: 4px max(16px, env(safe-area-inset-right)) 12px max(16px, env(safe-area-inset-left));
  }
  .practice > .t-body { justify-content: flex-start; gap: 10px; }
  /* Blocks keep their full height: a squeezed block would draw its text over the next one (prompt over answers). */
  .practice > .t-body > *, .practice > .p-stage > .p-hint { flex-shrink: 0; }
  .practice > .p-actions {
    flex: none; align-content: center; gap: 10px;
    min-height: calc(77px + env(safe-area-inset-bottom));
    margin: 0 calc(-1 * max(16px, env(safe-area-inset-right))) 0 calc(-1 * max(16px, env(safe-area-inset-left)));
    padding: 10px max(16px, env(safe-area-inset-right)) calc(10px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-left));
    background: var(--bg); border-top: 1px solid var(--line);
  }
  .practice > .p-actions:empty { border-top-color: transparent; }
  /* The question's sound button: at the bottom, above the answers, within thumb reach (it sat in the card's top
     corner). Shown only while the card has one to play (Produce hides it until the answer). Desktop keeps it in the
     card, plus the S key. */
  .t-prompt .speak { display: none; }
  .practice:has(.t-prompt .speak:not([hidden])) > .p-sound {
    flex: none; display: flex; justify-content: center;
    margin: 0 calc(-1 * max(16px, env(safe-area-inset-right))) 0 calc(-1 * max(16px, env(safe-area-inset-left)));
    padding: 8px max(16px, env(safe-area-inset-right)) 0 max(16px, env(safe-area-inset-left));
    background: var(--bg); border-top: 1px solid var(--line);
  }
  .practice:has(.t-prompt .speak:not([hidden])) > .p-actions { border-top-color: transparent; padding-top: 8px; min-height: calc(69px + env(safe-area-inset-bottom)); }
  .p-sound .btn { min-width: 50%; height: 44px; }
  .practice > .p-keys { display: none; }

  /* question card */
  .t-prompt { min-height: 0; padding: 40px 16px 18px; border-radius: 20px; }
  .t-prompt .face-label { top: 14px; }
  .t-prompt .again-tag, .t-prompt .new-tag { top: 10px; left: 10px; right: auto; }
  .t-prompt .f-ko { font-size: clamp(34px, 10vw, 52px); }
  .t-prompt .f-tr { font-size: clamp(22px, 6.2vw, 32px); }
  .t-prompt .f-rom { margin-top: 4px; font-size: 16px; }
  .review-card { padding-bottom: 18px; }
  .review-answer, .listen-reveal, .say-reveal { margin-top: 10px; padding-top: 10px; }
  .tf-claim { margin-top: 12px; padding-top: 10px; font-size: 20px; }

  /* answers and feedback */
  .options { gap: 8px; }
  .opt { min-height: 50px; padding: 8px 14px; font-size: 16px; border-radius: 14px; }
  .opt.tf { min-height: 54px; }
  /* Answered: only your choice (✗) and the right answer (✓) stay, so the word, its meaning and the example sentence
     get their own room below instead of pushing past the screen. */
  .options:has(.opt.right) .opt:not(.right):not(.wrong) { display: none; }
  .t-feedback, .w-feedback { min-height: 22px; font-size: 15px; }
  .extras { margin-top: 8px; gap: 4px; }
  .extra { padding: 6px 10px; font-size: 14px; }
  .w-feedback .extras, .t-feedback .extras { margin-top: 6px; }
  .w-answer { padding: 6px 16px; }
  .w-answer b { font-size: 22px; }
  .write-form input { height: 52px; font-size: 18px; }
  .write-form .btn-lg { height: 52px; }

  /* flashcards: the card takes the room that is left */
  .p-stage { justify-content: flex-start; gap: 10px; }
  .swipe { flex: 1 1 auto; height: auto; min-height: 220px; max-height: 480px; }
  .face { padding: 44px 18px 60px; border-radius: 24px; }

  /* listen, speak */
  .listen-btns { margin: 2px 0; }
  .listen-play, .say-mic { width: 68px; height: 68px; }
  .listen-play .i, .say-mic .i { width: 30px; height: 30px; }
  .listen-meaning { margin-top: 2px; font-size: 18px; }
  /* Answered: the meaning is already the ✓ answer below, and the play button can be smaller. */
  .t-body:has(.opt.right) .listen-meaning { display: none; }
  .listen-card:has(.listen-reveal:not([hidden])) .listen-play { width: 48px; height: 48px; box-shadow: none; }
  .listen-card:has(.listen-reveal:not([hidden])) .listen-play .i { width: 24px; height: 24px; }

  /* sentence builder: once checked, the sentence is shown in full, so the leftover tiles go */
  .t-prompt.compact { padding: 38px 14px 14px; }
  .b-sentence { font-size: clamp(18px, 5vw, 24px); }
  .b-answer { min-height: 54px; padding: 6px; gap: 6px; }
  .b-bank { gap: 6px; }
  .b-tile { min-height: 42px; padding: 6px 11px; font-size: 17px; border-bottom-width: 3px; }
  .t-body:has(.b-answer.ok) .b-bank, .t-body:has(.b-answer.no) .b-bank { display: none; }
  .b-full { margin-top: 4px; font-size: 18px; }

  /* match */
  .match-meta { padding: 0 2px 8px; }
  .practice > .match-grid { align-content: start; padding-top: 2px; }

  /* Large text on a phone: a little less than elsewhere, so a question still fits */
  :root[data-text='large'] .t-prompt .f-ko { font-size: clamp(38px, 11.5vw, 60px); }
  :root[data-text='large'] .t-prompt .f-tr { font-size: clamp(25px, 7vw, 36px); }
  :root[data-text='large'] .t-prompt { padding-top: 34px; padding-bottom: 12px; }
  :root[data-text='large'] .t-prompt .face-label { top: 10px; }
  :root[data-text='large'] .practice > .t-body { gap: 8px; padding-bottom: 8px; }
  :root[data-text='large'] .options { gap: 6px; }
  :root[data-text='large'] .extras { margin-top: 4px; }
  :root[data-text='large'] .extra { padding: 5px 9px; line-height: 1.4; }
  :root[data-text='large'] .opt { min-height: 48px; padding-top: 6px; padding-bottom: 6px; font-size: 18.5px; line-height: 1.3; }
  :root[data-text='large'] .b-sentence { font-size: clamp(21px, 5.8vw, 27px); }
  :root[data-text='large'] .b-tile { font-size: 19px; }
  :root[data-text='large'] .extra { font-size: 16px; }
  :root[data-text='large'] .t-feedback, :root[data-text='large'] .w-feedback { font-size: 16.5px; }
}

/* Phones up to about 760px tall: one example sentence with the answer (the rest are on the flashcard's back). */
@media (max-width: 640px) and (max-height: 760px), (max-height: 560px) {
  .practice .t-body .extra + .extra { display: none; }
}

/* Very short: the keyboard is open (Write, Listen) or the phone is turned sideways. */
@media (max-height: 500px) {
  .practice > .p-top { padding: 0; }
  .t-prompt { padding: 28px 12px 10px; border-radius: 16px; }
  .t-prompt .face-label { top: 8px; font-size: 11px; }
  .t-prompt .f-ko, :root[data-text='large'] .t-prompt .f-ko { font-size: 30px; }
  .t-prompt .f-tr, :root[data-text='large'] .t-prompt .f-tr { font-size: 21px; }
  .practice > .t-body { gap: 8px; padding-bottom: 8px; }
  .practice > .p-actions { min-height: 0; padding-top: 6px; padding-bottom: calc(6px + env(safe-area-inset-bottom)); }
  .practice > .p-actions .btn-lg { height: 46px; font-size: 16px; }
  .practice > .p-actions .grade { min-height: 50px; }
  .write-form input, .write-form .btn-lg { height: 46px; }
  .listen-play, .say-mic { width: 54px; height: 54px; }
  .swipe { min-height: 160px; }
  .t-body .extras { display: none; }
}

/* Long words and phrases (look.js marks them): smaller, so idioms and long translations keep to a line or two. */
:root .f-ko.long { font-size: clamp(30px, 8.6vw, 56px); }
:root .f-ko.longer { font-size: clamp(25px, 7vw, 44px); }
:root .f-tr.long { font-size: clamp(21px, 5.8vw, 34px); }
:root .f-tr.longer { font-size: clamp(18px, 4.8vw, 28px); }
:root[data-text='large'] .f-ko.long { font-size: clamp(33px, 9.6vw, 62px); }
:root[data-text='large'] .f-ko.longer { font-size: clamp(28px, 7.8vw, 50px); }
:root[data-text='large'] .f-tr.long { font-size: clamp(23px, 6.4vw, 38px); }
:root[data-text='large'] .f-tr.longer { font-size: clamp(20px, 5.4vw, 31px); }

/* ---------- step 9: answer feedback, celebrations, practice notices, opening logo (fx.js, guard.js, intro.js) ---------- */
/* Confetti colours per theme: bright on Light, softer and lighter on Dark, earthy on Calm. */
:root { --fx-1: #3f5ee8; --fx-2: #f5b82e; --fx-3: #ef6a5b; --fx-4: #2fb36f; --fx-5: #9a6bf0; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) { --fx-1: #8ea2ff; --fx-2: #f2c75c; --fx-3: #ff8f84; --fx-4: #5fd6a0; --fx-5: #c3a6ff; }
}
:root[data-theme='dark'] { --fx-1: #8ea2ff; --fx-2: #f2c75c; --fx-3: #ff8f84; --fx-4: #5fd6a0; --fx-5: #c3a6ff; }
:root[data-theme='calm'] { --fx-1: #2f7f75; --fx-2: #d49a3a; --fx-3: #c66a52; --fx-4: #6f9a4f; --fx-5: #8d6fb0; }

/* Animations off (Settings, or the device's "reduce motion" while the setting is untouched): no movement at all. */
[data-motion='off'] *, [data-motion='off'] *::before, [data-motion='off'] *::after {
  animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important;
}

.fx-shake { animation: fx-shake 0.38s ease; }
.fx-pop { animation: fx-pop 0.26s ease-out; }
@keyframes fx-shake { 15%, 55% { transform: translateX(-6px); } 35%, 75% { transform: translateX(6px); } 90% { transform: translateX(-2px); } }
@keyframes fx-pop { 40% { transform: scale(1.035); } }
.fx-confetti { position: fixed; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 90; }
.ring.celebrate { box-shadow: 0 0 0 7px var(--good-soft); }

/* Practice notices (guard.js): over the practice screen, like a dialog; the screen under it waits. */
.guard {
  position: fixed; inset: 0; z-index: 80; display: grid; place-items: center;
  padding: calc(24px + env(safe-area-inset-top)) 16px calc(24px + env(safe-area-inset-bottom));
  background: var(--overlay); opacity: 0; transition: opacity 0.2s ease;
}
.guard.open { opacity: 1; }
.guard-card {
  width: min(100%, 380px); max-height: 100%; overflow: auto; padding: 26px 22px 22px; border-radius: 20px;
  background: var(--surface); color: var(--ink); box-shadow: var(--card-shadow); text-align: center;
  transform: translateY(8px); transition: transform 0.2s ease;
}
.guard.open .guard-card { transform: none; }
.guard-mark { width: 52px; height: 52px; margin: 0 auto 12px; display: grid; place-items: center; border-radius: 50%; background: var(--good-soft); color: var(--good); }
.guard-bot .guard-mark { background: var(--accent-soft); color: var(--accent); }
.guard-mark .i { width: 26px; height: 26px; }
.guard h2 { margin: 0 0 6px; font-size: 20px; }
.guard p { margin: 0 0 18px; color: var(--ink-2); line-height: 1.45; }
.guard-wait { height: 6px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.guard-wait i { display: block; width: 100%; height: 100%; background: var(--good); transform-origin: left; animation: guard-wait linear both; }
@keyframes guard-wait { from { transform: scaleX(0); } }

/* Opening logo (intro.js, G7b): on every visit and launch. One timeline, scaled by --k:
     .first (the very first visit, k = 1, about 2.5 s, started by the tap on a language): the stem rises, the ray strokes draw in one
       by one (still dim), the bulb switches on at 740 ms (the click) and the rays light up, the letters of the name appear
       one by one from 900 ms (Calm bloom starts), the tagline fades in, and a soft glow pulse closes it;
     .later (every other visit, k = .39, about 1 s): the same, silent.
   Before the language tap (.await) the logo rests dim: stem low, bulb off, no rays, no words, the language buttons below. Only transform and opacity move,
   except the ray strokes (stroke-dashoffset on five tiny paths). Without motion (.still) nothing animates: dim while waiting
   for the language tap, then the lit logo. A tap or a key ends it (intro.js). */
.splash {
  --k: 1;
  position: fixed; inset: 0; z-index: 120; display: grid; place-content: center; justify-items: center; gap: 10px; padding: 24px;
  background: var(--bg); transition: opacity 0.22s ease; cursor: pointer;
}
.splash.later { --k: 0.39; }
.splash.out { opacity: 0; pointer-events: none; }
.splash-mark { position: relative; display: grid; margin-bottom: 4px; }
.splash .mark { position: relative; width: 92px; height: auto; color: var(--accent); overflow: visible; }
.splash-mark::before, .splash-mark::after { /* glow around the bulb, centred on it; ::after is the closing pulse */
  content: ''; position: absolute; left: 50%; top: 38.9%; width: 150px; height: 150px; margin: -75px 0 0 -75px; border-radius: 50%;
  background: radial-gradient(circle, color-mix(in srgb, var(--accent) 34%, transparent) 0%, transparent 68%);
}
.splash-mark::before { opacity: 0.55; }
.splash-mark::after { opacity: 0; }
.splash-text { display: grid; justify-items: center; gap: 10px; }
.splash-name { grid-area: 1 / 1; margin: 0; display: flex; font-size: 42px; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; color: var(--ink); }
.splash-name span { display: inline-block; }
.splash-tag { grid-area: 2 / 1; margin: 0; min-height: 1.4em; max-width: 86vw; text-align: center; font-size: 16px; font-weight: 500; color: var(--ink-2); }
.splash-text { position: relative; }
.splash-langs { /* over the space below the logo, outside the layout, so the logo never moves */
  position: absolute; top: 24px; left: 50%; width: min(280px, 80vw); transform: translateX(-50%); display: grid; gap: 10px; transition: opacity 0.2s ease;
}
.splash-langs button {
  min-height: 52px; padding: 0 18px; border: 2px solid var(--line); border-radius: 16px; background: var(--surface); color: var(--ink);
  font: inherit; font-size: 18px; font-weight: 650; cursor: pointer; transition: border-color 0.15s, background 0.15s;
}
@media (hover: hover) { .splash-langs button:hover { border-color: var(--accent); } }
.splash-langs button:active { background: var(--accent-soft); border-color: var(--accent); }
.splash.go .splash-langs { opacity: 0; pointer-events: none; }
.splash-wait { display: flex; gap: 7px; height: 8px; margin-top: 14px; opacity: 0; transition: opacity 0.3s ease; }
.splash.waiting .splash-wait { opacity: 1; }
.splash-wait i { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); animation: intro-dot 1.4s ease-in-out infinite; }
.splash-wait i:nth-child(2) { animation-delay: 0.2s; }
.splash-wait i:nth-child(3) { animation-delay: 0.4s; }

/* waiting for a language: light off */
.splash.await .m-stem { opacity: 0.55; transform: translateY(10px); }
.splash.await .m-dot { transform-box: fill-box; transform-origin: center; opacity: 0.22; transform: scale(0.8); }
.splash.await .m-rays, .splash.await .splash-name, .splash.await .splash-tag, .splash.await .splash-mark::before { opacity: 0; }

/* the timeline */
.splash.go .m-stem { animation: splash-stem-later calc(300ms * var(--k)) cubic-bezier(0.2, 0.8, 0.2, 1) both; }
.splash.first.go .m-stem { animation-name: splash-stem-first; }
.splash.go .m-dot { transform-box: fill-box; transform-origin: center;
  animation: splash-dim calc(200ms * var(--k)) both, splash-on calc(420ms * var(--k)) calc(740ms * var(--k)) cubic-bezier(0.2, 0.8, 0.2, 1.25) both; }
.splash.first.go .m-dot { animation: splash-on calc(420ms * var(--k)) calc(740ms * var(--k)) cubic-bezier(0.2, 0.8, 0.2, 1.25) both; }
.splash.go .m-rays path { stroke-dasharray: 1 1;
  animation: splash-ray calc(260ms * var(--k)) calc((60ms + var(--r) * 100ms) * var(--k)) ease-out both,
    splash-lit calc(260ms * var(--k)) calc(740ms * var(--k)) ease-out forwards; }
.splash.go .splash-mark::before { animation: splash-glow calc(1300ms * var(--k)) calc(740ms * var(--k)) ease-out both; }
.splash.go .splash-mark::after { animation: splash-pulse calc(450ms * var(--k)) calc(2100ms * var(--k)) ease-out both; }
.splash.go .splash-name span { animation: splash-rise calc(260ms * var(--k)) calc((900ms + var(--i) * 80ms) * var(--k)) ease-out both; }
.splash.go .splash-tag { animation: splash-rise calc(400ms * var(--k)) calc(1450ms * var(--k)) ease-out both; }
.splash.still *, .splash.still *::before, .splash.still *::after { animation: none !important; }
@keyframes splash-stem-first { from { opacity: 0.55; transform: translateY(10px); } }
@keyframes splash-stem-later { from { opacity: 0; transform: translateY(16px); } }
@keyframes splash-dim { from { opacity: 0; } to { opacity: 0.22; } }
@keyframes splash-on { from { opacity: 0.22; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.25); } to { opacity: 1; transform: scale(1); } }
@keyframes splash-ray { from { stroke-dashoffset: 1; opacity: 0; } 20% { opacity: 0.3; } to { stroke-dashoffset: 0; opacity: 0.3; } }
@keyframes splash-lit { from { opacity: 0.3; } to { opacity: 1; } }
@keyframes splash-glow { 0% { opacity: 0; transform: scale(0.3); } 30% { opacity: 1; } 100% { opacity: 0.55; transform: scale(1); } }
@keyframes splash-pulse { 0% { opacity: 0; transform: scale(0.7); } 40% { opacity: 0.7; } 100% { opacity: 0; transform: scale(1.5); } }
@keyframes splash-rise { from { opacity: 0; transform: translateY(10px); } }
@keyframes intro-dot { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } }

/* ---------- offline (step 5, offline.js) ---------- */
/* Shown only while offline: html[data-net] is set by offline.js before the first page is drawn. */
.net-chip {
  display: none; width: 32px; height: 32px; flex: none; place-items: center; border-radius: 50%;
  background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn);
}
.net-chip .i { width: 18px; height: 18px; }
:root[data-net='offline'] .net-chip { display: grid; }
.offline-note { display: none; align-items: flex-start; gap: 8px; margin: 0 0 14px; padding: 10px 12px; border-radius: 12px;
  background: color-mix(in srgb, var(--warn) 12%, var(--surface)); color: var(--ink); font-size: 14px; }
.offline-note .i { flex: none; width: 18px; height: 18px; margin-top: 1px; color: var(--warn); }
:root[data-net='offline'] .offline-note { display: flex; }
.opt-note.offline-note { margin: -8px 0 18px; }
.voice-off { display: flex; align-items: flex-start; gap: 6px; margin: 6px 0 10px; }
.voice-off .i { flex: none; width: 16px; height: 16px; margin-top: 1px; color: var(--warn); }
/* "New version — tap to refresh": in the page flow above the header, so it never covers anything. */
.update-bar {
  display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 44px;
  padding: calc(8px + env(safe-area-inset-top)) 16px 8px; border: 0; cursor: pointer;
  background: var(--accent); color: var(--accent-ink); font: inherit; font-size: 15px; font-weight: 700; text-align: left;
}
.update-bar .i { flex: none; width: 18px; height: 18px; }
.update-bar:disabled { opacity: 0.7; cursor: default; }
.tip-banner > div { min-width: 0; }
.tip-banner p { margin: 0 0 10px; }
.tip-banner .account-actions { margin-bottom: 0; }

/* ---------- home (app.js renderHome) ----------
   The page fills the screen so the footer sits at the bottom. Under the header: a "today" panel (a start card for
   someone new), the five levels as one path from 1 to 5, a quiet sign-in line for guests, the footer.
   Every class starts with home-: a shared name (.intro) once hid the whole page. */
.home { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; }
.home-main { width: 100%; padding-bottom: 24px; }
.home .site-foot { width: 100%; margin: auto auto 0; padding-top: 12px; }

/* today: goal ring, streak, review, continue */
.home-today { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); padding: 6px; margin: 8px 0 28px; }
.home-cell { display: flex; align-items: center; gap: 12px; min-width: 0; padding: 12px; }
.home-num { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.home-num b { font-size: 26px; font-weight: 750; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.home-num b small { font-size: 15px; font-weight: 600; letter-spacing: 0; color: var(--ink-3); }
.home-num span { font-size: 13px; color: var(--ink-2); overflow-wrap: break-word; }
.home-ring { width: 44px; height: 44px; flex: none; transform: rotate(-90deg); }
.home-ring circle { fill: none; stroke: var(--surface-2); stroke-width: 5; }
.home-ring .on { stroke: var(--accent); stroke-linecap: round; }
.home-goal.done .home-ring .on { stroke: var(--good); }
.home-goal.done .home-num b { color: var(--good); }
.home-streak { border-left: 1px solid var(--line); }
.home-review, .home-continue { grid-column: 1 / -1; border-top: 1px solid var(--line); }
.home-review { justify-content: space-between; }
.home-review > .home-num { flex: 1 1 auto; }
.home-review-act { flex: none; display: flex; align-items: center; gap: 2px; }
.home-more { width: 40px; height: 40px; }
/* narrow phones: the count on one line, the button under it at full width (long Russian and Uzbek labels) */
@media (max-width: 479px) {
  .home-review.has-due { flex-wrap: wrap; row-gap: 10px; }
  .home-review.has-due > .home-num { flex: 1 1 100%; flex-direction: row; align-items: baseline; gap: 8px; }
  .home-review.has-due .home-review-act { flex: 1 1 100%; }
  .home-review.has-due .home-review-act .btn { flex: 1; }
}
.home-more .i { width: 18px; height: 18px; color: var(--ink-3); }
.home-caught { flex-direction: row; align-items: flex-start; gap: 8px; }
.home-caught > .i { margin-top: 1px; color: var(--good); }
.home-caught b { display: block; font-size: 15px; font-weight: 650; letter-spacing: 0; color: var(--ink); }
.home-caught small { display: block; font-size: 13px; color: var(--ink-2); }
.home-continue { justify-content: space-between; border-radius: 0 0 14px 14px; transition: background-color 0.15s; }
.home-continue:hover { background: var(--surface-2); }
.home-continue-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.home-continue-txt span { font-size: 13px; color: var(--ink-2); }
.home-continue-txt b { font-size: 16px; overflow-wrap: anywhere; }
.home-continue > .i { color: var(--accent); }
@media (min-width: 600px) {
  .home-review, .home-continue { grid-column: auto; }
  .home-continue { border-left: 1px solid var(--line); border-radius: 0 0 14px 0; }
}
/* wide: one row; flex so a missing cell (no review yet) leaves no hole */
@media (min-width: 960px) {
  .home-today { display: flex; align-items: stretch; }
  .home-cell { padding: 10px 18px; }
  .home-goal, .home-streak { flex: none; }
  .home-review { flex: 1.25 1 0; }
  .home-continue { flex: 1 1 0; border-radius: 14px; }
  .home-cell + .home-cell { border-top: 0; border-left: 1px solid var(--line); }
}

/* someone new: one first step */
.home-start { display: flex; flex-wrap: wrap; align-items: center; gap: 16px 28px; padding: 22px; margin: 8px 0 28px; }
.home-start-txt { flex: 1 1 320px; min-width: 0; }
.home-start-k { margin: 0 0 2px; font-size: 14px; font-weight: 650; color: var(--accent); }
.home-start h2 { margin: 0 0 6px; font-size: 22px; letter-spacing: -0.01em; overflow-wrap: anywhere; }
.home-start .muted { margin: 0; max-width: 560px; }
.home-start-btn { flex: none; }
@media (max-width: 599px) { .home-start { padding: 18px; } .home-start-btn { width: 100%; } }

/* the levels: one path, 1 to 5. The number badges deepen with the level (the theme's accent, mixed in). */
.home-h { margin: 0 4px 12px; font-size: 20px; font-weight: 750; letter-spacing: -0.01em; }
.home-path { list-style: none; margin: 0 0 18px; padding: 6px; background: var(--surface); border-radius: 20px; box-shadow: var(--shadow); }
.home-lv {
  position: relative; overflow: hidden; display: grid;
  grid-template-columns: 44px minmax(0, 1fr) auto; grid-template-areas: 'num info go' '. prog prog';
  column-gap: 14px; align-items: center; padding: 14px 12px; border-radius: 14px; transition: background-color 0.15s;
}
.home-lv:hover { background: color-mix(in srgb, var(--surface-2) 60%, var(--surface)); }
/* a hairline between steps that leaves the rail of numbers unbroken */
.home-lv + .home-lv::before { content: ''; position: absolute; top: 0; left: 70px; right: 12px; height: 1px; background: var(--line); }
.home-lv-num {
  grid-area: num; align-self: start; position: relative; width: 44px; height: 44px; display: grid; place-items: center;
  border-radius: 12px; background: var(--accent-soft); color: var(--ink);
  font-size: 19px; font-weight: 750; font-variant-numeric: tabular-nums;
}
.home-lv-num::before, .home-lv-num::after { content: ''; position: absolute; left: 21px; width: 2px; background: var(--line); }
.home-lv:not(:first-child) .home-lv-num::before { bottom: 100%; height: 14px; }
.home-lv:not(:last-child) .home-lv-num::after { top: 100%; height: 400px; }
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .home-lv:nth-child(1) .home-lv-num { background: color-mix(in srgb, var(--accent) 12%, var(--surface)); }
  .home-lv:nth-child(2) .home-lv-num { background: color-mix(in srgb, var(--accent) 22%, var(--surface)); }
  .home-lv:nth-child(3) .home-lv-num { background: color-mix(in srgb, var(--accent) 32%, var(--surface)); }
  .home-lv:nth-child(4) .home-lv-num { background: color-mix(in srgb, var(--accent) 43%, var(--surface)); }
  .home-lv:nth-child(5) .home-lv-num { background: color-mix(in srgb, var(--accent) 54%, var(--surface)); }
}
.home-lv-link { grid-area: info; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.home-lv-link::after { content: ''; position: absolute; inset: 0; border-radius: 14px; }
.home-lv-link:focus-visible { outline: 0; }
.home-lv-link:focus-visible::after { outline: 2px solid var(--accent); outline-offset: -2px; }
.home-lv-link h3 { margin: 0 0 2px; font-size: 18px; overflow-wrap: anywhere; transition: color 0.15s; }
.home-lv:hover h3 { color: var(--accent); }
.home-lv-meta { font-size: 14px; color: var(--ink-2); }
.home-lv-meta span { white-space: nowrap; }
.home-lv-prog { grid-area: prog; min-width: 0; margin-top: 10px; }
.home-lv-prog .pbar { height: 6px; margin: 0 0 5px; }
.home-lv-prog span { display: block; font-size: 13px; color: var(--ink-3); }
@media (max-width: 759px) { .home-lv-none { display: none; } }
.home-lv-go { grid-area: go; display: grid; place-items: center; color: var(--ink-3); transition: color 0.15s, transform 0.15s; }
.home-lv:hover .home-lv-go { color: var(--accent); transform: translateX(2px); }
@media (min-width: 760px) {
  .home-lv { grid-template-columns: 44px minmax(0, 1fr) minmax(0, 1.15fr) auto; grid-template-areas: 'num info prog go'; column-gap: 20px; padding: 14px 16px; }
  .home-lv + .home-lv::before { left: 76px; right: 16px; }
  .home-lv-num::before, .home-lv-num::after { left: 21px; }
  .home-lv-prog { margin-top: 0; }
}
@media (max-width: 380px) {
  .home-lv { column-gap: 10px; padding: 12px 8px; }
  .home-lv + .home-lv::before { left: 62px; right: 8px; }
  .home-lv:not(:first-child) .home-lv-num::before { height: 12px; }
}

/* guests: one quiet line */

:root[data-text='large'] .home-num b { font-size: 29px; }
:root[data-text='large'] .home-num span, :root[data-text='large'] .home-continue-txt span, :root[data-text='large'] .home-caught small,
:root[data-text='large'] .home-lv-prog span, :root[data-text='large'] :root[data-text='large'] .home-continue-txt b, :root[data-text='large'] .home-caught b { font-size: 18px; }
:root[data-text='large'] .home-h { font-size: 22px; }
:root[data-text='large'] .home-start h2 { font-size: 24px; }
:root[data-text='large'] .home-start-k { font-size: 15.5px; }
:root[data-text='large'] .home-lv-link h3 { font-size: 20px; }
:root[data-text='large'] .home-lv-meta { font-size: 16px; }
:root[data-text='large'] .home-lv-num { font-size: 21px; }


/* ---------- home search (G4, search.js) ----------
   The bar sits at the top of the home page. While it holds text the rest of the page steps aside (.hs-on) and the
   results fill the space under it: words, then lessons, then similar matches. The keyboard's active row is
   aria-selected; the focus stays in the bar. Classes start with hs-. */
.hs { margin: 4px 0 20px; }
.hs-bar {
  display: flex; align-items: center; gap: 6px; min-height: 52px; padding: 0 4px 0 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 14px; box-shadow: var(--shadow);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.hs-bar:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.hs-bar > .i { color: var(--ink-3); }
.hs-bar input {
  flex: 1; min-width: 0; height: 50px; padding: 0 4px; border: 0; background: transparent; outline: none;
  font-size: 16px; color: var(--ink); text-overflow: ellipsis; -webkit-appearance: none; appearance: none;
}
.hs-bar input::placeholder { color: var(--ink-3); opacity: 1; }
.hs-bar input::-webkit-search-cancel-button, .hs-bar input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }
.hs-key { display: none; margin-right: 10px; color: var(--ink-3); }
@media (hover: hover) and (pointer: fine) { .hs:not(.has-q) .hs-key { display: inline-block; } }
.hs-clear { width: 44px; height: 44px; color: var(--ink-3); }
.hs-clear:hover { color: var(--ink); }
.hs-status { margin: 10px 6px 0; font-size: 13px; color: var(--ink-2); }
.hs-status:empty { display: none; }
.hs-status.hs-quiet { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.hs-status.hs-loading::before {
  content: ''; display: inline-block; width: 11px; height: 11px; margin-right: 8px; vertical-align: -1px;
  border: 2px solid var(--surface-2); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite;
}
.home-main.hs-on > :not(.hs) { display: none; }
.hs-results { margin: 8px 0 0; padding: 6px; }
.hs-group + .hs-group { margin-top: 4px; padding-top: 4px; border-top: 1px solid var(--line); }
.hs-gh { padding: 10px 12px 4px; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3); }
.hs-opt {
  display: flex; align-items: center; gap: 12px; min-height: 56px; padding: 10px 12px;
  border-radius: 12px; cursor: pointer; transition: background-color 0.12s;
}
.hs-opt:hover { background: var(--surface-2); }
.hs-opt[aria-selected='true'] { background: var(--accent-soft); box-shadow: inset 0 0 0 2px var(--accent); }
.hs-opt mark { background: none; color: var(--accent); font-weight: 750; }
.hs-ko { flex: 0 1 auto; min-width: 0; display: flex; flex-direction: column; }
.hs-ko b { font-size: 17px; word-break: keep-all; overflow-wrap: anywhere; }
.hs-main { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.hs-word .hs-main { align-items: flex-end; text-align: right; }
.hs-tr { color: var(--ink); overflow-wrap: anywhere; }
.hs-word .hs-tr { color: var(--ink-2); }
.hs-also { font-size: 13px; color: var(--ink-2); overflow-wrap: anywhere; }
.hs-tag {
  display: inline-block; padding: 0 5px; border-radius: 5px; background: var(--surface-2);
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; line-height: 17px; color: var(--ink-2); vertical-align: 1px;
}
.hs-opt[aria-selected='true'] .hs-tag { background: var(--surface); }
.hs-where { display: inline-flex; align-items: baseline; gap: 5px; max-width: 100%; font-size: 12.5px; color: var(--ink-3); }
.hs-where .i { width: 14px; height: 14px; align-self: center; }
.hs-where span { min-width: 0; overflow-wrap: anywhere; }
.hs-ch-ic { flex: none; width: 38px; height: 38px; display: grid; place-items: center; border-radius: 11px; background: var(--surface-2); color: var(--accent); }
.hs-ch-ic .i { width: 19px; height: 19px; }
.hs-ch-name { font-weight: 650; overflow-wrap: anywhere; }
.hs-ch-title { font-weight: 500; }
.hs-ch .hs-also { display: block; margin-top: 2px; font-weight: 400; }
.hs-ch > .i { color: var(--ink-3); }
.hs-ch:hover > .i, .hs-ch[aria-selected='true'] > .i { color: var(--accent); }
.hs-none { display: flex; flex-direction: column; gap: 4px; padding: 26px 16px; text-align: center; }
.hs-none b { font-size: 17px; }
.hs-none span { color: var(--ink-2); font-size: 14px; }
@media (min-width: 760px) {
  .hs { margin-top: 8px; }
  .hs-word .hs-main { flex-direction: row; align-items: center; justify-content: flex-end; gap: 16px; }
  .hs-word .hs-where { order: -1; margin-right: auto; padding-left: 12px; }
  .hs-word .hs-tr, .hs-word .hs-also { max-width: 50%; }
}
@media (max-width: 380px) { .hs-opt { gap: 10px; padding: 10px 8px; } }
:root[data-text='large'] .hs-bar input { font-size: 18px; }
:root[data-text='large'] .hs-ko b { font-size: 20px; }
:root[data-text='large'] .hs-status, :root[data-text='large'] .hs-also, :root[data-text='large'] .hs-where { font-size: 15px; }
:root[data-text='large'] .hs-gh { font-size: 13.5px; }
:root[data-text='large'] .hs-none b { font-size: 19px; }
:root[data-text='large'] .hs-none span { font-size: 16px; }

/* ---------- Random (G5): weak words, each question in another mode ---------- */
.rnd-kind {
  flex: none; padding: 3px 10px; border-radius: 99px; background: var(--accent-soft); color: var(--accent);
  font-size: 12px; font-weight: 700; letter-spacing: 0.04em; white-space: nowrap;
}
.rnd-empty { display: flex; gap: 10px; margin: 0 0 16px; padding: 12px 14px; border-radius: 14px; background: var(--surface-2); font-size: 14px; color: var(--ink); }
.rnd-empty > .i { flex: none; margin-top: 1px; color: var(--accent); }
.rnd-empty p { margin: 0 0 10px; }
.rnd-empty-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.home-rnd { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px 20px; margin: -14px 0 28px; padding: 14px 18px; }
.home-rnd-txt { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
.home-rnd-txt b { font-size: 16px; }
.home-rnd-txt span { font-size: 13px; color: var(--ink-2); }
@media (max-width: 479px) { .home-rnd .btn { flex: 1 1 100%; } }
:root[data-text='large'] .mode-hint, :root[data-text='large'] .rnd-empty, :root[data-text='large'] .home-rnd-txt span { font-size: 16px; }
:root[data-text='large'] .rnd-kind { font-size: 13.5px; }
:root[data-text='large'] .home-rnd-txt b { font-size: 18px; }

/* ---------- saved words (G6b, saved.js) ---------- */
/* The bookmark (icon only): an outline to save, filled in the accent colour once saved; grey (still tappable, it
   says why) at the limit. Tap targets of 44 px or more. */
.wc-save .i path, .hs-save .i path { fill: none; transition: fill 0.15s; }
.wc-save.on .i path, .hs-save.on .i path { fill: currentColor; }
.wc-save { flex: none; width: 48px; height: 48px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: var(--surface-2); color: var(--ink-2); cursor: pointer; transition: background 0.15s, color 0.15s; }
.wc-save .i { width: 22px; height: 22px; }
.wc-save:hover { color: var(--accent); }
.wc-save.on { background: var(--accent-soft); color: var(--accent); }
.wc-save.off, .hs-save.off { color: var(--ink-3); opacity: 0.55; cursor: not-allowed; }
.wc-save.off:hover, .hs-save.off:hover { color: var(--ink-3); background: var(--surface-2); }
.wc-save:focus-visible, .hs-save:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.hs-save { width: 44px; height: 44px; margin: -6px -8px -6px 0; color: var(--ink-3); }
.hs-save .i { width: 20px; height: 20px; }
.hs-save:hover { color: var(--accent); background: var(--surface); }
.hs-save.on { color: var(--accent); }
.hs-save.off { background: transparent; }

/* home: the collections, above the levels */
.home-saved { margin-bottom: 24px; }
.home-saved[hidden] { display: none; }
.sv-home-head { gap: 12px; flex-wrap: wrap; }
.sv-home-head .home-h { margin-bottom: 0; }
.sv-more { margin-top: 8px; color: var(--accent); }
.sv-grid { gap: 10px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 150px), 1fr)); }
@media (min-width: 640px) { .sv-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; } }
.sv-tile { display: flex; flex-direction: column; gap: 4px; height: 100%; padding: 12px 14px 14px; }
.sv-tile h3 { display: flex; align-items: flex-start; gap: 7px; margin: 0; font-size: 16px; line-height: 1.3; }
.sv-tile h3 .i { flex: none; width: 16px; height: 16px; margin-top: 2px; color: var(--accent); }
.sv-tile h3 .i path { fill: currentColor; }
.sv-tile h3 span { min-width: 0; overflow-wrap: anywhere; }
.sv-tile .meta { flex: 1; font-size: 13px; }
.sv-tile .pbar { height: 6px; margin: 6px 0 0; }
:root[data-text='large'] .sv-tile h3 { font-size: 18px; }
:root[data-text='large'] .sv-tile .meta { font-size: 15px; }

/* a collection's page */
.sv-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: -4px 0 8px; }
.sv-size { display: flex; align-items: center; gap: 7px; margin: 0 4px; }
.sv-size .i { width: 16px; height: 16px; color: var(--accent); }
.sv-size .i path { fill: currentColor; }
.sv-menu { display: grid; gap: 10px; margin-top: 14px; }
.sv-menu .btn { justify-content: flex-start; }
.sv-r-label { display: inline-flex; align-items: center; gap: 6px; }

/* profile: the lessons' mistakes, apart from "My words" */
.pf-mistakes { margin: -4px 0 12px; font-size: 14px; color: var(--ink-2); }

:root[data-text='large'] .pf-mistakes { font-size: 16px; }

/* G7: "My words" on the home page (own.js): the add and import buttons, own folders, then the saved collections */
.home-mine { margin-bottom: 24px; }
.mine-head { display: flex; align-items: center; gap: 2px; margin: 0 0 12px; }
.mine-head .home-h { margin-bottom: 0; }
.mine-head .info-btn { margin-left: 4px; }
.mine-add { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 16px; margin-bottom: 16px; padding: 16px; }
.mine-add-txt { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mine-add-txt b { font-size: 16px; }
.mine-actions { display: flex; flex-wrap: wrap; gap: 8px; }
@media (max-width: 479px) { .mine-actions { width: 100%; } .mine-actions .btn { flex: 1 1 0; min-width: 0; padding: 0 10px; } }
.mine-sub { margin: 4px 4px 10px; gap: 8px; }
.mine-h { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink-2); }
.mine-new { color: var(--accent); margin-right: -8px; }
#own-grid + .sv-more, #own-grid { margin-bottom: 16px; }
#own-grid + .sv-more { margin-top: -8px; }
.home-mine .home-saved { margin-bottom: 0; }
.own-tile h3 .i path { fill: none; }
.own-lang {
  display: inline-block; margin-right: 6px; padding: 0 5px; border: 1px solid var(--line); border-radius: 6px; vertical-align: 1px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; line-height: 1.5; color: var(--ink-2);
}
:root[data-text='large'] .mine-add-txt b { font-size: 18px; }
:root[data-text='large'] .mine-h { font-size: 17px; }
:root[data-text='large'] .own-lang { font-size: 12.5px; }

/* a button at its limit: grey, a tap says why */
.btn.is-off, .btn.is-off:hover { background: var(--surface-2); border-color: var(--line); color: var(--ink-3); filter: none; cursor: not-allowed; }
.btn.is-off:active { transform: none; }

/* the add-word form: counters near the cap, a note when a paste was cut, the "help improve" box */
.cap-count { font-weight: 500; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.cap-count.at-cap { color: var(--warn); }
.cap-cut { margin-top: -2px; font-size: 12.5px; color: var(--warn); }
.cap-cut[hidden] { display: none; }
.field input[aria-invalid='true'] { border-color: var(--bad); }
.field select { appearance: auto; }
.own-lang-seg { margin: 0; }
.share-row { display: flex; align-items: center; gap: 4px; margin: 4px 0 8px; }
.share-check { display: flex; align-items: center; gap: 10px; min-height: 44px; font-size: 14.5px; font-weight: 600; color: var(--ink-2); cursor: pointer; }
.share-check input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--accent); cursor: pointer; }
.account-box .share-row { margin-bottom: 0; }
.preview-note { display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 8px 14px; border-top: 1px solid var(--line); font-size: 13.5px; color: var(--ink-2); }
.preview-note .i { flex: none; width: 16px; height: 16px; margin-top: 2px; color: var(--ink-3); }
.preview-note.warn, .preview-note.warn .i { color: var(--warn); }
.preview-list li.over { opacity: 0.45; }
.preview-list li > span { min-width: 0; overflow-wrap: anywhere; }
:root[data-text='large'] .share-check, :root[data-text='large'] .preview-note { font-size: 16px; }
/* G7: own words may be long and without spaces (up to the caps in own.js): such text wraps instead of running off */
.f-rom, .word-ko .rom, .word-tr, .preview-list .rom { overflow-wrap: anywhere; }
.options { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) { .options { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.opt > span, .a-ko, .a-tr { min-width: 0; overflow-wrap: anywhere; }
/* Match: columns never widen for one long word; a long Korean word or phrase (own words: up to 40) gets a smaller size */
.match-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-rows: max-content; } /* rows as tall as their text */
.match-grid.many { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (min-width: 560px) { .match-grid, .match-grid.many { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.tile-m.ko.long b, .match-grid.many .tile-m.ko.long b { font-size: 16px; line-height: 1.3; }
.tile-m > * { max-width: 100%; }
.practice, .sheet, .t-feedback, .w-feedback { overflow-wrap: break-word; }
