    /* ── Reset & Base ─────────────────────────────────────────────────────── */
    *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
    
    :root {
      /* The pixel accent face, named once so a locale can change it.
         Press Start 2P has no Vietnamese diacritics — its Google Fonts build ships latin,
         latin-ext, greek and cyrillic and no vietnamese subset — so "BÀI 10" came out
         "BAI 10" and every tone mark fell through to whatever the system had, at whatever
         size that font happened to be. VT323 is the other pixel face the page already
         loads and it does carry them.
         font-size-adjust is what makes the swap invisible: VT323 at the same px is about
         two-thirds the height, and 0.769 is Press Start 2P's own x-height ratio, so the
         replacement renders at the height of the face it replaces rather than smaller. */
      --font-pixel: 'Press Start 2P', monospace;
      --font-pixel-adjust: none;

      /* 64-Bit Pixel Glass Surface Palette */
      --glass-bg-primary: rgba(15, 23, 42, 0.85);
      --glass-bg-darker: rgba(10, 15, 30, 0.92);
      --glass-bg-purple: rgba(20, 15, 45, 0.92);
      --glass-bg-green: rgba(15, 35, 20, 0.92);
      --glass-bg-pink: rgba(35, 15, 25, 0.92);
      --glass-bg-blue: rgba(12, 30, 55, 0.92);

      --glass-blur: blur(16px);
      --glass-blur-webkit: blur(16px);

      /* Multi-Color Neon Accents */
      --neon-cyan: #38bdf8;
      --neon-purple: #c084fc;
      --neon-gold: #f59e0b;
      --neon-green: #4ade80;
      --neon-pink: #f43f5e;
      --neon-blue: #60a5fa;

      /* Neon Glow Box Shadows */
      --glow-cyan: 0 0 16px rgba(56, 189, 248, 0.5), inset 0 0 10px rgba(56, 189, 248, 0.2);
      --glow-purple: 0 0 18px rgba(192, 132, 252, 0.5), inset 0 0 10px rgba(192, 132, 252, 0.2);
      --glow-gold: 0 0 18px rgba(245, 158, 11, 0.55), inset 0 0 10px rgba(245, 158, 11, 0.2);
      --glow-green: 0 0 18px rgba(74, 222, 128, 0.5), inset 0 0 10px rgba(74, 222, 128, 0.2);
      --glow-pink: 0 0 18px rgba(244, 63, 94, 0.5), inset 0 0 10px rgba(244, 63, 94, 0.2);

      /* Retro Wood & Parchment Tokens for Fallback / Accent */
      --wood-l:   #c4893a;
      --wood-m:   #8b5a2b;
      --wood-d:   #4a2a0d;
      --parch:    #f4d6a0;
      --parch-d:  #e8c07a;
      --parch-l:  #fff8e8;
      --ink:      #2a1a0a;
      --grass:    #3d7a1a;
      --gold:     #f59e0b;
      --green-l:  #4ade80;
      --green-d:  #16a34a;
      --farm-veil: rgba(42, 26, 10, 0.58);
    }

    /* js/i18n.js writes the language onto <html> before first paint, so this is settled by
       the time anything is measured. Any locale whose script Press Start 2P does not cover
       joins this rule; every other locale keeps the face the game was designed in. */
    html[lang="vi"] {
      --font-pixel: 'VT323', monospace;
      --font-pixel-adjust: 0.769;
    }

    body {
      margin: 0; overflow: hidden; background: #0f172a;
      font-family: 'Be Vietnam Pro', 'Nunito', 'Segoe UI', system-ui, sans-serif;
      color: #e2e8f0;
    }

    canvas {
      image-rendering: -webkit-optimize-contrast;
      image-rendering: crisp-edges;
      image-rendering: pixelated;
      -ms-interpolation-mode: nearest-neighbor;
      transition: width 0.1s ease, height 0.1s ease;
    }

    /* Korean & Vietnamese Typography Rules */
    .vn-text, p, span:not(.quiz-crop-icon):not(.key-badge),
    div:not(#hud):not(#hud *), button:not(.hud-btn) {
      font-family: 'Be Vietnam Pro', 'Nunito', 'Noto Sans KR', system-ui, sans-serif;
    }
    .ko-text, #cat-ko, .vc-ko, .fish-card-ko {
      font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif !important;
    }

    /* ── 64-Bit CRT Scanlines Texture Overlay ────────────────────────────── */
    #level-select-overlay::before,
    #quiz-ui::before,
    #vocab-panel::before,
    #shop-panel::before,
    #fish-album-panel::before,
    #trophy-panel::before,
    #memory-panel::before,
    #vff-inner::before,
    #cat-dialog-inner::before,
    #inventory-panel::before,
    #levelup-card::before,
    #alldone-card::before {
      content: '';
      position: absolute;
      inset: 0;
      background: repeating-linear-gradient(
        0deg,
        rgba(74, 42, 13, 0.05) 0px,
        rgba(74, 42, 13, 0.05) 1px,
        transparent 1px,
        transparent 3px
      );
      pointer-events: none;
      z-index: 1;
      border-radius: inherit;
    }

    /* Content child elevated above scanlines */
    #quiz-ui > *, #vocab-panel > *, #shop-panel > *, #fish-album-panel > *,
    #trophy-panel > *, #memory-panel > *, #vff-inner > *,
    #cat-dialog-inner > *, #inventory-panel > *, #levelup-card > *, #alldone-card > * {
      position: relative;
      z-index: 2;
    }

    /* ── Animations ──────────────────────────────────────────────────────── */
    @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
    @keyframes slideUp { from { transform: translateY(24px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
    @keyframes popIn { 0% { transform: scale(0.88); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
    @keyframes pulseGold { 0%, 100% { box-shadow: 0 0 16px rgba(245,158,11,0.3); } 50% { box-shadow: 0 0 32px rgba(245,158,11,0.6); } }
    @keyframes pulseGreen { 0%, 100% { box-shadow: 0 0 16px rgba(74,222,128,0.3); } 50% { box-shadow: 0 0 32px rgba(74,222,128,0.6); } }
    @keyframes catBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-4px); } }

    /* ── INVENTORY STORAGE OVERLAY & SLOTS ───────────────────────────────── */
    /* Palette note: the slots were always parchment, but the chrome around them —
       capacity box, tabs, search, detail strip — was built in the dark theme this game
       no longer has. `.glass-modal` paints a light parchment gradient, so the panel read
       as two designs bolted together next to the cooking kitchen, which uses parchment
       throughout. Same structure as before; one palette now. */
    #inventory-overlay {
      position: fixed; inset: 0; z-index: 870; display: none;
      background: var(--farm-veil); backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #inventory-overlay.visible { display: flex; }
    /* Was inline on the element. Moved here so the panel can act as the positioning and
       scrolling context for the sticky detail strip at the bottom. */
    #inventory-panel {
      max-width: 760px; width: 94%; max-height: 88vh;
      overflow-y: auto; padding: 24px; position: relative;
    }

    .inv-header {
      display: flex; justify-content: space-between; align-items: center;
      border-bottom: 2px solid var(--wood-m);
      padding-bottom: 14px; margin-bottom: 16px;
    }
    .inv-header-id { display: flex; align-items: center; gap: 10px; }
    .inv-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 15px; color: var(--wood-d); line-height: 1.4; }
    .inv-subtitle { font-size: 12px; color: #7a3e12; margin-top: 5px; font-family: 'Be Vietnam Pro', sans-serif; }
    .inv-close {
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 4px 12px; font-size: 16px;
      cursor: pointer; line-height: 1.4; flex: 0 0 auto;
      transition: background .15s, border-color .15s, color .15s;
    }
    .inv-close:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }
    .inv-close:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }

    /* ── Capacity ─────────────────────────────────────────────────────────── */
    .inv-capacity {
      background: #fff3d6; border: 1.5px solid var(--wood-l);
      border-radius: 8px; padding: 12px 16px; margin-bottom: 14px;
      box-shadow: inset 0 1px 0 #fff;
    }
    .inv-capacity-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
    .inv-capacity-label { font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 700; color: #5b3412; }
    .inv-capacity-badge {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); padding: 5px 10px; border-radius: 4px; white-space: nowrap;
      transition: color .2s, border-color .2s, background .2s;
    }
    .inv-capacity-track {
      height: 9px; margin: 10px 0 8px; border-radius: 2px; overflow: hidden;
      background: #e0bd85; border: 1px solid var(--wood-m);
    }
    /* Green through amber to red: on a capacity bar the colour is the whole message, and
       "nearly full" is the state worth acting on. A bare count never said it. */
    .inv-capacity-fill {
      height: 100%; width: 0%; border-radius: 2px;
      background: linear-gradient(90deg, #16a34a, #4ade80);
      transition: width .25s ease, background .2s;
    }
    .inv-capacity.warn .inv-capacity-fill { background: linear-gradient(90deg, #b45309, #f59e0b); }
    .inv-capacity.warn .inv-capacity-badge {
      background: #fef3c7; border-color: #b45309; color: #78350f;
    }
    .inv-capacity.full .inv-capacity-fill { background: linear-gradient(90deg, #991b1b, #dc2626); }
    .inv-capacity.full .inv-capacity-badge {
      background: #ffe4e4; border-color: #b91c1c; color: #7f1d1d;
    }
    .inv-capacity-foot {
      display: flex; justify-content: space-between; align-items: center;
      flex-wrap: wrap; gap: 10px;
    }
    .inv-capacity-hint {
      font-size: 12px; color: #7a3e12; font-family: 'Be Vietnam Pro', sans-serif;
      flex: 1 1 140px; min-width: 0;
    }
    .inv-capacity-hint strong { color: #b45309; }
    /* `.hud-btn` is a fixed 36x36 icon button — width, height and min-width are all
       pinned. This is the one hud-btn carrying a text label, so it has to opt out of the
       square or "Expand +5 🪙 50" overflows a 36px box. The old inline style set padding
       and font-size only, which is why the label was spilling out of the button before.
       Two classes to outrank `.hud-btn`, which appears later in this file. */
    /* It also pins colour, background and border with !important, all tuned for the dark
       HUD bar. On the parchment capacity box that became pale text on a pale ground —
       1.0:1, i.e. invisible. Those three need !important of their own here, because
       specificity alone cannot outrank an !important declaration. */
    .inv-capacity .inv-expand-btn {
      width: auto; height: auto; min-width: 0;
      padding: 7px 14px; font-size: 10px; line-height: 1.4;
      flex: 0 0 auto; white-space: nowrap;
      display: inline-flex; align-items: center; gap: 5px;
      background: var(--parch-l) !important;
      border: 1.5px solid var(--wood-m) !important;
      color: var(--wood-d) !important;
    }
    .inv-capacity .inv-expand-btn:hover:not([disabled]) {
      background: #ffe9b8 !important; border-color: var(--wood-d) !important;
    }
    .inv-capacity .inv-expand-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    /* Priced out rather than hidden: the player still learns the cost, and clicking no
       longer spends a turn to be told no. */
    .inv-expand-btn[disabled] { opacity: 0.45; cursor: not-allowed; filter: grayscale(0.6); }
    .inv-capacity.full .inv-expand-btn:not([disabled]) { animation: pulseGold 1.8s ease-in-out infinite; }
    @keyframes pulseGold {
      0%, 100% { box-shadow: 0 0 0 rgba(245,158,11,0); }
      50%      { box-shadow: 0 0 14px rgba(245,158,11,0.65); }
    }

    /* ── Toolbar ──────────────────────────────────────────────────────────── */
    .inv-toolbar {
      display: flex; justify-content: space-between; align-items: center;
      gap: 10px; flex-wrap: wrap; margin-bottom: 12px;
    }
    .inv-tabs { display: flex; gap: 6px; flex-wrap: wrap; }
    .inv-tab {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px;
      padding: 7px 9px; border-radius: 4px; cursor: pointer;
      background: var(--parch-l); color: #7a3e12; border: 1.5px solid var(--wood-l);
      display: inline-flex; align-items: center; gap: 5px;
      transition: background .15s, border-color .15s;
    }
    .inv-tab:hover { border-color: var(--wood-m); }
    .inv-tab.active { background: var(--wood-m); color: #fff8e8; border-color: var(--wood-d); }
    .inv-tab:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.4); }
    .inv-tab-count {
      font-size: 8px; padding: 2px 5px; border-radius: 3px;
      background: #e8c07a; color: var(--wood-d); min-width: 16px; text-align: center;
    }
    .inv-tab.active .inv-tab-count { background: #fff8e8; color: var(--wood-d); }
    .inv-tab-count.zero { opacity: 0.5; }

    .inv-search { position: relative; display: flex; align-items: center; flex: 1 1 190px; max-width: 260px; }
    .inv-search-icon { position: absolute; left: 10px; font-size: 12px; pointer-events: none; opacity: 0.65; }
    .inv-search-input {
      width: 100%; padding: 8px 10px 8px 30px; border-radius: 4px;
      background: var(--parch-l); border: 1.5px solid var(--wood-l);
      color: var(--ink); font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px;
    }
    .inv-search-input::placeholder { color: #a9793f; }
    .inv-search-input:focus { outline: none; border-color: var(--wood-d); box-shadow: 0 0 0 2px rgba(74,42,13,0.25); }

    .inv-empty-msg {
      font-size: 13px; color: #7a3e12; margin-bottom: 10px; font-weight: 600;
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    .inv-empty-msg.hidden { display: none; }

    /* ── Grid and slots ───────────────────────────────────────────────────── */
    #inventory-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 10px;
    }
    .inv-slot {
      background: var(--parch-l);
      border: 1.5px solid #c4893a;
      border-radius: 6px; padding: 10px 6px 8px; text-align: center;
      position: relative; transition: transform .15s, border-color .15s, box-shadow .15s;
      cursor: pointer; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 108px;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b;
    }
    .inv-slot:hover { transform: translateY(-2px); border-color: #166534; }
    /* Keyboard parity with the mouse: every filled slot is reachable by Tab and answers
       Enter and Space. */
    .inv-slot:focus-visible {
      outline: none; border-color: var(--wood-d);
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b, 0 0 0 3px rgba(74,42,13,0.42);
    }
    .inv-slot.selected {
      border-color: #166534; background: #eaffe9;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #15803d, 0 0 0 2px rgba(22,101,52,0.5);
    }
    .inv-slot.empty { opacity: 0.55; border-style: dashed; border-color: #c4893a; cursor: default; box-shadow: none; }
    .inv-slot.empty:hover { transform: none; box-shadow: none; }
    .inv-slot-icon { line-height: 1; margin-bottom: 6px; min-height: 40px; display: flex; align-items: center; justify-content: center; }
    .inv-slot-icon img, .inv-slot-icon .vocab-art-icon, .inv-slot-icon .inv-art-icon {
      width: 40px; height: 40px; object-fit: contain;
      image-rendering: pixelated; image-rendering: crisp-edges;
    }
    .inv-slot-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 13px; font-weight: bold; color: var(--ink); line-height: 1.2; }
    .inv-slot-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; color: #7a3e12; margin-top: 1px; }
    .inv-qty-badge {
      position: absolute; top: 6px; right: 6px;
      background: #fef3c7; color: #78350f; border: 1px solid #b45309;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; font-weight: bold;
      padding: 2px 5px; border-radius: 3px;
    }
    /* A dish and a crop are different things to the player, and the slot said so only in
       the title tooltip — which a touch device never shows. */
    .inv-kind-badge {
      position: absolute; top: 5px; left: 5px; font-size: 13px; line-height: 1;
      padding: 2px 3px; border-radius: 3px;
      background: rgba(255,248,232,0.92); border: 1px solid rgba(139,90,43,0.3);
    }

    /* ── Selection detail ─────────────────────────────────────────────────── */
    /* Selector carries the panel id on purpose: `#inventory-panel > *` above sets
       position:relative on every direct child, and it would otherwise win on
       specificity and quietly un-stick this strip. */
    #inventory-panel > .inv-detail {
      position: sticky; bottom: -24px; z-index: 3;
    }
    /* A shade darker than the panel plus a wood rail and a lift shadow: as a sticky
       footer it has to read as a tray laid over the grid, and matching the panel exactly
       would have merged the two. */
    .inv-detail {
      margin: 14px -24px -24px; padding: 14px 24px 18px;
      background: linear-gradient(180deg, #f0d9a8, #e8c07a);
      border-top: 2px solid var(--wood-m);
      box-shadow: 0 -4px 12px rgba(74,42,13,0.22);
      display: flex; gap: 14px; align-items: flex-start;
    }
    .inv-detail.hidden { display: none; }
    .inv-detail-icon { flex: 0 0 auto; width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; font-size: 34px; }
    .inv-detail-icon img { width: 56px; height: 56px; object-fit: contain; image-rendering: pixelated; image-rendering: crisp-edges; }
    .inv-detail-body { flex: 1 1 auto; min-width: 0; }
    .inv-detail-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 22px; font-weight: bold;
      color: var(--ink); line-height: 1.25;
    }
    .inv-detail-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; color: #7a3e12; margin-top: 2px; }
    .inv-detail-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
    .inv-chip {
      font-size: 11px; padding: 4px 8px; border-radius: 3px; font-weight: 600;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); color: #5b3412;
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    .inv-chip.gold { background: #fef3c7; border-color: #b45309; color: #78350f; }
    .inv-detail-note {
      font-size: 12px; color: #5b3412; margin-top: 8px; line-height: 1.5;
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    .inv-detail-actions { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
    .inv-detail-btn {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; padding: 8px 11px;
      border-radius: 4px; cursor: pointer; color: var(--wood-d);
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      transition: background .15s, border-color .15s;
    }
    .inv-detail-btn:hover { background: #ffe9b8; border-color: var(--wood-d); }
    .inv-detail-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.4); }
    .inv-detail-close {
      flex: 0 0 auto; background: none; border: none; color: var(--wood-d);
      font-size: 15px; cursor: pointer; padding: 2px 4px; line-height: 1;
    }
    .inv-detail-close:hover { color: #b91c1c; }

    @media (max-width: 560px) {
      #inventory-panel { padding: 16px; }
      #inventory-grid { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); gap: 8px; }
      .inv-slot { min-height: 96px; padding: 8px 4px 6px; }
      .inv-search { max-width: none; }
      .inv-title { font-size: 12px; }
      .inv-detail { margin: 12px -16px -16px; padding: 12px 16px 16px; }
      #inventory-panel > .inv-detail { bottom: -16px; }
      .inv-detail-icon, .inv-detail-icon img { width: 44px; height: 44px; }
      .inv-detail-ko { font-size: 18px; }
    }

    /* Honour the OS "reduce motion" setting across the inventory's transitions. */
    @media (prefers-reduced-motion: reduce) {
      #inventory-overlay { animation: none; }
      .inv-slot, .inv-capacity-fill, .inv-close, .inv-detail-btn, .inv-tab { transition: none; }
      .inv-slot:hover { transform: none; }
      .inv-capacity.full .inv-expand-btn:not([disabled]) { animation: none; }
    }

    /* ── LEVEL SELECT OVERLAY ────────────────────────────────────────────── */
    #level-select-overlay {
      position: fixed; inset: 0; z-index: 500;
      background:
        radial-gradient(ellipse at 20% 8%, rgba(245, 158, 11, 0.18) 0%, transparent 46%),
        radial-gradient(ellipse at 80% 92%, rgba(74, 124, 89, 0.22) 0%, transparent 50%),
        linear-gradient(160deg, #3d2914 0%, #1a1008 100%);
      display: flex; flex-direction: column; align-items: center;
      overflow-y: auto; padding: clamp(16px, 3vw, 28px) 16px 40px;
      animation: fadeIn .35s ease;
    }
    #level-select-overlay.hidden { display: none; }

    .ls-title-wrap { text-align: center; margin-bottom: 16px; }
    .ls-logo { font-size: clamp(36px, 5vw, 48px); margin-bottom: 6px; filter: drop-shadow(0 0 12px rgba(245, 158, 11, 0.45)); }
    .ls-logo img { display: block; margin: 0 auto; object-fit: contain; image-rendering: pixelated; }
    .ls-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust);
      font-size: clamp(18px, 3vw, 26px); letter-spacing: 2px;
      color: #f4d6a0;
      text-shadow: 0 2px 0 #4a2a0d;
    }
    .ls-subtitle {
      font-family: 'VT323', monospace;
      font-size: clamp(16px, 2.2vw, 20px); color: #e8c07a; margin-top: 6px; letter-spacing: 2px;
    }

    /* ── LEVEL SELECT ─────────────────────────────────────────────────────────
       Rebuilt because the screen read as noise rather than as a list of choices, and
       the reasons were measurable rather than a matter of taste:

         · the level's own name was 11px, the smallest text on a card, while the
           metadata beside it was 16px — so the eye landed on "80 words" before the
           name, on all 28 cards
         · four typefaces inside one 236x218 box, none of them with a job
         · "2B Unit 10" printed twice per card, 📘 twice, and a "SNU 2B" chip sitting
           under a "── SNU Korean 2B ──" heading that already said it
         · #38bdf8 on cream measured 1.94 against a 4.5 requirement

       The identity is unchanged — parchment cards, pixel display type, night sky. What
       changed is that one thing per card is loud now.

       Three faces, one job each: Press Start 2P is the pixel accent and never body
       text, Noto Sans KR carries Korean, Be Vietnam Pro carries Latin. */

    .ls-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
      gap: 14px; width: 100%; max-width: 1000px;
      position: relative; z-index: 2;
    }
    #credential_picker_container { z-index: 40 !important; }

    /* Resume is the primary action, so it spans the grid and carries the only accent
       border on the screen. It used to pulse forever; a permanently animating element
       is the thing you cannot stop looking at, which is the opposite of what a default
       action needs. It lifts on hover instead. */
    .ls-resume-card {
      grid-column: 1 / -1;
      display: flex; align-items: center; gap: 16px;
      background: linear-gradient(180deg, rgba(20, 83, 45, 0.92), rgba(12, 47, 26, 0.94));
      border: 2px solid #4ade80; border-radius: 10px; padding: 16px 20px;
      cursor: pointer; transition: transform .16s ease, box-shadow .16s ease;
      box-shadow: 0 2px 0 #0b2618, 0 6px 16px rgba(0, 0, 0, .38);
    }
    .ls-resume-card:hover {
      transform: translateY(-2px);
      box-shadow: 0 2px 0 #0b2618, 0 10px 22px rgba(0, 0, 0, .48);
    }
    .ls-resume-card:focus-visible { outline: 3px solid #fde68a; outline-offset: 2px; }
    .lsr-icon {
      font-size: 20px; color: #0b2618; background: #4ade80;
      width: 38px; height: 38px; border-radius: 50%;
      display: grid; place-items: center; flex-shrink: 0; font-weight: 700;
    }
    #level-select-overlay .lsr-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; letter-spacing: .5px;
      color: #dcfce7; margin-bottom: 7px;
    }
    #level-select-overlay .lsr-sub {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; color: #a7f3d0;
      display: flex; gap: 14px; flex-wrap: wrap;
    }
    #level-select-overlay .lsr-sub b { color: #f0fdf4; font-weight: 700; }

    /* A heading, not four em dashes. The rule does the separating so the words do not
       have to. */
    #level-select-overlay .ls-sep {
      grid-column: 1 / -1;
      display: flex; align-items: center; gap: 12px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; letter-spacing: 1px;
      color: #fcd34d; text-transform: uppercase;
      margin: 10px 0 -2px;
    }
    #level-select-overlay .ls-sep::after {
      content: ''; flex: 1; height: 1px;
      background: linear-gradient(90deg, rgba(252, 211, 77, .45), rgba(252, 211, 77, 0));
    }
    #level-select-overlay .ls-sep.plain { display: block; text-align: center; color: rgba(226, 232, 240, .55); }
    #level-select-overlay .ls-sep.plain::after { content: none; }

    .level-card {
      display: flex; flex-direction: column;
      background: linear-gradient(180deg, #fff6e2, #f0d9a8);
      border: 2px solid #8b5a2b;
      border-radius: 10px; padding: 13px 14px 11px;
      cursor: pointer; position: relative; overflow: hidden;
      transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
      user-select: none;
      box-shadow: 0 2px 0 #6b4420, 0 4px 12px rgba(0, 0, 0, .28);
    }
    .level-card:hover:not(.locked) {
      transform: translateY(-3px); border-color: #a97139;
      box-shadow: 0 2px 0 #6b4420, 0 10px 22px rgba(0, 0, 0, .4);
    }
    .level-card:focus-visible { outline: 3px solid #fde68a; outline-offset: 2px; }

    /* Locked is dimmed, not greyscaled: the old filter drained the icon of the colour
       that identifies the pack, so every locked card looked like the same card. */
    /* Its own, cooler paper. Opacity alone left a locked card indistinguishable from one
       you own, so the only signal was the word in the footer. */
    .level-card.locked {
      cursor: not-allowed;
      background: linear-gradient(180deg, #e9e3d6, #d2c9b7);
      border-color: #9a8570; box-shadow: 0 2px 0 #6b5340;
    }
    .level-card.locked .lc-desc { color: #5c5346; }
    #level-select-overlay .lc-state.idle { color: #7a5a30; }
    .level-card.locked .lc-name, .level-card.locked .lc-name-ko { opacity: .8; }

    /* One coloured edge carries the state, so the card does not need a badge to say it. */
    .level-card::before {
      content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 6px;
      background: #b98a4e;
    }
    .level-card.world-card::before { background: #16a34a; }
    .level-card.completed::before { background: #0ea5e9; }
    .level-card.locked::before { background: #9a8570; }
    .level-card.world-card { border-color: #16a34a; }
    .level-card.completed { border-color: #0ea5e9; }

    .lc-art {
      --cover-paper: #e5edd5; --cover-edge: #b6c591;
      height: 120px; margin: -4px -5px 13px; padding: 12px 16px;
      display: flex; align-items: center; justify-content: center; gap: 8px;
      position: relative; isolation: isolate; overflow: hidden;
      background: linear-gradient(160deg, #fff7df 0%, var(--cover-paper) 75%);
      border: 1px solid var(--cover-edge); border-radius: 5px;
      box-shadow: inset 0 0 0 3px rgba(255, 250, 227, .8), 0 2px 0 rgba(107, 68, 32, .1);
    }
    .lc-art--honey { --cover-paper: #f0dfb1; --cover-edge: #d1b16d; }
    .lc-art--sky { --cover-paper: #dce9e8; --cover-edge: #a8bfba; }
    .lc-art--lilac { --cover-paper: #e8dde8; --cover-edge: #c3a9bc; }
    .lc-art--terracotta { --cover-paper: #efd8c9; --cover-edge: #c99e83; }
    .lc-art::before {
      content: ''; position: absolute; inset: 7px; z-index: -1;
      border: 1px solid var(--cover-edge); opacity: .65;
      clip-path: polygon(0 0, 18px 0, 18px 1px, calc(100% - 18px) 1px,
        calc(100% - 18px) 0, 100% 0, 100% 18px, calc(100% - 1px) 18px,
        calc(100% - 1px) calc(100% - 18px), 100% calc(100% - 18px),
        100% 100%, calc(100% - 18px) 100%, calc(100% - 18px) calc(100% - 1px),
        18px calc(100% - 1px), 18px 100%, 0 100%, 0 calc(100% - 18px),
        1px calc(100% - 18px), 1px 18px, 0 18px);
    }
    .lc-art img {
      display: block; width: auto; height: 96px; max-width: 100%;
      object-fit: contain; image-rendering: pixelated;
    }
    .lc-art--pair img { max-width: calc(50% - 4px); }
    .level-topic-icon {
      display: inline-block; flex: 0 0 28px; width: 28px; height: 28px;
      object-fit: contain; image-rendering: pixelated; vertical-align: middle;
    }
    .lc-top { display: flex; align-items: flex-start; }
    .lc-meta { flex: 1; min-width: 0; }

    /* The eyebrow: pixel type, small, quiet. It labels the card without competing with
       it — which is what the 16px cyan version was doing. #6b4420 on cream is 7.4:1. */
    #level-select-overlay .lc-num {
      display: block;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; letter-spacing: .5px;
      color: #6b4420; text-transform: uppercase; margin-bottom: 5px;
    }
    /* The hero. Korean first, because this is a Korean course and the Korean is the
       shortest, most recognisable thing on the card. */
    #level-select-overlay .lc-name-ko {
      display: block;
      font-family: 'Noto Sans KR', sans-serif; font-size: 19px; font-weight: 900;
      color: #2a1a0a; line-height: 1.22; letter-spacing: -.2px;
      overflow-wrap: anywhere;
    }
    #level-select-overlay .lc-name-ko:empty { display: none; }
    #level-select-overlay .lc-name {
      display: block;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 700;
      color: #5b3412; line-height: 1.3; margin-top: 3px;
      /* Two lines whether the name needs them or not. One card with a two-line name made its
         whole grid row taller than the others, which is what left the grid looking ragged. */
      min-height: 2.6em;
    }
    /* Kept, not deleted — it is the only thing that says what a pack is about. Clamped
       to three lines so 28 cards stay the same height and the grid can be scanned. */
    #level-select-overlay .lc-desc {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11.5px;
      color: #6b4a24; margin: 9px 0 0; line-height: 1.42;
      display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
      /* Three lines' worth of space whether the text fills it or not, so every card in the
         grid is the same height and the rows line up. A ragged grid is its own kind of noise. */
      min-height: 4.26em;
      overflow: hidden;
    }
    /* The clamp keeps the grid scannable and hid most of what some packs say — the TOPIK
       description runs fifteen lines and three of them showed, with nothing to say the rest
       existed. Hovering the card, or reaching it with Tab, lifts the clamp and floats the
       full text over the cards below.

       Floated rather than grown: the card keeps its place, so the grid does not reflow under
       the pointer. And floated rather than opened by a button inside the card, because the
       card is itself one button and a button inside a button is not markup a browser honours.
       Screen readers never see this — they are given the same text through aria-describedby,
       which is the one channel a hover cannot serve. */
    /* The lift on hover is a transform, and a transform makes the card a stacking context of
       its own — which traps the panel below at whatever z-index it asks for, and lets the
       next card in the DOM paint straight over it. The card itself has to rise. */
    #level-select-overlay .level-card:hover,
    #level-select-overlay .level-card:focus-visible { overflow: visible; z-index: 6; }
    #level-select-overlay .level-card:hover .lc-desc,
    #level-select-overlay .level-card:focus-visible .lc-desc {
      -webkit-line-clamp: unset; display: block;
      /* Below the card, not over it. An absolutely positioned child of a flex container
         takes its static position from the container's content box rather than from where
         its siblings left off, so with `top` unset this landed on top of the icon and the
         unit name — hiding the one thing that says which card you are reading. */
      position: absolute; top: calc(100% + 6px); left: 10px; right: 10px; z-index: 6;
      margin: 0; padding: 9px 11px; max-height: 24em; overflow-y: auto;
      background: #fff6e2; border: 2px solid #8b5a2b; border-radius: 8px;
      box-shadow: 0 6px 18px rgba(0, 0, 0, .34);
    }

    /* Progress is what a course chooser should show and this one never did. Owned packs
       get the bar; locked packs get the price where the bar would be. */
    .lc-progress { margin-top: 10px; }
    .lc-progress-track {
      height: 6px; border-radius: 3px; overflow: hidden;
      background: rgba(107, 68, 32, .22); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .12);
    }
    .lc-progress-fill {
      height: 100%; border-radius: 3px;
      background: linear-gradient(90deg, #16a34a, #4ade80);
      transition: width .3s ease;
    }
    /* Only once there is progress: min-width on the fill itself also widened it at 0%, which
       put a floating green nub on a track that is deliberately transparent there. At 1-2% the
       fill was otherwise a few pixels wide and its rounded ends made it read as a speck. */
    #level-select-overlay .lc-progress-track:not(.empty) .lc-progress-fill { min-width: 9px; }
    /* Reserved but unpainted at zero: the space keeps the grid rows level while an empty
       track drawn round nothing read as a broken input field. */
    #level-select-overlay .lc-progress-track.empty { background: transparent; box-shadow: none; }

    .lc-footer {
      display: flex; align-items: baseline; justify-content: space-between;
      gap: 8px; margin-top: 7px;
    }
    #level-select-overlay .lc-stat {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      color: #6b4420; letter-spacing: 0; white-space: nowrap;
    }
    #level-select-overlay .lc-stat b { color: #2a1a0a; }
    /* No chip background to fight the card. The word does the work. */
    #level-select-overlay .lc-state {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; letter-spacing: 0;
      color: #15803d; white-space: nowrap;
    }
    #level-select-overlay .lc-state.price { color: #92400e; }
    #level-select-overlay .lc-state.short { color: #7c2d12; opacity: .72; }

    #taste-overlay {
      position: fixed; inset: 0; z-index: 875; display: none;
      background: rgba(42, 26, 10, 0.62); align-items: center; justify-content: center;
    }
    #taste-overlay.visible { display: flex; }
    #taste-panel {
      max-width: 580px; width: 94%; padding: 18px 18px 16px; color: #2a1a0a;
      background: linear-gradient(180deg, #fff3d6 0%, #e8c07a 100%) !important;
    }
    #taste-bar {
      display: flex; justify-content: space-between; align-items: center; gap: 8px;
      font-family: 'VT323', monospace; font-size: 20px; margin-bottom: 8px;
    }
    #taste-awning {
      height: 18px; border-radius: 8px 8px 0 0; margin: -18px -18px 12px;
      background: repeating-linear-gradient(90deg, #dc2626 0 22px, #fff8e8 22px 44px);
      box-shadow: inset 0 -3px 0 #7f1d1d;
    }
    #taste-dish {
      text-align: center; background:
        radial-gradient(ellipse at 50% 70%, #fff8e8 40%, #f4d6a0 100%);
      border: 3px solid #8b5a2b; border-radius: 4px;
      width: 168px; height: 168px; margin: 8px auto 16px;
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      box-shadow: inset 0 0 0 6px #c4893a, 0 8px 0 #4a2a0d;
    }
    #taste-icon { font-size: 52px; line-height: 1; filter: drop-shadow(0 3px 0 rgba(0,0,0,.15)); }
    #taste-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 22px; font-weight: 900; }
    #taste-prompt { text-align: center; font-size: 14px; color: #7a3e12; margin: -6px 0 12px; }
    #taste-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
    .taste-btn {
      font-family: 'Noto Sans KR', sans-serif; font-size: 20px; font-weight: 800;
      padding: 12px 8px; border: 3px solid #8b5a2b; border-radius: 8px;
      background: #fff8e8; color: #2a1a0a; cursor: pointer;
      box-shadow: 0 3px 0 #4a2a0d;
    }
    .taste-btn[data-t="달다"] { border-color: #f59e0b; }
    .taste-btn[data-t="짜다"] { border-color: #64748b; }
    .taste-btn[data-t="쓰다"] { border-color: #166534; }
    .taste-btn[data-t="시다"] { border-color: #eab308; }
    .taste-btn[data-t="맵다"] { border-color: #dc2626; }
    .taste-btn:hover { transform: translateY(-2px); }
    .taste-btn.ok { background: #dcfce7; border-color: #166534; }
    .taste-btn.bad { background: #fee2e2; border-color: #9f1239; }

    #desk-quiz-overlay {
      position: fixed; inset: 0; z-index: 876; display: none;
      background: rgba(42, 26, 10, 0.62); align-items: center; justify-content: center;
    }
    #desk-quiz-overlay.visible { display: flex; }
    #desk-quiz-panel { max-width: 640px; width: 94%; padding: 20px; color: #2a1a0a; }
    #desk-lamp {
      height: 10px; margin: -20px -20px 12px; border-radius: 8px 8px 0 0;
      background: linear-gradient(90deg, #1e3a8a, #fde047 45%, #1e3a8a);
    }
    #desk-art {
      display: block; width: 100%; max-height: 220px; object-fit: contain;
      margin: 4px 0 10px; border-radius: 4px;
      image-rendering: pixelated; image-rendering: crisp-edges;
      background: #fff8e8;
    }
    #desk-art[hidden] { display: none; }
    #desk-q {
      font-family: 'Be Vietnam Pro', 'Noto Sans KR', sans-serif;
      font-size: 17px; font-weight: 800; line-height: 1.45; margin: 8px 0 12px;
    }
    #desk-choices { display: flex; flex-direction: column; gap: 8px; }
    .desk-opt {
      text-align: left; font-family: 'Be Vietnam Pro', 'Noto Sans KR', sans-serif;
      font-size: 15px; font-weight: 700; padding: 10px 12px;
      background: #fff8e8; border: 2px solid #8b5a2b; border-radius: 8px;
      color: #2a1a0a; cursor: pointer; box-shadow: 0 3px 0 #4a2a0d;
    }
    .desk-opt:hover { transform: translateY(-1px); border-color: #1e3a8a; }
    .desk-opt.ok { background: #dcfce7; border-color: #166534; }
    .desk-opt.bad { background: #fee2e2; border-color: #9f1239; }
    .fb {
      min-height: 22px; margin-top: 8px; text-align: center;
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; font-weight: 800;
    }
    .fb.good { color: #166534; }
    .fb.bad { color: #9f1239; }
    #desk-head { display: flex; justify-content: space-between; align-items: center;
      font-family: 'VT323', monospace; font-size: 20px; }
    .desk-xp {
      margin-top: 8px; font-size: 15px; font-weight: 800; color: #b45309;
    }

    #hud-rank {
      cursor: pointer; gap: 6px; padding: 2px 8px 2px 4px !important;
      border: 1px solid rgba(232, 192, 122, 0.35) !important; border-radius: 3px !important;
      background: transparent; color: #f6deaa;
    }
    #hud-rank.pop { transform: scale(1.1); }
    #hud-rank-icon { font-size: 14px; line-height: 1; display: inline-flex; align-items: center; }
    #hud-rank-icon .hud-art-icon { width: 18px; height: 18px; }
    #hud-rank-lv { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: #fde68a; }
    #hud-rank-bar {
      width: 42px; height: 6px; background: rgba(42,26,10,.55); border-radius: 2px; overflow: hidden;
      border: 1px solid rgba(232, 192, 122, 0.35);
    }
    #hud-rank-fill { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #f59e0b, #fde68a); }

    /* ── Google cloud save ───────────────────────────────────────────────── */
    /* A row, not a block. It was a stacked box — Google button over a 16px VT323 line, inside
       its own bordered panel — sitting in the middle of the column between the title and the
       first thing you can click, costing about 80px of the fold to say something you only need
       to read once.
       It now sits on the right edge of the same 1000px column the grid uses, so it reads as
       part of the screen's furniture rather than as a card competing with the cards. */
    #ls-auth {
      width: 100%; max-width: 1000px;
      display: flex; flex-direction: row; align-items: center; justify-content: flex-end;
      gap: 12px; margin: 0 0 12px; padding: 0;
      background: none; border: none;
    }
    #ls-auth.hidden { display: none !important; }
    /* Be Vietnam Pro rather than VT323: the redesign gave the screen three faces with one job
       each, and a fourth here for one line of helper text was the odd one out. */
    #ls-auth .ls-auth-hint {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 500;
      color: rgba(232, 192, 122, 0.7); letter-spacing: 0; text-align: right;
      line-height: 1.35; max-width: 190px;
      /* Before the button in reading order, though it comes after it in the markup —
         renderAuthUI rewrites that markup, so the sequence is set here instead. Explanation
         first, action in the corner where the eye expects it. */
      order: -1;
    }
    /* Once you are signed in the sentence has already come true, so it stops being a reason
       and starts being an unmet prompt. renderAuthUI fills #ls-auth-status only when signed
       in, which is the signal — no JS change needed to read it. */
    #ls-auth #ls-auth-status:not(:empty) ~ .ls-auth-hint {
      display: none;
    }
    /* Narrow screens drop the explanation and keep the button. The Google button already says
       what it does; the line only says why, and at 375px the row has no space for both. */
    @media (max-width: 560px) {
      #ls-auth { justify-content: center; }
      #ls-auth .ls-auth-hint { display: none; }
    }
    /* The switch that decides whether a sign-in survives the tab closing. Sits between the
       explanation and the button, in the same muted voice as the hint: it is a setting, not
       one of the two things on this row you might want to click. */
    #ls-auth .ls-auth-remember {
      order: -1;
      display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 500;
      color: rgba(232, 192, 122, 0.7); white-space: nowrap;
    }
    #ls-auth .ls-auth-remember.hidden { display: none !important; }
    #ls-auth .ls-auth-remember input { accent-color: #e8c07a; cursor: pointer; margin: 0; }
    @media (max-width: 560px) { #ls-auth .ls-auth-remember { display: none; } }
    /* Names the account this browser last used, so the Google button beside it reads as a
       way back to that account rather than a chooser to work through again. */
    .auth-remembered {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 600;
      color: rgba(232, 192, 122, 0.82); max-width: 220px;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* Shown in place of the Google button when the script or the config never arrived.
       Deliberately looks like the sign-out button rather than like Google's: it is ours, and
       it does something different. */
    .auth-retry {
      background: transparent; border: 1px solid rgba(232, 192, 122, 0.45);
      color: #e8c07a; border-radius: 3px; padding: 6px 12px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; font-weight: 700; cursor: pointer;
    }
    .auth-retry:hover { background: rgba(232, 192, 122, 0.12); }
    #ls-auth-status, #hud-auth-status {
      display: flex; align-items: center; gap: 8px;
    }
    #ls-auth-status:empty, #hud-auth-status:empty { display: none; }
    .auth-photo {
      width: 22px; height: 22px; border-radius: 4px; object-fit: cover;
      border: 1px solid rgba(232, 192, 122, 0.45);
    }
    .auth-name {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; font-weight: 700;
      color: #f6deaa; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* Shown beside the name when the last sync did not land. Amber rather than red: the
       progress is safe on the device, so this is a state to notice, not an emergency. */
    .auth-sync-warn {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 700;
      color: #fbbf24; border: 1px solid rgba(251, 191, 36, 0.45); border-radius: 3px;
      padding: 2px 6px; white-space: nowrap; cursor: help;
    }
    .auth-out {
      background: transparent; border: 1px solid rgba(232, 192, 122, 0.45);
      color: #e8c07a; border-radius: 3px; padding: 3px 8px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; cursor: pointer;
    }
    .auth-out:hover { background: rgba(232, 192, 122, 0.12); }
    #ls-auth .google-signin-slot { min-height: 0; justify-content: flex-end; }
    .google-signin-slot { min-height: 40px; display: flex; justify-content: center; }
    .google-signin-slot.hidden { display: none !important; }
    /* The HUD keeps only the avatar. The whole chip — avatar, email, the warning in words and
       Sign out — was ~330px of a 920px bar, and signing in squeezed the status group (level,
       progress, reviews-due badge) to nothing and pushed the last action button past the
       bar's right edge. The rest opens from the avatar, in #hud-account-menu. */
    #hud-account { position: relative; display: flex; align-items: center; flex: 0 0 auto; }
    #hud-account.hidden, #hud-account-menu.hidden, #hud-signin-slot.hidden { display: none !important; }
    .hud-account-btn {
      position: relative; width: 32px; height: 32px; padding: 0; cursor: pointer;
      display: inline-flex; align-items: center; justify-content: center;
      background: rgba(246, 222, 170, 0.10); color: #f6deaa;
      border: 1px solid rgba(232, 192, 122, 0.35); border-radius: 4px;
      transition: background .15s, border-color .15s;
    }
    .hud-account-btn:hover, .hud-account-btn[aria-expanded="true"] {
      background: rgba(246, 222, 170, 0.24); border-color: rgba(246, 222, 170, 0.62);
    }
    .hud-account-btn:focus-visible { outline: 2px solid #fde68a; outline-offset: 2px; }
    .hud-account-btn .auth-photo { width: 24px; height: 24px; }
    .auth-initial {
      width: 24px; height: 24px; border-radius: 4px; flex: 0 0 auto;
      display: inline-flex; align-items: center; justify-content: center;
      background: #c4893a; color: #2a1a0a;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 800; line-height: 1;
    }
    /* Amber, like the chip's warning was: the progress is safe on the device, so this asks to
       be noticed rather than raising an alarm. */
    .hud-account-btn.has-warn { border-color: rgba(251, 191, 36, 0.85); }
    .hud-account-alert {
      position: absolute; top: -6px; right: -6px; width: 15px; height: 15px; border-radius: 8px;
      background: #fbbf24; color: #2a1a0a; border: 1.5px solid #2a1a0a;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; font-weight: 900;
      line-height: 12px; text-align: center; pointer-events: none;
    }
    #hud-account-menu {
      position: absolute; top: calc(100% + 10px); right: -8px; z-index: 950;
      width: max-content; min-width: 220px; max-width: min(300px, calc(100vw - 24px));
      display: flex; flex-direction: column; gap: 8px; padding: 10px;
      background: #f6deaa; color: #2a1a0a;
      border: 1px solid #8b5a2b; border-radius: 8px;
      box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
      font-family: 'Be Vietnam Pro', sans-serif; text-align: left;
      animation: popIn .16s cubic-bezier(.4,0,.2,1);
    }
    #hud-account-info { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
    .hud-account-who { display: flex; align-items: center; gap: 8px; min-width: 0; }
    .hud-account-who .auth-name { color: #2a1a0a; font-size: 13px; max-width: none; flex: 1 1 auto; min-width: 0; }
    .hud-account-who .auth-photo { border-color: #8b5a2b; }
    .hud-account-warn { font-size: 12px; font-weight: 800; color: #92400e; cursor: help; }
    .hud-account-why { margin: 0; font-size: 12px; line-height: 1.45; color: #4a2a0d; }
    #hud-signin-slot { display: flex; justify-content: flex-start; min-height: 32px; }
    #hud-signin-slot .auth-retry { color: #2a1a0a; border-color: #8b5a2b; }
    .hud-account-out {
      align-self: stretch; padding: 7px 12px; cursor: pointer; text-align: left;
      background: transparent; color: #2a1a0a;
      border: 1px solid rgba(139, 90, 43, 0.45); border-radius: 4px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 700;
    }
    .hud-account-out:hover { background: #fff3d6; }

    #rank-card-overlay, #rankup-overlay {
      position: fixed; inset: 0; z-index: 890; display: none;
      background: rgba(10, 15, 30, 0.72); align-items: center; justify-content: center;
    }
    #rank-card-overlay.visible, #rankup-overlay.visible { display: flex; }
    /* The card a tab shows once another tab of the game has taken over (claimThisTab in
       js/systems/save.js). Above every other layer: nothing behind it saves any more. */
    #tab-elsewhere-overlay {
      position: fixed; inset: 0; z-index: 5000; display: none;
      background: rgba(10, 15, 30, 0.86); align-items: center; justify-content: center;
    }
    #tab-elsewhere-overlay.visible { display: flex; }
    #tab-elsewhere-card {
      width: min(420px, 92vw); padding: 24px; text-align: center; color: #fff8e8;
      background: linear-gradient(180deg, #2a1a0a 0%, #1a1008 100%);
      border: 3px solid #f59e0b; border-radius: 8px;
    }
    #tab-elsewhere-title { font-family: 'Be Vietnam Pro', sans-serif; font-size: 18px; font-weight: 800; color: #fde68a; }
    #tab-elsewhere-body { font-family: 'Be Vietnam Pro', sans-serif; font-size: 14px; line-height: 1.5; margin: 12px 0 18px; }
    #rank-card {
      width: min(420px, 92vw); padding: 28px 24px 22px; text-align: center; color: #fff8e8;
      background:
        radial-gradient(circle at 50% 0%, rgba(253,224,71,.22), transparent 55%),
        linear-gradient(180deg, #2a1a0a 0%, #1a1008 100%);
      border: 3px solid #f59e0b; border-radius: 8px;
      box-shadow: 0 0 0 2px #0f172a, 0 20px 50px rgba(0,0,0,.55), 0 0 28px rgba(245,158,11,.35);
    }
    #rank-seal { font-size: 56px; filter: drop-shadow(0 6px 12px rgba(0,0,0,.45)); }
    #rank-lv {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; color: #fde68a;
      letter-spacing: 2px; margin: 8px 0 6px;
    }
    #rank-title-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 34px; font-weight: 900; line-height: 1.2;
      color: #fff8e8;
    }
    #rank-title-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 16px; font-weight: 700; color: #fde68a; margin-bottom: 14px;
    }
    #rank-xp-wrap { margin: 8px 0 14px; }
    #rank-xp-bar {
      height: 10px; background: rgba(255,248,232,.12); border-radius: 2px; overflow: hidden;
      border: 1px solid rgba(253,230,138,.4);
    }
    #rank-xp-fill { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #f59e0b, #fde68a); }
    #rank-xp-num { font-family: 'VT323', monospace; font-size: 18px; color: #fde68a; margin-top: 4px; }
    #rank-stats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin: 12px 0; }
    .rank-stat {
      background: rgba(255,248,232,.08); border: 1px solid rgba(253,230,138,.25); border-radius: 8px; padding: 8px 4px;
    }
    .rank-stat b { display: block; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; color: #fde68a; margin-bottom: 4px; }
    .rank-stat span { font-size: 12px; font-weight: 700; color: #f6deaa; }
    #rank-next { font-size: 13px; font-weight: 700; color: #fde68a; margin: 6px 0 14px; }
    #rankup-card {
      width: min(400px, 92vw); padding: 32px 24px 24px; text-align: center; color: #fff8e8;
      background: linear-gradient(180deg, #1e3a8a 0%, #1a1008 70%);
      border: 3px solid #fde047; border-radius: 8px;
      box-shadow: 0 0 0 2px #0f172a, 0 0 40px rgba(253,224,71,.45);
      animation: popIn .35s cubic-bezier(.4,0,.2,1);
    }
    #rankup-kicker { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 12px; color: #fde047; letter-spacing: 2px; }
    #rankup-icon { font-size: 64px; margin: 10px 0; }
    #rankup-lv { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 16px; color: #fde68a; }
    #rankup-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 36px; font-weight: 900; color: #fff8e8; }
    #rankup-en { font-size: 16px; font-weight: 700; color: #fde68a; margin-bottom: 18px; }


    /* ── Quiz: recognition / listening modes ─────────────────────────────── */
    #quiz-ko-prompt { display: flex; align-items: center; justify-content: center; gap: 10px; margin-top: 8px; }
    #quiz-ko-prompt.hidden { display: none !important; }
    #quiz-ko-word {
      font-family: 'Noto Sans KR', sans-serif; font-size: 40px; font-weight: 900;
      color: #7a3e12; text-shadow: 0 1px 0 #fff3d6;
      letter-spacing: 1px;
    }
    #quiz-choices { display: grid; grid-template-columns: 1fr 1fr; gap: 9px; margin: 14px 0 4px; }
    #quiz-choices.hidden { display: none !important; }
    #quiz-listen-controls {
      display: flex; justify-content: center; margin: 4px 0 8px;
    }
    #quiz-listen-controls.hidden { display: none !important; }
    #quiz-listen-replay {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 15px; font-weight: 800;
      padding: 8px 16px; color: #1d4ed8; background: #dbeafe;
      border: 2px solid #1d4ed8; border-radius: 8px;
    }
    #quiz-listen-replay:hover { background: #bfdbfe; }
    .quiz-choice-btn {
      padding: 13px 12px; border-radius: 8px; cursor: pointer;
      background: #fff8e8; border: 2px solid #b8894a;
      color: #2a1a0a; font-family: 'Be Vietnam Pro', sans-serif;
      font-size: 15px; font-weight: 700; line-height: 1.35;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b;
      transition: transform .1s, border-color .15s, background .15s;
    }
    .quiz-choice-btn:hover:not(:disabled) { border-color: #16a34a; background: #f3fce8; }
    .quiz-choice-btn:active:not(:disabled) { transform: scale(.97); }
    .quiz-choice-btn:disabled { cursor: default; opacity: .75; }
    .quiz-choice-btn.correct { border-color: #16a34a; background: #dcfce7; color: #14532d; }
    .quiz-choice-btn.wrong   { border-color: #b91c1c; background: #fee2e2; color: #7f1d1d; }
    @media (max-width: 520px) { #quiz-choices { grid-template-columns: 1fr; } }

    /* ── Progress / SRS dashboard ────────────────────────────────────────── */
    #progress-overlay {
      position: fixed; inset: 0; z-index: 640; display: flex;
      align-items: center; justify-content: center;
      background: var(--farm-veil);
      backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
      animation: fadeIn .2s;
    }
    #progress-overlay.hidden { display: none !important; }
    #progress-panel {
      background: linear-gradient(180deg, #f6deaa, #e8c07a);
      border: 4px solid #8b5a2b; border-radius: 8px;
      max-width: 620px; width: 94%; max-height: 86vh; overflow-y: auto;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      color: var(--ink);
    }
    #progress-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 10px 14px; background: #fff3d6;
      border-bottom: 2px dashed #c4893a;
    }
    #progress-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; color: #4a2a0d;
      display: inline-flex; align-items: center; gap: 8px;
    }
    .prog-close {
      background: #fff8e8; border: 2px solid #8b5a2b;
      color: #2a1a0a; border-radius: 4px; padding: 4px 10px; font-size: 14px; cursor: pointer;
    }
    #progress-body { padding: 18px 20px 22px; color: #2a1a0a; }
    #prog-stat-grid {
      display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
      gap: 10px; margin-bottom: 20px;
    }
    .prog-stat {
      background: #fff8e8; border: 1px solid #8b5a2b;
      border-radius: 8px; padding: 8px 10px;
    }
    .prog-stat-val { font-family: 'VT323', monospace; font-size: 26px; line-height: 1; color: #4a2a0d; }
    .prog-stat-lbl { font-size: 12px; font-weight: 700; color: #5b3412; margin-top: 4px; letter-spacing: .3px; }
    .prog-stat.gold  .prog-stat-val { color: #b45309; }
    .prog-stat.green .prog-stat-val { color: #166534; }
    .prog-stat.rose  .prog-stat-val { color: #9f1239; }
    .prog-section { margin-bottom: 18px; }
    .prog-section-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      color: #4a2a0d; margin-bottom: 10px;
    }
    #prog-forecast { display: flex; align-items: flex-end; gap: 6px; height: 96px; }
    .prog-bar-col { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; justify-content: flex-end; }
    .prog-bar {
      width: 100%; min-height: 3px; border-radius: 4px 4px 0 0;
      background: linear-gradient(180deg, #1d4ed8, #93c5fd);
    }
    .prog-bar.today { background: linear-gradient(180deg, #b45309, #fbbf24); }
    .prog-bar-n { font-family: monospace; font-size: 11px; font-weight: 700; color: #4a2a0d; }
    .prog-bar-d { font-size: 10px; font-weight: 700; color: #5b3412; }
    .prog-level-row { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; font-size: 12px; color: #2a1a0a; }
    .prog-level-name { flex: 0 0 150px; color: #2a1a0a; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .prog-level-name--topic { display: flex; align-items: center; gap: 6px; }
    .prog-level-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    .prog-level-track { flex: 1; height: 12px; background: #e8c07a; border: 1px solid #8b5a2b; border-radius: 3px; overflow: hidden; position: relative; }
    .prog-level-learned { position: absolute; inset: 0 auto 0 0; background: #2563eb; }
    .prog-level-mature  { position: absolute; inset: 0 auto 0 0; background: #b45309; }
    .prog-level-pct { flex: 0 0 92px; text-align: right; font-family: monospace; font-size: 11px; font-weight: 700; color: #4a2a0d; }
    #prog-activity { display: flex; gap: 4px; }
    .prog-day {
      flex: 1; height: 26px; border-radius: 4px;
      background: #fff8e8; border: 1px solid #8b5a2b;
      display: flex; align-items: center; justify-content: center;
      font-size: 10px; color: #4a2a0d;
    }
    .prog-day.has { background: #86efac; border-color: #166534; color: #14532d; }
    #prog-footnote { font-size: 12px; color: #4a2a0d; line-height: 1.6; margin: 0; }

    /* ── Korean pronunciation (TTS) ──────────────────────────────────────────
       Every speak control carries .tts-only, so a browser with no Korean voice
       hides the whole feature instead of offering buttons that do nothing. */
    .tts-unavailable .tts-only { display: none !important; }
    .hud-btn-off { opacity: .55; filter: saturate(.4); }
    .speak-btn {
      background: rgba(103, 232, 249, .12);
      border: 1px solid rgba(103, 232, 249, .45);
      color: #67e8f9; border-radius: 4px; cursor: pointer;
      padding: 2px 8px; font-size: 14px; line-height: 1.4;
      transition: background .15s, transform .1s;
    }
    .speak-btn:hover { background: rgba(103, 232, 249, .26); }
    .speak-btn:active { transform: scale(.92); }
    .vc-speak {
      position: absolute; top: 6px; right: 6px;
      padding: 1px 6px; font-size: 13px;
    }
    /* ── MAIN HUD BAR ─────────────────────────────────────────────────────── */
    #hud {
      position: fixed; top: 10px; left: 50%; transform: translateX(-50%);
      width: min(920px, calc(100vw - 20px));
      z-index: 100;
      background: rgba(28, 18, 10, 0.82) !important;
      backdrop-filter: blur(10px) !important;
      -webkit-backdrop-filter: blur(10px) !important;
      border: 1px solid rgba(232, 192, 122, 0.45) !important;
      border-radius: 8px !important;
      padding: 5px 8px 5px 12px !important;
      color: #f6deaa;
      box-shadow: 0 8px 22px rgba(0, 0, 0, 0.35) !important;
      display: flex; align-items: center; justify-content: space-between; gap: 10px;
      flex-wrap: nowrap;
      user-select: none;
    }

    .hud-group {
      display: flex; align-items: center; gap: 6px; flex-shrink: 0;
    }

    /* The neighbouring groups were both `flex-shrink: 0`, so on a ~1035px window this group
       was handed 112px to hold 140px of children. Nothing here could give — the level name
       was already crushed to zero and the bar and badge have fixed widths — so the children
       simply spilled past the group's right edge, and the amber due badge painted itself
       over the rank chip in the next group.
       Two things stop that. `overflow: hidden` means a spill can only ever clip inside this
       group rather than reach a neighbour, and the shrink order below decides what gives
       first: the level name (it ellipsizes), then the progress bar, and the due badge last,
       because a review count is the one thing here that is unreadable when partly drawn.
       The group itself was still allowed to go to 0px, and signed in it did: the account chip
       took the room and the badge went with the rest. `min-width: min-content` is its floor —
       the name and the bar can give everything, the percentage and the badge stay whole. */
    #hud-status-group {
      min-width: min-content; flex: 1 1 auto; overflow: hidden;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #f6deaa;
    }
    #hud-due, #hud-progress, #active-buff-bar { flex: 0 0 auto; }

    /* The chips that must stay whole are pinned. The account in this group is only an avatar
       now (#hud-account), so what is left is narrow enough for the floor above to hold. */
    #hud-currency-group {
      padding: 0 4px;
      flex-shrink: 1;
    }
    #hud-currency-group > #hud-rank,
    #hud-currency-group > .hud-chip { flex: 0 0 auto; }

    #hud-actions-group {
      position: relative;
      margin-left: auto;
    }

    #hud-overflow-menu {
      position: absolute; top: calc(100% + 8px); right: 0;
      z-index: 950; display: flex; flex-direction: column; gap: 3px;
      padding: 6px; min-width: 188px;
      background: #f6deaa !important;
      border: 1px solid #8b5a2b !important;
      border-radius: 8px !important;
      box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35) !important;
      animation: popIn .16s cubic-bezier(.4,0,.2,1);
    }
    #hud-overflow-menu.hidden { display: none !important; }

    .hud-overflow-item {
      width: 100% !important; height: auto !important; min-width: 0 !important;
      min-height: 32px !important;
      border-radius: 4px !important;
      display: flex !important; align-items: center !important;
      justify-content: flex-start !important;
      gap: 10px !important;
      padding: 7px 12px !important; font-size: 13px !important;
      font-family: 'Be Vietnam Pro', sans-serif !important;
      background: transparent !important;
      border: 0 !important;
      color: #2a1a0a !important;
      box-shadow: none !important;
      overflow: visible !important;
      white-space: nowrap;
    }
    .hud-overflow-item .hud-art-icon {
      width: 18px; height: 18px; flex-shrink: 0;
      filter: none;
    }
    .hud-overflow-label {
      display: inline-block; line-height: 1.2; font-weight: 700;
      color: #2a1a0a; font-size: 13px;
    }
    .hud-overflow-item:hover {
      background: #fff3d6 !important;
      transform: none !important;
    }

    /* A fixed basis rather than `auto`. With `auto` the basis was the whole title — a TOPIK
       world's runs past 400px — so the name took nearly all of the squeeze, hit its 180px cap,
       froze there, and the rest fell on the progress bar, which went to zero. From a common
       basis the two give ground in proportion. `contain: inline-size` keeps the unbreakable
       title out of the group's min-content, which is the floor the group above is held to. */
    #hud-level {
      display: flex; align-items: center; gap: 6px;
      font-family: 'Be Vietnam Pro', sans-serif; font-weight: 800;
      font-size: 13px; color: #f6deaa; letter-spacing: 0;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
      max-width: 180px; flex: 1 1 120px; min-width: 0; contain: inline-size;
    }
    .hud-level-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    #hud-sep { display: none; }
    #hud-progress {
      font-family: 'VT323', monospace; font-size: 16px; color: #e8c07a;
      background: none; border: 0; padding: 0; min-width: 28px;
    }
    #hud-due {
      display: none; align-items: center; justify-content: center;
      min-width: 22px; height: 18px; padding: 0 6px;
      background: #b45309; color: #fff8e8;
      border-radius: 3px; font-family: 'VT323', monospace; font-size: 14px;
    }
    #hud-due.has-due { display: inline-flex; }

    .hud-chip {
      display: inline-flex; align-items: center; gap: 5px;
      padding: 2px 2px 2px 0;
      font-family: 'VT323', monospace; font-size: 18px; color: #f6deaa;
      line-height: 1;
    }
    .hud-chip .hud-art-icon { width: 18px; height: 18px; flex-shrink: 0; }
    #hud-gold, #hud-gems, #hud-honor { background: none; border: 0; border-radius: 0; }
    #hud-gold.pop { transform: scale(1.12); }

    .hud-btn {
      width: 36px; height: 36px; min-width: 36px;
      display: inline-flex; align-items: center; justify-content: center;
      background: rgba(246, 222, 170, 0.10) !important;
      border: 1px solid rgba(232, 192, 122, 0.32) !important;
      border-radius: 4px !important; color: #f6deaa !important;
      font-family: inherit !important; font-size: 15px !important;
      cursor: pointer; padding: 0 !important; letter-spacing: 0;
      box-shadow: none !important;
      transition: background .15s, border-color .15s, box-shadow .15s !important;
      pointer-events: all;
    }
    .hud-btn .hud-art-icon {
      width: 22px; height: 22px; pointer-events: none;
      filter: drop-shadow(0 1px 0 rgba(42, 26, 10, 0.35));
    }
    .hud-btn:hover {
      background: rgba(246, 222, 170, 0.24) !important;
      border-color: rgba(246, 222, 170, 0.62) !important;
      transform: none !important;
      filter: none !important;
    }
    .hud-btn:active { transform: scale(.96) !important; }
    .hud-btn.hud-btn-menu {
      background: rgba(196, 137, 58, 0.92) !important;
      border-color: #e8c07a !important;
      color: #2a1a0a !important;
      box-shadow: 0 0 0 1px rgba(42, 26, 10, 0.25) !important;
    }

    /* ── PROGRESS BAR ────────────────────────────────────────────────────── */
    /* Part of the status group, not a floating overlay. It was `position: fixed; top: 10px;
       right: 14px` — exactly where #hud sits, at the same z-index — so it covered the right
       end of the bar. In the flow it can never occlude anything.
       A grid, so the bar's 72px is a size the wrap can report. As a flex row the wrap was sized
       from its content, and an empty div has none: the wrap measured 34px — the percentage and
       its gap — and the bar was squeezed to 0px at every window size, so the HUD never drew it.
       `minmax(0, 72px)` gives the bar its 72px when there is room and lets it go first, all the
       way to nothing, when there is not; the percentage keeps its own width throughout. */
    #progress-bar-wrap {
      display: grid; grid-template-columns: minmax(0, 72px) auto; align-items: center;
      column-gap: 6px; pointer-events: none;
      flex: 0 1 auto; min-width: min-content;
    }
    #progress-bar-bg {
      min-width: 0; height: 6px;
      background: rgba(0, 0, 0, 0.45); border-radius: 2px; overflow: hidden;
      border: 0;
    }
    #progress-bar-fill {
      height: 100%; width: 0%;
      background: linear-gradient(90deg, #86efac, #e8c07a);
      border-radius: 2px;
      transition: width .45s cubic-bezier(.4,0,.2,1);
      box-shadow: none;
    }

    /* ── CONTROLS TIP ────────────────────────────────────────────────────── */
    #controls-tip {
      position: fixed; bottom: 12px; left: 50%; transform: translateX(-50%); z-index: 100;
      background: rgba(42, 26, 10, 0.82);
      border: 1.5px solid #c4893a;
      border-radius: 4px; padding: 5px 12px;
      font-family: 'VT323', monospace; font-size: 17px;
      color: #f4d6a0; letter-spacing: .4px;
      pointer-events: none; user-select: none;
      box-shadow: 0 0 0 2px #4a2a0d;
      /* The hint line is ~980px of `white-space: nowrap` text centred with translateX(-50%),
         so on anything narrower it hung off both edges — 15px each side at 950px, 40px at
         900px. A max-width clamp was only ever applied under a 768px media query, leaving the
         whole 769–980px range bleeding. Wrapping to a second line is what a centred hint
         should do; the previous `overflow-x: auto` could never have helped, since the element
         is `pointer-events: none` and so cannot be scrolled. */
      /* `width: max-content` first, then the clamp. Without it a shrink-to-fit fixed box
         collapses toward its longest unbreakable run instead of using the room available —
         at 375px it settled at 188px wide and five lines tall, a fifth of the screen. */
      width: max-content; max-width: calc(100vw - 28px);
      text-align: center; line-height: 1.5;
    }

    /* ── TOUCH CONTROLS ─────────────────────────────────────────────────────
       The container is pointer-events: none so it never steals taps from the game
       underneath; only the stick and the button opt back in. Sitting at z-index 150 puts
       them above the HUD (100) and below every modal backdrop (200+), so opening a quiz
       covers them rather than leaving a thumbstick floating over the answer field. */
    #touch-controls {
      position: fixed; inset: auto 0 0 0; z-index: 150;
      display: flex; align-items: flex-end; justify-content: space-between;
      padding: 0 18px 18px; pointer-events: none;
      /* Keep clear of the iOS home indicator and any notch-side inset. */
      padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px));
    }
    #touch-controls.hidden { display: none; }

    #tc-stick {
      pointer-events: auto; touch-action: none;
      width: 132px; height: 132px; border-radius: 4px;
      background: rgba(15, 23, 42, 0.55);
      border: 2px solid rgba(56, 189, 248, 0.45);
      box-shadow: 0 0 0 2px #0f172a, 0 0 18px rgba(56, 189, 248, 0.2);
      position: relative; backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
    }
    #tc-knob {
      position: absolute; left: 50%; top: 50%; width: 56px; height: 56px;
      margin: -28px 0 0 -28px; border-radius: 4px;
      background: radial-gradient(circle at 35% 30%, #7dd3fc, #0284c7);
      border: 2px solid rgba(255, 255, 255, 0.55);
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
      transition: transform .08s ease-out;
    }
    #tc-stick.dragging #tc-knob { transition: none; }

    #tc-action {
      pointer-events: auto; touch-action: none;
      width: 108px; height: 108px; border-radius: 4px;
      background: radial-gradient(circle at 35% 30%, #86efac, #16a34a);
      border: 3px solid rgba(255, 255, 255, 0.55);
      box-shadow: 0 0 0 2px #0f172a, 0 6px 18px rgba(0, 0, 0, 0.55);
      color: #06280f; cursor: pointer;
      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px;
      user-select: none; -webkit-user-select: none; -webkit-tap-highlight-color: transparent;
    }
    #tc-action:active { transform: scale(0.94); filter: brightness(1.1); }
    #tc-action-icon { font-size: 26px; line-height: 1; }

    /* The keyboard hint is noise where there is no keyboard, and it would sit under the
       thumbstick anyway. Done in CSS rather than JS because showLevelSelect/hideLevelSelect
       already drive `#controls-tip`'s inline display, and two owners of one property is how
       flicker starts. */
    @media (pointer: coarse) {
      #controls-tip { display: none !important; }
    }

    /* Short landscape phones: shrink so the controls do not eat the play area. */
    @media (max-height: 460px) {
      #touch-controls { padding: 0 12px 10px; padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }
      #tc-stick { width: 104px; height: 104px; }
      #tc-knob { width: 44px; height: 44px; margin: -22px 0 0 -22px; }
      #tc-action { width: 84px; height: 84px; font-size: 9px; }
      #tc-action-icon { font-size: 20px; }
    }

    .key-badge {
      display: inline-block;
      background: rgba(30, 41, 59, 0.9);
      border: 1.5px solid var(--neon-cyan); border-radius: 4px;
      padding: 0 6px; font-size: 12px; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust);
      color: #fff; box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3);
    }

    #quiz-study, #quiz-answer-area { display: contents; }
    .quiz-close-view { display: none; }

    /* ── QUIZ MODAL ──────────────────────────────────────────────────────── */
    #quiz-backdrop {
      display: none; position: fixed; inset: 0; z-index: 200;
      background: rgba(42, 26, 10, 0.62);
      backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
    }
    #quiz-backdrop.visible { display: flex; align-items: center; justify-content: center; animation: fadeIn .2s ease; }

    #quiz-ui {
      background:
        linear-gradient(180deg, rgba(255,248,232,0.18), transparent 28%),
        linear-gradient(180deg, #f6deaa 0%, #e8c07a 100%);
      border: 5px solid #8b5a2b;
      border-radius: 8px; padding: 22px 26px;
      /* Wide enough for the hint card to show a 96px illustration at 2× without
         the four widest tiles (up to 298px) having to shrink to fit. */
      width: min(600px, 94vw); max-height: 90vh; overflow-y: auto;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 22px 50px rgba(0,0,0,.55);
      display: flex; flex-direction: column; gap: 14px;
      animation: slideUp .25s cubic-bezier(.4,0,.2,1);
      position: relative;
      color: #2a1a0a;
    }

    .quiz-header {
      display: flex; align-items: center; gap: 12px; padding-bottom: 10px;
      border-bottom: 2px dashed #b8894a;
    }
    .quiz-crop-icon { font-size: 24px; }
    .quiz-title {
      font-family: 'VT323', monospace; font-size: 22px;
      color: #7a3e12; letter-spacing: 2px; text-transform: uppercase;
    }
    #question-text {
      font-family: 'VT323', monospace; font-size: 26px;
      color: #4a2a0d; text-align: center; letter-spacing: 1px;
    }
    #en-word-display {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 22px;
      color: #7a3e12; display: block; margin-top: 6px;
      text-shadow: 0 1px 0 #fff3d6;
    }

    #quiz-hint-box {
      background:
        radial-gradient(ellipse 62% 58% at 50% 44%, #fffdf4 0%, #fff6de 62%, #f8ecd0 100%);
      border: 2px solid #c4893a;
      border-radius: 8px; padding: 18px 16px 12px; text-align: center;
      position: relative;
      box-shadow: inset 0 1px 0 #fff;
    }
    #quiz-funfact-box {
      background: #fff6de;
      border: 2px solid #c4893a;
      border-radius: 8px; padding: 10px 12px;
      color: #4a2a0a;
    }
    #quiz-funfact-box.hidden { display: none !important; }
    #quiz-funfact-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px;
      color: #7a3e12; margin-bottom: 6px;
    }
    #quiz-funfact-text { font-size: 15px; font-weight: 700; line-height: 1.4; }
    #quiz-funfact-culture { font-size: 13px; color: #7a3e12; margin-top: 4px; }
    .recall-tiles {
      display: flex; justify-content: center; align-items: flex-end;
      flex-wrap: wrap;
      column-gap: 0.7em;
      row-gap: 8px;
      margin: 4px 0 2px;
    }
    .recall-word {
      display: inline-flex;
      gap: 3px;
      flex-wrap: nowrap;
    }
    .recall-tile {
      width: 28px; height: 28px;
      background: #fffaf0;
      border: 2px solid #8b5a2b;
      border-radius: 3px;
      box-shadow: inset 0 1px 0 #fff;
      position: relative;
      flex-shrink: 0;
    }
    .recall-tile.batchim::after {
      content: '';
      position: absolute; left: 5px; right: 5px; bottom: 4px;
      height: 5px; background: #c4893a; border-radius: 1px;
    }
    /* Pattern notation, printed rather than boxed: the hyphen of an ending, the slash of
       을/를, the brackets and bare jamo of -(으)ㄴ, the N or V that says what the pattern
       attaches to. A box is what the learner still owes; this is what they are given, so it
       is ink on the card and not a tile. Noto Sans KR leads the stack because the jamo are
       the whole point and a Latin face has none of them. */
    .recall-literal {
      display: inline-flex; align-items: center; justify-content: center;
      min-width: 10px; height: 28px;
      font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif;
      font-weight: 700; font-size: 18px; line-height: 1;
      color: #6b4a24;
      flex-shrink: 0;
    }
    /* .recall-word spaces its children by 3px, which is right between two boxes and wrong
       inside a run of notation: `V-` is two characters of one marker, not `V - `. Cancel the
       gap where two literals meet so the run reads as the string it is. */
    .recall-literal + .recall-literal { margin-left: -3px; }
    /* The illustration is the point of this card, so the stage is sized to the
       art rather than the art squeezed into the stage. A 192px stage clears every
       source generation at a whole-number scale: the Unit illustrations are 192px
       tall and land at 1:1, TOPIK's 96px tiles at 2×, the old farm set at 4×.
       Do not set this to a height the tallest generation does not divide. */
    #hint-emoji {
      position: relative;
      font-size: 130px; line-height: 1;
      display: flex; align-items: center; justify-content: center;
      min-height: 192px; margin-bottom: 6px;
      filter: drop-shadow(0 4px 10px rgba(0,0,0,.25));
    }
    #hint-emoji .quiz-image-status {
      position: absolute; bottom: 0; left: 50%; transform: translateX(-50%);
      font: 14px/1.4 sans-serif; white-space: nowrap; padding: 5px 10px;
      border: 1px solid #b8a78a; border-radius: 6px; background: #fff8e7; color: #493c30;
    }
    #hint-emoji .quiz-image-status:disabled { opacity: 1; cursor: default; }
    #hint-emoji .vocab-art-icon, #hint-emoji img {
      width: auto; max-width: 100%; height: 192px; object-fit: contain;
      image-rendering: pixelated; image-rendering: crisp-edges;
      filter: none; vertical-align: middle;
    }
    /* On a window tall enough that even the shape-card phase still fits without
       scrolling, the stage steps up one whole multiple of the largest source —
       2× the 192px illustration. It used to step to 288px, which was 3× the
       96px tile this rule was written for and 1.5× once 192px artwork arrived:
       every second row of the new illustrations was drawn twice and the rest once.
       The art grows by a whole source pixel or not at all. */
    /* The threshold moved with the step. At 1000px tall the old 288px stage fitted the harvest
       phase exactly; 384px does not, and the panel it overflows by 25px puts the submit button
       behind a scrollbar. 192px is already 1:1 for the artwork, so there is nothing to lose by
       waiting for a window that can hold the whole doubled card. */
    @media (min-width: 820px) and (min-height: 1200px) {
      #quiz-ui { width: min(680px, 94vw); }
      #hint-emoji { min-height: 384px; font-size: 190px; }
      #hint-emoji .vocab-art-icon, #hint-emoji img { height: 384px; }
    }
    /* Short window: the stage keeps its 2× art, and the room for it comes out of
       the padding instead. The Harvest phase is the tallest — art card, shape
       card, hint row, input and buttons — and its buttons must stay above the
       fold, because a submit button behind a scrollbar reads as a dead end. */
    @media (max-height: 900px) {
      #quiz-ui { padding: 16px 22px; gap: 11px; max-height: 94vh; }
      #quiz-hint-box { padding: 12px 14px 8px; }
      #hint-emoji { margin-bottom: 2px; }
    }
    /* A phone stacks the four answers, so the stage drops to 1× — the same 96px
       the Vocabulary Book uses on a phone. Still larger than the 72px box this
       card used to have, and it keeps the answers and the skip button on screen,
       which matters more on a small display than a second row of tile pixels. */
    @media (max-width: 560px) {
      #hint-emoji { min-height: 96px; font-size: 84px; }
      #hint-emoji .vocab-art-icon, #hint-emoji img { height: 96px; }
    }
    #hint-category {
      font-family: 'VT323', monospace; font-size: 18px; letter-spacing: 2px;
      color: #9a6800; text-transform: uppercase;
    }

    #answer-input {
      width: 100%;
      background: #fffaf0;
      border: 2px solid #8b5a2b;
      border-radius: 8px; padding: 12px 18px;
      font-size: 32px; font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif; font-weight: 700;
      color: #1a1208; outline: none; text-align: center; ime-mode: active;
      transition: border-color .2s, box-shadow .2s;
      box-shadow: inset 0 2px 6px rgba(74, 42, 13, .12);
    }
    #answer-input:focus {
      border-color: #16a34a;
      box-shadow: inset 0 2px 6px rgba(74, 42, 13, .12), 0 0 0 3px rgba(74, 222, 128, 0.35);
    }
    #answer-input::placeholder { color: #b8894a; font-size: 18px; font-family: 'Be Vietnam Pro', sans-serif; }

    #feedback-text {
      font-family: 'VT323', monospace; font-size: 22px;
      color: #b91c1c; text-align: center; min-height: 22px; letter-spacing: .5px;
    }
    #feedback-text.correct { color: #15803d; text-shadow: none; }

    .quiz-buttons { display: flex; gap: 10px; }
    #submit-btn, #cancel-btn {
      flex: 1; border-radius: 8px; padding: 12px 0;
      font-family: 'VT323', monospace; font-size: 22px;
      cursor: pointer; letter-spacing: 1px; transition: all .15s; border: 2px solid;
    }
    #submit-btn {
      background: linear-gradient(180deg, #86efac, #4ade80);
      border-color: #166534; color: #14532d;
      box-shadow: 0 3px 0 #166534;
    }
    #submit-btn:hover { transform: translateY(-2px); filter: brightness(1.05); }
    #cancel-btn {
      background: #f3e2b8;
      border-color: #8b5a2b; color: #5b3412;
    }
    #cancel-btn:hover { background: #efe0b0; color: #2a1a0a; }

    #quiz-tier-hints { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; margin-top: 4px; }
    .quiz-tier-btn {
      background: #fff3c7; border: 1.5px solid #b8894a;
      border-radius: 4px; color: #7a3e12; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust);
      font-size: 9px; padding: 6px 10px; cursor: pointer; transition: all 0.15s;
    }
    .quiz-tier-btn:hover { background: #fde68a; border-color: #92400e; transform: translateY(-1px); }
    #quiz-hint-reveal-card {
      background: #fffaf0; border: 1.5px solid #a855f7;
      border-radius: 8px; padding: 10px 14px; margin-top: 6px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 14px; color: #3b0764;
      line-height: 1.5; text-align: center;
    }
    #quiz-hint-reveal-card.hidden { display: none; }

    #quiz-phase-bar {
      display: flex; justify-content: space-between; align-items: center;
      gap: 10px; padding: 8px 10px; background: #ead198; border-radius: 4px;
      border: 1px solid #c4893a;
    }
    #quiz-steps {
      display: flex; align-items: center; gap: 6px; flex: 1;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 800;
    }
    .quiz-step {
      padding: 4px 8px; border-radius: 3px;
      background: #fff8e8; border: 1.5px solid #c4893a; color: #7a3e12;
    }
    .quiz-step.done { background: #dcfce7; border-color: #166534; color: #14532d; }
    .quiz-step.active {
      background: #166534; border-color: #14532d; color: #fff8e8;
    }
    #quiz-ui.phase-2 .quiz-step.active { background: #1d4ed8; border-color: #1e3a8a; }
    #quiz-ui.phase-3 .quiz-step.active { background: #b45309; border-color: #92400e; }
    .quiz-step-line { flex: 1; height: 2px; background: #c4893a; min-width: 8px; }
    #quiz-gold-reward {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: #b45309;
    }
    #quiz-ui.phase-1 { border-color: #166534; }
    #quiz-ui.phase-2 { border-color: #1d4ed8; }
    #quiz-ui.phase-3 { border-color: #b45309; }

    #quiz-result {
      display: flex; flex-direction: column; align-items: center; gap: 6px;
      padding: 12px 8px 4px; text-align: center;
    }
    #quiz-result.hidden { display: none !important; }
    /* The word is being shown to be read, so this is sized like the question stage
       above it: 192px is 1:1 for a Unit illustration and a whole multiple for the
       two older tile sizes. The 72px square it replaces cropped nothing — object-fit
       kept the aspect — but it painted a 192px drawing at roughly a third of its
       own resolution at the exact moment the learner looks at it. */
    #quiz-result-art .vocab-art-icon, #quiz-result-art img {
      width: auto; max-width: 100%; height: 192px; object-fit: contain;
      image-rendering: pixelated; image-rendering: crisp-edges;
    }
    #quiz-result-msg {
      font-family: 'VT323', monospace; font-size: 24px; color: #166534; font-weight: 700;
    }
    #quiz-result-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 36px; font-weight: 900; color: #2a1a0a;
    }
    #quiz-result-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 14px; color: #7a3e12; font-weight: 700;
    }
    #quiz-result-continue {
      margin-top: 8px; width: 100%; padding: 12px 0;
      background: linear-gradient(180deg, #86efac, #4ade80);
      border: 2px solid #166534; border-radius: 8px;
      color: #14532d; font-family: 'VT323', monospace; font-size: 22px;
      cursor: pointer; box-shadow: 0 3px 0 #166534;
    }
    #quiz-result-continue:hover { filter: brightness(1.05); }
    #quiz-result-typed {
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; color: #9a3412;
      text-decoration: line-through; text-decoration-color: #dc2626aa;
    }
    #quiz-result-note {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #92400e;
      background: #fef3c7; border: 1px solid #fcd34d; border-radius: 6px;
      padding: 5px 9px; margin-top: 2px;
    }
    #quiz-result-typed.hidden, #quiz-result-note.hidden { display: none !important; }

    /* The curated example, shown under the answer at phase 3. Quieter than #quiz-result-ko
       above it — that is the answer, this is the sentence it lives in — but the Korean still
       leads, with the translation under it in the gloss colour the panel already uses. */
    #quiz-result-example-box {
      margin-top: 8px; padding: 7px 10px; text-align: left;
      background: #fffbeb; border: 1px solid #fcd34d; border-radius: 6px;
    }
    #quiz-result-example-label {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; font-weight: 800;
      letter-spacing: .06em; text-transform: uppercase; color: #a16207; margin-bottom: 3px;
    }
    #quiz-result-example {
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; font-weight: 700;
      color: #2a1a0a; line-height: 1.45;
    }
    #quiz-result-example-tr {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #7a3e12;
      line-height: 1.4; margin-top: 2px;
    }
    #quiz-result-example-box.hidden, #quiz-result-example-tr.hidden { display: none !important; }

    /* An answered question hides the question, whether it was answered right or wrong —
       so the hiding hangs on .quiz-done, and .quiz-success / .quiz-lapsed carry only the
       colour. Before the lapse reveal existed the two were the same thing and the list
       below was keyed to .quiz-success, which is the sort of coupling that quietly makes
       a second outcome impossible to add. */
    #quiz-ui.quiz-done #quiz-hint-box,
    #quiz-ui.quiz-done #question-text,
    #quiz-ui.quiz-done #en-word-display,
    #quiz-ui.quiz-done #quiz-ko-prompt,
    #quiz-ui.quiz-done #quiz-choices,
    #quiz-ui.quiz-done #quiz-listen-controls,
    #quiz-ui.quiz-done #quiz-funfact-box,
    #quiz-ui.quiz-done #quiz-tier-hints,
    #quiz-ui.quiz-done #quiz-hint-reveal-card,
    #quiz-ui.quiz-done #answer-input,
    #quiz-ui.quiz-done #feedback-text,
    #quiz-ui.quiz-done .quiz-buttons { display: none !important; }

    #quiz-ui.quiz-lapsed { border-color: #b91c1c; }
    #quiz-ui.quiz-lapsed #quiz-result-msg { color: #b91c1c; }
    #quiz-ui.quiz-lapsed #quiz-result-continue {
      background: linear-gradient(180deg, #fdba74, #fb923c);
      border-color: #9a3412; color: #7c2d12; box-shadow: 0 3px 0 #9a3412;
    }

    /* ── VOCABULARY BOOK · FULL-SCREEN LIBRARY ───────────────────────────── */
    #vocab-overlay {
      display: none; position: fixed; inset: 0; z-index: 400;
      background: #2a1a0a; flex-direction: column;
    }
    #vocab-overlay.visible { display: flex; animation: fadeIn .2s ease; }

    #vocab-panel {
      position: relative; display: flex; flex-direction: column;
      width: 100%; height: 100vh; height: 100dvh; max-height: none; margin: 0;
      background:
        radial-gradient(circle at 12% 8%, rgba(255,255,255,.34), transparent 25%),
        linear-gradient(180deg, #f8e8c3 0%, #efd39a 52%, #e4bb72 100%);
      border: 0; border-radius: 0; overflow: hidden;
      box-shadow: inset 0 0 0 3px #8b5a2b, inset 0 0 0 6px #c4893a;
      color: var(--ink); animation: fadeIn .22s ease;
    }

    #vocab-header {
      min-height: 78px; padding: 14px clamp(18px, 3vw, 48px);
      background: linear-gradient(180deg, rgba(255,250,240,.96), rgba(246,222,170,.9));
      border-bottom: 2px dashed #b9792c;
      display: flex; align-items: center; gap: 16px; flex-shrink: 0;
      box-shadow: 0 4px 14px rgba(91,52,18,.12);
    }
    .vocab-book-mark {
      width: 54px; height: 54px; border-radius: 12px;
      display: grid; place-items: center; flex-shrink: 0;
      font-size: 34px; background: #fff8e8; border: 2px solid #c4893a;
      box-shadow: inset 0 1px #fff, 0 3px 0 #8b5a2b;
    }
    #vocab-title-wrap { flex: 1; min-width: 0; }
    #vocab-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: clamp(14px, 1.35vw, 20px);
      color: #5b3412; line-height: 1.35;
    }
    #vocab-subtitle {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 16px; font-weight: 700;
      color: #7a3e12; margin-top: 4px; letter-spacing: .2px;
    }
    #vocab-progress-summary {
      min-height: 18px; margin-top: 3px; color: #166534;
      font-size: 13px; font-weight: 700;
    }
    #vocab-close-btn {
      background: #fff8e8; border: 2px solid #8b5a2b;
      border-radius: 10px; color: #5b3412; font-size: 22px; width: 46px; height: 46px;
      cursor: pointer; display: flex; align-items: center; justify-content: center;
      flex-shrink: 0; transition: background .15s, border-color .15s, color .15s, transform .15s;
      box-shadow: 0 3px 0 #8b5a2b;
    }
    #vocab-close-btn:hover { background: #fee2e2; border-color: #b91c1c; color: #991b1b; transform: translateY(-1px); }
    #vocab-close-btn:focus-visible { outline: none; box-shadow: 0 3px 0 #8b5a2b, 0 0 0 4px rgba(74,42,13,.32); }

    #vocab-controls {
      padding: 14px clamp(18px, 3vw, 48px); display: grid;
      grid-template-columns: minmax(280px, 430px) minmax(0, 1fr); gap: 18px;
      flex-shrink: 0; border-bottom: 1px solid rgba(139,90,43,.3);
      background: rgba(255,248,232,.55);
    }
    .vocab-search-wrap, .vocab-filter-wrap { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
    .vocab-control-label {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; line-height: 1.4;
      color: #7a3e12; text-transform: uppercase; letter-spacing: .2px;
    }
    .vocab-search-field {
      height: 44px; display: flex; align-items: center; gap: 8px;
      background: #fffdf7; border: 2px solid #8b5a2b; border-radius: 8px;
      padding: 0 12px; color: #8b5a2b; box-shadow: inset 0 2px 5px rgba(91,52,18,.08);
    }
    .vocab-search-field:focus-within { border-color: #166534; box-shadow: 0 0 0 3px rgba(22,101,52,.2); }
    #vocab-search {
      flex: 1; min-width: 0; width: 100%; background: transparent; border: 0;
      padding: 8px 0; font-family: 'Be Vietnam Pro', sans-serif; font-size: 15px;
      color: var(--ink); outline: none;
    }
    #vocab-search::placeholder { color: #9a6f3a; opacity: .9; }
    #cat-filters {
      display: flex; align-items: center; gap: 7px; min-width: 0; min-height: 44px;
      overflow-x: auto; overflow-y: hidden; padding: 2px 3px 5px;
      scrollbar-width: thin; scrollbar-color: #8b5a2b rgba(139,90,43,.12);
    }
    .cat-filter-btn {
      min-height: 36px; border: 1.5px solid #b9792c; border-radius: 999px;
      background: #fff8e8; color: #5b3412; padding: 6px 12px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 750;
      cursor: pointer; white-space: nowrap; flex-shrink: 0;
      transition: background .15s, border-color .15s, color .15s, transform .15s;
    }
    .cat-filter-btn.active { background: #dcfce7; border-color: #166534; color: #14532d; }
    .cat-filter-btn:hover:not(.active) { background: #ffe9b8; border-color: #8b5a2b; color: #4a2a0d; transform: translateY(-1px); }
    .cat-filter-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,.32); }

    #vocab-grid-wrap {
      flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
      padding: 18px clamp(18px, 3vw, 48px) 44px;
    }
    #vocab-grid-wrap::-webkit-scrollbar { width: 10px; }
    #vocab-grid-wrap::-webkit-scrollbar-track { background: rgba(139,90,43,.14); }
    #vocab-grid-wrap::-webkit-scrollbar-thumb { background: #8b5a2b; border-radius: 8px; border: 2px solid #efd39a; }
    #vocab-grid-heading {
      display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
      margin-bottom: 14px;
    }
    #vocab-count {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #5b3412;
      line-height: 1.5; letter-spacing: .1px;
    }
    .vocab-grid-help { color: #7a3e12; font-size: 13px; text-align: right; }

    #vocab-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
      gap: 18px; align-items: stretch;
    }
    .vocab-card {
      background: linear-gradient(180deg, #fffdf7 0%, #fff4d9 100%);
      border: 2px solid #c4893a; border-radius: 12px;
      padding: 18px 14px 13px; text-align: center;
      transition: transform .15s, border-color .15s, box-shadow .15s;
      cursor: pointer; position: relative; overflow: hidden;
      display: flex; flex-direction: column; align-items: center;
      min-height: 382px;
      box-shadow: inset 0 1px 0 #fff, 0 4px 0 #8b5a2b, 0 9px 18px rgba(91,52,18,.12);
    }
    .vocab-card::after {
      content: ''; position: absolute; inset: auto 10px 8px; height: 3px;
      border-radius: 99px; background: rgba(196,137,58,.25); pointer-events: none;
    }
    .vocab-card:hover {
      transform: translateY(-4px); border-color: #166534;
      box-shadow: inset 0 1px 0 #fff, 0 4px 0 #166534, 0 12px 22px rgba(22,101,52,.15);
    }
    .vocab-card:focus-visible {
      outline: none; border-color: #166534;
      box-shadow: inset 0 1px 0 #fff, 0 4px 0 #166534, 0 0 0 4px rgba(22,101,52,.35);
    }
    .vocab-card.planted { border-color: #287448; background: linear-gradient(180deg, #f4fff0, #e4f5d8); }
    .vocab-card .vc-speak {
      top: 10px; right: 10px; width: 34px; height: 32px; padding: 0;
      color: #14532d; background: #ecfdf5; border-color: #4d9366;
    }
    .vocab-card .vc-speak:hover { background: #dcfce7; }
    .vc-category {
      align-self: flex-start; max-width: calc(100% - 38px); margin-bottom: 8px;
      padding: 4px 8px; border-radius: 999px; background: #f6deaa;
      border: 1px solid #d6a45e; color: #6b3d14; font-size: 10px; font-weight: 800;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .vc-emoji {
      font-size: 52px; display: flex; align-items: center; justify-content: center;
      line-height: 1; margin: 1px 0 10px; width: 100%; min-height: 192px;
    }
    /* 192px, not 96px: a desktop pixel is one device pixel, so a 96px box halved
       every Unit illustration on the way to the screen. The narrower layouts below
       keep 96px on purpose — a phone or tablet renders at 2× or better, where 96
       CSS pixels already is the full 192px source.
       object-fit is load-bearing rather than decorative: max-width clamps the box
       for a wide illustration while the explicit height stands, and without a fit
       rule the browser answers that by stretching the picture. */
    .vc-emoji img.vocab-art-icon {
      width: auto; max-width: 100%; height: 192px; display: inline-block;
      object-fit: contain;
      filter: none; image-rendering: pixelated; image-rendering: crisp-edges;
    }
    .vc-ko {
      font-size: 34px; font-weight: 900; color: #241407;
      font-family: 'Noto Sans KR', sans-serif; display: block;
      line-height: 1.18; margin-bottom: 7px; word-break: keep-all;
    }
    .vc-ko.vc-ko-sm { font-size: 27px; }
    .vc-ko.vc-ko-xs { font-size: 21px; }
    .vc-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 15px; font-weight: 650; color: #6b3d14;
      display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
      overflow: hidden; line-height: 1.45; letter-spacing: .1px;
    }
    .vc-meta {
      margin-top: auto; padding-top: 11px; display: flex; flex-direction: row;
      align-items: center; justify-content: center; flex-wrap: wrap; gap: 6px; width: 100%;
    }
    .vc-chosung {
      font-family: 'Noto Sans KR', monospace; font-size: 12px; font-weight: 800;
      color: #5b3412; background: #fff3d6; border: 1px solid #d9b072;
      border-radius: 5px; padding: 3px 7px; letter-spacing: 2px;
      max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* How many times this word has been studied through to a harvest. Green, because it is
       the one number on the card that only ever goes up — the mastery badge beside it can
       move backwards when a word lapses, and the two should not read as the same kind of
       fact. Hidden entirely at zero: a word you have never finished says so with its badge,
       and a row of "x0" would be noise on every new level. */
    .vc-studied {
      display: inline-flex; align-items: center; gap: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 7px;
      font-weight: 700; line-height: 1.5; padding: 4px 8px; border-radius: 5px;
      background: #dcfce7; color: #14532d; border: 1.5px solid #16a34a;
      max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }

    .vc-open-hint {
      margin-top: 9px; color: #166534; font-size: 11px; font-weight: 800;
      letter-spacing: .15px;
    }

    .mastery-badge {
      display: inline-block; padding: 4px 8px; border-radius: 5px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 7px; font-weight: 700;
      line-height: 1.5; border: 1.5px solid; max-width: 100%;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .mastery-badge.novice     { background: #ece3d3; color: #463523; border-color: #a08a6f; }
    .mastery-badge.practicing { background: #dbeafe; color: #1e3a8a; border-color: #2563eb; }
    .mastery-badge.mastered   { background: #f3e8ff; color: #581c87; border-color: #7e22ce; }
    .mastery-badge.legendary  { background: #fef3c7; color: #78350f; border-color: #b45309; }
    .vocab-card.mastered  { border-color: #7e22ce; box-shadow: inset 0 1px 0 #fff, 0 4px 0 #6b21a8, 0 9px 18px rgba(91,33,182,.12); }
    .vocab-card.legendary { border-color: #b45309; box-shadow: inset 0 1px 0 #fff, 0 4px 0 #92400e, 0 9px 18px rgba(146,64,14,.12); }

    .vocab-empty {
      grid-column: 1 / -1; text-align: center; padding: 64px 12px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 16px; color: #7a3e12;
    }

    @media (prefers-reduced-motion: reduce) {
      #vocab-overlay.visible, #vocab-panel { animation: none; }
      .vocab-card, .cat-filter-btn, #vocab-close-btn { transition: none; }
      .vocab-card:hover, .cat-filter-btn:hover:not(.active), #vocab-close-btn:hover { transform: none; }
    }


    /* ── SEED SHOP OVERLAY ──────────────────────────────────────────────── */
    #shop-overlay {
      position: fixed; inset: 0; z-index: 480; display: none;
      background: var(--farm-veil); backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #shop-overlay.visible { display: flex; }

    #shop-panel {
      background: linear-gradient(180deg, #f6deaa, #e8c07a);
      border: 4px solid #8b5a2b; border-radius: 8px; padding: 16px 18px;
      max-width: 680px; width: 94%; max-height: 86vh; overflow-y: auto;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      position: relative; color: var(--ink);
    }
    #shop-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
    #shop-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; color: #7a3e12; }
    /* Neon gold on parchment measured 1.35:1. Same gold semantics, in the palette
       `.inv-chip.gold` already uses for a gold value on a light ground. The trophy
       badge keeps the neon fill — its panel is still dark slate. */
    #shop-gold-badge {
      display: flex; align-items: center; gap: 7px; background: #fef3c7;
      border: 1.5px solid #b45309; border-radius: 8px; padding: 4px 16px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 14px; color: #78350f;
    }
    /* Was #fff on a parchment panel — a 1.45:1 ✕, the same defect the vocab book had. */
    #shop-close-btn {
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 6px 12px; font-size: 16px;
      cursor: pointer; transition: background .15s, border-color .15s, color .15s;
    }
    #shop-close-btn:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }
    #shop-close-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }
    #shop-level-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
    .shop-card {
      background: var(--parch-l);
      border: 1.5px solid #c4893a; border-radius: 8px; padding: 10px;
      transition: transform .15s, border-color .15s;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b;
    }
    .shop-card:not(.owned):not(.too-expensive):hover { transform: translateY(-2px); border-color: #166534; cursor: pointer; }
    .shop-card.owned { border-color: #166534; background: #e8f8dc; }
    .shop-card.too-expensive { opacity: .5; }
    .shop-card-icon { font-size: 26px; text-align: center; margin-bottom: 4px; }
    .shop-card-name { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: var(--ink); margin-bottom: 4px; }
    .shop-card-desc { font-size: 12px; color: #5b3412; margin-bottom: 8px; }
    .shop-card-price { display: flex; align-items: center; justify-content: space-between; }
    /* Neon gold on a cream card was 2.03:1, on 31 price labels. #b45309 is the gold-value
       tone `.inv-capacity-hint strong` and `.lb-pb-chip b` already use. */
    .shop-card-cost { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 12px; color: #b45309; }
    .shop-buy-btn {
      background: linear-gradient(180deg, var(--neon-gold), #d4a017);
      border: none; border-radius: 4px; padding: 6px 14px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #0f172a;
      cursor: pointer; transition: filter .15s, transform .1s;
    }
    .shop-buy-btn:hover { filter: brightness(1.15); transform: translateY(-1px); }
    .shop-buy-btn:disabled { opacity: .4; cursor: default; }
    .shop-owned-badge { font-size: 14px; color: #14532d; font-weight: 800; }

    /* ── FISH ALBUM OVERLAY ──────────────────────────────────────────────── */
    #fish-album-overlay {
      position: fixed; inset: 0; z-index: 520; display: none;
      background: var(--farm-veil); backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #fish-album-overlay.visible { display: flex; }
    #fish-album-panel {
      background: linear-gradient(180deg, #f6deaa, #e8c07a);
      border: 4px solid #8b5a2b; border-radius: 8px; padding: 16px;
      max-width: 680px; width: 94%; max-height: 86vh; overflow-y: auto;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      position: relative; color: var(--ink);
    }
    #fish-album-header {
      display: flex; align-items: center; gap: 12px; margin-bottom: 18px; padding-bottom: 12px;
      border-bottom: 1px solid rgba(56, 189, 248, 0.3);
    }
    #fish-album-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; color: #7a3e12; }
    #fish-album-sub { font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 4px; }
    #fish-album-close-btn {
      margin-left: auto; background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 4px 10px; font-size: 16px;
      cursor: pointer; transition: background .15s, border-color .15s, color .15s;
    }
    #fish-album-close-btn:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }
    #fish-album-close-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }
    #fish-album-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }
    .fish-card {
      background: #fff8e8; border: 1.5px solid #c4893a;
      border-radius: 6px; padding: 10px; text-align: center; transition: transform .15s;
    }
    .fish-card.unlocked { border-color: #0e7490; }
    .fish-card.locked { opacity: .5; filter: grayscale(1); }
    .fish-card:hover { transform: translateY(-2px); }
    .fish-card-icon { font-size: 28px; margin-bottom: 4px; }
    .fish-card-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 18px; font-weight: bold; color: var(--ink); }

    .fish-card-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 2px; }
    .fish-card-catches { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #b45309; margin-top: 8px; }

    /* ── TROPHIES ────────────────────────────────────────────────────────── */
    #trophy-overlay {
      position: fixed; inset: 0; z-index: 800; background: var(--farm-veil); backdrop-filter: blur(8px);
      -webkit-backdrop-filter: var(--glass-blur);
      display: none; align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #trophy-overlay.visible { display: flex; }
    #trophy-overlay #trophy-panel {
      background: #f7efd9; color: #44331e; border: 2px solid #987049; border-radius: 16px;
      max-width: 1080px; width: 94% !important; max-height: 90vh !important; max-height: 90dvh !important;
      padding: 0 !important; overflow-y: auto; position: relative; scrollbar-color: #bda27e #f7efd9;
      box-shadow: 0 0 0 5px rgba(247,239,217,.15), 0 22px 80px rgba(25,30,14,.5);
    }
    #trophy-panel::before { opacity: .35; }
    #trophy-panel #trophy-header { display:flex; align-items:center; justify-content:space-between; gap:16px; padding:24px 28px 20px; margin:0; background:#fbf6e9; border-bottom:1px solid #dac8a8; position:sticky; top:0; z-index:5; }
    .trophy-eyebrow { display:flex; align-items:center; gap:8px; font-size:10px; font-weight:800; letter-spacing:1.8px; color:#8a7050; margin-bottom:8px; }
    .trophy-eyebrow > span:first-child { color:#c8b79c; }
    #trophy-title { display:flex; align-items:center; gap:10px; font-size:25px; line-height:1.2; font-weight:900; color:#3d3822; }
    .trophy-subtitle { font-size:12px; color:#8a7050; margin-top:7px; }
    .trophy-header-actions { display:flex; align-items:center; gap:12px; flex-shrink:0; }
    #trophy-gold-badge { display:flex; align-items:center; gap:6px; background:#fff1c7; border:1px solid #dec48c; border-radius:20px; padding:8px 14px; font-size:13px; font-weight:800; color:#855616; }
    #trophy-close-btn { width:38px; height:38px; padding:0; border:1px solid #d8c5a5; border-radius:10px; background:#f1e6cf; color:#695333; font-size:17px; }
    .trophy-content { padding:24px 28px; }
    #trophy-journey { display:grid; grid-template-columns:110px minmax(0,1fr) 148px; gap:22px; align-items:center; padding:22px 26px; margin-bottom:24px; border:1px solid #587254; border-radius:12px; background:radial-gradient(ellipse at 12% 30%, #53714b 0, transparent 60%), #304e37; color:#fff7df; box-shadow:inset 0 1px 0 #6c8560,0 3px 0 #263f2d; }
    .trophy-journey-art { display:flex; justify-content:center; align-items:center; min-height:112px; background:radial-gradient(circle,#e7c27625,transparent 68%); filter:drop-shadow(0 7px 8px #17291f55); }
    .trophy-journey-kicker { font-size:9px; font-weight:800; letter-spacing:2px; color:#d7bd79; text-transform:uppercase; margin-bottom:8px; }
    .trophy-journey-copy h3 { font-size:21px; font-weight:800; line-height:1.3; margin-bottom:8px; }
    .trophy-journey-copy p { color:#c9d7bd; font-size:12px; line-height:1.6; max-width:420px; }
    #trophy-next-goal { display:flex; align-items:center; flex-wrap:wrap; gap:6px; margin-top:13px; border:0; background:transparent; color:#d7dcca; font-size:11px; text-align:left; cursor:pointer; padding:6px 0; min-height:32px; }
    #trophy-next-goal strong { color:#ffe2a0; font-weight:700; }
    #trophy-next-goal > span { color:#e5ca86; margin-left:4px; }
    .trophy-journey-stats { padding-left:20px; border-left:1px solid #698060; }
    .trophy-collection-total { display:flex; flex-direction:column; gap:5px; }
    .trophy-collection-total > strong { font-size:34px; color:#ffe5a2; line-height:1; }
    .trophy-collection-total > strong span { font-size:16px; font-weight:600; color:#aebfa0; }
    .trophy-collection-total > span { font-size:11px; color:#d0dbbf; }
    .trophy-collection-track { margin:12px 0 8px; height:5px; border-radius:4px; background:#1f3929; overflow:hidden; }
    .trophy-collection-track > span { display:block; height:100%; background:#e9c976; border-radius:inherit; }
    .trophy-ready-total { font-size:10px; color:#dcc78e; }
    .trophy-toolbar { margin-bottom:18px; }
    .trophy-tabs { display:flex; flex-wrap:wrap; gap:7px; padding-bottom:16px; border-bottom:1px solid #d9c8a9; }
    .trophy-tab { display:flex; align-items:center; justify-content:center; gap:8px; border:1px solid #d9c7a5; border-radius:7px; background:#fcf8ed; color:#806645; padding:10px 14px; min-height:42px; cursor:pointer; font-size:12px; font-weight:700; }
    .trophy-tab > span { display:inline-flex; align-items:center; justify-content:center; min-width:20px; height:19px; padding:0 4px; font-size:10px; border-radius:4px; background:#ece2cd; color:#8a7252; }
    .trophy-tab:hover { border-color:#8a9d76; }
    .trophy-tab.active { background:#3d5739; border-color:#3d5739; color:#fff4d9; box-shadow:0 2px 0 #283b26; }
    .trophy-tab.active > span { background:#ffffff20; color:#e6e9d3; }
    .trophy-view-controls { display:flex; align-items:center; gap:8px; padding-top:14px; color:#8a7252; font-size:11px; }
    #trophy-result-count { margin-right:auto; }
    #trophy-status-filter { padding:8px 28px 8px 10px; border:1px solid #d9c7a5; border-radius:6px; background:#fcf8ed; color:#655038; font-size:11px; min-height:36px; max-width:190px; }
    #trophy-grid { display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:14px; }
    .trophy-card { --trophy-accent:#a9754b; --trophy-tint:#efe0cb; --trophy-metal:#9f7049; background:#fdf9ee; border:1px solid #d4c2a4; border-radius:10px; padding:14px; position:relative; overflow:hidden; display:flex; flex-direction:column; min-width:0; box-shadow:0 3px 0 #b8a38245; transition:transform .15s,border-color .15s; }
    .trophy-card:hover { transform:translateY(-3px); border-color:var(--trophy-accent); }
    .trophy-tier-silver { --trophy-accent:#738994; --trophy-tint:#e3e9e7; --trophy-metal:#58737e; }
    .trophy-tier-gold { --trophy-accent:#c39a3b; --trophy-tint:#f5eac8; --trophy-metal:#9a701c; }
    .trophy-tier-diamond { --trophy-accent:#708faa; --trophy-tint:#dfebf0; --trophy-metal:#486c90; }
    .trophy-tier-legend { --trophy-accent:#907194; --trophy-tint:#eadee9; --trophy-metal:#77527e; }
    .trophy-card.unlocked { border-color:#89a273; background:#f8f9ec; }
    .trophy-card.ready { border-color:#c5a24f; box-shadow:0 0 0 1px #d8b76466,0 3px 0 #b8a38245; }
    .trophy-card-top { display:flex; align-items:center; justify-content:space-between; gap:6px; font-size:9px; }
    .trophy-tier-label { color:var(--trophy-metal); font-weight:800; text-transform:uppercase; letter-spacing:1px; }
    .trophy-card-state { color:#907c5e; font-size:9px; background:#f0e7d5; padding:4px 6px; border-radius:4px; white-space:nowrap; }
    .ready .trophy-card-state { background:#f7e9ba; color:#8b671a; }
    .unlocked .trophy-card-state { background:#e7edda; color:#52713b; }
    .trophy-pedestal { display:flex; flex-direction:column; align-items:center; justify-content:center; height:127px; margin:8px 0 11px; border-radius:6px; background:radial-gradient(ellipse at 50% 45%,var(--trophy-tint),transparent 70%); position:relative; }
    .trophy-icon { line-height:1; min-height:88px; display:flex; align-items:center; justify-content:center; z-index:1; filter:drop-shadow(0 4px 2px #7b613826); }
    .trophy-icon img, .trophy-icon svg, .trophy-art-icon { width:88px; height:88px; object-fit:contain; image-rendering:pixelated; image-rendering:crisp-edges; }
    .trophy-pedestal-base { width:104px; height:8px; margin-top:3px; border-top:2px solid #cbb896; border-bottom:3px solid #b5a080; border-radius:3px; background:#dfceb0; box-shadow:0 5px 7px #b7a38825; }
    .locked .trophy-icon { opacity:.85; }
    .trophy-card-copy { flex:1; }
    .trophy-category-label { font-size:9px; text-transform:uppercase; letter-spacing:1px; font-weight:700; color:#9a8461; margin-bottom:7px; }
    .trophy-name { font-size:14px; line-height:1.55; font-weight:800; color:#4c3c24; margin:0 0 7px; overflow-wrap:anywhere; }
    .trophy-description { font-size:11px; line-height:1.7; color:#887251; margin-bottom:15px; }
    .trophy-progress-caption { display:flex; align-items:center; justify-content:space-between; font-size:10px; color:#947e5c; margin-bottom:6px; }
    .trophy-progress-caption strong { color:#6d6245; font-weight:800; }
    .trophy-progress-track { height:5px; border-radius:4px; background:#e9dfcb; overflow:hidden; }
    .trophy-progress-track > span { display:block; height:100%; border-radius:inherit; background:var(--trophy-accent); }
    .unlocked .trophy-progress-track > span { background:#7b995e; }
    .trophy-requirements { margin:9px 0 13px; display:flex; flex-direction:column; gap:5px; }
    .trophy-requirement { display:flex; align-items:baseline; justify-content:space-between; gap:6px; font-size:10px; line-height:1.5; color:#8b7654; }
    .trophy-requirement > span { min-width:0; }
    .trophy-requirement strong { white-space:nowrap; color:#665436; font-weight:700; }
    .trophy-requirement strong > span { color:#aa9677; font-weight:500; }
    .trophy-requirement.met strong { color:#5c7a42; }
    .trophy-buy-btn { display:flex; align-items:center; justify-content:center; gap:4px; background:#3f5c3c; border:1px solid #31482e; border-radius:6px; padding:9px 6px; width:100%; min-height:40px; font-size:11px; font-weight:800; color:#fff6de; cursor:pointer; transition:background .15s; }
    .trophy-buy-btn:hover { background:#4f7149; }
    .trophy-buy-btn:disabled { background:#eee6d7; border-color:#e3d8c3; color:#907c5c; cursor:default; font-weight:500; }
    .trophy-unlocked-badge { display:flex; justify-content:center; align-items:center; gap:7px; min-height:44px; border:1px solid #c3d2b4; border-radius:6px; background:#edf1df; color:#57753e; font-size:11px; font-weight:700; }
    .trophy-empty { grid-column:1/-1; text-align:center; padding:40px 20px; color:#8a7353; border:1px dashed #ceb996; border-radius:10px; background:#fcf7ea; }
    .trophy-empty > span { font-size:36px; color:#b89a59; }
    .trophy-empty h3 { font-size:15px; margin:8px 0; }
    .trophy-empty p { font-size:12px; line-height:1.6; }
    .trophy-footnote { margin-top:20px; text-align:center; font-size:10px; line-height:1.8; color:#958263; }
    #trophy-panel button:focus-visible, #trophy-panel select:focus-visible, .trophy-card:focus-visible { outline:3px solid #ab7b34; outline-offset:3px; }
    @media (max-width:1000px) { #trophy-grid { grid-template-columns:repeat(3,minmax(0,1fr)); } }
    @media (max-width:700px) {
      #trophy-panel #trophy-header { padding:18px; gap:10px; }
      .trophy-content { padding:18px; }
      #trophy-title { font-size:21px; }
      .trophy-eyebrow { font-size:8px; letter-spacing:1px; }
      .trophy-subtitle { font-size:11px; }
      .trophy-header-actions { gap:8px; }
      #trophy-gold-badge { padding:6px 9px; font-size:11px; }
      #trophy-journey { grid-template-columns:76px minmax(0,1fr); padding:18px 16px; gap:14px; }
      .trophy-journey-art { min-height:85px; }
      .trophy-journey-art svg, .trophy-journey-art img { width:80px; height:80px; }
      .trophy-journey-copy h3 { font-size:17px; }
      .trophy-journey-stats { grid-column:1/-1; display:flex; align-items:center; gap:14px; border-left:0; border-top:1px solid #698060; padding:14px 0 0; }
      .trophy-collection-total { flex-direction:row; align-items:center; gap:10px; }
      .trophy-collection-total > strong { font-size:23px; }
      .trophy-collection-total > strong span { font-size:12px; }
      .trophy-collection-track { flex:1; margin:0; }
      .trophy-ready-total { white-space:nowrap; }
      #trophy-grid { grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; }
      .trophy-tab { font-size:11px; padding:9px 10px; gap:5px; }
    }
    @media (max-width:430px) {
      #trophy-panel #trophy-header { padding:14px 12px; align-items:flex-start; }
      .trophy-content { padding:14px 12px; }
      .trophy-heading { min-width:0; }
      #trophy-title { font-size:19px; }
      .trophy-eyebrow { gap:5px; font-size:7px; }
      .trophy-header-actions { gap:6px; }
      #trophy-close-btn { width:32px; height:34px; }
      #trophy-journey { padding:15px 12px; gap:10px; }
      .trophy-journey-kicker { font-size:8px; letter-spacing:1px; }
      .trophy-journey-copy p { font-size:11px; }
      .trophy-collection-total > span { display:none; }
      #trophy-grid { gap:10px; }
      .trophy-card { padding:11px 9px; }
      .trophy-card-top { flex-wrap:wrap; gap:5px; }
      .trophy-name { font-size:12px; }
      .trophy-pedestal { height:110px; }
      .trophy-requirement { flex-wrap:wrap; gap:0 5px; }
      .trophy-requirement strong { margin-left:auto; }
      .trophy-view-controls label { display:none; }
      .trophy-tab { flex:1 0 auto; }
    }
    @media (prefers-reduced-motion:reduce) { .trophy-card { transition:none; } .trophy-card:hover { transform:none; } }

    /* Shop / boss-gate multiple-choice buttons (kept after Spell Duel was removed). */
    .duel-option-btn {
      background: rgba(30, 27, 75, 0.8); border: 1.5px solid var(--neon-purple);
      border-radius: 8px; padding: 14px 12px; color: #fff; cursor: pointer;
      font-family: 'Be Vietnam Pro', 'Noto Sans KR', sans-serif; font-size: 16px; font-weight: 700;
      display: flex; align-items: center; justify-content: space-between; transition: all .15s;
    }
    .duel-option-btn:hover { background: rgba(50, 45, 110, 0.9); border-color: var(--neon-purple); transform: translateY(-2px); box-shadow: 0 0 16px rgba(192, 132, 252, 0.4); }
    .duel-option-btn.correct { background: rgba(22, 101, 52, 0.9) !important; border-color: var(--neon-green) !important; color: #fff !important; }
    .duel-option-btn.wrong { background: rgba(153, 27, 27, 0.9) !important; border-color: var(--neon-pink) !important; color: #fff !important; opacity: .75; }

    /* ── MEMORY MINIGAME ─────────────────────────────────────────────────── */
    #memory-overlay {
      position: fixed; inset: 0; z-index: 750; background: rgba(29, 24, 15, .83);
      backdrop-filter: var(--glass-blur); -webkit-backdrop-filter: var(--glass-blur);
      display: flex; align-items: center; justify-content: center; padding: 12px;
      opacity: 0; pointer-events: none; transition: opacity .2s;
    }
    #memory-overlay.visible { opacity: 1; visibility: visible; pointer-events: auto; }
    #memory-panel {
      width: min(100%, 650px); max-height: calc(100vh - 24px); max-height: calc(100dvh - 24px);
      overflow-y: auto; overscroll-behavior: contain; padding: 24px;
      background: #fff5df; color: #513d2b; border: 3px solid #98704b; border-radius: 20px;
      box-shadow: 0 5px 0 #5d422c, 0 22px 70px rgba(0,0,0,.42);
      font-family: 'Be Vietnam Pro', 'Noto Sans KR', sans-serif;
    }
    #memory-panel [hidden] { display: none !important; }
    #memory-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
    .pm-eyebrow { color: #75844e; font-size: 10px; font-weight: 800; letter-spacing: .13em; }
    #memory-title { margin: 6px 0; color: #594127; font-size: clamp(21px, 4.8vw, 29px); font-weight: 850; line-height: 1.25; }
    #memory-instructions { margin: 0; color: #826950; font-size: 13px; line-height: 1.65; }
    #memory-pool { margin: 10px 0 0; color: #667a50; font-size: 12px; line-height: 1.5; }
    #memory-close-btn {
      flex: 0 0 44px; width: 44px; height: 44px; border: 1px solid #c8ae83;
      border-radius: 12px; background: #f4e5c6; color: #725333; font-size: 18px; cursor: pointer;
    }
    #memory-stats { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px;
      margin: 16px 0 0; padding: 12px 14px; background: #eaf0d9; border: 1px solid #bcc99b;
      border-radius: 12px; color: #4c683a; font-size: 14px; font-weight: 750; }
    #memory-status { min-height: 38px; margin: 8px 0 4px; font-size: 12px; line-height: 1.6; color: #786048; }
    #memory-column-labels { display: grid; grid-template-columns: minmax(0, 1fr) 64px minmax(0, 1fr);
      margin: 0 0 9px; font-size: 11px; font-weight: 800; color: #8b7152; }
    #memory-column-labels span:last-child { grid-column: 3; text-align: center; }
    #memory-column-labels span:first-child { text-align: center; }
    #memory-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) 64px minmax(0, 1fr); }
    #memory-words, #memory-pictures { display: grid; grid-template-rows: subgrid; grid-row: 1 / span 5; gap: 10px; min-width: 0; }
    #memory-grid { grid-template-rows: repeat(5, minmax(78px, auto)); row-gap: 10px; }
    #memory-words { grid-column: 1; }
    #memory-pictures { grid-column: 3; }
    #memory-connections { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
    .pm-line { fill: none; stroke: #7e9e54; stroke-width: 3; stroke-linecap: round; }
    .pm-line.is-wrong { stroke: #c96954; stroke-dasharray: 5 5; }
    .pm-tile { position: relative; width: 100%; min-width: 0; height: 100%; padding: 7px 10px;
      display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
      border: 2px solid #cbb68e; border-radius: 13px; background: #fffcf2; color: #513d2b;
      box-shadow: 0 3px 0 #dfcfaf; cursor: pointer; font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif;
      font-size: 23px; font-weight: 750; line-height: 1.25; overflow-wrap: anywhere;
      transition: background .15s, border-color .15s, transform .15s; }
    .pm-tile:hover:not(:disabled) { background: #fff1c8; border-color: #b3935f; }
    .pm-tile.is-selected { background: #ffe7ab; border-color: #aa7f33; transform: translateY(-2px); }
    .pm-tile.is-selected::after { content: '●'; position: absolute; top: 4px; right: 7px; font-size: 10px; color: #aa7f33; }
    .pm-tile.is-matched { background: #eaf0db; border-color: #8ba765; box-shadow: 0 3px 0 #bccb9c; cursor: default; color: #436237; }
    .pm-tile.is-matched::after { content: '✓'; position: absolute; top: 4px; right: 6px; font-size: 13px; color: #56763f; }
    .pm-tile.is-wrong { background: #fae0d2; border-color: #c96954; }
    .pm-tile.is-wrong::after { content: '×'; position: absolute; top: 2px; right: 7px; font-size: 17px; color: #a74d3b; }
    .pm-image img { width: 70px; height: 70px; max-width: 100%; object-fit: contain;
      image-rendering: pixelated; user-select: none; pointer-events: none; }
    .pm-meaning { font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; font-weight: 600;
      max-width: 100%; line-height: 1.4; color: #667a50; }
    #memory-result { margin-top: 18px; padding: 16px; background: #eaf0d9; border: 1px solid #b5c393; border-radius: 14px; }
    #memory-result h3 { margin: 0; color: #4c683a; font-size: 19px; }
    #memory-result p { margin: 7px 0 13px; font-size: 13px; line-height: 1.6; }
    .pm-result-actions { display: flex; flex-wrap: wrap; gap: 9px; }
    .pm-action { min-height: 44px; padding: 11px 16px; border: 1px solid #526f3b; border-radius: 10px;
      background: #64854a; color: #fffdf0; font: 700 12px 'Be Vietnam Pro', sans-serif; cursor: pointer; }
    .pm-action-secondary { background: #fff6e1; color: #695236; border-color: #c5ad82; }
    #memory-retry-btn { margin-top: 12px; }
    #memory-panel button:focus-visible { outline: 3px solid #678da0; outline-offset: 3px; }
    @media (max-width: 520px) {
      #memory-panel { padding: 16px 13px; border-radius: 17px; }
      #memory-title { font-size: 22px; }
      #memory-instructions { font-size: 11px; }
      #memory-stats { font-size: 12px; padding: 10px; }
      #memory-column-labels, #memory-grid { grid-template-columns: minmax(0, 1fr) 40px minmax(0, 1fr); }
      #memory-grid { grid-template-rows: repeat(5, minmax(74px, auto)); row-gap: 9px; }
      #memory-words, #memory-pictures { gap: 9px; }
      .pm-tile { padding: 5px 6px; font-size: 19px; border-radius: 11px; }
      .pm-image img { width: 62px; height: 62px; }
      .pm-meaning { font-size: 9px; }
      #memory-result { padding: 12px; }
      .pm-result-actions .pm-action { flex: 1; }
    }
    @media (prefers-reduced-motion: reduce) {
      #memory-overlay, .pm-tile { transition: none; }
    }

    /* ── VOCABULARY DETAIL · FULL-SCREEN STUDY PAGE ─────────────────────── */
    #vocab-ff-modal {
      position: fixed; inset: 0; z-index: 600; display: none;
      background: #2a1a0a; align-items: stretch; justify-content: stretch;
      animation: fadeIn .18s;
    }
    #vocab-ff-modal.visible { display: flex; }
    #vff-inner {
      position: relative; display: flex; flex-direction: column;
      width: 100%; height: 100vh; height: 100dvh; max-width: none; max-height: none;
      overflow: hidden; border: 0; border-radius: 0;
      background:
        radial-gradient(circle at 80% 6%, rgba(255,255,255,.28), transparent 22%),
        linear-gradient(180deg, #f8e8c3 0%, #efd39a 100%);
      color: #241407; box-shadow: inset 0 0 0 3px #8b5a2b;
    }
    #vff-header {
      min-height: 62px; flex-shrink: 0; display: grid;
      grid-template-columns: minmax(180px, 1fr) auto minmax(260px, 1fr);
      align-items: center; gap: 16px; padding: 10px clamp(16px, 3vw, 44px);
      background: linear-gradient(180deg, #5b3412, #3f230d);
      border-bottom: 3px solid #c4893a; box-shadow: 0 4px 14px rgba(42,26,10,.28);
    }
    #vff-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px;
      color: #f6deaa; text-transform: uppercase; text-align: center;
    }
    #vff-header button {
      min-height: 38px; background: #fff3d6; border: 1.5px solid #d9b072;
      color: #4a2a0d; border-radius: 8px; padding: 7px 12px;
      font-size: 13px; font-weight: 800; cursor: pointer;
      transition: background .15s, transform .15s, opacity .15s;
    }
    #vff-header button:hover:not(:disabled) { background: #fffaf0; transform: translateY(-1px); }
    #vff-header button:focus-visible { outline: 3px solid #86efac; outline-offset: 2px; }
    #vff-header button:disabled { opacity: .4; cursor: default; }
    #vff-back-btn { justify-self: start; }
    #vff-nav { justify-self: end; display: flex; align-items: center; gap: 7px; }
    #vff-nav-position { min-width: 88px; color: #f6deaa; font-size: 12px; text-align: right; }
    #vff-prev-btn, #vff-next-btn, #vff-header-close { width: 40px; padding: 7px 0 !important; }
    #vff-header-close { margin-left: 4px; color: #991b1b !important; background: #fee2e2 !important; border-color: #fca5a5 !important; }

    #vff-scroll { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; }
    #vff-scroll::-webkit-scrollbar { width: 10px; }
    #vff-scroll::-webkit-scrollbar-track { background: rgba(139,90,43,.14); }
    #vff-scroll::-webkit-scrollbar-thumb { background: #8b5a2b; border: 2px solid #efd39a; border-radius: 9px; }
    #vff-word-row {
      display: grid; grid-template-columns: 208px minmax(0, 1fr) minmax(220px, 300px);
      align-items: center; gap: clamp(18px, 3vw, 42px);
      padding: clamp(22px, 3vw, 42px) clamp(18px, 5vw, 76px);
      background: rgba(255,250,240,.68); border-bottom: 2px dashed #c4893a;
    }
    #vff-emoji {
      width: 208px; height: 208px; flex-shrink: 0; display: flex;
      align-items: center; justify-content: center; font-size: 86px;
      background: #fffdf7; border: 2px solid #c4893a; border-radius: 18px;
      box-shadow: inset 0 1px #fff, 0 5px 0 #8b5a2b, 0 14px 24px rgba(91,52,18,.13);
    }
    /* The one screen in the app whose whole job is to show the picture, and it was
       the one painting a 192px illustration at 96px inside a 150px frame — half the
       artwork, and 54px of frame left empty to do it. */
    #vff-emoji img.vocab-art-icon {
      width: auto; max-width: 100%; height: 192px;
      image-rendering: pixelated; image-rendering: crisp-edges; object-fit: contain;
    }
    .vff-word-copy { min-width: 0; }
    #vff-ko-row { display: flex; align-items: center; flex-wrap: wrap; gap: 9px; }
    #vff-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: clamp(40px, 4.5vw, 68px);
      font-weight: 900; color: #241407; line-height: 1.12; word-break: keep-all;
    }
    .vff-audio-btn {
      width: 44px; height: 40px; padding: 0; font-size: 18px;
      color: #14532d; background: #ecfdf5; border: 1.5px solid #4d9366;
    }
    #vff-romanization {
      margin-top: 5px; color: #7a3e12; font-size: 16px; font-weight: 750;
      letter-spacing: .3px; font-style: italic;
    }
    #vff-en {
      margin-top: 10px; font-size: clamp(19px, 2vw, 28px); font-weight: 800;
      line-height: 1.3; color: #5b3412; font-family: 'Be Vietnam Pro', sans-serif;
    }
    #vff-cat {
      display: inline-flex; margin-top: 10px; padding: 5px 10px; border-radius: 999px;
      background: #dcfce7; border: 1px solid #4d9366; color: #14532d;
      font-size: 12px; font-weight: 800;
    }
    #vff-status {
      min-width: 0; padding: 17px 18px; text-align: left;
      background: #fff8e8; border: 2px solid #d6a45e; border-radius: 12px;
      box-shadow: inset 0 1px #fff, 0 3px 0 #b9792c;
    }
    .vff-status-label {
      margin-bottom: 7px; color: #7a3e12; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust);
      font-size: 8px; line-height: 1.4; text-transform: uppercase;
    }
    #vff-phase { color: #166534; font-size: 17px; font-weight: 900; line-height: 1.35; }
    #vff-harvests { color: #6b3d14; font-size: 12px; line-height: 1.55; margin-top: 4px; }

    #vff-content-grid {
      width: min(1440px, 100%); margin: 0 auto; padding: 24px clamp(16px, 3vw, 42px) 34px;
      display: grid; grid-template-columns: minmax(0, 2fr) minmax(310px, .85fr);
      gap: 20px; align-items: start;
    }
    #vff-main-content, #vff-side-content { display: grid; gap: 16px; min-width: 0; }
    .vff-section {
      padding: 20px; background: rgba(255,253,247,.86);
      border: 1.5px solid #d6a45e; border-radius: 12px;
      box-shadow: 0 3px 0 rgba(139,90,43,.55), 0 8px 18px rgba(91,52,18,.08);
    }
    .vff-section-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; line-height: 1.5;
      color: #6b3d14; margin-bottom: 13px; text-transform: uppercase;
    }
    .vff-fact-text {
      font-size: 15px; line-height: 1.72; color: #3f2a16;
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    #vff-overview-grid {
      display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px;
    }
    .vff-overview-item {
      min-width: 0; padding: 12px; background: #fff8e8;
      border: 1px solid #d9b072; border-radius: 8px;
    }
    .vff-overview-item span {
      display: block; margin-bottom: 5px; color: #8b5a2b; font-size: 10px;
      font-weight: 800; text-transform: uppercase; letter-spacing: .35px;
    }
    .vff-overview-item strong {
      display: block; color: #3f230d; font-size: 14px; line-height: 1.4;
      overflow-wrap: anywhere;
    }
    .vff-example-card {
      background: linear-gradient(135deg, #eff6ff, #e0f2fe);
      border: 1.5px solid #60a5fa; border-radius: 10px; padding: 16px;
    }
    #vff-example-row { display: flex; align-items: flex-start; gap: 12px; }
    #vff-fact-example {
      flex: 1; min-width: 0; font-family: 'Noto Sans KR', sans-serif;
      font-size: 21px; font-weight: 800; color: #172554; line-height: 1.55;
      word-break: keep-all; overflow-wrap: anywhere;
    }
    #vff-example-speak { flex-shrink: 0; color: #1e3a8a; border-color: #60a5fa; background: #dbeafe; }
    #vff-example-en { margin-top: 8px; color: #1e3a5f; font-size: 14px; font-weight: 550; line-height: 1.55; }
    #vff-example-en:empty { display: none; }
    .vff-chip-row { display: flex; flex-wrap: wrap; gap: 8px; }
    .vff-study-chip {
      display: inline-flex; align-items: center; min-height: 34px; padding: 5px 10px;
      border: 1px solid #d6a45e; border-radius: 8px; background: #fff3d6;
      color: #4a2a0d; font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif;
      font-size: 14px; font-weight: 800;
    }
    #vff-syllable-grid { display: flex; align-items: stretch; flex-wrap: wrap; gap: 10px; }
    .vff-syllable-card {
      min-width: 104px; padding: 12px 10px; text-align: center;
      background: #fff8e8; border: 1.5px solid #b9792c; border-radius: 10px;
    }
    .vff-syllable-char {
      display: block; font-family: 'Noto Sans KR', sans-serif; font-size: 34px;
      font-weight: 900; line-height: 1.1; color: #241407;
    }
    .vff-syllable-jamo {
      display: block; margin-top: 7px; color: #6b3d14; font-size: 13px;
      font-family: 'Noto Sans KR', sans-serif; font-weight: 750;
    }
    .vff-syllable-roman { display: block; margin-top: 4px; color: #166534; font-size: 11px; font-weight: 800; }
    .vff-structure-note { margin-top: 11px; color: #6b3d14; font-size: 13px; line-height: 1.55; }
    .vff-romanization-note {
      margin-top: 8px; padding: 9px 11px; color: #713f12; background: #fef3c7;
      border-left: 4px solid #d97706; border-radius: 6px; font-size: 12px; line-height: 1.55;
    }
    .vff-study-note { padding-left: 14px; border-left: 4px solid #16a34a; }

    #vff-skill-grid { display: grid; gap: 9px; }
    .vff-skill-card {
      display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: center;
      padding: 11px; background: #fff8e8; border: 1px solid #d9b072; border-radius: 9px;
    }
    .vff-skill-icon { width: 32px; height: 32px; display: grid; place-items: center; font-size: 20px; }
    .vff-skill-name { color: #4a2a0d; font-size: 12px; font-weight: 900; }
    .vff-skill-state { margin-top: 2px; color: #7a3e12; font-size: 11px; line-height: 1.45; }
    #vff-category-hint { padding-left: 13px; border-left: 4px solid #d97706; }
    #vff-related-grid { display: grid; gap: 8px; }
    .vff-related-word {
      width: 100%; min-width: 0; display: grid; grid-template-columns: 42px minmax(0, 1fr) auto;
      align-items: center; gap: 9px; padding: 8px 9px; text-align: left;
      background: #fff8e8; border: 1px solid #d9b072; border-radius: 8px;
      color: #4a2a0d; cursor: pointer; transition: border-color .15s, transform .15s, background .15s;
    }
    .vff-related-word:hover { background: #ecfdf5; border-color: #4d9366; transform: translateX(2px); }
    .vff-related-word:focus-visible { outline: 3px solid rgba(22,101,52,.35); outline-offset: 1px; }
    .vff-related-art { width: 42px; height: 42px; display: grid; place-items: center; font-size: 24px; }
    .vff-related-art img.vocab-art-icon { width: auto; max-width: 42px; height: 40px; }
    .vff-related-copy { min-width: 0; }
    .vff-related-ko { display: block; font-family: 'Noto Sans KR', sans-serif; font-size: 17px; font-weight: 900; }
    .vff-related-en { display: block; margin-top: 1px; color: #7a3e12; font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .vff-related-arrow { color: #166534; font-weight: 900; }
    .vff-related-empty { color: #7a3e12; font-size: 12px; line-height: 1.5; }

    #vff-detail-footer {
      display: flex; align-items: center; justify-content: space-between; gap: 16px;
      padding: 0 clamp(16px, 3vw, 42px) 42px; width: min(1440px, 100%); margin: 0 auto;
      color: #6b3d14; font-size: 12px;
    }
    #vff-close-btn {
      min-height: 46px; margin: 0; padding: 10px 18px;
      background: linear-gradient(180deg, #4ade80, #22c55e);
      border: 2px solid #166534; border-radius: 9px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 14px; font-weight: 900;
      color: #052e16; cursor: pointer; box-shadow: 0 3px 0 #166534;
      transition: filter .15s, transform .15s;
    }
    #vff-close-btn:hover { filter: brightness(1.06); transform: translateY(-1px); }

    /* ── CAT NPC DIALOG ──────────────────────────────────────────────────── */
    #cat-dialog {
      position: fixed; inset: 0; z-index: 490; display: none;
      background: rgba(15, 5, 15, 0.85); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: flex-end; justify-content: center;
      padding-bottom: 40px; animation: fadeIn .18s;
    }
    #cat-dialog.visible { display: flex; }
    #cat-dialog-inner {
      background: rgba(35, 15, 25, 0.92);
      border: 2px solid var(--neon-pink); border-radius: 8px;
      padding: 0; max-width: 720px; width: 96%;
      box-shadow: 0 0 0 2px #0f172a, var(--glow-pink), 0 20px 60px rgba(0,0,0,.9);
      position: relative;
    }
    #cat-dialog-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 10px 18px; background: rgba(244, 63, 94, 0.12);
      border-bottom: 1px solid rgba(244, 63, 94, 0.2);
    }
    #cat-dialog-name { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 12px; color: var(--neon-pink); }
    #cat-dialog-close {
      background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.2);
      color: #fff; border-radius: 4px; padding: 4px 10px; font-size: 14px; cursor: pointer;
    }
    #cat-dialog-body { display: flex; gap: 0; align-items: center; min-height: 190px; }
    #cat-portrait-wrap {
      flex-shrink: 0; width: 140px;
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      padding: 16px 8px 16px 12px;
      background: rgba(244, 63, 94, 0.05);
      border-right: 1px solid rgba(244, 63, 94, 0.15); position: relative;
    }
    #cat-portrait-canvas {
      image-rendering: pixelated; image-rendering: crisp-edges;
      width: 108px; height: 162px; display: block;
      filter: drop-shadow(0 6px 14px rgba(0,0,0,.7));
      animation: catBob 2s ease-in-out infinite;
    }
    #cat-speech-tail { display: none; }
    #cat-word-wrap { flex: 1; padding: 18px 20px 14px 18px; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
    #cat-dialog-label { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: rgba(226, 232, 240, 0.4); margin-bottom: 10px; text-transform: uppercase; letter-spacing: 1px; }
    #cat-dialog-emoji-word { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; }
    #cat-emoji { font-size: 42px; flex-shrink: 0; }
    #cat-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 38px; font-weight: 900; color: #fff; text-shadow: 0 0 12px rgba(244, 63, 94, 0.5); line-height: 1.2; }
    #cat-en { font-size: 20px; color: var(--neon-gold); font-weight: 700; font-family: 'Be Vietnam Pro', sans-serif; margin-top: 3px; }
    #cat-dialog-tip {
      font-size: 15px; color: rgba(226, 232, 240, 0.85);
      font-family: 'Be Vietnam Pro', sans-serif; line-height: 1.65; padding: 9px 12px;
      background: rgba(244, 63, 94, 0.08); border-radius: 4px; border-left: 3px solid rgba(244, 63, 94, 0.5);
    }
    #cat-dialog-footer { display: flex; gap: 8px; padding: 10px 16px; border-top: 1px solid rgba(255, 255, 255, 0.08); }
    #cat-another-btn, #cat-close-btn2 {
      flex: 1; border-radius: 8px; padding: 10px 8px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 15px; font-weight: 800; cursor: pointer; transition: all .15s; white-space: nowrap;
    }
    #cat-another-btn { background: rgba(30, 41, 59, 0.8); border: 1.5px solid var(--neon-pink); color: #fff; }
    #cat-another-btn:hover { background: rgba(244, 63, 94, 0.25); transform: translateY(-1px); }
    #cat-close-btn2 { background: linear-gradient(180deg, var(--neon-pink), #e11d48); border: 1.5px solid #fda4af; color: #fff; }
    #cat-close-btn2:hover { filter: brightness(1.15); transform: translateY(-1px); }

    /* ── LEVEL UP & ALL DONE ─────────────────────────────────────────────── */
    #levelup-overlay, #alldone-overlay {
      display: none; position: fixed; inset: 0; z-index: 300;
      background: rgba(10, 15, 30, 0.85); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: center; justify-content: center;
    }
    #levelup-overlay.visible, #alldone-overlay.visible { display: flex; animation: fadeIn .3s ease; }
    #levelup-card {
      background: rgba(15, 23, 42, 0.92);
      border: 2px solid var(--neon-gold); border-radius: 8px; padding: 36px 44px; text-align: center;
      box-shadow: 0 0 0 2px #0f172a, var(--glow-gold), 0 24px 60px rgba(0,0,0,.9);
      animation: popIn .35s cubic-bezier(.4,0,.2,1); position: relative;
    }
    #levelup-card .trophy { font-size: 58px; margin-bottom: 14px; filter: drop-shadow(0 0 16px rgba(245, 158, 11, 0.6)); }
    #levelup-card h1 { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 22px; color: var(--neon-gold); margin-bottom: 10px; }
    #levelup-card p { font-family: 'VT323', monospace; font-size: 22px; color: rgba(226, 232, 240, 0.8); margin-bottom: 24px; }
    .levelup-btns, .alldone-btns { display: flex; gap: 12px; }
    #levelup-next-btn, #levelup-menu-btn, #replay-btn, #menu-btn {
      flex: 1; border-radius: 8px; padding: 12px 0;
      font-family: 'VT323', monospace; font-size: 24px;
      cursor: pointer; letter-spacing: 1px; border: 2px solid; transition: all .15s;
    }
    #levelup-next-btn { background: linear-gradient(180deg, var(--neon-gold), #d4a017); border-color: #fde047; color: #0f172a; font-weight: bold; }
    #levelup-next-btn:hover { filter: brightness(1.15); transform: translateY(-2px); }
    #levelup-menu-btn, #menu-btn { background: rgba(30, 41, 59, 0.8); border-color: rgba(226, 232, 240, 0.3); color: #fff; }
    #levelup-menu-btn:hover, #menu-btn:hover { border-color: #fff; }

    #alldone-card {
      background: rgba(15, 35, 20, 0.92);
      border: 2px solid var(--neon-green); border-radius: 8px; padding: 36px 44px; text-align: center;
      box-shadow: 0 0 0 2px #0f172a, var(--glow-green), 0 24px 60px rgba(0,0,0,.9);
      animation: popIn .4s cubic-bezier(.4,0,.2,1); position: relative;
    }
    #alldone-card .star { font-size: 64px; margin-bottom: 14px; filter: drop-shadow(0 0 16px rgba(74, 222, 128, 0.6)); }
    #alldone-card h1 { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 22px; color: var(--neon-green); margin-bottom: 10px; }
    #alldone-card p { font-family: 'VT323', monospace; font-size: 22px; color: rgba(226, 232, 240, 0.8); margin-bottom: 24px; }
    #replay-btn { background: linear-gradient(180deg, var(--neon-green), #16a34a); border-color: #86efac; color: #0f172a; font-weight: bold; }
    #replay-btn:hover { filter: brightness(1.15); transform: translateY(-2px); }

    /* ── TOAST NOTIFICATION ──────────────────────────────────────────────── */
    #toast {
      position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%);
      background: rgba(15, 23, 42, 0.95); color: var(--neon-gold);
      border: 2px solid var(--neon-gold); border-radius: 4px;
      padding: 10px 20px; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px;
      z-index: 600; pointer-events: none; opacity: 0; transition: opacity .3s, transform .3s;
      box-shadow: 0 0 0 2px #0f172a, var(--glow-gold);
    }
    #toast.show { opacity: 1; transform: translateX(-50%) translateY(-5px); }

    @media (max-width: 1100px) {
      #vff-content-grid { grid-template-columns: minmax(0, 1.6fr) minmax(280px, .9fr); }
      #vff-overview-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    }

    @media (max-width: 900px) {
      #vocab-controls { grid-template-columns: 1fr; gap: 11px; }
      #cat-filters { min-height: 40px; }
      #vff-content-grid { grid-template-columns: 1fr; }
      #vff-side-content { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      #vff-side-content .vff-section:first-child { grid-row: span 2; }
    }

    /* ── RESPONSIVE MEDIA QUERIES (MAX-WIDTH: 768px & 480px) ──────────────── */
    @media (max-width: 768px) {
      #hud {
        top: 8px !important; left: 50% !important; right: auto !important;
        width: calc(100vw - 16px) !important;
        padding: 5px 6px !important; gap: 6px !important;
        border-radius: 8px !important;
        flex-wrap: wrap;
      }
      .hud-group { gap: 5px; }
      #hud-currency-group { padding: 0; }
      #hud-level { max-width: 120px; font-size: 12px; }
      #hud-progress { font-size: 14px; }
      .hud-btn:not(.hud-overflow-item) { width: 32px !important; height: 32px !important; min-width: 32px !important; font-size: 14px !important; }
      .hud-btn:not(.hud-overflow-item) .hud-art-icon { width: 20px; height: 20px; }

      /* No top/right here any more — it is a HUD group, so it moves with the bar. */
      #progress-bar-wrap { grid-template-columns: minmax(0, 80px) auto; }
      #progress-bar-bg { height: 10px; }

      #controls-tip { bottom: 6px; font-size: 14px; padding: 4px 10px; }

      body:not(.close-view) #quiz-ui, #shop-panel, #fish-album-panel,
      #trophy-panel, #memory-panel,
      #cat-dialog-inner, #levelup-card, #alldone-card {
        width: 96vw !important; max-height: 90vh !important;
        padding: 16px !important; margin: auto !important;
      }

      .ls-grid { grid-template-columns: 1fr; }
      #vocab-header { min-height: 68px; padding: 10px 14px; gap: 10px; }
      .vocab-book-mark { width: 44px; height: 44px; font-size: 27px; border-radius: 9px; }
      #vocab-title { font-size: 12px; }
      #vocab-subtitle { font-size: 13px; line-height: 1.35; }
      #vocab-progress-summary { font-size: 11px; }
      #vocab-close-btn { width: 42px; height: 42px; }
      #vocab-controls { padding: 10px 14px; gap: 9px; }
      .vocab-search-field { height: 40px; }
      #cat-filters { min-height: 36px; padding-bottom: 3px; }
      #cat-filters .cat-filter-btn { min-height: 34px; font-size: 12px; }
      #vocab-grid-wrap { padding: 13px 14px 34px; }
      #vocab-grid-heading { align-items: flex-start; margin-bottom: 10px; }
      .vocab-grid-help { display: none; }
      #vocab-grid { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 12px; }
      .vocab-card { min-height: 278px; padding: 14px 10px 11px; border-radius: 10px; }
      .vc-category { font-size: 9px; margin-bottom: 6px; }
      .vc-emoji { min-height: 96px; margin-bottom: 7px; }
      .vc-emoji img.vocab-art-icon { height: 96px; }
      .vc-ko { font-size: 29px; }
      .vc-ko.vc-ko-sm { font-size: 23px; }
      .vc-ko.vc-ko-xs { font-size: 18px; }
      .vc-en { font-size: 13px; }

      #vff-header {
        grid-template-columns: auto 1fr; min-height: 58px; gap: 9px;
        padding: 8px 12px;
      }
      #vff-title { display: none; }
      #vff-nav { justify-self: end; }
      #vff-nav-position { min-width: 58px; font-size: 10px; }
      #vff-header button { min-height: 36px; padding: 6px 9px; font-size: 11px; }
      #vff-word-row {
        grid-template-columns: 112px minmax(0, 1fr); gap: 16px;
        padding: 20px 16px;
      }
      #vff-emoji { width: 112px; height: 112px; font-size: 58px; border-radius: 13px; }
      #vff-emoji img.vocab-art-icon { max-width: 96px; height: 96px; }
      #vff-ko { font-size: clamp(32px, 8vw, 46px); }
      #vff-en { font-size: 18px; }
      #vff-status { grid-column: 1 / -1; padding: 12px 14px; }
      #vff-content-grid { padding: 16px 12px 26px; gap: 13px; }
      #vff-main-content, #vff-side-content { gap: 12px; }
      #vff-side-content { grid-template-columns: 1fr; }
      #vff-side-content .vff-section:first-child { grid-row: auto; }
      .vff-section { padding: 16px; }
      #vff-overview-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
      #vff-fact-example { font-size: 18px; }
      #vff-detail-footer { padding: 0 12px 28px; }
      #vff-detail-footer > span { display: none; }
      #shop-level-grid { grid-template-columns: 1fr; }
      #fish-album-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
      .trophy-grid { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }

      #cat-dialog-body { flex-direction: column; text-align: center; }
      #cat-portrait-wrap { border-right: none; border-bottom: 1px solid rgba(244, 63, 94, 0.2); width: 100%; padding: 8px; }
      #cat-portrait-canvas { width: 90px; height: 135px; }
      #cat-word-wrap { padding: 12px; }
      #cat-ko { font-size: 32px; }
      #cat-dialog-emoji-word { justify-content: center; }

    }

    @media (max-width: 480px) {
      #hud { padding: 5px 6px !important; gap: 4px !important; }
      .hud-chip { font-size: 16px; }
      /* The currency row — rank, three counts and the avatar — ran 18px past the bar at 375px
         once a count reached four digits. The rank's XP bar is the part that can go: its
         level stays on the chip, and the chip still opens the card that shows the XP. */
      #hud-rank-bar { display: none; }
      body:not(.close-view) #quiz-ui, #shop-panel, #fish-album-panel,
      #trophy-panel, #memory-panel,
      #cat-dialog-inner, #levelup-card, #alldone-card {
        width: 98vw !important; max-height: 92vh !important;
        padding: 12px !important;
      }
      #vocab-header { padding: 8px 10px; }
      .vocab-book-mark { display: none; }
      #vocab-title { font-size: 10px; }
      #vocab-subtitle { font-size: 12px; }
      #vocab-progress-summary { display: none; }
      #vocab-controls { padding: 8px 10px; }
      .vocab-control-label { display: none; }
      #vocab-grid-wrap { padding: 10px 10px 28px; }
      #vocab-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
      .vocab-card { min-height: 272px; padding: 12px 7px 9px; }
      .vocab-card .vc-speak { top: 7px; right: 7px; }
      .vc-category { max-width: calc(100% - 34px); padding: 3px 6px; }
      .vc-emoji { min-height: 96px; }
      .vc-emoji img.vocab-art-icon { height: 96px; }
      .vc-ko { font-size: 25px; }
      .vc-ko.vc-ko-sm { font-size: 19px; }
      .vc-ko.vc-ko-xs { font-size: 15px; }
      .vc-en { font-size: 12px; -webkit-line-clamp: 3; }
      .vc-open-hint { font-size: 10px; }
      #vff-back-btn { max-width: 118px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
      #vff-nav-position { display: none; }
      #vff-word-row { grid-template-columns: 112px minmax(0, 1fr); padding: 16px 11px; gap: 12px; }
      #vff-emoji { width: 112px; height: 112px; font-size: 46px; }
      #vff-emoji img.vocab-art-icon { max-width: 96px; height: 96px; }
      #vff-ko { font-size: 30px; }
      .vff-audio-btn { width: 37px; height: 35px; font-size: 15px; }
      #vff-romanization { font-size: 13px; }
      #vff-en { font-size: 16px; margin-top: 6px; }
      #vff-cat { font-size: 10px; }
      #vff-overview-grid { grid-template-columns: 1fr; }
      #vff-syllable-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
      .vff-syllable-card { min-width: 0; }
      #vff-close-btn { width: 100%; }
    }

    /* ── 64-BIT RETRO GLASSMORPHISM UTILITIES & QUEST / QUIZ / BOSS MODALS ── */
    /* ══════════ CASSETTE PLAYER ══════════
       The deck borrows the study desk's vocabulary wholesale — parchment panel,
       #fff8e8 rows on a wood drop-shadow, Press Start 2P for anything that reads as
       a label rather than as language. It is the same furniture in the same room. */
    #cassette-overlay, #listen-overlay, #dictation-overlay {
      position: fixed; inset: 0; z-index: 880; display: none;
      background: var(--farm-veil); backdrop-filter: blur(8px);
      -webkit-backdrop-filter: blur(8px);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #cassette-overlay.visible, #listen-overlay.visible, #dictation-overlay.visible { display: flex; }
    #cassette-panel { width: 460px; max-width: 94vw; }
    #listen-panel { width: 700px; max-width: 96vw; max-height: 90vh; display: flex; flex-direction: column; }
    #dictation-panel { width: 620px; max-width: 96vw; max-height: 90vh; display: flex; flex-direction: column; }

    .cs-head {
      display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
      padding: 14px 18px; border-bottom: 2px solid var(--wood-l); flex: 0 0 auto;
    }
    .cs-headright { display: flex; align-items: center; gap: 10px; }
    #cassette-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; line-height: 1.5; color: var(--wood-d); }
    #cassette-sub { font-size: 12px; color: #6b4a22; margin-top: 5px; }
    #listen-title, #dict-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; color: var(--wood-d); }
    #dict-pos { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: var(--wood-m); }
    .cs-x {
      flex: 0 0 auto; background: var(--parch-l); border: 2px solid var(--wood-m);
      border-radius: 4px; padding: 2px 10px; cursor: pointer; font-size: 13px; color: var(--ink);
    }
    .cs-x:hover { background: #fff3d6; }

    #cassette-list { display: flex; flex-direction: column; gap: 9px; padding: 16px 18px; }
    #cassette-foot {
      display: flex; align-items: center; justify-content: space-between; gap: 10px;
      padding: 11px 18px 13px; border-top: 2px solid var(--wood-l); background: rgba(255,248,232,0.45);
    }
    .cs-foot-ko { font-size: 11.5px; color: #6b4a22; }
    .cs-foot-n { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m); }

    /* ── 듣기 ── */
    #listen-body { display: grid; grid-template-columns: 268px minmax(0, 1fr); min-height: 0; flex: 1 1 auto; }
    #listen-tracks {
      display: flex; flex-direction: column; gap: 6px; padding: 14px;
      border-right: 2px solid var(--wood-l); overflow-y: auto;
    }
    .cs-track {
      display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
      background: var(--parch-l); border: 2px solid var(--wood-m); border-radius: 6px;
      padding: 9px 10px; cursor: pointer; color: var(--ink);
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s;
    }
    .cs-track:hover { background: #fff3d6; transform: translateY(-1px); }
    .cs-track.on { border-color: #1e3a8a; background: #fff3d6; box-shadow: inset 0 1px 0 #fff, 0 2px 0 #1e3a8a; }
    .cs-tn {
      flex: 0 0 auto; min-width: 24px; height: 20px; line-height: 18px; text-align: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-d);
    }
    .cs-tt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
    .cs-tko { font-size: 13px; font-weight: 500; }
    .cs-ten { font-size: 10.5px; color: #6b4a22; }
    .cs-td { flex: 0 0 auto; margin-left: auto; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m); }

    /* min-height: 0 is doing real work here, not tidying. This is a grid item, so its
       default min-height:auto refuses to shrink below its content — it grew to 1016px inside
       a 614px row, .cs-script never overflowed and so never scrolled, and #listen-panel
       clips at overflow:hidden. The last few lines of a long transcript were simply gone,
       with no way to reach them. */
    #listen-right { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
    #listen-transport {
      display: flex; align-items: center; gap: 12px; padding: 14px 16px;
      border-bottom: 2px solid var(--wood-l); flex: 0 0 auto;
    }
    .cs-play {
      flex: 0 0 auto; display: flex; align-items: center; justify-content: center;
      width: 38px; height: 38px; background: var(--parch-l); border: 2px solid var(--wood-m);
      border-radius: 5px; box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      cursor: pointer; font-size: 14px; color: var(--wood-d);
    }
    .cs-play.big { width: 44px; height: 44px; font-size: 16px; }
    .cs-play:hover { background: #fff3d6; }
    .cs-play.on { border-color: #1e3a8a; background: #fff3d6; box-shadow: inset 0 1px 0 #fff, 0 2px 0 #1e3a8a; }
    .cs-meter { display: flex; flex-direction: column; gap: 6px; flex-grow: 1; min-width: 0; }
    .cs-meterrow { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
    .cs-meterrow span:first-child { font-size: 12px; color: var(--wood-d); }
    .cs-meterrow span:last-child { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m); }
    /* The thin progress bar this transport used to carry is gone. #listen-wave draws the
       playhead now, and two progress readings on one row disagreed on rounding. */
    #listen-rates, #dict-rates { flex: 0 0 auto; display: flex; gap: 5px; }
    .cs-rate {
      padding: 3px 7px; background: var(--parch-l); border: 1.5px solid var(--wood-l);
      border-radius: 3px; cursor: pointer;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m);
    }
    .cs-rate.on { border-color: #1e3a8a; background: #fff3d6; color: #1e3a8a; }

    /* ── the waveform and its loop controls ────────────────────────────────── */
    /* Shared by 듣기 and 받아쓰기: one strip, one set of controls, so the two screens do not
       drift apart on something a learner uses on both. */
    #listen-waverow, #dict-waverow {
      display: flex; flex-direction: column; gap: 8px;
      padding: 12px 16px 13px; border-bottom: 2px solid var(--wood-l); flex: 0 0 auto;
    }
    #listen-wave, #dict-wave {
      display: block; width: 100%; height: 56px;
      background: var(--parch-l); border: 1.5px solid var(--wood-m); border-radius: 4px;
      cursor: crosshair;
      /* Without this the browser claims the drag for scrolling and the A-B gesture
         never fires on a touchscreen — the same reason the workbook chips set it. */
      touch-action: none;
    }
    #dict-wave { height: 48px; }
    #listen-loopbar, #dict-loopbar { display: flex; align-items: center; gap: 5px; }
    #dict-clock {
      margin-left: auto; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px;
      color: var(--wood-m); white-space: nowrap;
    }
    .cs-lb {
      padding: 3px 7px; background: var(--parch-l); border: 1.5px solid var(--wood-l);
      border-radius: 3px; cursor: pointer;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m);
    }
    .cs-lb:hover { background: #fff3d6; }
    .cs-lb.on { border-color: #1e3a8a; background: #fff3d6; color: #1e3a8a; }
    .cs-lb:disabled { opacity: .4; cursor: default; }
    .cs-lb:disabled:hover { background: var(--parch-l); }
    .cs-lbsep { width: 1.5px; height: 13px; background: var(--wood-l); margin: 0 3px; }
    /* ── the practice log ──────────────────────────────────────────────── */
    /* A count beside the thing it counts, in the list where you pick what to do next. */
    .prac-badge {
      margin-left: 6px; padding: 1px 4px; border-radius: 3px;
      background: var(--parch-l); border: 1.5px solid var(--wood-l);
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 7px; color: var(--wood-m);
      white-space: nowrap;
    }
    .prac-badge.good { border-color: #1e7a3a; color: #1e7a3a; background: #eafaef; }
    #dict-log {
      margin-left: 8px; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px;
      color: var(--wood-m); white-space: nowrap;
    }
    .prac-row {
      display: flex; align-items: baseline; gap: 8px; padding: 5px 2px;
      border-bottom: 1px solid rgba(139, 90, 43, .18);
    }
    .prac-row:last-child { border-bottom: none; }
    .prac-icon { flex: 0 0 auto; font-size: 13px; }
    .prac-lbl { flex: 0 0 84px; font-size: 12px; color: var(--wood-d); }
    .prac-n {
      flex: 0 0 auto; min-width: 28px; text-align: right;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; color: var(--wood-d);
    }
    .prac-sub { flex: 1 1 auto; font-size: 11px; color: var(--wood-m); }
    .prac-pct {
      flex: 0 0 auto; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: #1e7a3a;
    }
    .prac-pct.low { color: #a32b1c; }
    .prac-empty { font-size: 11.5px; color: var(--wood-m); padding: 6px 2px; }

    #listen-abinfo, #dict-abinfo {
      margin-left: auto; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px;
      color: var(--wood-m); white-space: nowrap;
    }
    #dict-abinfo { margin-left: 8px; }
    #listen-abinfo.on, #dict-abinfo.on { color: #1e3a8a; }

    .cs-script { padding: 14px 16px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
    .cs-line { display: flex; gap: 9px; align-items: baseline; margin-bottom: 8px; }
    .cs-who {
      flex: 0 0 auto; min-width: 34px; padding: 1px 5px; text-align: center;
      background: var(--parch); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-size: 10.5px; color: var(--wood-d);
    }
    .cs-ko { font-size: 14px; line-height: 1.65; color: var(--ink); text-wrap: pretty; }
    /* The per-sentence ▶. A line the audio cannot place keeps the indent and offers
       nothing — an inert button that does nothing when pressed is worse than no button. */
    .cs-lineplay {
      flex: 0 0 auto; align-self: flex-start; width: 22px; height: 22px; padding: 0;
      display: inline-flex; align-items: center; justify-content: center;
      background: var(--parch); border: 1.5px solid var(--wood-l); border-radius: 4px;
      color: var(--wood-d); font-size: 9px; line-height: 1; cursor: pointer;
      transition: background .12s, border-color .12s;
    }
    .cs-lineplay:hover { background: #ffe9b8; border-color: var(--wood-d); }
    .cs-lineplay.on { background: var(--wood-d); border-color: var(--wood-d); color: var(--parch); }
    .cs-lineplay:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,.35); }
    .cs-lineplay-off { flex: 0 0 auto; width: 22px; height: 22px; }
    .cs-line.playing { background: rgba(255,225,160,.62); border-radius: 5px; }
    .cs-script.empty { display: flex; align-items: center; justify-content: center; }
    .cs-none {
      display: flex; flex-direction: column; gap: 10px; padding: 22px 18px;
      background: rgba(255,248,232,0.5); border: 2px dashed var(--wood-l); border-radius: 6px;
    }
    .cs-none-ko { font-weight: 700; font-size: 14px; color: var(--wood-d); }
    .cs-none-en { font-size: 12.5px; line-height: 1.7; color: #6b4a22; text-wrap: pretty; }

    /* ── 받아쓰기 ── */
    #dict-body { display: flex; flex-direction: column; gap: 14px; padding: 18px; overflow-y: auto; min-height: 0; }
    #dict-tags { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
    .cs-tag { padding: 3px 8px; border-radius: 3px; font-size: 11px; }
    .cs-tag.trk { background: var(--parch); border: 1.5px solid var(--wood-l); color: var(--wood-d); font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; }
    .cs-tag.who { background: var(--parch); border: 1.5px solid var(--wood-l); color: var(--wood-d); }
    .cs-tag.lesson { background: rgba(30,58,138,0.09); border: 1.5px solid #1e3a8a; color: #1e3a8a; }
    #dict-transport {
      display: flex; align-items: center; gap: 10px; padding: 14px;
      background: rgba(255,248,232,0.55); border: 2px solid var(--wood-l); border-radius: 6px;
    }
    .cs-again {
      flex: 0 0 auto; padding: 0 12px; height: 44px; background: var(--parch-l);
      border: 2px solid var(--wood-m); border-radius: 5px;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      cursor: pointer; font-size: 12px; color: var(--ink);
    }
    .cs-again:hover { background: #fff3d6; }
    #dict-hint { margin-left: auto; font-size: 11.5px; color: #6b4a22; text-align: right; }
    #dict-inputrow { display: flex; gap: 9px; }
    #dict-input {
      flex-grow: 1; min-width: 0; background: var(--parch-l); border: 2px solid var(--wood-m);
      border-radius: 6px; box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      padding: 12px 13px; font-family: inherit; font-size: 16px; color: var(--ink);
    }
    #dict-input:focus { outline: none; border-color: #1e3a8a; box-shadow: inset 0 1px 0 #fff, 0 2px 0 #1e3a8a; }
    #dict-input:disabled { opacity: .75; }
    #dict-check {
      flex: 0 0 auto; padding: 0 18px; background: #1e3a8a; border: 2px solid #16306e;
      border-radius: 6px; box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 2px 0 #16306e;
      cursor: pointer; font-family: inherit; font-weight: 700; font-size: 14px; color: var(--parch-l);
    }
    #dict-check:hover { background: #24479f; }
    .cs-result { display: none; }
    .cs-result.on { display: flex; flex-direction: column; gap: 12px; }
    .cs-ansbox {
      display: flex; flex-direction: column; gap: 7px; padding: 13px 14px;
      background: rgba(255,248,232,0.7); border: 2px solid var(--wood-l); border-radius: 6px;
    }
    .cs-ansrow { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
    .cs-lbl { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-m); }
    .cs-lbl.bad { color: #9f1239; }
    .cs-score { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; }
    .cs-score.good { color: #166534; }
    .cs-score.bad { color: #9f1239; }
    .cs-ans { font-size: 19px; line-height: 1.6; word-break: keep-all; }
    .cs-ans .ok { color: var(--ink); }
    .cs-ans .miss { padding: 1px 3px; background: #9f1239; color: var(--parch-l); border-radius: 3px; }
    .cs-ans .extra { padding: 1px 3px; background: rgba(159,18,57,.16); color: #9f1239; border-radius: 3px; text-decoration: line-through; }
    .cs-ans .sp { display: inline-block; width: .34em; }
    .cs-yours {
      display: flex; flex-direction: column; gap: 6px; padding: 11px 14px;
      background: rgba(159,18,57,0.05); border: 2px solid #9f1239; border-radius: 6px;
    }
    .cs-yours .cs-ans { font-size: 17px; }
    .cs-why {
      display: flex; flex-direction: column; gap: 6px; padding: 13px 14px;
      background: rgba(255,248,232,0.5); border-left: 3px solid #1e3a8a; border-radius: 0 6px 6px 0;
    }
    .cs-en { font-size: 13.5px; font-style: italic; color: var(--wood-d); text-wrap: pretty; }
    .cs-note { font-size: 12.5px; line-height: 1.75; color: var(--ink); text-wrap: pretty; }

    /* ── Cassette · daily-use layout ───────────────────────────────────────
       Listening is a repeat destination, so the important controls stay large,
       the current track is named once in a stable place, and advanced A/B tools
       sit below the waveform instead of competing with Play. */
    #cassette-panel { width: min(700px, 94vw); }
    #listen-panel { width: min(1040px, 97vw); max-height: 94vh; }
    #dictation-panel { width: min(760px, 96vw); max-height: 94vh; }

    .cs-home-head {
      align-items: center; padding: 18px 20px;
      background: linear-gradient(180deg, rgba(255,248,232,.86), rgba(255,248,232,.3));
    }
    .cs-titleblock { flex: 1 1 auto; min-width: 0; }
    .cs-kicker {
      display: block; margin-bottom: 5px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; font-weight: 900;
      letter-spacing: .14em; color: #8a541e;
    }
    .cs-deck {
      position: relative; flex: 0 0 auto; width: 78px; height: 52px;
      display: flex; align-items: center; justify-content: center; gap: 16px;
      background: #4a2a0d; border: 3px solid #2d1808; border-radius: 7px;
      box-shadow: inset 0 0 0 3px #8b5a2b, 0 3px 0 rgba(45,24,8,.35);
    }
    .cs-deck::before {
      content: ''; position: absolute; left: 13px; right: 13px; bottom: 7px; height: 8px;
      background: #e8c07a; border: 2px solid #2d1808; border-radius: 2px;
    }
    .cs-reel {
      position: relative; z-index: 1; width: 20px; height: 20px; border-radius: 50%;
      background: #fff8e8; border: 4px solid #c4893a;
      box-shadow: inset 0 0 0 3px #4a2a0d;
    }
    .cs-tape {
      position: absolute; left: 24px; right: 24px; top: 22px; height: 3px;
      background: #17100a;
    }
    .cs-work-head {
      align-items: center; padding: 14px 18px;
      background: rgba(255,248,232,.65); border-bottom-style: solid;
    }
    #listen-title, #dict-title {
      font-family: 'Noto Sans KR', sans-serif; font-size: 20px; font-weight: 900;
      letter-spacing: -.02em; line-height: 1.25; color: var(--ink);
    }
    #listen-context {
      margin-top: 3px; font-family: 'Be Vietnam Pro', sans-serif;
      font-size: 11.5px; color: #6b4a22;
    }
    .cs-x {
      min-height: 38px; display: inline-flex; align-items: center; justify-content: center;
      font-family: 'Be Vietnam Pro', sans-serif; font-weight: 900;
      transition: background .15s, border-color .15s, transform .12s;
    }
    .cs-x:hover { border-color: var(--wood-d); transform: translateY(-1px); }
    .cs-x:focus-visible, .cs-mode-card:focus-visible, .cs-track:focus-visible,
    .cs-play:focus-visible, .cs-skip:focus-visible, .cs-rate:focus-visible,
    .cs-lb:focus-visible, .cs-script-toggle:focus-visible, .cs-again:focus-visible {
      outline: none; box-shadow: 0 0 0 3px rgba(30,58,138,.28), 0 2px 0 var(--wood-m);
    }

    #cassette-list {
      display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
      padding: 20px;
    }
    .cs-mode-card {
      position: relative; min-height: 190px; display: flex; flex-direction: column;
      align-items: flex-start; gap: 10px; padding: 18px; text-align: left;
      background: #fff8e8; color: var(--ink); border: 2px solid var(--wood-m);
      border-radius: 8px; cursor: pointer;
      box-shadow: inset 0 1px 0 #fff, 0 4px 0 var(--wood-m);
      transition: transform .12s, border-color .15s, background .15s;
    }
    .cs-mode-card:hover, .cs-mode-card.focus {
      transform: translateY(-2px); border-color: #1e3a8a; background: #fff3d6;
      box-shadow: inset 0 1px 0 #fff, 0 4px 0 #1e3a8a;
    }
    .cs-mode-top { display: flex; align-items: center; justify-content: space-between; width: 100%; }
    .cs-mode-icon {
      width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center;
      background: #e8dcc4; border: 2px solid var(--wood-l); border-radius: 6px; font-size: 25px;
    }
    .cs-mode-key {
      width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 4px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: var(--wood-d);
    }
    .cs-mode-title {
      display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
      font-family: 'Noto Sans KR', sans-serif; font-size: 20px; font-weight: 900;
      letter-spacing: -.02em;
    }
    .cs-mode-title small {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 10px; font-weight: 900;
      letter-spacing: .1em; color: #7a4a18;
    }
    .cs-mode-desc {
      min-height: 40px; font-family: 'Be Vietnam Pro', sans-serif; font-size: 12.5px;
      line-height: 1.55; color: #5b3412;
    }
    .cs-mode-meta {
      width: 100%; display: flex; justify-content: space-between; gap: 8px; margin-top: auto;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 800; color: #6b4a22;
    }
    .cs-mode-progress {
      width: 100%; height: 8px; overflow: hidden; background: #e8dcc4;
      border: 1px solid var(--wood-l); border-radius: 3px;
    }
    .cs-mode-progress > span {
      display: block; height: 100%; background: linear-gradient(90deg, #1e3a8a, #4d6fc7);
    }
    #cassette-foot {
      font-family: 'Be Vietnam Pro', sans-serif; padding: 12px 20px 15px;
    }
    .cs-foot-n { font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; font-weight: 900; letter-spacing: .06em; }

    #listen-body { grid-template-columns: 310px minmax(0, 1fr); }
    #listen-tracknav {
      min-height: 0; display: flex; flex-direction: column;
      border-right: 2px solid var(--wood-l); background: rgba(255,248,232,.28);
    }
    .cs-rail-head {
      display: flex; align-items: center; justify-content: space-between; gap: 8px;
      padding: 12px 14px 8px; font-family: 'Be Vietnam Pro', sans-serif;
      font-size: 10px; font-weight: 900; letter-spacing: .1em; color: #7a4a18;
    }
    #listen-track-count { font-size: 10px; letter-spacing: 0; }
    .cs-search {
      display: flex; align-items: center; gap: 7px; margin: 0 12px 8px; padding: 8px 10px;
      background: #fff8e8; border: 1.5px solid var(--wood-l); border-radius: 5px;
      color: #7a4a18;
    }
    .cs-search:focus-within { border-color: #1e3a8a; box-shadow: 0 0 0 3px rgba(30,58,138,.13); }
    .cs-search input {
      min-width: 0; width: 100%; padding: 0; border: 0; outline: 0; background: transparent;
      font-family: 'Noto Sans KR', 'Be Vietnam Pro', sans-serif; font-size: 12px; color: var(--ink);
    }
    #listen-tracks {
      flex: 1 1 auto; min-height: 0; padding: 4px 12px 14px; gap: 8px; border-right: 0;
    }
    .cs-track { padding: 10px; box-shadow: inset 0 1px 0 #fff, 0 2px 0 rgba(139,90,43,.75); }
    .cs-track.on {
      position: relative; border-color: #1e3a8a; background: #eef3ff;
      box-shadow: inset 4px 0 0 #1e3a8a, 0 2px 0 #1e3a8a;
    }
    .cs-tko { font-size: 13.5px; font-weight: 800; line-height: 1.35; }
    .cs-ten { font-size: 11px; line-height: 1.35; }
    .cs-td { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }

    #listen-nowcard {
      display: flex; align-items: center; justify-content: space-between; gap: 14px;
      padding: 14px 16px 12px; background: rgba(255,248,232,.55);
      border-bottom: 1.5px solid var(--wood-l);
    }
    .cs-nowcopy { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
    #listen-now-kicker {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 9px; font-weight: 900;
      letter-spacing: .12em; color: #8a541e;
    }
    #listen-now {
      font-family: 'Noto Sans KR', sans-serif; font-size: 18px; line-height: 1.35;
      font-weight: 900; color: var(--ink);
    }
    #listen-now-en { font-size: 11.5px; color: #6b4a22; }
    .cs-script-toggle {
      flex: 0 0 auto; min-height: 36px; padding: 7px 10px; cursor: pointer;
      background: var(--parch-l); border: 1.5px solid var(--wood-m); border-radius: 4px;
      font-family: 'Noto Sans KR', sans-serif; font-size: 11px; font-weight: 800; color: var(--wood-d);
    }
    .cs-script-toggle[aria-pressed="true"] { background: #dbe4fb; border-color: #1e3a8a; color: #1e3a8a; }
    #listen-transport {
      display: grid; grid-template-columns: auto minmax(150px, 1fr) auto; gap: 12px;
      padding: 13px 16px; background: rgba(255,248,232,.3);
    }
    .cs-main-controls { display: flex; align-items: center; gap: 6px; }
    .cs-skip {
      flex: 0 0 auto; min-width: 38px; height: 40px; padding: 0 8px;
      display: inline-flex; align-items: center; justify-content: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-m); border-radius: 5px;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      cursor: pointer; font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px;
      font-weight: 900; color: var(--wood-d);
    }
    .cs-skip:hover { background: #fff3d6; }
    .cs-play-primary {
      width: 50px; height: 50px; border-radius: 50%; background: #1e3a8a; color: #fff8e8;
      border-color: #14295e; box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 3px 0 #14295e;
    }
    .cs-play-primary:hover, .cs-play-primary.on { background: #294ca8; color: #fff8e8; }
    .cs-meter { justify-content: center; }
    .cs-meterrow span:first-child { font-size: 9px; font-weight: 900; letter-spacing: .09em; }
    #listen-rates, #dict-rates { align-items: center; }
    .cs-rate { min-height: 34px; padding: 5px 8px; }
    .cs-rate.on { background: #dbe4fb; }
    #listen-waverow, #dict-waverow { background: rgba(255,248,232,.32); }
    #listen-wave, #dict-wave { background: #fffaf0; }
    #listen-loopbar, #dict-loopbar { flex-wrap: wrap; }
    .cs-lb { min-height: 31px; padding: 5px 8px; font-family: 'Noto Sans KR', sans-serif; font-size: 10.5px; font-weight: 800; }
    #listen-abinfo, #dict-abinfo { font-family: 'Be Vietnam Pro', sans-serif; font-size: 9.5px; font-weight: 800; }
    .cs-hotkeys, .cs-input-help {
      flex-basis: 100%; font-family: 'Be Vietnam Pro', sans-serif;
      font-size: 10px; line-height: 1.45; color: #7a4a18;
    }
    .cs-script { padding: 16px 18px 20px; }
    .cs-line {
      align-items: flex-start; margin-bottom: 10px; padding: 9px 10px;
      background: rgba(255,248,232,.5); border-radius: 5px;
    }
    .cs-ko { font-size: 15px; line-height: 1.75; font-weight: 500; }
    .cs-script.is-hidden {
      display: flex; align-items: center; justify-content: center; min-height: 180px;
    }
    .cs-script.is-hidden .cs-line, .cs-script.is-hidden .cs-none { display: none; }
    .cs-script-cover {
      max-width: 360px; padding: 20px; text-align: center;
      background: rgba(255,248,232,.62); border: 2px dashed var(--wood-l); border-radius: 7px;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12.5px; line-height: 1.65; color: #5b3412;
    }

    .cs-dict-progress {
      width: min(300px, 45vw); height: 6px; margin-top: 7px; overflow: hidden;
      background: #e8dcc4; border: 1px solid var(--wood-l); border-radius: 3px;
    }
    #dict-progress-fill {
      display: block; width: 0; height: 100%;
      background: linear-gradient(90deg, #1e3a8a, #4d6fc7); transition: width .2s;
    }
    #dict-body { gap: 12px; }
    #dict-transport { padding: 12px; }
    #dict-inputrow { min-height: 50px; }
    #dict-input { font-size: 17px; }
    #dict-check { min-width: 92px; }
    .cs-input-help { margin-top: -4px; padding-left: 2px; }

    @media (max-width: 720px) {
      #cassette-list { grid-template-columns: 1fr; padding: 14px; }
      .cs-mode-card { min-height: 155px; }
      .cs-deck { width: 64px; height: 46px; gap: 10px; }
      .cs-reel { width: 17px; height: 17px; }
      #listen-panel, #dictation-panel {
        width: 100vw; max-width: 100vw; max-height: 100vh; height: 100vh; border-radius: 0;
      }
      /* minmax(0, …) on the column, not only on the rows. A bare 1fr track is floored at the
         min-content width of what it holds, and what it holds is the track rail: ten cards at
         a fixed 232px, which comes to 2,416px. The column grew to fit them instead of letting
         them scroll, and everything else in the column went with it — the play button, the
         skip buttons and the speed control were pushed a page and a half off the right edge,
         on every screen 720px and under.

         Nothing looked broken. The panel has overflow-x: hidden, so the controls did not
         spill or scroll into view; they were simply not there, and the only way left to start
         a track was the spacebar, which nothing on the screen mentions. */
      #listen-body { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr); }
      #listen-tracknav { border-right: none; border-bottom: 2px solid var(--wood-l); }
      .cs-rail-head { padding-top: 9px; }
      #listen-tracks {
        flex-direction: row; overflow-x: auto; overflow-y: hidden; max-height: none;
        padding: 4px 12px 12px; scroll-snap-type: x proximity;
      }
      .cs-track { flex: 0 0 232px; scroll-snap-align: start; }
      #listen-transport { grid-template-columns: minmax(0, 1fr); }
      .cs-main-controls, #listen-rates { justify-content: center; }
      .cs-meterrow { justify-content: center; }
      .cs-hotkeys { text-align: center; }
      #listen-now { font-size: 17px; }
      #dict-transport { flex-wrap: wrap; }
      #dict-hint { margin-left: 0; flex-basis: 100%; text-align: left; }
      .cs-work-head { padding: 11px 12px; }
      .cs-back { padding-left: 8px; padding-right: 8px; }
    }

    @media (max-width: 460px) {
      .cs-home-head { padding: 14px; }
      .cs-deck { display: none; }
      #cassette-list { padding: 12px; }
      #listen-nowcard { align-items: flex-start; }
      .cs-script-toggle { padding-left: 7px; padding-right: 7px; }
      .cs-main-controls { gap: 4px; }
      .cs-skip { min-width: 34px; padding: 0 6px; }
      .cs-play-primary { width: 48px; height: 48px; }
      #dict-inputrow { flex-direction: column; }
      #dict-check { min-height: 44px; }
      #dict-pos { display: none; }
    }

    @media (prefers-reduced-motion: reduce) {
      .cs-x, .cs-mode-card, .cs-track, #dict-progress-fill { transition: none; }
      .cs-x:hover, .cs-mode-card:hover, .cs-mode-card.focus, .cs-track:hover { transform: none; }
    }

    .glass-modal {
      background: linear-gradient(180deg, #f6deaa 0%, #e8c07a 100%) !important;
      border: 4px solid #8b5a2b;
      border-radius: 8px;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      position: relative;
      overflow: hidden;
      color: #2a1a0a;
    }
    .glass-hud {
      background: rgba(15, 23, 42, 0.85) !important;
      backdrop-filter: var(--glass-blur) !important;
      -webkit-backdrop-filter: var(--glass-blur) !important;
      border: 1.5px solid rgba(245, 158, 11, 0.4);
      box-shadow: 0 0 12px rgba(245, 158, 11, 0.25);
    }
    .neon-border {
      border-color: var(--neon-gold) !important;
      box-shadow: var(--glow-gold) !important;
    }
    .pixel-art-detail {
      image-rendering: pixelated;
      image-rendering: crisp-edges;
    }

    /* ── QUEST LOG OVERLAY ────────────────────────────────────────────────── */
    #quest-overlay {
      position: fixed; inset: 0; z-index: 880; display: none;
      background: var(--farm-veil);
      backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #quest-overlay.visible { display: flex; }
    #quest-panel {
      background: linear-gradient(180deg, #f6deaa, #e8c07a);
      border: 4px solid #8b5a2b; border-radius: 8px;
      max-width: 640px; width: 94%; max-height: 88vh; overflow: hidden;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      color: var(--ink); display: flex; flex-direction: column;
    }
    #quest-header {
      display: flex; align-items: center; justify-content: space-between;
      padding: 10px 14px; background: #fff3d6;
      border-bottom: 2px dashed #c4893a; flex-shrink: 0;
    }
    #quest-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; color: #4a2a0d;
      display: inline-flex; align-items: center; gap: 8px;
    }
    #quest-body { padding: 14px 16px 18px; overflow-y: auto; }
    .quest-tabs { display: flex; gap: 8px; margin-bottom: 10px; }
    .quest-tab-btn {
      flex: 1; padding: 8px 6px; background: #fff8e8;
      border: 2px solid #8b5a2b; border-radius: 8px;
      color: #5b3412; font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 800;
      cursor: pointer; transition: background .15s, border-color .15s, color .15s;
      text-align: center; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    }
    .quest-tab-btn.active {
      background: #4a2a0d; border-color: #4a2a0d; color: #fff8e8;
    }
    .quest-tab-btn:hover { border-color: #4a2a0d; }
    .quest-tab-count {
      min-width: 18px; height: 18px; padding: 0 5px; border-radius: 3px;
      background: #dc2626; color: #fff; font-size: 11px; line-height: 18px; font-weight: 800;
    }
    .quest-tab-btn.active .quest-tab-count { background: #fbbf24; color: #4a2a0d; }
    #quest-meta {
      display: flex; align-items: center; justify-content: space-between; gap: 10px;
      margin-bottom: 12px; flex-wrap: wrap;
    }
    .quest-meta-line { font-size: 12px; font-weight: 700; color: #5b3412; }
    .quest-claim-all {
      background: #166534; border: 2px solid #14532d; color: #ecfdf5;
      border-radius: 4px; padding: 5px 10px; font-size: 12px; font-weight: 800; cursor: pointer;
    }
    .quest-claim-all:hover { filter: brightness(1.08); }

    .quest-list { display: flex; flex-direction: column; gap: 10px; }
    .quest-empty { text-align: center; padding: 24px 8px; font-weight: 700; color: #5b3412; }
    .quest-card {
      background: #fff8e8; border: 2px solid #8b5a2b;
      border-radius: 8px; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px;
    }
    .quest-card.current { border-color: #b45309; box-shadow: inset 0 0 0 1px #fbbf24; }
    .quest-card.ready { border-color: #16a34a; background: #f3fce8; }
    .quest-card.completed { border-color: #166534; background: #ecfdf3; opacity: .92; }
    .quest-card.locked { opacity: .55; }
    .quest-card-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; }
    .quest-card-title-wrap { display: flex; align-items: center; gap: 8px; min-width: 0; }
    .quest-card-icon { font-size: 20px; line-height: 1; flex-shrink: 0; }
    .quest-card-title { font-size: 15px; font-weight: 800; color: #2a1a0a; line-height: 1.25; }
    .quest-card-badges { display: flex; align-items: center; gap: 6px; flex-shrink: 0; flex-wrap: wrap; justify-content: flex-end; }
    .quest-card-tag {
      font-size: 10px; font-weight: 800; letter-spacing: .4px; text-transform: uppercase;
      padding: 2px 7px; border-radius: 3px; background: #f6deaa; color: #5b3412; border: 1px solid #c4893a;
    }
    .quest-card-badge {
      font-size: 11px; font-weight: 800; padding: 3px 8px; border-radius: 3px;
      background: #fff3d6; border: 1px solid #c4893a; color: #4a2a0d;
    }
    .quest-card-badge.ready { background: #dcfce7; border-color: #16a34a; color: #14532d; }
    .quest-card-badge.claimed { background: #dcfce7; border-color: #166534; color: #14532d; }
    .quest-card-badge.locked { background: #e8c07a; border-color: #8b5a2b; color: #5b3412; }
    .quest-card-desc { font-size: 13px; color: #5b3412; font-weight: 600; line-height: 1.4; }
    .quest-card-how { font-size: 12px; color: #7a4a18; font-weight: 600; line-height: 1.35; }
    .quest-progress-labels {
      display: flex; justify-content: space-between; font-size: 11px; font-weight: 800; color: #5b3412;
    }
    .quest-progress-bg {
      width: 100%; height: 10px; background: #e8c07a; border-radius: 3px; overflow: hidden;
      border: 1px solid #8b5a2b;
    }
    .quest-progress-fill {
      height: 100%; background: linear-gradient(90deg, #b45309, #fbbf24); transition: width .3s ease;
    }
    .quest-progress-fill.full { background: linear-gradient(90deg, #166534, #4ade80); }

    .quest-rewards-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; }
    .quest-reward-tags { display: flex; gap: 8px; font-size: 12px; font-weight: 800; color: #4a2a0d; }
    .quest-claimed-label { font-size: 12px; font-weight: 800; color: #166534; }
    .quest-claim-btn {
      background: #166534; border: 2px solid #14532d; border-radius: 4px; padding: 6px 12px;
      font-size: 12px; font-weight: 800; color: #ecfdf5; cursor: pointer;
    }
    .quest-claim-btn:hover:not(:disabled) { filter: brightness(1.08); }
    .quest-claim-btn:disabled { background: #c4893a; border-color: #8b5a2b; color: #fff8e8; opacity: .7; cursor: default; }

    #quest-btn { position: relative; }
    #quest-btn[data-quest-ready]::after {
      content: attr(data-quest-ready);
      position: absolute; top: 50%; right: 10px; transform: translateY(-50%);
      min-width: 16px; height: 16px; padding: 0 4px; border-radius: 3px;
      background: #dc2626; color: #fff; font-size: 10px; font-weight: 800; line-height: 16px;
      text-align: center; pointer-events: none;
    }
    #hud-more-btn { position: relative; overflow: visible; }
    #hud-more-btn.has-quest-ready::after {
      content: '';
      position: absolute; top: 3px; right: 3px;
      width: 8px; height: 8px; border-radius: 4px;
      background: #dc2626; border: 1.5px solid #fff8e8; pointer-events: none;
    }

    /* ── SHOP QUIZ GATE OVERLAY ──────────────────────────────────────────── */
    #shop-quiz-overlay {
      position: fixed; inset: 0; z-index: 900; display: none;
      background: rgba(10, 15, 30, 0.92); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #shop-quiz-overlay.visible { display: flex; }
    #shop-quiz-panel {
      background: rgba(15, 23, 42, 0.95);
      border: 2px solid var(--neon-cyan); border-radius: 8px; padding: 24px;
      max-width: 540px; width: 92%; box-shadow: 0 0 0 2px #0f172a, var(--glow-cyan), 0 20px 60px rgba(0,0,0,.95);
      text-align: center; position: relative;
    }

    /* ── BOSS GATE OVERLAY ───────────────────────────────────────────────── */
    #boss-gate-overlay {
      position: fixed; inset: 0; z-index: 910; display: none;
      background: rgba(20, 5, 15, 0.93); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #boss-gate-overlay.visible { display: flex; }
    #boss-gate-panel {
      background: rgba(35, 15, 25, 0.95);
      border: 2px solid var(--neon-pink); border-radius: 8px; padding: 24px;
      max-width: 560px; width: 92%; box-shadow: 0 0 0 2px #0f172a, var(--glow-pink), 0 20px 60px rgba(0,0,0,.95);
      text-align: center; position: relative;
    }
    /* ── R3 CRAFTING/COOKING OVERLAYS ──────────────────────────────── */
    #recipe-overlay, #cooking-overlay, #cooking-minigame-overlay, #cultural-fact-overlay {
      position: fixed; inset: 0; z-index: 890; display: none;
      background: rgba(10, 15, 30, 0.88); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #recipe-overlay.visible, #cooking-overlay.visible, #cooking-minigame-overlay.visible, #cultural-fact-overlay.visible {
      display: flex;
    }
    .recipe-grid {
      display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 14px; margin-top: 14px;
    }
    .recipe-card {
      background: #fff8e8; border: 1.5px solid #c4893a;
      border-radius: 6px; padding: 10px; display: flex; flex-direction: column; gap: 6px;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b; transition: transform 0.15s, border-color 0.15s;
    }
    .recipe-card:hover { transform: translateY(-2px); border-color: #166534; }
    .recipe-card-icon { text-align: center; min-height: 48px; display: flex; align-items: center; justify-content: center; }
    .recipe-card-icon img, .recipe-card-icon .vocab-art-icon {
      width: 48px; height: 48px; object-fit: contain;
      image-rendering: pixelated; image-rendering: crisp-edges;
    }
    .recipe-card.ready { border-color: #16a34a; }
    .recipe-card-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #7a3e12; text-align: center; }
    .recipe-card-sub { font-size: 11px; color: #5b3412; text-align: center; }
    .recipe-req-list { display: flex; flex-wrap: wrap; gap: 4px; background: #fff3d6; padding: 6px; border-radius: 4px; }
    .recipe-req-chip {
      display: inline-flex; align-items: center; gap: 4px;
      font-size: 10px; color: #5b3412; background: #fff8e8; border-radius: 3px; padding: 2px 6px;
    }
    .recipe-req-chip img { width: 16px; height: 16px; object-fit: contain; image-rendering: pixelated; }
    .recipe-req-chip.ok { color: #166534; }
    .recipe-req-chip.miss { color: #b45309; }
    .recipe-pantry-chip {
      display: inline-flex; align-items: center; gap: 6px;
      background: rgba(15,23,42,0.8); border: 1px solid rgba(255,255,255,0.15);
      border-radius: 4px; padding: 4px 8px; color: #e2e8f0; font-size: 12px;
    }
    .recipe-pantry-chip img { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; }
    .recipe-pantry-empty { color: #94a3b8; }
    .recipe-buff-badge { font-size: 10px; color: var(--neon-cyan); background: rgba(6,182,212,0.15); border: 1px solid var(--neon-cyan); border-radius: 3px; padding: 4px; text-align: center; font-weight: bold; }
    .recipe-card-actions { display: flex; gap: 6px; margin-top: 4px; }
    .recipe-card-actions .cook-btn { flex: 1; }
    .recipe-info-btn {
      background: #fff8e8; border: 1.5px solid #c4893a; color: #7a3e12;
      border-radius: 4px; padding: 8px 10px; font-size: 10px; cursor: pointer;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust);
    }
    .cook-btn {
      background: linear-gradient(135deg, #f59e0b, #d97706); border: none; border-radius: 4px;
      color: #fff; font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; padding: 8px;
      cursor: pointer; transition: opacity 0.15s, transform 0.1s; text-align: center;
    }
    .cook-btn:hover { opacity: 0.9; transform: scale(1.02); }
    .cook-btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

    /* ── COOKING KITCHEN (요리) ─────────────────────────────────────────────
       The kitchen used to be built from ~50 inline style attributes in
       renderCookingGrid, which is why it had no breakpoint, no focus states and no
       reduced-motion story.

       It also inherited a dark-theme palette — slate cards, neon text — from a version
       of this game that no longer exists. `.glass-modal` paints a light parchment
       gradient (#f6deaa → #e8c07a), so pale-yellow-on-translucent-amber was landing on
       parchment and reading as almost nothing. The kitchen now uses the same parchment
       palette as the inventory slots and the recipe book cards. */
    #cooking-panel {
      max-width: 840px; width: 94%; max-height: 88vh;
      overflow-y: auto; padding: 24px; position: relative;
    }

    .ck-header {
      display: flex; justify-content: space-between; align-items: center;
      border-bottom: 2px solid var(--wood-m);
      padding-bottom: 14px; margin-bottom: 14px;
    }
    .ck-header-id { display: flex; align-items: center; gap: 10px; }
    .ck-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 15px; color: var(--wood-d); line-height: 1.4; }
    .ck-subtitle { font-size: 12px; color: #7a3e12; margin-top: 5px; font-family: 'Be Vietnam Pro', sans-serif; }
    .ck-close {
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 4px 12px; font-size: 16px;
      cursor: pointer; line-height: 1.4; flex: 0 0 auto;
      transition: background .15s, border-color .15s;
    }
    .ck-close:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }

    /* ── Mastery progress ─────────────────────────────────────────────────── */
    .ck-progress {
      background: #fff3d6; border: 1.5px solid var(--wood-l);
      border-radius: 8px; padding: 12px 16px; margin-bottom: 12px;
      box-shadow: inset 0 1px 0 #fff;
    }
    .ck-progress-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
    .ck-progress-label { font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 700; color: #5b3412; }
    .ck-progress-badge {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); padding: 5px 10px; border-radius: 4px; white-space: nowrap;
    }
    .ck-progress-track {
      height: 9px; margin-top: 10px; border-radius: 2px; overflow: hidden;
      background: #e0bd85; border: 1px solid var(--wood-m);
    }
    .ck-progress-fill {
      height: 100%; width: 0%; border-radius: 2px;
      background: linear-gradient(90deg, #16a34a, #4ade80);
      transition: width .25s ease;
    }

    /* ── Pantry ───────────────────────────────────────────────────────────── */
    .ck-pantry {
      background: #fff3d6; border: 1.5px solid var(--wood-l);
      border-radius: 8px; padding: 12px 16px; margin-bottom: 12px;
      box-shadow: inset 0 1px 0 #fff;
    }
    .ck-pantry-head {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px;
      color: var(--wood-d); margin-bottom: 8px;
    }
    .ck-pantry-list { display: flex; flex-wrap: wrap; gap: 6px; }
    .ck-pantry-chip {
      display: inline-flex; align-items: center; gap: 5px;
      background: var(--parch-l); border: 1.5px solid var(--wood-l);
      border-radius: 4px; padding: 3px 8px; font-size: 12px; color: #5b3412;
      font-family: 'Noto Sans KR', sans-serif; font-weight: 700;
    }
    .ck-pantry-chip img { width: 20px; height: 20px; object-fit: contain; image-rendering: pixelated; }
    /* An ingredient the selected dish actually calls for. Without this the pantry was a
       flat list and the player had to cross-reference it against the recipe by eye. */
    .ck-pantry-chip.needed { border-color: #16a34a; background: #eaffe9; color: #14532d; }
    .ck-pantry-chip.short  { border-color: #b91c1c; background: #ffe9e9; color: #7f1d1d; }
    .ck-pantry-empty { color: #7a3e12; font-size: 12px; font-family: 'Be Vietnam Pro', sans-serif; }

    /* ── Toolbar ──────────────────────────────────────────────────────────── */
    .ck-toolbar {
      display: flex; justify-content: space-between; align-items: center;
      gap: 10px; flex-wrap: wrap; margin-bottom: 12px;
    }
    .ck-filters { display: flex; gap: 6px; flex-wrap: wrap; }
    .ck-filter {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px;
      padding: 7px 9px; border-radius: 4px; cursor: pointer;
      background: var(--parch-l); color: #7a3e12; border: 1.5px solid var(--wood-l);
      display: inline-flex; align-items: center; gap: 5px;
      transition: background .15s, border-color .15s;
    }
    .ck-filter:hover { border-color: var(--wood-m); }
    .ck-filter.active {
      background: var(--wood-m); color: #fff8e8; border-color: var(--wood-d);
    }
    .ck-filter:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.4); }
    .ck-filter-count {
      font-size: 8px; padding: 2px 5px; border-radius: 3px;
      background: #e8c07a; color: var(--wood-d); min-width: 16px; text-align: center;
    }
    .ck-filter.active .ck-filter-count { background: #fff8e8; color: var(--wood-d); }
    .ck-filter-count.zero { opacity: 0.5; }

    .ck-search { position: relative; display: flex; align-items: center; flex: 1 1 180px; max-width: 250px; }
    .ck-search-icon { position: absolute; left: 10px; font-size: 12px; pointer-events: none; opacity: 0.65; }
    .ck-search-input {
      width: 100%; padding: 8px 10px 8px 30px; border-radius: 4px;
      background: var(--parch-l); border: 1.5px solid var(--wood-l);
      color: var(--ink); font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px;
    }
    .ck-search-input::placeholder { color: #a9793f; }
    .ck-search-input:focus { outline: none; border-color: var(--wood-d); box-shadow: 0 0 0 2px rgba(74,42,13,0.25); }

    .ck-empty-msg {
      font-size: 13px; color: #7a3e12; margin-bottom: 10px; font-weight: 600;
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    .ck-empty-msg.hidden { display: none; }

    /* ── Two-column layout ────────────────────────────────────────────────── */
    .ck-layout { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
    .ck-col { min-width: 0; }
    .ck-col-head {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      color: var(--wood-d); margin-bottom: 8px;
    }
    .ck-recipe-list {
      display: grid; grid-template-columns: 1fr; gap: 8px;
      max-height: 460px; overflow-y: auto; padding-right: 4px;
    }

    /* ── Recipe card ──────────────────────────────────────────────────────── */
    .ck-card {
      background: var(--parch-l); border: 1.5px solid var(--wood-l);
      border-radius: 6px; padding: 9px 11px; cursor: pointer;
      display: flex; align-items: center; gap: 9px;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: border-color .15s, background .15s, transform .12s;
      text-align: left; width: 100%;
    }
    .ck-card:hover { transform: translateY(-1px); border-color: var(--wood-m); }
    .ck-card:focus-visible {
      outline: none; border-color: var(--wood-d);
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m), 0 0 0 3px rgba(74,42,13,0.42);
    }
    /* The list computed cookability per recipe and then threw the answer away — every
       card looked identical whether the pantry could support it or not. */
    .ck-card.ready { border-color: #16a34a; background: #eaffe9; box-shadow: inset 0 1px 0 #fff, 0 2px 0 #15803d; }
    .ck-card.short { background: #f3e3c4; }
    .ck-card.selected {
      border-color: var(--wood-d); background: #ffe9b8;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-d), 0 0 0 2px rgba(74,42,13,0.35);
    }
    .ck-card-icon { flex: 0 0 auto; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; font-size: 22px; }
    .ck-card-icon img { width: 30px; height: 30px; object-fit: contain; image-rendering: pixelated; image-rendering: crisp-edges; }
    .ck-card-body { flex: 1 1 auto; min-width: 0; display: block; }
    /* Spans, not divs: the card is a <button>, and a <div> inside a button is invalid
       markup that browsers reflow unpredictably. They need explicit block display. */
    .ck-card-ko {
      display: block; font-family: 'Noto Sans KR', sans-serif; font-size: 13px;
      font-weight: bold; color: var(--ink); line-height: 1.3;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .ck-card-en {
      display: block; font-size: 10px; color: #7a3e12; font-family: 'Be Vietnam Pro', sans-serif;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .ck-card-tags { flex: 0 0 auto; display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
    .ck-tag {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 7px;
      padding: 3px 5px; border-radius: 4px; white-space: nowrap; border: 1px solid;
    }
    .ck-tag.cooked { background: #dcfce7; border-color: #15803d; color: #14532d; }
    .ck-tag.ready  { background: #bbf7d0; border-color: #16a34a; color: #14532d; }
    .ck-tag.short  { background: #ffe4e4; border-color: #b91c1c; color: #7f1d1d; }

    /* ── Detail panel ─────────────────────────────────────────────────────── */
    .ck-detail {
      background: #fff3d6; border: 2px solid var(--wood-m);
      border-radius: 6px; padding: 18px; min-height: 300px;
      display: flex; flex-direction: column; gap: 12px;
      box-shadow: inset 0 1px 0 #fff;
    }
    .ck-detail-head { display: flex; align-items: center; gap: 12px; }
    .ck-detail-icon { flex: 0 0 auto; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; font-size: 36px; }
    .ck-detail-icon img { width: 48px; height: 48px; object-fit: contain; image-rendering: pixelated; image-rendering: crisp-edges; }
    .ck-detail-ko { font-family: 'Noto Sans KR', sans-serif; font-size: 18px; font-weight: bold; color: var(--ink); line-height: 1.25; }
    .ck-detail-en { font-size: 12px; color: #7a3e12; margin-top: 2px; font-family: 'Be Vietnam Pro', sans-serif; }
    .ck-detail-desc { font-size: 12px; color: #5b3412; line-height: 1.55; font-family: 'Be Vietnam Pro', sans-serif; }
    .ck-section { border-top: 1.5px solid rgba(139,90,43,0.35); padding-top: 10px; }
    .ck-section-head {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px;
      color: var(--wood-d); margin-bottom: 8px;
    }
    .ck-chips { display: flex; flex-wrap: wrap; gap: 6px; }
    .ck-ing {
      display: inline-flex; align-items: center; gap: 4px;
      padding: 4px 8px; border-radius: 3px; font-size: 12px; font-weight: bold;
      font-family: 'Noto Sans KR', sans-serif; border: 1.5px solid;
    }
    .ck-ing img { width: 18px; height: 18px; object-fit: contain; image-rendering: pixelated; }
    .ck-ing.ok   { background: #eaffe9; border-color: #16a34a; color: #14532d; }
    .ck-ing.miss { background: #ffe9e9; border-color: #b91c1c; color: #7f1d1d; }
    .ck-reward {
      padding: 5px 10px; border-radius: 3px; font-size: 9px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); white-space: nowrap; border: 1.5px solid;
    }
    .ck-reward.xp     { background: #f3e8ff; border-color: #7e22ce; color: #581c87; }
    .ck-reward.gold   { background: #fef3c7; border-color: #b45309; color: #78350f; }
    .ck-reward.master { background: #dcfce7; border-color: #15803d; color: #14532d; }

    .ck-cook-wrap { margin-top: auto; padding-top: 10px; }
    .ck-cook-btn {
      width: 100%; padding: 13px; border: 2px solid #b45309; border-radius: 8px; color: #fff;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 11px; line-height: 1.5;
      background: linear-gradient(180deg, #f59e0b, #d97706);
      box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 3px 0 #92400e;
      cursor: pointer; transition: filter .15s, transform .1s;
    }
    .ck-cook-btn:hover:not(:disabled) { filter: brightness(1.07); transform: translateY(-1px); }
    .ck-cook-btn:active:not(:disabled) { transform: translateY(1px); box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 1px 0 #92400e; }
    .ck-cook-btn:focus-visible { outline: none; box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 0 3px 0 #92400e, 0 0 0 3px rgba(74,42,13,0.45); }
    .ck-cook-btn:disabled {
      background: #d9c9a8; border-color: #a9793f; color: #6b533a;
      box-shadow: none; cursor: not-allowed; transform: none;
    }
    /* A greyed button says "no" without saying why. This line does. */
    .ck-cook-hint {
      font-size: 12px; color: #7f1d1d; margin-top: 8px; text-align: center;
      font-family: 'Be Vietnam Pro', sans-serif; line-height: 1.5; font-weight: 600;
    }

    /* Below this the two columns cannot both hold a readable card, so the detail panel
       moves under the list instead of both being squeezed to ~150px. */
    @media (max-width: 720px) {
      .ck-layout { grid-template-columns: 1fr; }
      .ck-recipe-list { max-height: 260px; }
      .ck-detail { min-height: 0; }
    }
    @media (max-width: 560px) {
      #cooking-panel { padding: 16px; }
      .ck-title { font-size: 12px; }
      .ck-search { max-width: none; }
      .ck-detail { padding: 14px; }
      .ck-detail-ko { font-size: 16px; }
    }

    @media (prefers-reduced-motion: reduce) {
      #cooking-overlay { animation: none; }
      .ck-card, .ck-cook-btn, .ck-close, .ck-progress-fill, .ck-filter { transition: none; }
      .ck-card:hover { transform: none; }
      .ck-cook-btn:hover:not(:disabled) { transform: none; }
    }




    .buff-badge {
      background: rgba(246, 222, 170, 0.14); border: 1px solid rgba(232, 192, 122, 0.4); color: #f6deaa;
      border-radius: 3px; padding: 1px 6px; font-size: 10px; font-weight: 700; display: flex; align-items: center; gap: 3px;
    }

    /* ── STUDY DESK · MODE CHOOSER ───────────────────────────────────────── */
    /* 875 and 877 bracket the desk quiz at 876: the chooser sits just under the
       screen it launches, and the workbook just over it, so neither can be
       covered by the overlay it replaced. */
    #desk-menu-overlay {
      position: fixed; inset: 0; z-index: 875; display: none;
      background: rgba(42, 26, 10, 0.62); align-items: center; justify-content: center;
    }
    #desk-menu-overlay.visible { display: flex; }
    #desk-menu-panel { width: min(420px, 92vw); padding: 18px; color: var(--ink); }
    #desk-menu-head {
      display: flex; align-items: flex-start; gap: 12px;
      padding-bottom: 12px; margin-bottom: 14px; border-bottom: 2px dashed #c4893a;
    }
    #desk-menu-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; color: #7a3e12; line-height: 1.4;
    }
    #desk-menu-sub {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 5px;
    }
    .desk-menu-close, .wb-close {
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 4px 12px; font-size: 16px;
      cursor: pointer; line-height: 1.4; flex: 0 0 auto; margin-left: auto;
      transition: background .15s, border-color .15s, color .15s;
    }
    .desk-menu-close:hover, .wb-close:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }
    .desk-menu-close:focus-visible, .wb-close:focus-visible {
      outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45);
    }
    #desk-menu-list { display: flex; flex-direction: column; gap: 9px; }
    .desk-mode {
      display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
      background: #fff8e8; border: 2px solid var(--wood-m); border-radius: 6px;
      padding: 11px 12px; cursor: pointer; color: var(--ink);
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s;
    }
    .desk-mode:hover { background: #fff3d6; transform: translateY(-1px); }
    /* The keyboard cursor has to be visible without a mouse ever moving, so the
       focused row is drawn rather than left to :hover. */
    .desk-mode.focus { border-color: #1e3a8a; background: #fff3d6; box-shadow: inset 0 1px 0 #fff, 0 2px 0 #1e3a8a; }
    .desk-mode:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    .desk-mode-key {
      flex: 0 0 auto; min-width: 20px; height: 20px; line-height: 18px; text-align: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: var(--wood-d);
    }
    .desk-mode-icon { flex: 0 0 auto; font-size: 22px; line-height: 1; }
    .desk-mode-text { display: flex; flex-direction: column; min-width: 0; }
    .desk-mode-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 16px; font-weight: 800; color: var(--ink);
    }
    .desk-mode-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 2px; }
    #desk-menu-hint {
      margin-top: 13px; font-family: 'Be Vietnam Pro', sans-serif;
      font-size: 11px; color: #7a3e12; text-align: center;
    }

    /* ── STUDY DESK · WORKBOOK PAGE ──────────────────────────────────────── */
    #workbook-overlay {
      position: fixed; inset: 0; z-index: 877; display: none;
      background: rgba(42, 26, 10, 0.68); align-items: center; justify-content: center;
    }
    #workbook-overlay.visible { display: flex; }
    #workbook-panel {
      width: min(660px, 95vw); max-height: 92vh; padding: 0; color: var(--ink);
      display: flex; flex-direction: column;
    }
    #wb-head {
      display: flex; align-items: flex-start; gap: 10px; flex-shrink: 0;
      padding: 14px 16px; border-bottom: 2px dashed #c4893a;
      background: linear-gradient(180deg, #fff3d6 0%, transparent);
    }
    #wb-title-wrap { flex: 1; min-width: 0; }
    #wb-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 12px; color: #7a3e12; line-height: 1.4; }
    #wb-sub { font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 5px; }
    #wb-count {
      flex: 0 0 auto; font-family: 'VT323', monospace; font-size: 20px; color: #7a3e12;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 4px;
      padding: 2px 9px; font-variant-numeric: tabular-nums;
    }
    #wb-count.wb-count-all { background: #dcfce7; border-color: #166534; color: #14532d; }
    #wb-count.wb-count-some { background: #fef3c7; border-color: #b45309; color: #78350f; }

    #wb-body { padding: 14px 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; }
    .wb-inst-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; font-weight: 700; color: var(--ink);
    }
    .wb-inst-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412; margin-top: 3px; }
    .wb-strategy { margin-top: 12px; border: 1px solid #bac69a; border-radius: 8px; background: #f1f3e4; }
    .wb-strategy > summary { padding: 10px 12px; color: #3b5535; font: 600 13px 'Be Vietnam Pro', sans-serif; cursor: pointer; }
    .wb-strategy > summary:focus-visible { outline: 2px solid #55734b; outline-offset: 2px; }
    .wb-strategy .wb-inst-note { padding: 0 12px 12px; margin: 0; line-height: 1.7; }
    .wb-inst-note {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #7a3e12;
      margin-top: 6px; padding: 7px 9px; border-radius: 4px;
      background: #fff3d6; border: 1px solid var(--wood-l);
      /* The exam notes are written with paragraphs and a numbered list of the shapes a
         wrong answer takes. Every one of those breaks was being collapsed, so a note
         meant to be scanned arrived as a wall. The 60 unit notes hold no newlines at
         all, so this changes nothing for them. */
      white-space: pre-wrap;
    }
    #wb-example {
      background: #eef4ff; border: 1.5px solid #1e3a8a; border-radius: 4px;
      padding: 10px 12px; font-family: 'Noto Sans KR', sans-serif; font-size: 15px; color: #1a1208;
    }
    .wb-example-tag {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: #1e3a8a; margin-right: 4px;
    }
    .wb-example-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #3b4a6b; margin-top: 4px;
    }

    #wb-bank { display: flex; flex-wrap: wrap; gap: 7px; }
    .wb-chip {
      display: inline-flex; align-items: center; gap: 6px;
      background: #fff8e8; border: 2px solid var(--wood-m); border-radius: 4px;
      padding: 8px 10px; cursor: pointer; color: var(--ink);
      font-family: 'Noto Sans KR', sans-serif; font-size: 14px; font-weight: 700;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s, opacity .15s;
    }
    .wb-chip:hover:not(:disabled) { background: #fff3d6; transform: translateY(-1px); }
    .wb-chip:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    /* Placed, not gone: the chip stays readable so the learner can still see the
       expression they used, and clicking the blank is what returns it. */
    .wb-chip.used { opacity: 0.4; border-style: dashed; box-shadow: none; }
    .wb-chip:disabled { cursor: default; }

    /* ── Dragging a name onto its blank ─────────────────────────────────────
       The chip stays where it is and a ghost follows the cursor, so the box
       does not reflow mid-drag and the row you are aiming at holds still.
       touch-action on the chip is what lets a finger drag it instead of
       scrolling the page; the rows keep theirs so the list can still be
       scrolled with a thumb. */
    .wb-chip { touch-action: none; }
    .wb-chip:not(:disabled) { cursor: grab; }
    .wb-chip.dragging { opacity: 0.3; }
    .wb-ghost {
      position: fixed; z-index: 900; pointer-events: none;
      transform: translate(-50%, -150%);
      background: #dbe4fb; border: 2px solid #1e3a8a; border-radius: 4px;
      padding: 6px 11px;
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; font-weight: 700;
      color: var(--ink); white-space: nowrap;
      box-shadow: 0 6px 18px rgba(0,0,0,0.35);
    }
    /* The row being aimed at. Same blue as focus, but filled, so it reads as
       "let go here" rather than "this one is selected". */
    .wb-row.drop {
      border-color: #1e3a8a; border-width: 2px; background: #dbe4fb;
    }
    .wb-chip-key {
      min-width: 18px; height: 18px; line-height: 16px; text-align: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-d);
    }

    #wb-items { display: flex; flex-direction: column; gap: 8px; }
    .wb-row {
      display: flex; align-items: baseline; gap: 8px;
      background: #fff8e8; border: 1.5px solid var(--wood-l); border-radius: 4px;
      padding: 10px 11px; cursor: pointer;
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; color: var(--ink);
      transition: border-color .15s, background .15s;
    }
    .wb-row.focus { border-color: #55734b; border-width: 2px; background: #fff3d6; }
    .wb-row.ok { border-color: #166534; background: #f2fdf3; cursor: default; }
    .wb-row.bad { border-color: #b91c1c; background: #fff4f4; cursor: default; }
    .wb-row:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    .wb-n { flex: 0 0 auto; font-weight: 800; color: #7a3e12; }
    .wb-sentence { flex: 1 1 auto; line-height: 1.7; }
    .wb-blank {
      display: inline-block; min-width: 128px; padding: 0 6px;
      border-bottom: 2px solid var(--wood-m); text-align: center;
    }
    .wb-blank.filled { color: #14532d; border-bottom-color: #166534; font-weight: 800; }
    .wb-blank.empty { border-bottom-style: dashed; }
    .wb-mark { flex: 0 0 auto; font-size: 17px; font-weight: 800; }
    .wb-row.ok .wb-mark { color: #166534; }
    .wb-row.bad .wb-mark { color: #b91c1c; }

    /* ── Why each answer is the answer ──────────────────────────────────────
       The point of the exercise is not the tick. Each card names the etiquette
       reason and the conjugation separately, because those are two different
       mistakes a learner can make on the same blank. */
    #wb-explain { display: none; }
    #wb-explain.shown { display: flex; flex-direction: column; gap: 9px; }
    .wb-why {
      border-radius: 4px; padding: 11px 12px;
      background: #fff3d6; border: 1.5px solid var(--wood-l);
      font-family: 'Be Vietnam Pro', sans-serif;
    }
    .wb-why.ok { border-color: #166534; background: #f2fdf3; }
    .wb-why.bad { border-color: #b45309; background: #fffaf0; }
    .wb-why-head {
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; color: var(--ink); line-height: 1.6;
    }
    .wb-why-yours {
      font-size: 12px; font-weight: 700; color: #7f1d1d; margin-top: 4px;
      font-family: 'Noto Sans KR', sans-serif;
    }
    .wb-why-en { font-size: 12px; color: #5b3412; margin-top: 5px; font-style: italic; }
    .wb-why-body { font-size: 13px; color: #4a2a0d; margin-top: 6px; line-height: 1.6; }
    .wb-why-gram {
      font-size: 12px; color: #3b0764; margin-top: 7px; line-height: 1.6;
      background: #f7f0ff; border: 1px solid #a855f7; border-radius: 3px; padding: 6px 8px;
    }

    /* TOPIK answers carry several paragraphs because each distractor is part of the lesson.
       Show the answer, meaning and one hinge first; the full comparison remains one click
       away and keeps its original wording. This avoids turning good content into a text wall. */
    #wb-explain.shown { margin-top: 4px; }
    .wb-why-topik {
      padding: 0; overflow: hidden; border-width: 2px; border-radius: 8px;
      background: #fffdf7; font-family: 'Be Vietnam Pro', sans-serif;
    }
    .wb-topik-status {
      display: flex; align-items: center; justify-content: space-between; gap: 10px;
      padding: 10px 13px; background: #f4ead5; border-bottom: 1.5px solid var(--wood-l);
      font-size: 10px; font-weight: 900; letter-spacing: .08em; color: #6b4a22;
    }
    .wb-topik-status > span {
      padding: 4px 7px; border-radius: 3px; background: #e8dcc4; color: #5b3412;
    }
    .wb-why-topik.ok .wb-topik-status > span { background: #dcfce7; color: #14532d; }
    .wb-why-topik.bad .wb-topik-status > span { background: #ffedd5; color: #9a3412; }
    .wb-topik-status > b { font-size: 9px; color: #7a4a18; }
    .wb-why-topik .wb-why-head {
      padding: 15px 16px 13px; font-size: 17px; font-weight: 600; line-height: 1.75;
      background: #fff8e8; border-bottom: 1px solid rgba(139,90,43,.2);
      word-break: keep-all;
      display: flex; align-items: baseline; gap: 8px;
    }
    .wb-why-n { flex: 0 0 auto; font-weight: 800; color: #7a3e12; }
    .wb-why-lines { flex: 1 1 auto; min-width: 0; }
    /* A lone line's speaker chip (문장) labels nothing, as on the question itself. */
    .wb-why-lines > .wb-dlg:only-child > .wb-spk { display: none; }
    .wb-why-topik .wb-why-yours {
      margin: 0; padding: 8px 16px; background: #fff1f2; border-bottom: 1px solid #fecdd3;
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; letter-spacing: .03em;
    }
    .wb-topik-meaning {
      display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 12px;
      align-items: baseline; margin: 13px 16px 0; padding: 10px 12px;
      background: #f8f1e3; border-radius: 5px;
    }
    .wb-topik-meaning > span,
    .wb-learn-card > span {
      font-size: 9.5px; font-weight: 900; letter-spacing: .08em; color: #7a4a18;
    }
    .wb-topik-meaning p { margin: 0; font-size: 13px; line-height: 1.65; color: #4a2a0d; }
    /* A listening row's script, under the answer once it is checked. */
    .wb-topik-script {
      margin: 13px 16px 0; padding: 10px 12px; background: #f0f3e3;
      border-left: 4px solid #55734b; border-radius: 5px;
    }
    .wb-topik-script > span {
      display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline;
      font-size: 9.5px; font-weight: 900; letter-spacing: .08em; color: #3b5535;
    }
    .wb-topik-script > span i { font-style: normal; font-weight: 700; letter-spacing: .04em; color: #6b7f5f; }
    .wb-script-lines p {
      display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 0 10px;
      margin: 6px 0 0; font-size: 14px; line-height: 1.7; color: #2f2410;
    }
    .wb-script-lines p > span:only-child { grid-column: 1 / -1; }
    .wb-script-who { font-weight: 800; color: #7a3e12; }
    .wb-learn-grid {
      display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
      margin: 10px 16px 16px;
    }
    .wb-learn-card {
      min-width: 0; padding: 13px 14px; border-radius: 6px;
      background: #fff8e8; border: 1.5px solid var(--wood-l);
    }
    .wb-learn-card p {
      max-width: 72ch; margin: 7px 0 0; font-size: 13.5px; font-weight: 450;
      line-height: 1.75; color: #39220f; text-wrap: pretty;
    }
    .wb-learn-clue { border-left: 4px solid #b45309; }
    .wb-learn-rule { border-left: 4px solid #55734b; background: #f0f3e3; }
    .wb-learn-rule > span { color: #3b5535; }
    .wb-analysis {
      margin: 0 16px 16px; border: 1.5px solid var(--wood-l); border-radius: 6px;
      background: #faf4e8; overflow: hidden;
    }
    .wb-analysis > summary {
      min-height: 44px; display: flex; align-items: center; justify-content: space-between;
      gap: 12px; padding: 10px 12px; cursor: pointer; list-style: none;
      font-size: 10px; font-weight: 900; letter-spacing: .06em; color: #5b3412;
      background: #f4ead5;
    }
    .wb-analysis > summary::-webkit-details-marker { display: none; }
    .wb-analysis > summary::before {
      content: '＋'; flex: 0 0 auto; width: 22px; height: 22px;
      display: inline-flex; align-items: center; justify-content: center;
      background: #fff8e8; border: 1px solid var(--wood-l); border-radius: 3px;
      color: #7a4a18; font-size: 14px;
    }
    .wb-analysis[open] > summary::before { content: '−'; }
    .wb-analysis > summary span { flex: 1 1 auto; }
    .wb-analysis > summary b {
      flex: 0 0 auto; padding: 3px 6px; border-radius: 3px;
      background: #fff8e8; color: #7a4a18; font-size: 9px;
    }
    .wb-analysis > summary:hover { background: #eee0c6; }
    .wb-analysis > summary:focus-visible { outline: 3px solid rgba(81,110,64,.35); outline-offset: -3px; }
    .wb-analysis-list { display: flex; flex-direction: column; padding: 5px 14px 10px; }
    .wb-analysis-step {
      display: grid; grid-template-columns: 28px minmax(0, 1fr); gap: 10px;
      padding: 11px 0; border-bottom: 1px solid rgba(139,90,43,.2);
    }
    .wb-analysis-step:last-child { border-bottom: 0; }
    .wb-analysis-step > span {
      width: 26px; height: 22px; display: inline-flex; align-items: center; justify-content: center;
      background: #e8dcc4; border-radius: 3px; color: #7a4a18;
      font-size: 9px; font-weight: 900;
    }
    .wb-analysis-step p {
      max-width: 76ch; margin: 0; font-size: 13.5px; font-weight: 400;
      line-height: 1.8; color: #39220f; text-wrap: pretty;
    }

    @media (max-width: 680px) {
      .wb-learn-grid { grid-template-columns: 1fr; }
      .wb-topik-meaning { grid-template-columns: 1fr; gap: 5px; }
      .wb-why-topik .wb-why-head { font-size: 15.5px; padding: 13px 14px; }
      .wb-topik-meaning, .wb-topik-script, .wb-learn-grid, .wb-analysis { margin-left: 12px; margin-right: 12px; }
      .wb-analysis > summary { letter-spacing: .02em; }
      .wb-analysis-step p, .wb-learn-card p { font-size: 13px; }
    }

    /* A hard word inside an explanation, hoverable for its meaning. Dotted rather than
       solid so a sentence full of them still reads as a sentence. The meaning itself is a
       card css/rich.css draws (js/richText.js glossTips), above the word so it never covers
       the line you are still reading. */
    .wb-gl {
      border-bottom: 1px dotted #a16207; cursor: help; position: relative; outline: none;
    }
    .wb-gl:hover, .wb-gl:focus-visible { background: #fef3c7; border-bottom-style: solid; }
    /* The bubble from before the card, for a page the card has not started in. */
    html:not(.hv-gtip) .wb-gl:hover::after, html:not(.hv-gtip) .wb-gl:focus-visible::after {
      content: attr(data-gl);
      position: absolute; left: 50%; bottom: 100%; transform: translate(-50%, -7px);
      background: #3b2410; color: #fdf6e3; font-size: 11px; font-style: normal;
      line-height: 1.45; letter-spacing: 0; text-align: left;
      padding: 5px 8px; border-radius: 4px; border: 1px solid #a16207;
      /* Wide enough for a real gloss, capped so it never spans the panel. */
      min-width: 80px; max-width: 260px; width: max-content;
      white-space: pre-line; z-index: 40; pointer-events: none;
      box-shadow: 0 3px 10px rgba(0, 0, 0, .35);
    }
    html:not(.hv-gtip) .wb-gl:hover::before, html:not(.hv-gtip) .wb-gl:focus-visible::before {
      content: ''; position: absolute; left: 50%; bottom: 100%;
      transform: translate(-50%, -1px);
      border: 5px solid transparent; border-top-color: #3b2410; z-index: 41;
      pointer-events: none;
    }

    #wb-foot {
      display: flex; align-items: center; gap: 10px; flex-shrink: 0;
      padding: 12px 16px; border-top: 2px dashed #c4893a;
    }
    #wb-hint {
      flex: 1 1 auto; font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #5b3412;
    }
    #wb-check {
      flex: 0 0 auto; padding: 10px 18px; border-radius: 4px; cursor: pointer;
      background: linear-gradient(180deg, #86efac, #4ade80);
      border: 2px solid #166534; color: #14532d;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px;
      box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 0 3px 0 #166534;
    }
    #wb-check:hover:not(:disabled) { filter: brightness(1.05); }
    #wb-check:disabled {
      opacity: 0.5; cursor: not-allowed; filter: grayscale(0.5);
      background: var(--parch-l); border-color: var(--wood-l); color: #7a3e12; box-shadow: none;
    }
    #wb-check:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }

    @media (max-width: 560px) {
      #wb-title { font-size: 10px; }
      #wb-body { padding: 12px; gap: 10px; }
      .wb-row { font-size: 14px; padding: 9px; }
      .wb-blank { min-width: 96px; }
      .wb-chip { font-size: 13px; padding: 7px 9px; }
      #desk-menu-title { font-size: 11px; }
    }
    @media (prefers-reduced-motion: reduce) {
      .desk-mode, .wb-chip, .wb-row { transition: none; }
      .desk-mode:hover, .wb-chip:hover:not(:disabled) { transform: none; }
    }

    /* ── Workbook · full screen ───────────────────────────────────────────────
       A workbook page is a page. Boxed into a 660px modal, 연습 3 spent most of
       its height scrolling two-line dialogues through a letterbox, so the panel
       takes the whole viewport and lets the content breathe instead. */
    #workbook-panel {
      width: 100%; max-width: none; height: 100%; max-height: none;
      border-radius: 0; border-left: 0; border-right: 0;
      box-shadow: none;
    }
    /* flex-grow keeps the foot on the bottom edge when a page is short — one drawn question,
       say — instead of floating under it halfway down an empty screen. */
    #wb-body { max-width: 900px; width: 100%; margin: 0 auto; padding: 18px 20px 24px; flex: 1 1 auto; }
    #wb-head, #wb-foot { padding-left: max(20px, calc((100vw - 900px) / 2)); padding-right: max(20px, calc((100vw - 900px) / 2)); }
    .wb-hidden { display: none !important; }

    #wb-back {
      flex: 0 0 auto; padding: 9px 14px; border-radius: 4px; cursor: pointer;
      background: var(--parch-l); border: 2px solid var(--wood-m); color: var(--wood-d);
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 800;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s;
    }
    #wb-back:hover { background: #ffe9b8; border-color: var(--wood-d); }
    #wb-back:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }

    /* ── Workbook · the exercise list ───────────────────────────────────────── */
    .wb-items-pick { gap: 11px !important; }
    .wb-pick {
      display: grid; grid-template-columns: auto auto 1fr auto;
      align-items: center; gap: 13px; width: 100%; text-align: left;
      background: #fff8e8; border: 2px solid var(--wood-m); border-radius: 6px;
      padding: 14px 16px; cursor: pointer; color: var(--ink);
      box-shadow: inset 0 1px 0 #fff, 0 3px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s;
    }
    .wb-pick:hover { background: #fff3d6; transform: translateY(-1px); }
    .wb-pick.focus { border-color: #55734b; background: #fff3d6; box-shadow: inset 0 1px 0 #fff, 0 3px 0 #55734b; }
    .wb-pick:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    .wb-pick-key {
      min-width: 22px; height: 22px; line-height: 20px; text-align: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: var(--wood-d);
    }
    .wb-pick-icon { font-size: 28px; line-height: 1; }
    .wb-pick-text { display: flex; flex-direction: column; min-width: 0; gap: 4px; }
    /* The headline: the grammar point where there is one, the 연습 number where
       there is not. Several rows share a 연습 number and three share their
       Korean instruction word for word, so the pattern is the only thing that
       can carry this line. */
    .wb-pick-title { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; }
    .wb-pick-pat, .wb-pick-name {
      font-family: 'Noto Sans KR', sans-serif; font-size: 16px; font-weight: 800;
      color: var(--ink); letter-spacing: 0;
    }
    .wb-pick-no {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #7a3e12;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      padding: 3px 6px; white-space: nowrap;
    }
    .wb-pick-en { font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; color: #5b3412; }

    /* 어휘 and 문법과 표현. Nine rows in one column read as nine of the same
       thing; split in two they read as three and six. */
    .wb-group {
      display: flex; align-items: baseline; gap: 9px;
      margin: 6px 2px 0; padding-bottom: 7px;
      border-bottom: 2px dashed var(--wood-l);
    }
    .wb-group + .wb-pick { margin-top: -3px; }
    .wb-group-ko {
      font-family: 'Noto Sans KR', sans-serif; font-size: 14px; font-weight: 800; color: #7a3e12;
    }
    .wb-group-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 11px; color: #8b5a2b;
      text-transform: uppercase; letter-spacing: .09em;
    }
    .wb-pick-count {
      font-family: 'VT323', monospace; font-size: 17px; color: #7a3e12; white-space: nowrap;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px; padding: 2px 8px;
    }

    /* ── Workbook · 연습 2, joining two columns ──────────────────────────────
       The book draws two columns and a pencil line between them. On a screen a
       line the learner cannot see the end of is worse than a row that states the
       join outright, so the pairing reads left → right on one line. */
    .wb-items-match .wb-sentence {
      display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.2fr);
      align-items: center; gap: 10px;
    }
    .wb-left { font-weight: 700; }
    .wb-prompt-picture { display: flex; justify-content: center; max-width: 100%; }
    .wb-prompt-picture .wb-art { height: 128px; object-fit: contain; }

    /* A shipped food icon standing in for the prompt. Pixel art, so it scales
       with no smoothing. The row it sits in wants different proportions from a
       text one: the picture takes only its own width and the name gets the rest,
       instead of a text-sized column with a picture rattling around in it. */
    .wb-photo {
      display: block; width: 92px; height: 92px; object-fit: contain;
      image-rendering: pixelated;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 4px;
      padding: 4px;
    }
    /* Centred, not baseline-aligned: against a 92px picture a baseline puts the
       row number down by the plate. */
    .wb-row.photo { align-items: center; }
    .wb-items-match .wb-row.photo .wb-sentence {
      grid-template-columns: auto auto minmax(0, 1fr);
    }
    .wb-row.photo .wb-left { display: flex; }

    /* ── Workbook · matching two columns ────────────────────────────────────
       Pictures down one side, names down the other, the way the book prints it.
       Stacking the names above the pictures — which is what the shared box does
       everywhere else — turned one exercise into two unrelated lists. */
    .wb-items-match.wb-paired { gap: 0 !important; }
    .wb-cols {
      display: grid; grid-template-columns: minmax(0, 1fr) minmax(170px, 0.5fr);
      gap: 16px; align-items: start;
    }
    .wb-col { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
    /* The names stay put while the pictures scroll past them; with six rows the
       column you are picking from would otherwise leave the screen. */
    .wb-names { position: sticky; top: 0; }
    .wb-names .wb-chip { justify-content: flex-start; width: 100%; }
    .wb-paired .wb-row { padding: 8px 10px; }
    /* No dashed rule running the width of the cell. The blank is a grid item, so
       width:auto still stretches it — justify-self is what actually stops it. */
    /* Both classes sit on #wb-items, so this has to out-specify the
       .wb-items-match rule that sets width:100% rather than merely follow it. */
    .wb-items-match.wb-paired .wb-blank {
      min-width: 120px; width: auto; justify-self: start; text-align: center;
    }
    .wb-join { color: #7a3e12; font-weight: 800; }
    .wb-items-match .wb-blank { min-width: 0; width: 100%; text-align: left; }
    .wb-bank-match { flex-direction: column; align-items: stretch; }
    .wb-bank-match .wb-chip { justify-content: flex-start; }

    /* ── Workbook · 연습 3, two-line dialogue ───────────────────────────────── */
    .wb-items-dialogue .wb-row { align-items: flex-start; }
    .wb-dlg { display: flex; align-items: baseline; gap: 8px; line-height: 1.8; }
    .wb-dlg + .wb-dlg { margin-top: 4px; }
    .wb-dlg.reply { color: #5b3412; }
    .wb-spk {
      flex: 0 0 auto; min-width: 19px; height: 19px; line-height: 17px; text-align: center;
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 8px; color: var(--wood-d);
    }
    /* A name rather than an initial: 스티븐 at 8px in a 19px box is a smudge, so it
       gets room and a readable size. The family is stated for intent only — the
       broad span:not(...) rule further up wins on font-family, and Hangul falls
       through that stack to Noto Sans KR anyway. */
    .wb-spk[data-name], .wb-picks-tag[data-name] {
      min-width: 0; height: auto; padding: 1px 5px; line-height: 1.4;
      font-family: 'Noto Sans KR', sans-serif; font-size: 11px; font-weight: 700;
    }
    .wb-dlg.reply .wb-spk { background: #e8dcc4; }
    #wb-example .wb-dlg { line-height: 1.7; }
    #wb-example .wb-spk { background: #dbe4fb; border-color: #1e3a8a; color: #1e3a8a; }

    @media (max-width: 720px) {
      #wb-head, #wb-foot { padding-left: 14px; padding-right: 14px; }
      #wb-body { padding: 14px; }
      .wb-pick { grid-template-columns: auto auto 1fr; padding: 12px; gap: 10px; }
      .wb-pick-count { display: none; }
      .wb-items-match .wb-sentence { grid-template-columns: 1fr; gap: 4px; }
      .wb-join { display: none; }
      .wb-items-match .wb-blank { border-bottom-width: 2px; }
      /* Two columns do not fit a phone. The names go back above the pictures,
         but stay in the list so the exercise still reads as one thing. */
      .wb-cols { grid-template-columns: 1fr; gap: 12px; }
      .wb-names { position: static; order: -1; }
      .wb-row.photo .wb-sentence { grid-template-columns: auto auto minmax(0, 1fr) !important; }
    }
    @media (prefers-reduced-motion: reduce) {
      .wb-pick, #wb-back { transition: none; }
      .wb-pick:hover { transform: none; }
    }

    /* ── Workbook · 문법과 표현, "have you ever…" ────────────────────────────
       Two decisions per question, and they are not the same kind of decision.
       The form is graded; 있어요/없어요 is the learner's own life and is only
       recorded. They are drawn as separate groups, split by a rule, so the page
       never implies that one of the two answers on the right is wrong. */
    .wb-items-experience .wb-row,
    .wb-items-build .wb-row { align-items: flex-start; flex-direction: row; }
    .wb-exp { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
    .wb-exp-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
    .wb-art { display: block; flex: 0 0 auto; image-rendering: pixelated; }
    .wb-exp-head .wb-art {
      background: var(--parch-l); border: 1.5px solid var(--wood-l); border-radius: 4px; padding: 3px;
    }
    .wb-exp-phrase {
      font-family: 'Noto Sans KR', sans-serif; font-size: 16px; font-weight: 800; color: var(--ink);
    }
    .wb-exp-en {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px; color: #7a3e12; font-style: italic;
    }
    .wb-exp-line {
      font-family: 'Noto Sans KR', sans-serif; font-size: 16px; line-height: 2; color: var(--ink);
      padding: 6px 10px; border-radius: 4px;
      background: #fff3d6; border: 1px solid var(--wood-l);
    }
    .wb-exp-picks { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; }
    .wb-exp-sep {
      width: 1px; height: 26px; background: var(--wood-l); margin: 0 5px;
    }
    .wb-pick-form, .wb-pick-own {
      display: inline-flex; align-items: center; gap: 6px;
      background: #fff8e8; border: 2px solid var(--wood-m); border-radius: 4px;
      padding: 7px 10px; cursor: pointer; color: var(--ink);
      font-family: 'Noto Sans KR', sans-serif; font-size: 15px; font-weight: 700;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s;
    }
    .wb-pick-form:hover:not(:disabled), .wb-pick-own:hover:not(:disabled) {
      background: #fff3d6; transform: translateY(-1px);
    }
    .wb-pick-form:focus-visible, .wb-pick-own:focus-visible {
      outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42);
    }
    .wb-pick-form.on { background: #dbe4fb; border-color: #1e3a8a; color: #1a1208; }
    /* Deliberately a neutral choice, not a right one: the same blue as the form
       picker would read as "correct", and this answer is never marked. */
    .wb-pick-own.on { background: #e8dcc4; border-color: var(--wood-d); }
    .wb-pick-form:disabled, .wb-pick-own:disabled { cursor: default; }
    /* After marking, the correct form is outlined even if it was not chosen. */
    .wb-pick-form.key { border-color: #166534; background: #eaffe9; }
    .wb-pick-form.on.key { background: #dcfce7; }
    .wb-row.bad .wb-pick-form.on:not(.key) { border-color: #b91c1c; background: #ffe9e9; }
    .wb-blank.own { min-width: 84px; }

    /* ── Workbook · the sentence being built out of a short script ───────────
       A 'build' row prints one or two spoken lines with the gap wherever the
       book puts it. The speaker chip stays on its own baseline and the line
       beside it takes the rest of the width, so a long B line wraps under
       itself instead of pushing the chip off the row. */
    .wb-dlg .wb-line { flex: 1 1 auto; min-width: 0; }
    .wb-line-solo { line-height: 2; }
    .wb-line-solo + .wb-line-solo { margin-top: 4px; }
    .wb-items-build .wb-blank { min-width: 108px; }
    .wb-items-build .wb-exp-line { font-size: 17px; padding: 8px 12px; }

    /* A row with two blanks gets two groups of buttons, and which group fills
       which blank is not readable off the buttons themselves. The break puts
       each group on its own line and the tag repeats the speaker chip from the
       script above, so the pairing is visible rather than inferred. */
    /* Listen to the row. Sits at the end of the header line rather than beside
       the sentence, because the sentence is the thing being built and a control
       inside it would read as part of the puzzle. */
    .wb-say {
      margin-left: auto; flex: 0 0 auto;
      width: 32px; height: 32px; padding: 0; line-height: 1; font-size: 15px;
      background: var(--parch-l); border: 2px solid var(--wood-m); border-radius: 4px;
      cursor: pointer; color: var(--ink);
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, transform .12s;
    }
    .wb-say:hover { background: #fff3d6; transform: translateY(-1px); }
    .wb-say:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    /* A row backed by the book's own recording rather than a synthesised voice.
       Worth marking: it is the difference between a model to copy and an
       approximation of one. */
    .wb-say.book { border-color: #1e3a8a; background: #dbe4fb; }
    .wb-say.book:hover { background: #ccd9f7; }
    #wb-example .wb-say { margin-top: 8px; margin-left: 0; }

    .wb-picks-break { flex-basis: 100%; height: 0; margin: 0; }
    .wb-picks-tag {
      display: inline-flex; align-items: center; justify-content: center;
      min-width: 22px; height: 24px; padding: 0 6px;
      background: #e8dcc4; border: 1.5px solid var(--wood-m); border-radius: 3px;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: var(--wood-d);
    }

    @media (max-width: 720px) {
      .wb-exp-line { font-size: 15px; line-height: 1.9; }
      .wb-exp-phrase { font-size: 15px; }
      .wb-exp-sep { display: none; }
      .wb-exp-picks { gap: 6px; }
      .wb-pick-form, .wb-pick-own { font-size: 14px; padding: 6px 9px; }
      .wb-items-build .wb-blank { min-width: 88px; }
      .wb-say { width: 30px; height: 30px; font-size: 14px; }
    }
    @media (prefers-reduced-motion: reduce) {
      .wb-say { transition: none; }
      .wb-say:hover { transform: none; }
    }
    @media (prefers-reduced-motion: reduce) {
      .wb-pick-form, .wb-pick-own { transition: none; }
      .wb-pick-form:hover:not(:disabled), .wb-pick-own:hover:not(:disabled) { transform: none; }
    }

    /* ── Workbook · a test question ──────────────────────────────────────────
       A row with no headline, picture or translation to show has an empty head
       (js/ui.js wbHeadline); left in, it was a blank line and a gap above the
       sentence. */
    .wb-exp-head:empty { display: none; }
    /* The part a 밑줄 question is about, underlined the way the paper prints it. */
    .wb-under {
      text-decoration: underline; text-decoration-thickness: 2px;
      text-underline-offset: 5px; text-decoration-color: #b45309;
    }
    /* wbQuestionClasses: the options of a test question in an even grid, the
       way a paper sets them out, their columns as wide as the longest option
       needs — four across for an ending (two on a phone), two for a phrase,
       one each for a headline-length sentence. */
    .wb-row.wb-q .wb-exp-picks {
      display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px;
    }
    .wb-row.wb-q.wb-q-wide .wb-exp-picks { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
    .wb-row.wb-q.wb-q-long .wb-exp-picks { grid-template-columns: minmax(0, 1fr); }
    .wb-row.wb-q .wb-pick-form { justify-content: flex-start; text-align: left; }
    .wb-row.wb-q .wb-exp-line { background: #fffdf6; }
    /* Nothing above the sentence: the number sits on its first line, and a lone
       line's speaker chip (문장) labels nothing and goes. */
    .wb-items-build .wb-row.wb-q-bare { align-items: baseline; }
    .wb-row.wb-q-bare .wb-exp-line > .wb-dlg:only-child > .wb-spk { display: none; }

    /* ── Workbook · one question at a time ───────────────────────────────────
       The switch above the questions, and while a question is drawn, the line
       saying which one and how far into the round (js/ui.js wbRenderDrawBar). */
    #wb-draw { display: flex; align-items: center; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
    #wb-draw.on {
      justify-content: space-between; padding: 8px 8px 8px 12px; border-radius: 6px;
      background: #eef4ff; border: 1.5px solid #1e3a8a;
    }
    .wb-draw-status { font-size: 13px; font-weight: 700; color: #1e3a8a; line-height: 1.45; }
    .wb-draw-btn {
      flex: 0 0 auto; padding: 7px 12px; border-radius: 4px; cursor: pointer;
      background: var(--parch-l); border: 2px solid var(--wood-m); color: var(--wood-d);
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 800;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, transform .12s;
    }
    .wb-draw-btn:hover { background: #ffe9b8; border-color: var(--wood-d); transform: translateY(-1px); }
    .wb-draw-btn:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }
    @media (max-width: 560px) {
      #wb-draw.on { padding: 8px 10px; }
      .wb-draw-btn { font-size: 12px; padding: 6px 10px; }
    }
    @media (prefers-reduced-motion: reduce) {
      .wb-draw-btn { transition: none; }
      .wb-draw-btn:hover { transform: none; }
    }

    /* ── AUDIO MIXER OVERLAY ─────────────────────────────────────────────── */
    /* 645 sits just above the progress dashboard at 640 and below the inventory
       family at 870: sound is reachable from the More menu like they are, and
       nothing else should ever open on top of it. */
    #audio-overlay {
      position: fixed; inset: 0; z-index: 645; display: none;
      align-items: center; justify-content: center;
      background: var(--farm-veil); backdrop-filter: blur(8px);
    }
    #audio-overlay.visible { display: flex; }
    #audio-panel {
      background: linear-gradient(180deg, #f6deaa, #e8c07a);
      border: 4px solid #8b5a2b; border-radius: 8px;
      width: min(460px, 94vw); max-height: 88vh; overflow-y: auto;
      box-shadow: 0 0 0 3px #4a2a0d, inset 0 0 0 2px #c4893a, 0 18px 40px rgba(0,0,0,.45);
      color: var(--ink);
    }
    #audio-header {
      display: flex; align-items: flex-start; gap: 12px;
      padding: 14px 16px; border-bottom: 2px dashed #c4893a;
      background: linear-gradient(180deg, #fff3d6 0%, transparent);
    }
    #audio-title-wrap { flex: 1; min-width: 0; }
    #audio-title {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 13px; color: #7a3e12;
      display: flex; align-items: center; gap: 8px; line-height: 1.4;
    }
    #audio-sub {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px;
      color: #5b3412; margin-top: 5px;
    }
    .audio-close {
      background: var(--parch-l); border: 1.5px solid var(--wood-m);
      color: var(--wood-d); border-radius: 4px; padding: 4px 12px; font-size: 16px;
      cursor: pointer; line-height: 1.4; flex: 0 0 auto;
      transition: background .15s, border-color .15s, color .15s;
    }
    .audio-close:hover { background: #ffd9d9; border-color: #b91c1c; color: #b91c1c; }
    .audio-close:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }

    #audio-body { padding: 14px 16px 18px; display: flex; flex-direction: column; gap: 10px; }

    .study-settings {
      display: flex; flex-direction: column; gap: 10px;
      padding: 14px; margin-bottom: 6px; background: #fff8e8;
      border: 2px solid #b8894a; border-radius: 8px;
      font-family: 'Be Vietnam Pro', sans-serif; color: #4a2a0d;
    }
    .study-settings h2 { font-size: 18px; }
    .study-settings label { font-size: 15px; font-weight: 800; }
    .study-settings p { font-size: 13px; line-height: 1.6; }
    .study-settings .settings-device-note { color: #765735; font-size: 12px; }
    .settings-media-clear { padding: 10px 12px; min-height: 44px; border: 2px solid #8b5a2b; border-radius: 6px; background: #fffdf5; color: #4a2a0d; font: inherit; cursor: pointer; }
    .settings-media-clear:focus-visible { outline: 3px solid #15803d; outline-offset: 3px; }
    .settings-view-toggle { display: flex; align-items: center; justify-content: space-between; gap: 14px; min-height: 44px; cursor: pointer; }
    #settings-close-view { width: 26px; height: 26px; flex-shrink: 0; accent-color: #166534; cursor: pointer; }
    #settings-daily-reviews {
      width: 100%; min-height: 48px; padding: 8px 12px; font: 800 22px 'Be Vietnam Pro', sans-serif;
      border: 2px solid #8b5a2b; border-radius: 6px; background: #fffdf5; color: #2a1a0a;
    }
    .study-settings input:focus-visible { outline: 3px solid #15803d; outline-offset: 3px; }

    .audio-switch {
      width: 100%; padding: 11px; border-radius: 4px; cursor: pointer;
      background: var(--parch-l); border: 2px solid var(--wood-m); color: var(--wood-d);
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 14px; font-weight: 800;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 var(--wood-m);
      transition: background .15s, border-color .15s, color .15s;
    }
    .audio-switch:hover { background: #ffe9b8; border-color: var(--wood-d); }
    .audio-switch:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(74,42,13,0.42); }
    /* Off is a state worth seeing at a glance, not a word to read. */
    .audio-switch.audio-off {
      background: #f0d6c4; border-color: #b91c1c; color: #7f1d1d;
      box-shadow: inset 0 1px 0 #fff, 0 2px 0 #8b5a2b;
    }

    .audio-row {
      display: grid; grid-template-columns: 118px 1fr 42px;
      align-items: center; gap: 10px;
      background: #fff3d6; border: 1.5px solid var(--wood-l);
      border-radius: 4px; padding: 9px 11px;
      box-shadow: inset 0 1px 0 #fff;
    }
    .audio-row-name {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px;
      font-weight: 700; color: #5b3412; white-space: nowrap;
      overflow: hidden; text-overflow: ellipsis;
    }
    .audio-row-val {
      font-family: 'VT323', monospace; font-size: 17px; color: #7a3e12;
      text-align: right; font-variant-numeric: tabular-nums;
    }

    /* A range input inherits none of the parchment, and the platform default is
       a grey pill that reads as a foreign control on this panel. Both vendor
       tracks and thumbs are styled, and the thumb is square like the rest of the
       chrome now. */
    .audio-slider {
      -webkit-appearance: none; appearance: none;
      width: 100%; height: 20px; background: transparent; cursor: pointer; margin: 0;
    }
    .audio-slider::-webkit-slider-runnable-track {
      height: 9px; border-radius: 2px;
      background: #e0bd85; border: 1px solid var(--wood-m);
    }
    .audio-slider::-webkit-slider-thumb {
      -webkit-appearance: none; appearance: none;
      width: 16px; height: 18px; margin-top: -6px; border-radius: 3px;
      background: linear-gradient(180deg, #fff8e8, #e8c07a);
      border: 1.5px solid var(--wood-d);
      box-shadow: inset 0 1px 0 #fff, 0 1px 0 var(--wood-m);
    }
    .audio-slider::-moz-range-track {
      height: 9px; border-radius: 2px;
      background: #e0bd85; border: 1px solid var(--wood-m);
    }
    .audio-slider::-moz-range-thumb {
      width: 14px; height: 16px; border-radius: 3px;
      background: linear-gradient(180deg, #fff8e8, #e8c07a);
      border: 1.5px solid var(--wood-d);
    }
    .audio-slider:focus-visible { outline: none; }
    .audio-slider:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }
    .audio-slider:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 3px rgba(74,42,13,0.45); }

    .audio-note {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 12px;
      line-height: 1.5; color: #5b3412; margin: 2px 0 0;
    }

    /* ── Interface language ────────────────────────────────────────────────
       Two columns rather than the three a volume row uses: there is no numeric
       readout, and the buttons want the width. Be Vietnam Pro is already the UI
       face throughout, so Vietnamese diacritics need nothing added here. */
    .audio-row-lang { grid-template-columns: 118px 1fr; }
    .hv-lang-picker { display: flex; gap: 6px; flex-wrap: wrap; }
    .hv-lang-btn {
      font-family: 'Be Vietnam Pro', sans-serif; font-size: 13px; font-weight: 700;
      color: #5b3412; background: #ffe9b8; border: 1.5px solid var(--wood-l);
      border-radius: 4px; padding: 6px 10px; cursor: pointer;
      box-shadow: inset 0 1px 0 #fff; transition: background .12s, transform .12s;
    }
    .hv-lang-btn:hover { background: #fff3d6; transform: translateY(-1px); }
    .hv-lang-btn.active {
      background: var(--wood-d, #7a3e12); color: #ffe9b8; border-color: var(--wood-d, #7a3e12);
      box-shadow: inset 0 1px 0 rgba(255,255,255,.18);
    }

    /* On the level select the picker floats under the grid, on the dark backdrop
       rather than on the panel's parchment, so it takes its own colours. */
    #ls-lang { justify-content: center; margin: 18px auto 4px; }
    #ls-lang .hv-lang-btn {
      background: rgba(15, 23, 42, .55); color: #e2e8f0;
      border-color: rgba(226, 232, 240, .28);
      box-shadow: none; backdrop-filter: blur(4px);
    }
    #ls-lang .hv-lang-btn:hover { background: rgba(30, 41, 59, .8); }
    #ls-lang .hv-lang-btn.active {
      background: #4ade80; color: #0f172a; border-color: #4ade80; font-weight: 800;
    }

    @media (max-width: 560px) {
      .audio-row { grid-template-columns: 92px 1fr 38px; gap: 8px; padding: 8px 9px; }
      .audio-row-name { font-size: 12px; }
      #audio-title { font-size: 11px; }
    }
    @media (prefers-reduced-motion: reduce) {
      .audio-switch, .audio-close { transition: none; }
    }

    /* ── LOCAL LEADERBOARD OVERLAY ──────────────────────────────────────────── */
    #leaderboard-overlay {
      position: fixed; inset: 0; z-index: 890; display: none;
      background: rgba(10, 15, 30, 0.88); backdrop-filter: var(--glass-blur);
      -webkit-backdrop-filter: var(--glass-blur);
      align-items: center; justify-content: center; animation: fadeIn .2s;
    }
    #leaderboard-overlay.visible { display: flex; }

    .lb-head { display: flex; justify-content: space-between; align-items: center; border-bottom: 2px dashed #c4893a; padding-bottom: 14px; margin-bottom: 16px; }
    .lb-head-copy { display: flex; align-items: center; gap: 10px; }
    .lb-seal { font-size: 32px; line-height: 1; }
    .lb-title { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 14px; color: #4a2a0d; }
    .lb-sub { font-size: 12px; font-weight: 700; color: #5b3412; margin-top: 4px; }
    .lb-close {
      background: #fff8e8; border: 2px solid #8b5a2b; color: #2a1a0a;
      border-radius: 4px; padding: 4px 12px; font-size: 16px; cursor: pointer;
    }
    #lb-pb-summary {
      background: #fff8e8; border: 2px solid #8b5a2b; border-radius: 8px;
      padding: 14px; margin-bottom: 16px; color: #2a1a0a;
    }
    .lb-pb-kicker {
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 10px; color: #4a2a0d; margin-bottom: 8px;
    }
    #lb-pb-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; font-size: 12px; }
    .lb-pb-chip {
      background: #fff3d6; border: 1px solid #c4893a; border-radius: 4px;
      padding: 8px; color: #2a1a0a; font-weight: 700;
    }
    .lb-pb-chip b { color: #b45309; }

    .lb-tabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px; border-bottom: 2px dashed #c4893a; padding-bottom: 8px; }
    .lb-tab-btn {
      background: #fff8e8; border: 2px solid #8b5a2b; border-radius: 4px; color: #4a2a0d;
      font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; padding: 6px 10px; cursor: pointer;
    }
    .lb-tab-btn.active { background: #fde68a; border-color: #b45309; color: #4a2a0d; }

    .lb-table { width: 100%; border-collapse: collapse; margin-top: 8px; color: #2a1a0a; }
    .lb-table th { font-family: var(--font-pixel); font-size-adjust: var(--font-pixel-adjust); font-size: 9px; color: #4a2a0d; text-align: left; padding: 8px; border-bottom: 2px solid #8b5a2b; }
    .lb-table td { font-size: 13px; font-weight: 600; padding: 8px; border-bottom: 1px solid #e8c07a; color: #2a1a0a; }
    .lb-table .lb-title-cell { color: #5b3412; }
    .lb-table .lb-val { color: #b45309; font-weight: 800; }
    .lb-row-player { background: #fff3d6; font-weight: bold; border-left: 3px solid #b45309; }
    /* The board is fetched now, so it has states a hard-coded list never had: loading, offline,
       not configured, and nobody on it yet. Each one says what happened rather than showing an
       empty table, which reads as a bug. */
    .lb-empty {
      padding: 18px 14px; text-align: center; color: #78350f; line-height: 1.5;
      background: rgba(255, 251, 235, 0.7); border: 1px dashed rgba(139, 90, 43, 0.45);
    }
    /* The break between the top of the board and your own row when you are below it. */
    .lb-row-gap td {
      text-align: center; color: #b45309; letter-spacing: 4px; padding: 2px 0;
      background: rgba(255, 251, 235, 0.5);
    }
    .lb-foot { margin-top: 8px; font-size: 11px; color: #8b5a2b; text-align: center; }


    /* ── Something to aim at ─────────────────────────────────────────────────
       These are the controls that came in under the 44px a finger needs: the ✕ on six
       panels sat at roughly 35x31, and the one on the memory game at 15x32 — narrower
       than the glyph it draws.

       The hit area grows, the button does not. A ::after box centred on the control takes
       the press, so the parchment squares stay the size the panels were drawn around and
       the target underneath them is the size a thumb expects. The buy buttons are the
       exception: they are the primary action on a card and had room to grow honestly. */
    #shop-close-btn, #fish-album-close-btn, #memory-close-btn, #trophy-close-btn,
    #cat-dialog-close, .prog-close, .lb-close, .audio-close, #vocab-close-btn,
    #vff-header-close {
      position: relative;
    }
    #shop-close-btn::after, #fish-album-close-btn::after, #memory-close-btn::after,
    #trophy-close-btn::after, #cat-dialog-close::after, .prog-close::after,
    .lb-close::after, .audio-close::after, #vocab-close-btn::after,
    #vff-header-close::after {
      content: ''; position: absolute; top: 50%; left: 50%;
      width: 44px; height: 44px; transform: translate(-50%, -50%);
      /* Behind the glyph so it never covers it, and above nothing else — the button is
         already the top of its own stacking context. */
      z-index: 0;
    }
    .shop-buy-btn, .trophy-buy-btn {
      min-height: 44px;
    }

/* Picture references and listening choices in illustrated textbook lessons. */
.wb-visual-guide { display:grid; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); gap:10px; margin:16px 0 4px; }
.wb-visual-guide figure { margin:0; padding:10px 6px; text-align:center; background:#fff9e9; border:1px solid #cfb582; border-radius:10px; color:#49351f; }
.wb-visual-guide .wb-art { display:block; width:100%; height:112px; margin:0 auto 8px; object-fit:contain; }
.wb-visual-guide figcaption { font-weight:700; line-height:1.45; overflow-wrap:anywhere; }
.wb-pick-form.wb-pick-picture { display:flex; flex:1 1 150px; flex-direction:column; align-items:center; gap:8px; max-width:240px; white-space:normal; text-align:center; padding:12px; }
.wb-pick-picture .wb-art { width:100%; height:112px; object-fit:contain; }

/* Close-up study mode: the farm zoom is handled by Phaser; the question uses
   the full viewport with a separate illustration column on wide screens. */
body.close-view #quiz-ui {
  width: 100%; height: 100vh; height: 100dvh; max-height: none;
  border-radius: 0; border-width: 3px; box-shadow: none;
  padding: max(16px, env(safe-area-inset-top)) max(20px, env(safe-area-inset-right)) max(16px, env(safe-area-inset-bottom)) max(20px, env(safe-area-inset-left));
  gap: 16px; overflow-x: hidden; overscroll-behavior: contain;
}
body.close-view #quiz-ui > * { flex-shrink: 0; }
body.close-view #quiz-ui .quiz-header { position: sticky; top: 0; z-index: 3; background: #f6deaa; }
body.close-view .quiz-title { font: 800 clamp(20px, 2vw, 28px)/1.4 'Be Vietnam Pro', sans-serif; letter-spacing: 0; }
body.close-view #quiz-level-tag { font-size: 16px !important; color: #765735 !important; }
body.close-view .quiz-close-view {
  display: inline-flex; align-items: center; justify-content: center;
  width: 48px; min-height: 48px; flex-shrink: 0; cursor: pointer;
  font-size: 24px; color: #4a2a0d; background: #fff8e8; border: 2px solid #8b5a2b; border-radius: 8px;
}
body.close-view #quiz-study {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center; gap: clamp(20px, 3vw, 48px);
  width: 100%; max-width: 1480px; margin: auto; padding: 8px 0;
}
body.close-view #quiz-answer-area { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
body.close-view #quiz-hint-box { display: flex; flex-direction: column; justify-content: center; min-width: 0; padding: 24px 16px; }
body.close-view #hint-emoji { min-height: 384px; font-size: 220px; }
body.close-view #hint-emoji img, body.close-view #hint-emoji .vocab-art-icon,
body.close-view #quiz-result-art img, body.close-view #quiz-result-art .vocab-art-icon {
  width: auto; height: 384px; max-width: 100%; object-fit: contain;
}
body.close-view #hint-category { font: 700 20px/1.5 'Be Vietnam Pro', sans-serif; letter-spacing: 0; }
body.close-view #question-text { font: 700 clamp(22px, 2vw, 28px)/1.5 'Be Vietnam Pro', sans-serif; letter-spacing: 0; }
body.close-view #en-word-display { font: 800 clamp(26px, 2.5vw, 36px)/1.4 'Be Vietnam Pro', sans-serif; font-size-adjust: none; overflow-wrap: anywhere; }
body.close-view #quiz-ko-word, body.close-view #quiz-result-ko { font-size: clamp(36px, 4vw, 56px); overflow-wrap: anywhere; }
body.close-view #answer-input { font-size: 40px; min-height: 68px; }
body.close-view #answer-input::placeholder { font-size: 22px; }
body.close-view .quiz-choice-btn { font-size: 22px; min-height: 64px; padding: 14px; overflow-wrap: anywhere; }
body.close-view #quiz-steps { font-size: 16px; }
body.close-view #quiz-gold-reward { font: 700 16px/1.4 'Be Vietnam Pro', sans-serif; font-size-adjust: none; }
body.close-view .quiz-tier-btn, body.close-view #quiz-listen-replay {
  font: 700 16px/1.4 'Be Vietnam Pro', sans-serif; font-size-adjust: none; min-height: 48px; padding: 10px 12px;
}
body.close-view #quiz-ko-speak { min-width: 48px; min-height: 48px; font-size: 24px; }
body.close-view #quiz-funfact-title, body.close-view #quiz-result-example-label { font: 800 16px/1.4 'Be Vietnam Pro', sans-serif; font-size-adjust: none; }
body.close-view #quiz-funfact-text, body.close-view #quiz-hint-reveal-card { font-size: 20px; }
body.close-view #quiz-funfact-culture, body.close-view #quiz-result-note { font-size: 18px; }
body.close-view .recall-tile { width: 34px; height: 34px; }
body.close-view .recall-word { max-width: 100%; flex-wrap: wrap; row-gap: 4px; }
body.close-view .recall-literal { height: 34px; font-size: 24px; }
body.close-view #submit-btn, body.close-view #cancel-btn, body.close-view #quiz-result-continue {
  font: 800 22px/1.4 'Be Vietnam Pro', sans-serif; letter-spacing: 0; min-height: 60px; padding: 12px;
}
body.close-view .quiz-buttons { position: sticky; bottom: -16px; z-index: 1; background: #e8c07a; padding: 8px 0; }
body.close-view #quiz-result {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  width: 100%; max-width: 1200px; margin: auto; gap: 14px 32px; text-align: left;
}
body.close-view #quiz-result > * { grid-column: 2; min-width: 0; }
body.close-view #quiz-result #quiz-result-art { grid-column: 1; grid-row: 1 / span 8; max-width: 100%; }
body.close-view #quiz-result-msg, body.close-view #feedback-text { font: 800 26px/1.4 'Be Vietnam Pro', sans-serif; }
body.close-view #quiz-result-en, body.close-view #quiz-result-example { font-size: 24px; line-height: 1.5; }
body.close-view #quiz-result-example-tr, body.close-view #quiz-result-typed { font-size: 20px; line-height: 1.5; }
body.close-view #quiz-ui.quiz-done #quiz-study { display: none; }
body.close-view #quiz-ui button:focus-visible { outline: 3px solid #166534; outline-offset: 3px; }
@media (max-width: 800px) {
  body.close-view #quiz-ui { padding: 12px; gap: 12px; }
  body.close-view #quiz-study { grid-template-columns: minmax(0, 1fr); gap: 18px; margin: 0 auto; }
  body.close-view #quiz-hint-box { padding: 16px 10px; }
  body.close-view #hint-emoji { min-height: 192px; font-size: 140px; }
  body.close-view #hint-emoji img, body.close-view #hint-emoji .vocab-art-icon,
  body.close-view #quiz-result-art img, body.close-view #quiz-result-art .vocab-art-icon { height: 192px; }
  body.close-view .quiz-header { gap: 8px; }
  body.close-view .quiz-title { font-size: 20px; }
  body.close-view #quiz-phase-bar { flex-wrap: wrap; }
  body.close-view #quiz-steps { font-size: 14px; }
  body.close-view .quiz-step { padding: 4px 6px; }
  body.close-view .quiz-buttons { bottom: -12px; }
  body.close-view #quiz-result-ko { font-size: 36px; }
  body.close-view #quiz-result { display: flex; text-align: center; }
  body.close-view #quiz-result-continue { position: sticky; bottom: 0; }
}
/* A delayed, dismissible-by-closing-player status, shared by speech and recordings. */
#media-audio-status { position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%); z-index: 30000; padding: 10px 16px; border-radius: 12px; border: 1px solid #c9d4b9; background: #fff8df; color: #29482d; font: inherit; box-shadow: 0 3px 12px #0003; }
