        :root {
            /* ── Color roles — "living maths exercise book" ───────
               ink on paper, fountain-pen blue actions, pencil-brass
               rewards, marking-pen tick/cross feedback. ─────────── */
            --primary: #3B47C4;        /* fountain pen */
            --primary-dark: #2E38A6;
            --primary-light: #E9EBFB;
            --success: #178A50;        /* marking-pen tick */
            --success-dark: #0F6B3C;
            --success-light: #E0F4E8;
            --error: #C42B3D;          /* marking-pen cross */
            --error-light: #FBE7EA;
            --gold: #F0B429;           /* pencil brass */
            --gold-light: #FBF3D9;
            --gold-line: #EBD7A4;
            --gold-dark: #B7791F;
            --text: #1E2A4A;           /* ink */
            --text-muted: #5A6785;
            --background: #EEF1FA;     /* desk */
            --background-dim: #E2E6F2;
            --line-dashed: #C5CCE0;    /* pencil grey */
            --card-bg: #FDFBF7;        /* paper */
            /* Exercise-book page furniture */
            --grid-line: rgba(59,71,196,0.065);
            --margin-rule: rgba(196,43,61,0.32);
            /* Accent set (felt-tip pens) */
            --grape: #6D4AC4;
            --grape-dark: #5A38B0;
            --berry: #C4387C;
            --berry-bright: #DE4E90;
            --indigo-2: #4A57D6;
            --navy-800: #27325A;       /* chalkboard */
            --navy-900: #182142;
            --sky: #0B6E99;
            --sky-2: #3E8DC4;
            --butter: #FFE08A;         /* chalk yellow */
            /* Dungeon-board materials (maze modal frame & reward medallion —
               DOM-side companions to the canvas-internal MAZE_PAL) */
            --wood-hi: #7A5A3A;
            --wood: #5C4330;
            --wood-dark: #3B2A1C;
            --iron: #3A3F4A;

            /* ── Type ────────────────────────────────────────────── */
            --font-display: 'Baloo 2', 'Andika', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            --font-body: 'Andika', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            --font-hand: 'Caveat', cursive;

            /* ── Space (4px base) ────────────────────────────────── */
            --sp-1: 4px;
            --sp-2: 8px;
            --sp-3: 12px;
            --sp-4: 16px;
            --sp-5: 20px;
            --sp-6: 24px;
            --sp-8: 32px;

            /* ── Radii ───────────────────────────────────────────── */
            --r-sm: 10px;
            --r-md: 14px;
            --radius-card: 20px;
            --radius-pill: 999px;

            /* ── Elevation ───────────────────────────────────────── */
            --border-subtle: 1px solid rgba(28,35,51,0.07);
            --shadow-1: 0 2px 12px rgba(28,35,51,0.08);
            --shadow-2: 0 2px 6px rgba(28,35,51,0.05), 0 8px 24px rgba(28,35,51,0.07);
            --shadow-3: 0 10px 30px rgba(28,35,51,0.2), 0 2px 8px rgba(28,35,51,0.1);

            /* ── Z ladder (matches long-standing stacking order; Netlify
                   Identity widget is forced to 2000 further down) ──── */
            --z-nav: 55;
            --z-header: 60;
            --z-menu: 70;
            --z-fullscreen: 200;
            --z-sheet: 900;
            --z-modal: 1000;
            --z-overlay: 1050;
            --z-customize: 1100;
            --z-toast: 1300;
            --z-gate: 1400;

            /* ── Motion ──────────────────────────────────────────── */
            --dur-fast: 120ms;
            --dur-base: 200ms;
            --dur-celebrate: 450ms;
            --ease-standard: cubic-bezier(0.22, 1, 0.36, 1);
            --ease-out-back: cubic-bezier(0.22, 1.6, 0.4, 1);

            /* Only read at (min-width: 801px). The header is a single flex row
               (logo/title + three action pills), measured at desktop width —
               re-measure if header padding or pill sizing changes. */
            --arena-header-h: 56px;
        }

        * {
            box-sizing: border-box;
            font-family: var(--font-body);
            margin: 0;
            padding: 0;
        }

        ::selection { background: var(--primary-light); color: var(--primary); }

        .font-display { font-family: var(--font-display); font-weight: 800; }
        .font-mono { font-variant-numeric: tabular-nums; font-weight: 700; }

        body {
            background-color: var(--background);
            background-image: radial-gradient(ellipse 80% 60% at 50% 0%, #F3F0FA 0%, var(--background) 55%, #E9EEF9 100%);
            color: var(--text);
            display: flex;
            flex-direction: column;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
            line-height: 1.5;
            position: relative;
        }
        body::before {
            content: '';
            position: fixed;
            inset: 0;
            pointer-events: none;
            z-index: 0;
            opacity: 0.028;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23noise)'/%3E%3C/svg%3E");
            background-size: 200px 200px;
        }
        body > * { position: relative; z-index: 1; }

        header {
            text-align: center;
            margin-bottom: 16px;
            width: 100%;
            max-width: 700px;
        }

        h1 {
            font-family: var(--font-display);
            font-weight: 800;
            color: var(--text);
            font-size: 2.5rem;
            margin-bottom: 10px;
            letter-spacing: -0.02em;
        }
        h1::after {
            content: '';
            display: block;
            width: 48px;
            height: 4px;
            border-radius: 2px;
            background: var(--gold);
            margin: 6px auto 0;
        }

        h2 { font-family: var(--font-display); }
        h3 { font-family: var(--font-display); }
        h4 { font-family: var(--font-display); font-size: 1rem; }

        header p { color: var(--text-muted); font-size: 0.95rem; margin-top: 4px; font-style: italic; }

        .status-chip {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            background: var(--background-dim);
            color: var(--text-muted);
            padding: 6px 14px;
            border-radius: 20px;
            font-weight: 700;
            font-size: 0.9rem;
        }
        .status-chip:empty { display: none; }
        /* Gold chips are stickers: pale-gold face, white sticker edge, soft lift */
        .status-chip-gold { background: var(--gold-light); color: var(--gold-dark); box-shadow: 0 0 0 1px var(--gold-line), 0 0 0 3px var(--card-bg), 0 2px 8px rgba(240,180,41,0.25); }
        .status-chip.level-pulse { animation: levelChipPulse var(--dur-celebrate) var(--ease-out-back); }
        @keyframes levelChipPulse {
            0% { transform: scale(1); }
            45% { transform: scale(1.25); }
            100% { transform: scale(1); }
        }
        @keyframes flamePulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.06); opacity: 0.9; } }
        #streak-text { animation: flamePulse 1.8s ease-in-out infinite; }

        .score-board {
            display: flex;
            flex-wrap: wrap;
            justify-content: space-between;
            align-items: center;
            gap: 6px 16px;
            background: linear-gradient(135deg, var(--navy-900) 0%, var(--navy-800) 100%);
            padding: 15px 25px;
            border-radius: 14px;
            box-shadow: 0 4px 16px rgba(28,35,51,0.22), inset 0 1px 0 rgba(255,255,255,0.08);
            width: 100%;
            max-width: 700px;
            font-family: var(--font-display);
            font-size: 0.9rem;
            color: rgba(255,255,255,0.6);
        }
        /* Each chip wraps to its own line as a whole unit rather than breaking
           mid-phrase — without this, narrow screens shrink these flex items until
           their text wraps internally, interleaving "Practicing:" / "Session:" /
           the timer / round dots into unreadable runs. */
        .score-board > * { white-space: nowrap; }
        .score-board .font-mono {
            font-size: 1rem;
            color: var(--butter);
        }
        .score-chip-wrap { position: relative; display: inline-block; }

        /* Every card is a page from an exercise book: faint squared grid,
           a red margin rule down the left, content sitting on the "paper".
           All three layers are background-image, so there are zero stacking
           side-effects on card content. */
        .card {
            /* --rule-x keeps the red margin rule inside the card's padding
               gutter at every card padding (35px desktop, 18px mobile). */
            --rule-x: 22px;
            background-color: var(--card-bg);
            background-image:
                linear-gradient(90deg, transparent var(--rule-x), var(--margin-rule) var(--rule-x), var(--margin-rule) calc(var(--rule-x) + 1.5px), transparent calc(var(--rule-x) + 1.5px)),
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 100% 100%, 26px 26px, 26px 26px;
            /* --paper-shift phases only the horizontal-lines layer so intro prose
               (.card h2 + p below) baselines sit on the lines like handwriting. */
            background-position: 0 0, 0 var(--paper-shift, 0px), 0 0;
            border-radius: 20px;
            box-shadow: var(--shadow-2);
            padding: 35px;
            width: 100%;
            max-width: 700px;
            margin-top: 20px;
            position: relative;
        }

        .card h2 { margin-bottom: 12px; }

        /* Card intro prose "handwritten on the lines": line boxes match the 26px
           grid square, and the offset from card top (35px padding + 36px h2 line
           box + 12px collapsed margin = 83px) puts each baseline ~2px above a
           grid line. Deliberately scoped to h2-adjacent prose sitting directly
           on the paper — tiles/buttons/modals stay on the grid-as-texture.
           Invariant: card padding, h2 line box and this line-height must keep
           (offset mod 26) where it is, or the effect silently drifts. */
        .card h2 + p { line-height: 26px; }

        /* Corner ✕ that exits a focused quiz/skill/speed-burst session — sits on the card
           itself rather than the global header, so it stays put through the completion
           screen too (see quizCloseBtnClick() / exitSkillPractice()). */
        .practice-close-btn {
            display: none;
            position: absolute;
            top: 14px; right: 14px;
            z-index: 5;
            width: 34px; height: 34px;
            border-radius: 50%;
            border: none;
            background: rgba(59,71,196,0.15);
            color: var(--primary-dark);
            font-size: 0.95rem;
            font-weight: 700;
            cursor: pointer;
            align-items: center;
            justify-content: center;
            padding: 0;
            transition: background 0.15s, transform 0.1s;
        }
        .practice-close-btn:hover { background: rgba(59,71,196,0.3); transform: scale(1.08); }
        .practice-close-btn:active { transform: scale(0.93); }

        /* Cards read as uniform exercise-book pages; the topic badge, not a
           colored spine, carries each section's identity. */

        /* Topic badge = the teacher's stamp on the page margin: sticker edge.
           Kept perfectly level — tilted labels read as a rendering glitch. */
        .topic-badge {
            background: var(--primary-light);
            color: var(--primary);
            padding: 6px 12px;
            border-radius: 20px;
            font-size: 0.85rem;
            font-weight: 700;
            display: inline-block;
            margin-bottom: 20px;
            box-shadow: 0 0 0 3px var(--card-bg), 0 2px 6px rgba(30,42,74,0.14);
        }
        .topic-badge[data-topic="fractions"]    { background: #FEF3C7; color: #92400E; }
        .topic-badge[data-topic="percentages"]  { background: #FCE7F3; color: #9D174D; }
        .topic-badge[data-topic="ratios"]       { background: #ECFDF5; color: #065F46; }
        .topic-badge[data-topic="sequences"]    { background: #EFF6FF; color: #1E40AF; }
        .topic-badge[data-topic="algebra"]      { background: #F5F3FF; color: #5B21B6; }
        .topic-badge[data-topic="geometry"]     { background: #FFF7ED; color: #9A3412; }
        .topic-badge[data-topic="number"]       { background: #F0FDF4; color: #166534; }
        .topic-badge[data-topic="time"]         { background: #FFF1F2; color: #9F1239; }
        .topic-badge[data-topic="money"]        { background: #ECFDF5; color: #166534; }

        .context {
            color: var(--text-muted);
            background: var(--gold-light);
            padding: 15px;
            border-left: 4px solid var(--gold);
            border-radius: 0 10px 10px 0;
            margin-bottom: 20px;
            line-height: 1.5;
            font-size: 0.95rem;
            font-weight: 600;
        }

        .question {
            font-size: 1.4rem;
            font-weight: 600;
            margin-bottom: 25px;
            line-height: 1.6;
        }

        .interaction-area {
            margin-bottom: 30px;
        }

        .input-wrapper {
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 1.2rem;
            flex-wrap: wrap;
        }

        /* Answer boxes: dashed like the box you'd draw for your working —
           snaps solid pen-blue when the pupil is writing in it. */
        input[type="text"] {
            padding: 14px 18px;
            border: 2px dashed var(--line-dashed);
            border-radius: 12px;
            font-size: 1.25rem;
            font-family: var(--font-display);
            width: 150px;
            text-align: center;
            background: #fff;
            color: var(--text);
            transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;
        }

        input[type="text"]:hover {
            border-color: var(--text-muted);
        }

        input[type="text"]::placeholder {
            color: var(--text-muted);
            opacity: 0.6;
        }

        .name-input {
            width: 100%;
            text-align: left;
        }

        input[type="text"]:focus {
            outline: none;
            border-style: solid;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(59,71,196,0.18);
            background: #fff;
        }

        button:focus-visible,
        input:focus-visible,
        .tab-btn:focus-visible {
            outline: 3px solid var(--primary);
            outline-offset: 2px;
        }

        .feedback {
            padding: 15px;
            border-radius: 14px;
            margin-bottom: 25px;
            font-weight: 600;
            font-size: 1rem;
            display: none;
            white-space: pre-line;
        }
        .feedback.correct {
            display: block;
            background: var(--success-light);
            color: var(--success);
            border-left: 4px solid var(--success);
            animation: feedbackPopIn var(--dur-celebrate) var(--ease-out-back);
        }
        .feedback.wrong {
            display: block;
            background: var(--error-light);
            color: var(--error);
            border-left: 4px solid var(--error);
            animation: feedbackPopIn var(--dur-base) var(--ease-standard), feedbackShake 380ms var(--ease-standard);
        }
        .algebra-block {
            background: #fff;
            border-left: 3px solid var(--primary);
            border-radius: 8px;
            padding: 12px 16px;
            margin-top: 14px;
            color: var(--text);
            font-weight: 400;
            overflow-x: auto;
            position: relative;
        }
        .algebra-label {
            display: block;
            font-family: var(--font-body);
            font-size: 0.7em;
            font-weight: 700;
            text-transform: uppercase;
            letter-spacing: 0.07em;
            color: var(--primary);
            margin-bottom: 6px;
            white-space: normal;
        }
        .alg-sep    { color: var(--line-dashed); }
        .alg-def    { color: var(--text-muted); font-style: italic; }
        .alg-check  { color: var(--text-muted); }
        .alg-note   { color: var(--gold-dark); font-weight: 600; }
        .alg-key    { color: var(--gold-dark); font-weight: 600; }
        .alg-answer { color: #0a7a6a; font-weight: 700; }
        .alg-v1     { color: #c26400; font-weight: 700; }
        .alg-v2     { color: var(--success); font-weight: 700; }
        @keyframes feedbackPopIn {
            0% { opacity: 0; transform: translateY(6px) scale(0.96); }
            100% { opacity: 1; transform: translateY(0) scale(1); }
        }
        @keyframes feedbackShake {
            0%, 100% { transform: translateX(0); }
            20% { transform: translateX(-6px); }
            40% { transform: translateX(5px); }
            60% { transform: translateX(-3px); }
            80% { transform: translateX(2px); }
        }
        @keyframes questionFadeIn {
            0% { opacity: 0; transform: translateY(8px); }
            100% { opacity: 1; transform: translateY(0); }
        }
        .q-enter { animation: questionFadeIn var(--dur-base) var(--ease-standard); }

        .actions {
            display: flex;
            gap: 15px;
        }

        button {
            padding: 12px 25px;
            border: none;
            border-radius: 14px;
            font-size: 1.1rem;
            font-weight: 700;
            cursor: pointer;
            transition: background 0.2s, transform 0.1s, box-shadow 0.1s;
            flex: 1;
            font-family: var(--font-display);
        }

        button:active { transform: scale(0.98); }
        .btn-submit {
            background: linear-gradient(180deg, var(--indigo-2) 0%, var(--primary) 100%);
            box-shadow: 0 4px 0 var(--primary-dark), 0 6px 12px rgba(59,71,196,0.3);
            color: white;
        }
        .btn-submit:hover { background: linear-gradient(180deg, #5A66DE 0%, #4550CE 100%); }
        .btn-submit:active {
            transform: translateY(2px);
            box-shadow: 0 2px 0 var(--primary-dark), 0 3px 6px rgba(59,71,196,0.2);
        }
        .btn-next { background: var(--success); color: white; display: none; animation: feedbackPopIn var(--dur-base) var(--ease-standard); }
        .btn-next:hover { background: var(--success-dark); }
        #btn-next-nav { background: var(--success); color: white; display: none; animation: feedbackPopIn var(--dur-base) var(--ease-standard); }
        #btn-next-nav:hover { background: var(--success-dark); }
        /* Secondary = pencil-outline button: drawn on the page, not printed on it */
        .btn-secondary { background: var(--card-bg); color: var(--text-muted); border: 2px solid var(--line-dashed); }
        .btn-secondary:hover { background: var(--primary-light); color: var(--primary); border-color: var(--primary); }
        #btn-customize { background: linear-gradient(135deg, var(--grape), var(--berry-bright)); color: white; border: none; box-shadow: 0 3px 8px rgba(109,74,196,0.30); }
        #btn-customize:hover { background: linear-gradient(135deg, var(--grape-dark), var(--berry)); box-shadow: 0 4px 12px rgba(109,74,196,0.40); }
        /* Gold CTAs carry ink text — white-on-gold fails contrast for young readers */
        .btn-warning { background: var(--gold); color: var(--text); }
        .btn-warning:hover { background: var(--gold-dark); color: #fff; }
        .btn-compact { margin-top: 12px; max-width: 220px; }
        @keyframes easierPulse {
            0%, 100% { box-shadow: 0 0 0 0 rgba(240,180,41,0); }
            50%       { box-shadow: 0 0 0 5px rgba(240,180,41,0.22); }
        }
        .btn-easier {
            background: transparent;
            border: 2px solid var(--gold);
            color: var(--gold-dark);
            font-size: 0.92rem;
            padding: 8px 14px;
            border-radius: 20px;
            flex: 0 0 auto;
            box-shadow: none;
            display: block;
            width: fit-content;
            margin-bottom: 10px;
            animation: easierPulse 2.4s ease-in-out infinite;
        }
        .btn-easier:hover { background: var(--gold-light); border-color: var(--gold-dark); }
        .step-badge { background: var(--gold-light); color: var(--gold-dark); padding: 6px 12px; border-radius: 20px; font-size: 0.85rem; font-weight: 700; display: inline-block; margin-bottom: 15px; }
        /* The maze door modal builds the same blocks with maze-prefixed ids —
           they must share this panel styling or the steps/strategy content sits
           unpadded against the final answer field (buttons touching inputs). */
        #easy-steps-block, #maze-easy-steps-block { background: var(--gold-light); border: 1px solid var(--gold-line); border-radius: 12px; padding: 20px; margin-bottom: 20px; }
        #strategy-block, #maze-strategy-block { background: var(--primary-light); border: 1px solid var(--primary-light); border-radius: 12px; padding: 20px; margin-bottom: 20px; }
        #strategy-block .step-badge, #maze-strategy-block .step-badge { background: var(--card-bg); color: var(--primary); }
        .easy-step { margin-bottom: 14px; padding-bottom: 14px; border-bottom: 1px solid var(--gold-line); }
        .easy-step:last-child { margin-bottom: 0; padding-bottom: 0; border-bottom: none; }
        .easy-step-prompt { font-weight: 600; margin-bottom: 8px; line-height: 1.4; }
        .btn-check-step { background: var(--gold); color: var(--text); padding: 8px 16px; border: none; border-radius: var(--r-sm); font-weight: 700; cursor: pointer; font-size: 0.95rem; flex: 0 0 auto; }
        .btn-check-step:hover { background: var(--gold-dark); color: #fff; }
        .easy-step-feedback { margin-top: 6px; font-weight: 600; font-size: 0.95rem; min-height: 1.2em; }
        .easy-step-feedback.correct { color: var(--success); animation: feedbackPopIn var(--dur-base) var(--ease-standard); }
        .easy-step-feedback.wrong { color: var(--error); animation: feedbackPopIn var(--dur-base) var(--ease-standard), feedbackShake 380ms var(--ease-standard); }
        .easy-step-visual { margin: 10px 0; text-align: center; }
        .question-visual { margin: 12px 0; text-align: center; }
        .completion-screen { text-align: center; display: none; padding: 10px 0; }
        .completion-trophy {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 88px; height: 88px;
            border-radius: 50%;
            background: radial-gradient(circle, #FEF9C3 0%, var(--butter) 60%, rgba(240,180,41,0.12) 100%);
            box-shadow: 0 0 0 6px rgba(240,180,41,0.12), 0 0 32px rgba(240,180,41,0.3);
            margin: 0 auto 4px;
            font-size: 4rem;
            line-height: 1;
        }
        .completion-screen > * {
            animation: questionFadeIn var(--dur-base) var(--ease-standard) backwards;
        }
        .completion-screen > *:nth-child(1) { animation-delay: 0ms; }
        .completion-screen > *:nth-child(2) { animation-delay: 70ms; }
        .completion-screen > *:nth-child(3) { animation-delay: 140ms; }
        .completion-screen > *:nth-child(4) { animation-delay: 210ms; }
        .completion-screen > *:nth-child(5) { animation-delay: 280ms; }
        .completion-screen h2 { color: var(--gold-dark); font-size: 2.6rem; margin-bottom: 15px; font-family: var(--font-display); text-shadow: 0 2px 8px rgba(240,180,41,0.3); }
        .review-list { text-align: left; margin-top: 20px; padding-left: 20px; }
        .review-list li { margin-bottom: 15px; line-height: 1.5; }

        .tab-bar { display: flex; gap: 4px; width: 100%; max-width: 700px; margin-top: 20px; min-height: 64px; align-items: center; padding: 6px; background: rgba(253,251,247,0.85); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-radius: 16px; box-shadow: 0 2px 12px rgba(28,35,51,0.08); }
        .tab-btn { flex: 1; padding: 8px 4px; border: none; background: transparent; color: var(--text-muted); font-weight: 700; cursor: pointer; font-size: 0.85rem; border-radius: 12px; transition: color 0.2s, background 0.2s; font-family: var(--font-display); }
        .tab-btn:hover { color: var(--primary); background: var(--primary-light); }
        .tab-btn.active { color: #fff; background: var(--primary); border-radius: 12px; box-shadow: 0 2px 8px rgba(59,71,196,0.35); }
        .tab-btn.tab-pop { animation: tabPop var(--dur-fast) var(--ease-standard); }

        /* "More" tab group: Maze/Study Buddy/Progress/Village collapsed behind one trigger */
        .tab-more-wrap { position: relative; flex: 1; display: flex; min-width: 0; }
        .tab-more-btn { display: flex; align-items: center; justify-content: center; gap: 4px; white-space: nowrap; min-width: 0; }
        /* Swapped in by updateMoreTabTrigger() to "🏆 Progress" / "🗺️ Maze" when that
           tab is active — "Progress" is long enough to overflow the pill's own rounded
           edge on narrow phones, so it needs to be able to shrink and ellipsize instead
           of hard-clipping past the tab-bar's border-radius. */
        #tab-more-label { overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
        .tab-more-caret { font-size: 0.7em; display: inline-block; flex: 0 0 auto; transition: transform 0.15s var(--ease-standard); }
        .tab-more-btn[aria-expanded="true"] .tab-more-caret { transform: rotate(180deg); }
        .tab-more-menu {
            position: absolute;
            bottom: calc(100% + 8px);
            left: 50%;
            transform: translateX(-50%) translateY(6px);
            min-width: 190px;
            background: var(--card-bg);
            border-radius: 14px;
            box-shadow: var(--shadow-3);
            padding: 6px;
            display: flex;
            flex-direction: column;
            gap: 2px;
            opacity: 0;
            visibility: hidden;
            pointer-events: none;
            transition: opacity 0.15s var(--ease-standard), transform 0.15s var(--ease-standard), visibility 0s linear 0.15s;
            z-index: 70;
        }
        .tab-more-menu.open {
            opacity: 1;
            visibility: visible;
            pointer-events: auto;
            transform: translateX(-50%) translateY(0);
            transition: opacity 0.15s var(--ease-standard), transform 0.15s var(--ease-standard);
        }
        .tab-more-item {
            display: block;
            width: 100%;
            text-align: left;
            padding: 10px 14px;
            border: none;
            background: transparent;
            border-radius: 10px;
            font-family: var(--font-display);
            font-weight: 700;
            font-size: 0.88rem;
            color: var(--text-muted);
            cursor: pointer;
            white-space: nowrap;
        }
        .tab-more-item:hover { background: var(--primary-light); color: var(--primary); }
        .tab-more-item.active { background: var(--primary-light); color: var(--primary); }
        @keyframes tabPop {
            0% { transform: scale(0.94); }
            100% { transform: scale(1); }
        }
        .pet-card { text-align: center; display: none; }
        .pet-card h2 { font-family: var(--font-display); font-size: 1.3rem; font-weight: 800; color: var(--primary); margin-bottom: 10px; }
        .creature-render-target { display: block; margin: 0 auto; min-height: 250px; cursor: pointer; }
        .pet-stage { position: relative; width: 100%; min-height: 265px; display: flex; align-items: center; justify-content: center; background: radial-gradient(circle at 50% 60%, rgba(59,71,196,0.18) 0%, transparent 68%); border-radius: 50%; padding: 10px; }
        .pet-stage .creature-render-target { margin: 0; }
        .mood-caption-target { position: relative; font-size: 1.15rem; font-weight: 600; margin-top: 8px; min-height: 1.4em; display: block; transition: opacity 0.25s; }
        /* The Buddy tab used to stack identity (name/creature/mood), a daily-want banner,
           a weakest-skill nudge and a full per-skill mastery breakdown with no visual
           grouping, so nothing signalled which parts were decorative vs. actionable — and
           the mastery breakdown duplicated the Skills tab's own per-tile bars. Reusing the
           Progress tab's tier/heading pattern splits it into "who your buddy is" (top,
           untitled hero), "what to do next" (one merged recommendation) and "how you're
           growing" (evolution stage, with full skill detail left to the Skills tab). */
        .pet-card .progress-tier, .pet-card .progress-tier-heading { text-align: left; }
        .pet-modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(30,42,74,0.18); backdrop-filter: blur(7px) saturate(130%); -webkit-backdrop-filter: blur(7px) saturate(130%); align-items: center; justify-content: center; z-index: 1000; animation: backdropFadeIn var(--dur-base) var(--ease-standard); }
        @keyframes backdropFadeIn {
            0% { opacity: 0; }
            100% { opacity: 1; }
        }
        /* Modals are torn-out pages: same paper + faint grid as .card, pen-blue edge. */
        .pet-modal-card {
            background-color: var(--card-bg);
            background-image:
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 26px 26px;
            border: 1.5px solid rgba(59,71,196,0.22);
            border-radius: 28px; padding: 35px; text-align: center; max-width: 320px; width: 90%; max-height: 88vh; overflow-y: auto; position: relative;
            box-shadow: 0 8px 40px rgba(30,42,74,0.20), 0 2px 8px rgba(30,42,74,0.08);
            animation: popIn 0.35s var(--ease-out-back);
        }
        .pet-modal-card h2 { font-family: var(--font-display); font-size: 1.6rem; font-weight: 800; color: var(--primary-dark); margin-bottom: 10px; }
        .login-gate-logo { width: 64px; height: 64px; display: block; margin: 0 auto 10px; }
        .pet-modal-close { position: absolute; top: 12px; right: 12px; background: rgba(59,71,196,0.15); color: var(--grape-dark); border: none; width: 32px; height: 32px; border-radius: 50%; font-size: 0.9rem; font-weight: 700; cursor: pointer; flex: 0 0 auto; padding: 0; transition: background 0.15s; }
        .pet-modal-close:hover { background: rgba(59,71,196,0.3); transform: scale(1.08); }
        .pet-modal-close:active { transform: scale(0.93); }
        @keyframes popIn { 0% { transform: scale(0.75); opacity: 0; } 70% { transform: scale(1.04); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
        .buddy-stage { position: relative; display: flex; align-items: center; justify-content: center; margin: 4px auto; }
        .buddy-stage::before { content: ''; position: absolute; width: 180px; height: 180px; border-radius: 50%; background: radial-gradient(circle, rgba(59,71,196,0.25) 0%, rgba(251,207,232,0.12) 60%, transparent 80%); animation: buddyGlow 3s ease-in-out infinite alternate; pointer-events: none; }
        @keyframes buddyGlow { from { transform: scale(0.95); opacity: 0.7; } to { transform: scale(1.05); opacity: 1; } }
        .customize-overlay { z-index: 1100; }
        .customize-card { max-width: 380px; }
        .customize-sub { color: var(--text-muted); font-size: 0.92rem; margin-bottom: 10px; }
        .customize-card .customize-sub { margin-bottom: 36px; }
        .customize-preview { min-height: 180px; }
        .customize-preview-sticky {
            position: sticky;
            top: -35px;
            margin: -35px -35px 0;
            padding: 35px 35px 8px;
            background: var(--card-bg);
            z-index: 5;
        }
        .customize-section { margin-top: 18px; text-align: left; }
        .customize-section h3 { font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 8px; }
        .swatch-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
        .swatch-btn { width: 34px; height: 34px; border-radius: 50%; border: 3px solid transparent; cursor: pointer; padding: 0; font-size: 1rem; line-height: 1; box-shadow: 0 1px 3px rgba(0,0,0,0.2); transition: border-color 0.15s, transform 0.15s; }
        .swatch-btn.selected { border-color: var(--primary); transform: scale(1.12); }
        .classic-swatch { background: conic-gradient(#64748B, #1C7ED6, #12B886, #F76707, #FFC107, #64748B); }
        #custom-color-input { width: 34px; height: 34px; border-radius: 50%; border: 3px solid transparent; padding: 0; cursor: pointer; }
        #custom-color-input.selected { border-color: var(--primary); }
        .option-row { display: flex; flex-wrap: wrap; gap: 8px; }
        .option-btn { padding: 8px 14px; border-radius: 20px; border: 2px solid var(--background-dim); background: var(--card-bg); color: var(--text); font-weight: 600; font-size: 0.88rem; cursor: pointer; transition: border-color 0.15s, background 0.15s, color 0.15s; }
        .option-btn.selected { border-color: var(--primary); background: var(--primary-light); color: var(--primary); }
        .option-btn-randomise { border-color: var(--gold); color: var(--gold-dark); }
        .option-btn-randomise:hover { background: var(--gold-light); border-color: var(--gold-dark); }

        @media (max-width: 480px) {
            body { padding: 10px; }
            /* 18px padding moves intro-prose top from 83px to 66px below card
               top; +9px rephases the horizontal lines back under the baselines. */
            .card { padding: 18px; --rule-x: 11px; --paper-shift: 9px; }
            .practice-close-btn { top: 10px; right: 10px; }
            .status-chip { padding: 5px 10px; font-size: 0.8rem; }
            .tab-btn { font-size: 0.8rem; padding: 8px 3px; min-height: 44px; }
            .score-board { padding: 10px 14px; font-size: 0.82rem; gap: 4px 10px; }
            .btn-submit { min-height: 52px; font-size: 1.05rem; }
            /* On a typical phone, header + score-board + topic/stage badges + context
               box already fill over half the viewport before the question text even
               starts, pushing the answer options and Check Answer button below the
               fold on nearly every question. None of these margins carry the intro-prose
               baseline-grid invariant (that's .card h2 + p only) — trim them here. */
            #topic-practice > .score-board { margin-bottom: 12px; }
            .topic-badge { margin-bottom: 12px; }
            .context { padding: 12px; margin-bottom: 12px; }
            .question { margin-bottom: 16px; }
            .quiz-progress-strip-track { margin: 0 0 8px; }
        }

        .combo-indicator {
            position: absolute;
            bottom: calc(100% + 6px);
            right: 0;
            background: var(--gold-light);
            color: var(--gold-dark);
            font-weight: 800;
            font-size: 0.78rem;
            white-space: nowrap;
            padding: 3px 10px;
            border-radius: 20px;
            opacity: 0;
            transform: translateY(4px) scale(0.9);
            transition: opacity 0.15s, transform 0.15s;
            pointer-events: none;
        }
        .combo-indicator.combo-visible {
            opacity: 1;
            /* animation controls transform; opacity still fades in via the base transition: opacity 0.15s */
            animation: comboBurn 1.8s ease-in-out infinite;
        }
        /* On a milestone pop: snap-scale first, then return to the slow burn.
           The 0.5s delay on comboBurn matches comboPulse duration exactly. */
        .combo-indicator.combo-visible.combo-flourish {
            animation: comboPulse 0.5s cubic-bezier(0.22, 1.6, 0.4, 1),
                       comboBurn  1.8s ease-in-out 0.5s infinite;
        }
        @keyframes comboPulse {
            0%   { transform: scale(1); }
            40%  { transform: scale(1.35); }  /* tweak 1.35 for bigger/smaller milestone pop */
            100% { transform: scale(1); }
        }
        /* Slow glow-pulse while the combo badge is "hot".
           Tweak 1.8s for faster/slower heartbeat; adjust rgba alpha for more/less glow intensity. */
        @keyframes comboBurn {
            0%,100% { box-shadow: 0 0 5px 2px rgba(240,180,41,0.3);  transform: scale(1); }
            50%     { box-shadow: 0 0 14px 5px rgba(240,180,41,0.65); transform: scale(1.03); }
        }
        /* Badge drop-and-fade when the streak breaks */
        @keyframes comboExtinguish {
            0%   { opacity: 1; transform: translateY(0)   scale(1); }
            100% { opacity: 0; transform: translateY(10px) scale(0.8); }
        }

        /* ---- Answer juice: Check Answer button pop (correct) and shake (wrong) ---- */

        /* Spring pop + green glow ring.
           cubic-bezier(0.22, 1.6, 0.4, 1) gives the strong overshoot that reads as "snap".
           Tweak scale(1.09) at 30% for a bigger/smaller physical feel. */
        @keyframes btnCorrectPop {
            0%   { transform: scale(1);    box-shadow: 0 0 0  0px rgba(23,138,80,0);    background: var(--primary); }
            30%  { transform: scale(1.09); box-shadow: 0 0 0 12px rgba(23,138,80,0.35); background: var(--success); }
            65%  { transform: scale(0.97); box-shadow: 0 0 0  4px rgba(23,138,80,0.1);  background: var(--primary); }
            100% { transform: scale(1);    box-shadow: 0 0 0  0px rgba(23,138,80,0);    background: var(--primary); }
        }
        /* Jarring lateral rattle — kept deliberately tight so it reads as "oops" not "scary".
           Tweak the translateX values at 12% / 28% to change severity. */
        @keyframes btnWrongShake {
            0%,100% { transform: translateX(0);    background: var(--primary); }
            12%     { transform: translateX(-9px);  background: var(--error); }
            28%     { transform: translateX( 8px);  background: var(--error); }
            44%     { transform: translateX(-6px); }
            58%     { transform: translateX( 4px); }
            72%     { transform: translateX(-2px); }
        }
        .btn-juice-correct { animation: btnCorrectPop 500ms cubic-bezier(0.22, 1.6, 0.4, 1) forwards; }
        .btn-juice-wrong   { animation: btnWrongShake 420ms ease-in-out forwards; }

        .round-progress { color: var(--gold-dark); font-size: 0.85rem; letter-spacing: 2px; }
        .quiz-progress-strip-track { height: 5px; background: var(--line-dashed); border-radius: 99px; overflow: hidden; margin: 0 0 14px; }
        .quiz-progress-strip-fill { height: 100%; background: var(--primary); border-radius: 99px; transition: width 0.4s ease; width: 0%; }
        .rp-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin: 0 3px; vertical-align: middle; transition: background 0.2s, transform 0.2s; }
        .rp-dot-correct { background: var(--success); animation: dotPop 0.3s var(--ease-out-back); }
        .rp-dot-wrong   { background: var(--error);   animation: dotPop 0.3s var(--ease-out-back); }
        .rp-dot-pending { background: var(--line-dashed); }
        @keyframes dotPop { 0% { transform: scale(0); } 80% { transform: scale(1.2); } 100% { transform: scale(1); } }
        .checkin-score { font-family: var(--font-display); font-weight: 800; color: var(--primary); margin-top: 14px; font-size: 1.4rem; letter-spacing: -0.01em; }
        .checkin-score.perfect { color: var(--gold-dark); font-size: 2rem; text-shadow: 0 2px 12px rgba(240,180,41,0.45); animation: scorePop 0.5s var(--ease-out-back); }
        @keyframes scorePop { 0% { transform: scale(0.7); opacity: 0; } 70% { transform: scale(1.08); } 100% { transform: scale(1); opacity: 1; } }
        .checkin-message { margin-top: 8px; }
        .checkin-message .checkin-icon { font-size: 2.2rem; display: flex; align-items: center; justify-content: center; width: 58px; height: 58px; margin: 10px auto 6px; border-radius: 50%; background: linear-gradient(135deg, #EEF2FF 0%, #FAF5FF 100%); box-shadow: 0 2px 10px rgba(90,56,176,0.15); line-height: 1; }
        .checkin-message .checkin-headline { font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; }
        .checkin-message .checkin-sub { color: var(--text-muted); font-size: 0.92rem; margin-top: 4px; }
        .checkin-bonus { display: inline-block; margin-top: 8px; padding: 4px 14px; background: var(--gold-light); border: 1.5px solid var(--gold-line); border-radius: 20px; font-size: 0.88rem; font-weight: 700; color: var(--gold-dark); }
        /* guaranteed per-round coin award — same gold pill family as .checkin-bonus */
        .checkin-coins { display: inline-block; margin-top: 10px; padding: 5px 16px; background: var(--gold-light); border: 1.5px solid var(--gold-line); border-radius: 20px; font-size: 0.95rem; font-weight: 800; color: var(--gold-dark); }
        .checkin-coins.pouch-full { background: transparent; border-color: var(--line-dashed); color: var(--text-muted); font-weight: 700; }
        .checkin-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 18px; }
        .checkin-actions button { margin: 0; width: 100%; }
        .pet-modal-card .btn-submit { border-radius: 30px; background: linear-gradient(135deg, var(--grape-dark) 0%, var(--primary) 100%); font-family: var(--font-display); font-size: 1.05rem; letter-spacing: 0.01em; box-shadow: 0 4px 16px rgba(30,42,74,0.3); }
        .pet-modal-card .btn-secondary { border-radius: 30px; font-family: var(--font-display); font-size: 0.95rem; }

        /* Exam Stamp celebration component */
        .celebration-toast { position: fixed; top: 20%; left: 50%; transform: translate(-50%, -50%) scale(0.6) rotate(-12deg); background: var(--card-bg); border: 3px solid var(--gold); border-radius: 50%; width: 165px; height: 165px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 14px; text-align: center; box-shadow: 0 10px 30px rgba(28,35,51,0.25); z-index: 1300; opacity: 0; pointer-events: none; cursor: pointer; transition: opacity 0.2s; }
        .celebration-toast.show { opacity: 1; pointer-events: auto; transform: translate(-50%, -50%) scale(1) rotate(-6deg); animation: stampDown 0.45s cubic-bezier(0.22, 1.6, 0.4, 1); }
        .celebration-toast-icon { font-size: 2.4rem; line-height: 1; }
        .celebration-toast-text { font-size: 0.92rem; font-weight: 800; color: var(--gold-dark); line-height: 1.3; text-transform: uppercase; letter-spacing: 0.02em; font-family: var(--font-display); }
        @keyframes stampDown { 0% { transform: translate(-50%, -50%) scale(1.7) rotate(-20deg); } 55% { transform: translate(-50%, -50%) scale(0.9) rotate(-3deg); } 100% { transform: translate(-50%, -50%) scale(1) rotate(-6deg); } }

        .progress-card { display: none; text-align: left; }
        .xp-bar-track { background: var(--primary-light); border-radius: 20px; height: 14px; overflow: hidden; margin: 6px 0 2px; }
        .xp-bar-fill { background: linear-gradient(90deg, var(--primary), var(--sky-2)); height: 100%; border-radius: 20px; transition: width 0.4s; animation: xpFillPulse var(--dur-celebrate) var(--ease-standard); position: relative; overflow: hidden; }
        .xp-bar-fill::after {
            content: ''; position: absolute; top: 0; left: -80%;
            width: 60%; height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.38), transparent);
            animation: xpShine 2.4s ease-in-out infinite;
        }
        @keyframes xpFillPulse {
            0% { filter: brightness(1); }
            40% { filter: brightness(1.35); }
            100% { filter: brightness(1); }
        }
        @keyframes xpShine {
            0%   { left: -80%; }
            100% { left: 160%; }
        }
        .progress-level-value { font-family: var(--font-display); font-weight: 800; font-size: 1.5rem; color: var(--primary); }
        .progress-caption { font-size: 0.85rem; color: var(--text-muted); }
        .progress-streak-line { margin-top: 14px; font-weight: 700; }
        /* Two visual tiers so "did I do enough today" (streak, missions) reads before
           "lifetime stats" (level, accuracy, badge shelf) rather than one undifferentiated
           scroll of equal-weight cards. */
        .progress-tier { margin-top: 22px; }
        .progress-tier:first-of-type { margin-top: 8px; }
        .progress-tier-heading {
            font-size: 0.76rem;
            letter-spacing: 0.06em;
            text-transform: uppercase;
            color: var(--text-muted);
            font-weight: 800;
            margin: 0 0 12px;
            padding-bottom: 8px;
            border-bottom: 2px solid var(--background-dim);
        }
        .badge-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 14px; margin-top: 12px; }
        .badge-item { text-align: center; padding: 14px 8px 10px; border-radius: 14px; background: transparent; border: 2px dashed var(--line-dashed); }
        .badge-item.earned { background: var(--gold-light); border: 2px solid var(--gold); }
        .badge-item .badge-icon { font-size: 1.7rem; display: inline-flex; align-items: center; justify-content: center; width: 48px; height: 48px; border-radius: 50%; margin-bottom: 6px; background: var(--card-bg); }
        .badge-item.earned .badge-icon { background: var(--gold); box-shadow: 0 2px 6px rgba(200,145,18,0.4); }
        .badge-item.locked {
            background: rgba(240,180,41,0.05);
            border: 2px dashed rgba(240,180,41,0.38);
            position: relative;
        }
        .badge-item.locked .badge-icon { filter: brightness(0) opacity(0.18); }
        .badge-item.locked .badge-name  { opacity: 0.65; }
        .badge-item.locked .badge-desc  { opacity: 0.45; }
        .badge-item.locked::after {
            content: '🔒';
            position: absolute;
            top: 5px; right: 6px;
            font-size: 0.7rem;
            line-height: 1;
        }
        .badge-item.badge-pop { animation: badgePop var(--dur-celebrate) var(--ease-out-back); }
        @keyframes badgePop {
            0% { transform: scale(0.7); box-shadow: 0 0 0 rgba(240,180,41,0); }
            55% { transform: scale(1.12); box-shadow: 0 0 18px rgba(240,180,41,0.55); }
            100% { transform: scale(1); box-shadow: 0 0 0 rgba(240,180,41,0); }
        }
        .badge-item .badge-name { font-size: 0.82rem; font-weight: 800; color: var(--text); }
        .badge-item .badge-desc { font-size: 0.7rem; color: var(--text-muted); margin-top: 2px; line-height: 1.3; }

        .skills-card { display: none; text-align: left; }
        .skills-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; margin-top: 14px; }
        /* Tiles are boxes drawn on the page: white face lifts them off the paper,
           pencil-grey rule, pen-blue when the pupil reaches for them. */
        .skill-tile { position: relative; display: flex; flex-direction: column; align-items: center; background: #fff; border: 2px solid var(--line-dashed); border-radius: 14px; padding: 18px 12px; text-align: center; cursor: pointer; transition: border-color 0.15s, transform 0.1s, box-shadow 0.15s; }
        .topic-stage2-badge { position: absolute; top: 6px; right: 8px; font-size: 0.85rem; }
        .skill-tile:hover { border-color: var(--primary); transform: translateY(-2px); box-shadow: 0 4px 16px rgba(59,71,196,0.14); }
        .skill-tile[data-mastery="high"]   { background: linear-gradient(to bottom, var(--success-light), #fff); border-color: #9BD8B7; }
        .skill-tile[data-mastery="high"]:hover   { border-color: var(--success); box-shadow: 0 4px 16px rgba(23,138,80,0.18); }
        .skill-tile[data-mastery="medium"] { background: linear-gradient(to bottom, var(--gold-light), #fff); border-color: var(--gold-line); }
        .skill-tile[data-mastery="medium"]:hover { border-color: var(--gold); box-shadow: 0 4px 16px rgba(240,180,41,0.2); }
        .skill-tile .skill-icon { font-size: 2rem; display: block; margin-bottom: 6px; }
        .skill-tile .skill-name { font-weight: 800; font-size: 0.95rem; line-height: 1.25; }
        .skill-tile .skill-name-formal { display: block; font-size: 0.68rem; font-weight: 600; color: var(--text-muted); margin-top: 1px; }
        .skill-tile .skill-level-tag { display: block; font-size: 0.72rem; font-weight: 700; color: var(--primary); letter-spacing: 0.01em; margin-top: 6px; white-space: nowrap; }
        .skill-tile .skill-stats { display: block; font-size: 0.75rem; color: var(--text-muted); margin-top: 6px; }

        /* One highlighted card above the topic grid so a first-time (or just-undecided)
           visitor has a single obvious next step instead of 14 equally-weighted choices. */
        .skill-tile-recommended {
            background: linear-gradient(to bottom, var(--gold-light), var(--card-bg));
            border-color: var(--gold);
            box-shadow: 0 4px 16px rgba(240,180,41,0.18);
        }
        .skill-tile-recommended:hover { border-color: var(--gold-dark); box-shadow: 0 4px 16px rgba(240,180,41,0.3); }
        .skill-tile-recommended-badge {
            position: absolute;
            top: -9px; left: 50%;
            transform: translateX(-50%);
            background: var(--gold-dark);
            color: #fff;
            font-size: 0.66rem;
            font-weight: 800;
            letter-spacing: 0.02em;
            padding: 2px 10px;
            border-radius: 20px;
            white-space: nowrap;
            box-shadow: 0 2px 6px rgba(28,35,51,0.18);
        }
        .skill-session-stats { margin-top: 16px; color: var(--text-muted); font-weight: 600; }
        .skill-mini-bar-track { width: 100%; background: var(--background-dim); border-radius: 20px; height: 9px; overflow: hidden; margin-top: 4px; }
        .skill-mini-bar-fill { background: linear-gradient(90deg, var(--primary), var(--sky-2)); height: 100%; transition: width 0.4s; animation: xpFillPulse var(--dur-celebrate) var(--ease-standard); position: relative; overflow: hidden; }
        .skill-mini-bar-fill::after {
            content: ''; position: absolute; top: 0; left: -80%;
            width: 60%; height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.38), transparent);
            animation: xpShine 2.4s ease-in-out infinite;
        }

        .mastery-nudge { background: var(--gold-light); border-left: 3px solid var(--gold); border-radius: 10px; padding: 12px 15px; margin-top: 8px; text-align: left; }
        /* The premium upsell is its own section at the foot of the progress card,
           so it gets tier-level breathing room rather than the in-tier 8px. */
        #premium-progress-hint { margin-top: 22px; }
        .mastery-nudge p { font-weight: 600; margin-bottom: 8px; }

        .swatch-btn.locked { opacity: 1; cursor: not-allowed; background: var(--card-bg) !important; border: 2px dashed var(--line-dashed) !important; color: var(--text-muted); display: flex; align-items: center; justify-content: center; font-size: 0.8rem; }
        .option-btn.locked { opacity: 0.7; cursor: not-allowed; background: transparent !important; border: 2px dashed var(--line-dashed) !important; color: var(--text-muted); }
        .retry-pill { display: inline-block; margin-top: 10px; padding: 3px 10px; border-radius: 20px; background: var(--gold-light); color: var(--gold-dark); font-size: 0.78rem; font-weight: 700; }
        .retry-banner {
            background: #FFFBEB;
            border-left: 4px solid var(--gold);
            padding: 10px 14px;
            border-radius: 8px;
            margin: 8px 0;
            font-size: 0.9rem;
            font-weight: 600;
            color: var(--gold-dark);
            line-height: 1.4;
        }

        @media (prefers-reduced-motion: reduce) {
            *, *::before, *::after {
                animation-duration: 0.001ms !important;
                animation-iteration-count: 1 !important;
                transition-duration: 0.001ms !important;
                scroll-behavior: auto !important;
            }
        }

        #login-gate-overlay { z-index: 1400; }
        #login-gate-overlay .customize-sub { margin-bottom: 4px; }

        /* The Netlify Identity widget injects its own iframe with an inline z-index:99 —
           lower than every .pet-modal-overlay (1000+) here. So opening login from inside
           a paywall/other modal rendered it invisible and unclickable behind that modal
           (the "Unlock Premium does nothing" bug: the login form was there, just hidden).
           !important is required to beat the widget's own inline style. */
        #netlify-identity-widget { z-index: 2000 !important; }

        /* ===== Premium paywall blur + CTA ===== */
        .premium-paywall {
            position: relative;
            margin: 16px 0 20px;
            border-radius: 18px;
            border: 4px solid var(--primary-light);
            background: rgba(233,235,251,0.55);
            padding: 18px 16px 20px;
        }
        .paywall-header {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 14px;
            font-size: 1.05rem;
            font-weight: 800;
            color: var(--primary-dark);
        }
        .paywall-header .emoji { font-size: 1.4rem; }
        .paywall-blur-wrap { position: relative; }
        .paywall-blur-preview {
            background: white;
            border-radius: 12px;
            padding: 16px;
            filter: blur(5px);
            user-select: none;
            pointer-events: none;
        }
        .paywall-blur-preview .paywall-step {
            margin-bottom: 12px;
            padding-bottom: 12px;
            border-bottom: 1px solid var(--gold-line);
            font-weight: 600;
            font-size: 0.95rem;
        }
        .paywall-blur-preview .paywall-step:last-child {
            margin-bottom: 0;
            padding-bottom: 0;
            border-bottom: none;
        }
        .paywall-overlay {
            position: absolute;
            inset: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 10px;
            padding: 16px;
            text-align: center;
        }
        .paywall-cta-btn {
            flex: none;
            background: var(--primary);
            color: white;
            border: none;
            border-radius: 14px;
            padding: 14px 22px;
            font-size: 1rem;
            font-weight: 800;
            cursor: pointer;
            text-align: center;
            line-height: 1.35;
            box-shadow: 0 4px 16px rgba(28,35,51,0.3);
            outline: 4px solid white;
            transition: background 0.2s, transform 0.1s;
            width: 100%;
            max-width: 340px;
        }
        .paywall-cta-btn:hover { background: var(--primary-dark); transform: scale(1.03); }
        .paywall-cta-btn:active { transform: scale(0.97); }
        .paywall-cta-btn.loading { opacity: 0.7; cursor: wait; }
        .paywall-subtext {
            max-width: 280px;
            font-size: 0.82rem;
            font-weight: 600;
            color: var(--primary-dark);
            background: rgba(255,255,255,0.85);
            border-radius: 8px;
            padding: 6px 10px;
        }
        @media (max-width: 480px) {
            .paywall-cta-btn { font-size: 0.92rem; padding: 13px 16px; }
        }

        /* ===== Speed / Stage 2 mode switcher ===== */
        .mode-switcher {
            display: flex;
            gap: 6px;
            margin-top: 16px;
            padding: 5px;
            background: var(--primary-light);
            border-radius: 18px;
        }
        .mode-switch-btn {
            flex: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 2px;
            position: relative;
            border: none;
            background: transparent;
            color: var(--text-muted);
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.85rem;
            padding: 12px 10px;
            border-radius: 14px;
            cursor: pointer;
            transition: background 0.2s var(--ease-standard), color 0.2s, transform 0.1s;
        }
        .mode-switch-btn:hover { transform: translateY(-1px); }
        .mode-switch-btn:active { transform: scale(0.97); }
        .mode-switch-icon { font-size: 1.3rem; }
        .mode-switch-btn.active {
            background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
            color: white;
            box-shadow: 0 4px 14px rgba(59,71,196,0.32);
        }
        .mode-switch-btn:not(.active):nth-child(2) { color: var(--gold-dark); }
        .mode-switch-lock {
            position: absolute;
            top: 6px;
            right: 8px;
            font-size: 0.75rem;
        }
        .mode-switcher-caption {
            color: var(--text-muted);
            font-size: 0.82rem;
            font-weight: 600;
            margin-top: 8px;
            text-align: center;
        }
        .stage2-teaser-badge {
            display: inline-block;
            margin-top: 8px;
            font-size: 0.72rem;
            font-weight: 800;
            letter-spacing: 0.01em;
            color: var(--gold-dark);
            background: var(--gold-light);
            border: 1px solid var(--gold-line);
            border-radius: 20px;
            padding: 4px 12px;
        }
        .stage2-teaser-badge.teaser-used {
            color: var(--text-muted);
            background: var(--primary-light);
            border-color: transparent;
        }

        /* ===== Stage 2 paywall modal ===== */
        .stage2-paywall-card { max-width: 360px; }
        .stage2-paywall-badge {
            display: inline-block;
            background: var(--gold-light);
            color: var(--gold-dark);
            border: 1px solid var(--gold-line);
            font-weight: 800;
            font-size: 0.78rem;
            padding: 4px 12px;
            border-radius: 20px;
            margin-bottom: 10px;
        }
        .stage2-paywall-copy { color: var(--text-muted); font-weight: 500; font-size: 0.92rem; margin: 4px 0 14px; line-height: 1.45; }
        .stage2-paywall-features { text-align: left; margin-bottom: 16px; }
        .stage2-paywall-feature {
            font-size: 0.85rem;
            font-weight: 600;
            color: var(--text);
            padding: 8px 10px;
            background: rgba(255,255,255,0.7);
            border-radius: 10px;
            margin-bottom: 6px;
        }
        .stage2-paywall-cta { width: 100%; }

        /* ===== Stage 2 worked-solution walkthrough ===== */
        .stage2-walkthrough {
            position: relative;
            margin: 16px 0 20px;
            border-radius: 18px;
            border: 4px solid var(--gold-line);
            background: var(--gold-light);
            padding: 16px;
        }
        .stage2-walkthrough-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 8px;
            margin-bottom: 12px;
            font-family: var(--font-display);
            font-weight: 800;
            color: var(--gold-dark);
        }
        .stage2-marks-counter {
            font-family: var(--font-display);
            font-size: 0.85rem;
            background: white;
            border-radius: 12px;
            padding: 4px 10px;
            color: var(--primary);
        }
        .stage2-step {
            background: white;
            border-radius: 12px;
            padding: 12px 14px;
            margin-bottom: 10px;
            animation: popIn 0.3s var(--ease-out-back);
        }
        .stage2-step-head { display: flex; align-items: flex-start; gap: 8px; }
        .stage2-mark-chip {
            flex: none;
            font-family: var(--font-display);
            font-size: 0.72rem;
            font-weight: 800;
            color: white;
            background: var(--primary);
            border-radius: 8px;
            padding: 2px 7px;
            margin-top: 1px;
        }
        .stage2-mark-chip.mark-A { background: var(--success); }
        .stage2-step-prompt { font-weight: 600; font-size: 0.92rem; line-height: 1.4; }
        .stage2-step-reveal {
            display: none;
            margin-top: 8px;
            padding-top: 8px;
            border-top: 1px dashed var(--gold-line);
            font-weight: 700;
            color: var(--success);
            font-size: 0.92rem;
        }
        .stage2-step.revealed .stage2-step-reveal { display: block; }
        .stage2-step-btn {
            margin-top: 10px;
            border: none;
            background: var(--gold);
            color: var(--text);
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.85rem;
            padding: 9px 16px;
            border-radius: 12px;
            cursor: pointer;
            transition: transform 0.1s, background 0.2s;
        }
        .stage2-step-btn:hover { background: var(--gold-dark); }
        .stage2-step-btn:active { transform: scale(0.96); }
        .stage2-complete-banner {
            text-align: center;
            font-family: var(--font-display);
            font-weight: 800;
            color: var(--gold-dark);
            padding-top: 6px;
        }

        /* ===== Classroom Whiteboard tab ===== */
        /* Single column by design, not just a mobile fallback: the tab's whole
           premise is attempt-then-reveal (see the classroom-placeholder copy
           in classroom.js), so the question and the whiteboard read as one
           top-to-bottom worksheet rather than two panels competing for eyes.
           Width matches the app's standard single-column .card (700px) for
           reading-line-length consistency instead of the old 2-col 980px. */
        .classroom-card { max-width: 700px; }
        .classroom-header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
        .classroom-header h2 { margin: 0; }
        .classroom-new-q-btn { width: auto; margin-top: 0; }
        .classroom-subtitle { color: var(--text-muted); margin: 6px 0 14px; }
        .classroom-topic-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 20px; }
        #classroom-topic-select {
            font-family: var(--font-display);
            font-weight: 700;
            font-size: 0.85rem;
            color: var(--text);
            background: var(--card-bg);
            border: 2px solid var(--line-dashed);
            border-radius: var(--r-sm);
            padding: 8px 12px;
            cursor: pointer;
        }
        .classroom-layout { display: flex; flex-direction: column; gap: 22px; }

        .classroom-panel-label {
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.8rem;
            color: var(--primary);
            text-transform: uppercase;
            letter-spacing: 0.03em;
            margin-bottom: 10px;
        }
        .classroom-left {
            background: var(--card-bg);
            border: var(--border-subtle);
            border-radius: var(--r-md);
            padding: 18px;
        }

        .classroom-right { display: flex; flex-direction: column; gap: 12px; }
        /* Whiteboard surface reuses the same graph-paper layers as .card, on a
           near-white ground with a chalkboard-navy frame, so it reads as a
           distinct physical object rather than another exercise-book page. */
        .classroom-whiteboard-frame {
            border-radius: 18px;
            border: 4px solid var(--navy-800);
            background-color: #FCFEFF;
            background-image:
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 22px 22px;
            box-shadow: var(--shadow-2);
            overflow: hidden;
        }
        .classroom-whiteboard-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 8px;
            background: var(--navy-800);
            color: white;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.88rem;
            padding: 10px 16px;
        }
        .classroom-step-counter {
            font-family: var(--font-display);
            font-size: 0.78rem;
            background: rgba(255,255,255,0.16);
            padding: 3px 10px;
            border-radius: var(--radius-pill);
        }
        .classroom-whiteboard-surface {
            min-height: 220px;
            padding: 20px 22px;
            display: flex;
            flex-direction: column;
            gap: 14px;
            justify-content: center;
        }
        .classroom-placeholder {
            color: var(--text-muted);
            font-style: italic;
            text-align: center;
            padding: 24px 10px;
        }
        .classroom-board-line { display: flex; align-items: flex-start; gap: 10px; }
        .classroom-step-chip {
            flex: none;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            background: var(--primary);
            color: white;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.76rem;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-top: 2px;
        }
        .classroom-board-line.classroom-final-line .classroom-step-chip { background: var(--success); }
        .classroom-step-text {
            font-family: var(--font-hand);
            font-size: 1.4rem;
            line-height: 1.35;
            color: var(--navy-900);
        }
        .classroom-board-line.classroom-final-line .classroom-step-text { font-weight: 700; color: var(--success-dark); }

        .classroom-controls { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
        .classroom-nav-btn {
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.85rem;
            border: none;
            border-radius: 12px;
            padding: 10px 16px;
            cursor: pointer;
            background: var(--primary-light);
            color: var(--primary-dark);
            transition: transform 0.1s, background 0.2s, color 0.2s;
        }
        .classroom-nav-btn:hover:not(:disabled) { background: var(--primary); color: white; }
        .classroom-nav-btn:active:not(:disabled) { transform: scale(0.96); }
        .classroom-nav-btn:disabled { opacity: 0.4; cursor: default; }
        .classroom-nav-btn-primary { background: var(--primary); color: white; }
        .classroom-nav-btn-primary:hover:not(:disabled) { background: var(--primary-dark); }

        .classroom-progress-dots { display: flex; gap: 6px; }
        .classroom-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--line-dashed); transition: background 0.2s; }
        .classroom-dot.filled { background: var(--primary); }

        /* A secondary, optional alternate to the whiteboard — not a second
           required reveal — so it's a small ghost pill (same token palette as
           .btn-secondary), not a full-width competing CTA. */
        .classroom-comic-btn {
            width: auto;
            align-self: flex-end;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.8rem;
            border: 2px solid var(--line-dashed);
            border-radius: var(--radius-pill);
            padding: 8px 14px;
            cursor: pointer;
            background: var(--card-bg);
            color: var(--text-muted);
            transition: transform 0.12s, background 0.2s, color 0.2s, border-color 0.2s;
        }
        .classroom-comic-btn:hover { transform: translateY(-1px); background: var(--primary-light); color: var(--primary); border-color: var(--primary); }
        .classroom-comic-btn:active { transform: scale(0.97); }

        /* Comic strip modal: reuses .pet-modal-overlay/.pet-modal-card (same
           backdrop + pop-in as the check-in and paywall modals) but wider, to
           hold a horizontally-scrolling row of panels. */
        .classroom-comic-card { max-width: 920px; width: 94%; text-align: left; }
        .classroom-comic-card:focus { outline: none; }
        .classroom-comic-card:focus-visible { outline: 3px solid var(--primary); outline-offset: -3px; }
        .classroom-comic-card h2 { text-align: center; margin-bottom: 4px; }
        .classroom-comic-question {
            text-align: center;
            font-weight: 700;
            font-size: 0.95rem;
            color: var(--text);
            line-height: 1.4;
            max-width: 640px;
            margin: 10px auto 0;
            padding-bottom: 12px;
            border-bottom: 1px dashed var(--gold-line);
        }
        .classroom-comic-context { font-weight: 400; color: var(--text-muted); }
        /* Wrap owns the edge-fade hint (::before/::after) so the fade can sit
           above the strip's own content without being clipped by its
           overflow-x: auto. Opacity toggled by updateClassroomComicNav() via
           .can-scroll-left/.can-scroll-right, based on scroll position. */
        .classroom-comic-strip-wrap { position: relative; }
        .classroom-comic-strip-wrap::before,
        .classroom-comic-strip-wrap::after {
            content: '';
            position: absolute;
            top: 0;
            bottom: 10px;
            width: 28px;
            pointer-events: none;
            opacity: 0;
            transition: opacity 0.2s;
            z-index: 1;
        }
        .classroom-comic-strip-wrap::before {
            left: 0;
            background: linear-gradient(90deg, var(--card-bg), transparent);
        }
        .classroom-comic-strip-wrap::after {
            right: 0;
            background: linear-gradient(270deg, var(--card-bg), transparent);
        }
        .classroom-comic-strip-wrap.can-scroll-left::before { opacity: 1; }
        .classroom-comic-strip-wrap.can-scroll-right::after { opacity: 1; }
        .classroom-comic-strip {
            display: flex;
            gap: 14px;
            overflow-x: auto;
            padding: 14px 4px 10px;
            scroll-snap-type: x proximity;
            /* Without this, the browser's scroll-anchoring heuristic (meant to
               stop reflows from visibly jumping content already on screen)
               mistakes a fresh set of just-inserted, still-animating panels
               for a shifted anchor and silently nudges scrollLeft off 0 the
               moment layout is first flushed. */
            overflow-anchor: none;
        }
        .classroom-comic-strip:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
        /* Prev/Next + "Panel X of Y" — same visual weight and pattern as the
           whiteboard's .classroom-controls, so the two panes feel like one
           family rather than the comic being a bolted-on afterthought. */
        .classroom-comic-nav {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 14px;
            margin-top: 4px;
        }
        .classroom-comic-nav-btn {
            /* Overrides the global `button { flex: 1; padding: 12px 25px; }` —
               without this a 34px circular icon button stretches to fill the
               row and its padding turns it into a pill. */
            flex: none;
            padding: 0;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 1.1rem;
            line-height: 1;
            width: 34px;
            height: 34px;
            border: 2px solid var(--line-dashed);
            border-radius: 50%;
            background: var(--card-bg);
            color: var(--primary);
            cursor: pointer;
            transition: transform 0.12s, background 0.2s, border-color 0.2s, opacity 0.2s;
        }
        .classroom-comic-nav-btn:hover:not(:disabled) { transform: translateY(-1px); background: var(--primary-light); border-color: var(--primary); }
        .classroom-comic-nav-btn:active:not(:disabled) { transform: scale(0.94); }
        .classroom-comic-nav-btn:disabled { opacity: 0.35; cursor: default; }
        .classroom-comic-counter {
            font-family: var(--font-display);
            font-weight: 700;
            font-size: 0.8rem;
            color: var(--text-muted);
            min-width: 90px;
            text-align: center;
        }
        .classroom-comic-panel {
            flex: 0 0 210px;
            scroll-snap-align: start;
            background-color: var(--card-bg);
            background-image:
                linear-gradient(var(--grid-line) 1px, transparent 1px),
                linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
            background-size: 18px 18px;
            border: 2.5px solid var(--navy-800);
            border-radius: 14px;
            padding: 10px 10px 12px;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 6px;
            animation: popIn 0.3s var(--ease-out-back);
            /* backwards: holds the 0% keyframe state (scale 0.75, opacity 0)
               during animation-delay (set per-panel in JS for a left-to-right
               stagger), instead of flashing the panel at full opacity first. */
            animation-fill-mode: backwards;
        }
        .classroom-comic-panel-num {
            align-self: flex-start;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.7rem;
            color: white;
            background: var(--primary);
            border-radius: 8px;
            padding: 2px 7px;
            white-space: nowrap;
        }
        /* Chip colour carries the information hierarchy at a glance: purple/gold
           framing chips (question type, what's given) read as a different kind
           of thinking from the blue numbered working steps, which resolve to a
           green final answer — same traffic-light logic as the stage2 mark chips. */
        .classroom-comic-panel-num.chip-type { background: var(--grape); }
        .classroom-comic-panel-num.chip-given { background: var(--gold-dark); }
        .classroom-comic-panel-num.chip-answer { background: var(--success); }
        /* Framing panels (type/given) get a tinted wash + dashed border so they
           read as "orienting" rather than "calculating", without a heavier
           per-panel restyle. */
        .classroom-comic-panel-frame {
            background-color: var(--primary-light);
            border-style: dashed;
            border-color: var(--grape);
        }
        /* Buddy sits below the bubble now — a supporting/reinforcing element
           under the panel's actual content, not its visual anchor, so it's
           sized down from the original 72px. Stays close to the ~80px the
           creature-draw "compact" mode is calibrated for (see creature-draw.js),
           so detail doesn't degrade at this size. */
        .classroom-comic-panel canvas.creature-render-target { width: 64px; height: 64px; }
        .classroom-comic-bubble {
            position: relative;
            background: white;
            border: 1.5px solid var(--line-dashed);
            border-radius: 14px;
            padding: 11px 12px;
            font-size: 0.9rem;
            line-height: 1.45;
            color: var(--text);
            min-height: 70px;
        }
        /* Tail points down to the buddy sitting underneath the bubble. */
        .classroom-comic-bubble::before {
            content: '';
            position: absolute;
            bottom: -8px;
            left: 50%;
            transform: translateX(-50%);
            border-width: 8px 8px 0 8px;
            border-style: solid;
            border-color: white transparent transparent transparent;
        }
        /* Colour thread: chip → bubble top accent → lead-in word all share the
           same hue per panel kind, so the hierarchy reads instantly even
           before the text is read — purple/gold = orienting, blue = working,
           green = resolved. */
        .classroom-comic-bubble.chip-type { border-top: 3px solid var(--grape); }
        .classroom-comic-bubble.chip-given { border-top: 3px solid var(--gold-dark); }
        .classroom-comic-bubble.chip-step { border-top: 3px solid var(--primary); }
        .classroom-comic-bubble.chip-answer {
            border-top: 3px solid var(--success);
            background: var(--success-light);
            color: var(--success-dark);
            font-weight: 700;
        }
        .classroom-comic-bubble.chip-answer::before { border-color: var(--success-light) transparent transparent transparent; }
        .comic-lead { font-weight: 800; }
        .classroom-comic-bubble.chip-type .comic-lead { color: var(--grape-dark); }
        .classroom-comic-bubble.chip-given .comic-lead { color: var(--gold-dark); }
        .classroom-comic-bubble.chip-step .comic-lead { color: var(--primary-dark); }
        .classroom-comic-bubble.chip-answer .comic-lead { color: var(--success-dark); }
        @media (max-width: 480px) { .classroom-comic-panel { flex: 0 0 175px; } }

        /* ===== Nonsuch Mock Exam: dashboard widget ===== */
        .mockexam-widget {
            position: relative;
            border-radius: 20px;
            border: 2px solid var(--primary);
            background: linear-gradient(135deg, var(--primary-light) 0%, var(--gold-light) 100%);
            padding: 16px 18px;
            margin-top: 24px;
        }
        .mockexam-widget-badge {
            display: inline-block;
            font-family: var(--font-display);
            font-size: 0.72rem;
            font-weight: 800;
            letter-spacing: 0.02em;
            color: white;
            background: var(--primary);
            border-radius: 20px;
            padding: 4px 12px;
            margin-bottom: 8px;
        }
        .mockexam-widget-title { font-family: var(--font-display); font-weight: 800; font-size: 1.02rem; color: var(--text); margin-bottom: 2px; }
        .mockexam-widget-countdown { font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; color: var(--primary-dark); margin: 2px 0 6px; }
        .mockexam-widget-copy { color: var(--text-muted); font-weight: 500; font-size: 0.85rem; margin-bottom: 12px; line-height: 1.4; }
        .mockexam-widget-cta {
            border: none;
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.9rem;
            padding: 10px 18px;
            border-radius: 14px;
            cursor: pointer;
            background: var(--primary);
            color: white;
            transition: transform 0.1s, background 0.2s;
        }
        .mockexam-widget-cta:hover { background: var(--primary-dark); }
        .mockexam-widget-cta:active { transform: scale(0.97); }

        /* ===== Nonsuch Mock Exam: paywall modal ===== */
        .mockexam-paywall-card { max-width: 360px; }
        .mockexam-paywall-badge {
            display: inline-block;
            background: var(--gold-light);
            color: var(--gold-dark);
            border: 1px solid var(--gold-line);
            font-weight: 800;
            font-size: 0.78rem;
            padding: 4px 12px;
            border-radius: 20px;
            margin-bottom: 10px;
        }
        .mockexam-paywall-copy { color: var(--text-muted); font-weight: 500; font-size: 0.92rem; margin: 4px 0 14px; line-height: 1.45; }
        .mockexam-paywall-features { text-align: left; margin-bottom: 16px; }
        .mockexam-paywall-feature {
            font-size: 0.85rem;
            font-weight: 600;
            color: var(--text);
            padding: 8px 10px;
            background: rgba(255,255,255,0.7);
            border-radius: 10px;
            margin-bottom: 6px;
        }
        .mockexam-paywall-cta { width: 100%; }

        /* ===== Nonsuch Mock Exam: full-screen simulator ===== */
        #mockexam-card { display: none; }
        .mockexam-view { display: none; }
        .mockexam-view.active { display: block; }
        .mockexam-intro { text-align: center; padding: 8px 4px 4px; }
        .mockexam-intro-part {
            text-align: left;
            background: white;
            border-radius: 14px;
            border: 1px solid var(--line-dashed);
            padding: 12px 16px;
            margin: 14px 0;
        }
        .mockexam-intro-part h3 { font-family: var(--font-display); font-size: 1rem; margin-bottom: 4px; }
        .mockexam-intro-part p { color: var(--text-muted); font-size: 0.88rem; line-height: 1.45; }
        .mockexam-phase-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 10px;
            margin-bottom: 14px;
        }
        .mockexam-phase-title { font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; }
        .mockexam-leave-btn {
            flex: 0 0 auto;
            font-family: var(--font-display);
            font-weight: 700;
            font-size: 0.78rem;
            color: var(--text-muted);
            background: transparent;
            border: 1px solid var(--line-dashed);
            border-radius: var(--radius-pill);
            padding: 5px 12px;
            cursor: pointer;
            transition: color 0.2s, border-color 0.2s;
        }
        .mockexam-leave-btn:hover { color: var(--error); border-color: var(--error); }
        .mockexam-timer {
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 1.1rem;
            background: var(--primary-light);
            color: var(--primary-dark);
            border-radius: 12px;
            padding: 6px 14px;
        }
        .mockexam-timer.low-time { background: var(--error-light); color: var(--error); animation: pulseWarn 1s infinite; }
        @keyframes pulseWarn { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
        .mockexam-progress { color: var(--text-muted); font-weight: 700; font-size: 0.85rem; margin-bottom: 10px; }
        .mockexam-choice-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 6px; }
        .mockexam-choice-btn {
            text-align: left;
            border: 2px solid var(--line-dashed);
            background: white;
            border-radius: 14px;
            padding: 14px 16px;
            font-family: var(--font-display);
            font-weight: 700;
            font-size: 0.95rem;
            color: var(--text);
            cursor: pointer;
            transition: transform 0.1s, border-color 0.2s, background 0.2s;
        }
        .mockexam-choice-btn:hover:not(:disabled) { border-color: var(--primary); }
        .mockexam-choice-btn:active:not(:disabled) { transform: scale(0.97); }
        .mockexam-choice-btn:disabled { cursor: default; opacity: 0.6; }
        /* "Chosen but not yet submitted" — used by Stage 1 (SET) practice mode in the Quiz
           tab, where a choice click doesn't auto-submit like the Mock Exam Simulator does. */
        .mockexam-choice-btn.selected:not(:disabled) { border-color: var(--primary); background: var(--primary-light); }
        .mockexam-choice-btn.choice-correct { background: var(--success-light); border-color: var(--success); opacity: 1; }
        .mockexam-choice-btn.choice-wrong { background: var(--error-light); border-color: var(--error); opacity: 1; }
        @media (max-width: 480px) { .mockexam-choice-grid { grid-template-columns: 1fr; } }

        /* ===== Nonsuch Mock Review ===== */
        .mockexam-review-block { margin-bottom: 22px; }
        .mockexam-review-heading { font-family: var(--font-display); font-weight: 800; font-size: 1rem; margin-bottom: 10px; }
        .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
        .mockexam-speed-table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
        .mockexam-speed-table td, .mockexam-speed-table th { padding: 7px 8px; border-bottom: 1px solid var(--line-dashed); text-align: left; }
        .mockexam-speed-correct { color: var(--success); font-weight: 800; }
        .mockexam-speed-wrong { color: var(--error); font-weight: 800; }
        .mockexam-readiness-card {
            text-align: center;
            border-radius: 18px;
            padding: 18px;
            margin-bottom: 16px;
        }
        .mockexam-readiness-card.band-strong { background: var(--success-light); }
        .mockexam-readiness-card.band-developing { background: var(--gold-light); }
        .mockexam-readiness-card.band-practice { background: var(--error-light); }
        .mockexam-readiness-label { font-family: var(--font-display); font-weight: 800; font-size: 1.3rem; }
        .mockexam-caveat { color: var(--text-muted); font-size: 0.78rem; font-style: italic; margin-top: 6px; }

        /* ===== Adventure / Maze ===== */
        #adventure-card { display: none; }
        /* The page itself is squared paper now, so the intro needs no
           second grid of its own. */
        .adventure-intro {
            text-align: center;
            padding: 24px 20px 28px;
            border-radius: 14px;
        }
        .adventure-intro p { color: var(--text-muted); margin-top: 6px; }
        .maze-wrap { display: flex; flex-direction: column; align-items: center; gap: 18px; }
        .maze-canvas-container { width: 100%; max-width: 580px; position: relative; }
        /* Buddy wrapper owns position via a transitioned transform so tile-to-tile
           moves glide instead of teleporting; the inner flip layer owns facing +
           the hop, leaving the creature canvas free for the engine's own motion. */
        #maze-buddy-wrap {
            position: absolute; left: 0; top: 0;
            pointer-events: none; display: none;
            transition: transform 0.32s cubic-bezier(0.34, 1.3, 0.5, 1);
            will-change: transform;
        }
        #maze-buddy-flip { --maze-face: 1; transform: scaleX(var(--maze-face)); transform-origin: 50% 100%; }
        #maze-buddy-flip.maze-face-left { --maze-face: -1; }
        #maze-buddy-flip.maze-hop { animation: mazeBuddyHop 0.32s var(--ease-standard); }
        @keyframes mazeBuddyHop {
            0%   { transform: scaleX(var(--maze-face)) translateY(0)      scale(1, 1); }
            35%  { transform: scaleX(var(--maze-face)) translateY(-13%)   scale(0.94, 1.07); }
            72%  { transform: scaleX(var(--maze-face)) translateY(0.5%)   scale(1.06, 0.92); }
            100% { transform: scaleX(var(--maze-face)) translateY(0)      scale(1, 1); }
        }
        #maze-buddy-emote {
            position: absolute; left: 50%; top: -0.55em;
            font-size: 1em; line-height: 1;
            transform: translate(-50%, 0) scale(0);
            filter: drop-shadow(0 2px 6px rgba(0,0,0,0.5));
            display: none;
        }
        #maze-buddy-emote.show { display: block; animation: mazeEmotePop 1.15s var(--ease-out-back) both; }
        @keyframes mazeEmotePop {
            0%   { transform: translate(-50%, 8px)   scale(0);    opacity: 0; }
            16%  { transform: translate(-50%, -4px)  scale(1.18); opacity: 1; }
            28%  { transform: translate(-50%, 0)     scale(1); }
            78%  { transform: translate(-50%, -2px)  scale(1);    opacity: 1; }
            100% { transform: translate(-50%, -12px) scale(0.6);  opacity: 0; }
        }
        #maze-buddy-canvas { display: block; min-height: 0; }
        #maze-canvas {
            width: 100%; height: auto; border-radius: 14px; display: block;
            box-shadow: 0 0 0 2px rgba(240,180,41,0.30), 0 16px 52px rgba(0,0,0,0.52);
        }
        .maze-stats { background: linear-gradient(90deg, #1a1408, #2a1f0c, #1a1408); border: 1px solid rgba(240,180,41,0.3); border-radius: 6px; padding: 6px 20px; font-family: var(--font-display); font-size: 0.82rem; font-weight: 700; color: var(--gold); letter-spacing: 0.04em; text-align: center; }
        .maze-controls { display: grid; grid-template-areas: ". n ." "w . e" ". s ."; gap: 0; }
        .maze-ctrl-btn {
            width: 62px; height: 62px; border: none; border-radius: 10px;
            font-size: 1.5rem; font-weight: 800; cursor: pointer;
            box-shadow: inset 0 2px 4px rgba(0,0,0,0.4), inset 0 -2px 3px rgba(255,255,255,0.06);
            transition: background 0.15s, transform 0.1s, box-shadow 0.15s;
        }
        .maze-ctrl-btn:active:not(:disabled) { transform: scale(0.88); }
        .maze-ctrl-btn:disabled { opacity: 1; cursor: default; background: #23263A; color: #3a3f58; box-shadow: inset 0 1px 3px rgba(0,0,0,0.6); }
        .maze-ctrl-btn.door {
            background: linear-gradient(145deg, #F5C530, #D4970F);
            color: white;
            box-shadow: 0 0 20px rgba(240,180,41,0.65), 0 4px 10px rgba(0,0,0,0.2), inset 0 2px 4px rgba(255,255,255,0.15);
            text-shadow: 0 1px 3px rgba(0,0,0,0.22);
            animation: mazeDoorBtnBreath 2.1s ease-in-out infinite;
        }
        @keyframes mazeDoorBtnBreath {
            0%, 100% { box-shadow: 0 0 14px rgba(240,180,41,0.45), 0 4px 10px rgba(0,0,0,0.2), inset 0 2px 4px rgba(255,255,255,0.15); }
            50%      { box-shadow: 0 0 26px rgba(240,180,41,0.85), 0 4px 10px rgba(0,0,0,0.2), inset 0 2px 4px rgba(255,255,255,0.15); }
        }
        .maze-ctrl-btn.free {
            background: linear-gradient(145deg, var(--indigo-2), var(--primary));
            color: white;
            box-shadow: 0 4px 10px rgba(59,71,196,0.35), inset 0 2px 4px rgba(255,255,255,0.12);
        }
        #maze-btn-n { grid-area: n; border-radius: 10px 10px 0 0; }
        #maze-btn-w { grid-area: w; border-radius: 10px 0 0 10px; }
        #maze-btn-e { grid-area: e; border-radius: 0 10px 10px 0; }
        #maze-btn-s { grid-area: s; border-radius: 0 0 10px 10px; }
        /* Door question modal */
        #maze-door-overlay {
            position: fixed;
            inset: 0;
            background: rgba(12, 16, 28, 0.74);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
            display: flex;
            z-index: 900;
            padding: 20px;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }
        /* Wooden notice-board frame: paper interior painted to the padding box,
           plank seams + wood grain to the border box, gold pinstripe between. */
        .maze-question-area {
            margin: auto;
            background:
                linear-gradient(var(--card-bg), var(--card-bg)) padding-box,
                repeating-linear-gradient(90deg, rgba(0,0,0,0) 0 44px, rgba(0,0,0,0.22) 44px 46px) border-box,
                linear-gradient(155deg, var(--wood-hi) 0%, var(--wood) 32%, var(--wood-dark) 64%, var(--wood) 100%) border-box;
            border: 9px solid transparent;
            border-radius: 18px;
            padding: 28px 24px 24px;
            width: 100%;
            max-width: 440px;
            position: relative;
            z-index: 1; /* above the success-burst layer inside the overlay */
            box-shadow: 0 28px 72px rgba(0,0,0,0.52), inset 0 0 0 1.5px rgba(240,180,41,0.45), 0 0 0 1px rgba(0,0,0,0.4);
            animation: maze-modal-in 0.24s var(--ease-out-back) both;
        }
        /* The maze board is narrower than the quiz card (440px minus wood frame
           and the steps-panel padding) — slim the step fields so field + unit
           + Check button fit on one line even at phone widths. */
        .maze-question-area .maze-easy-step-field { width: 110px; }
        /* Focused answer boxes glow like lantern light so the active field is unmissable */
        .maze-question-area input[type="text"]:focus {
            border-color: var(--gold);
            transform: scale(1.03);
            animation: mazeInputGlow 1.5s ease-in-out infinite;
        }
        @keyframes mazeInputGlow {
            0%, 100% { box-shadow: 0 0 0 4px rgba(240,180,41,0.20), 0 0 14px rgba(240,180,41,0.28); }
            50%      { box-shadow: 0 0 0 6px rgba(240,180,41,0.30), 0 0 22px rgba(240,180,41,0.45); }
        }
        /* Success burst — DOM particles that fly out from behind the board */
        .maze-burst { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
        .maze-burst span {
            position: absolute;
            display: block;
            line-height: 1;
            animation: mazeBurstFly 0.85s cubic-bezier(0.16, 0.8, 0.4, 1) both;
        }
        .maze-burst .mb-coin {
            width: 13px; height: 13px; border-radius: 50%;
            background: radial-gradient(circle at 32% 30%, var(--butter), var(--gold) 58%, var(--gold-dark));
            box-shadow: 0 0 8px rgba(240,180,41,0.85);
        }
        .maze-burst .mb-star-gold { color: var(--gold); text-shadow: 0 0 8px rgba(240,180,41,0.8); }
        .maze-burst .mb-star-green { color: var(--success); text-shadow: 0 0 8px rgba(23,138,80,0.7); }
        @keyframes mazeBurstFly {
            0%   { transform: translate(-50%, -50%) scale(0.35) rotate(0deg); opacity: 1; }
            70%  { opacity: 1; }
            100% { transform: translate(calc(-50% + var(--bx)), calc(-50% + var(--by))) scale(1) rotate(var(--br)); opacity: 0; }
        }
        @keyframes maze-modal-in {
            from { opacity: 0; transform: scale(0.90) translateY(14px); }
            to   { opacity: 1; transform: none; }
        }
        #maze-modal-close {
            position: absolute;
            top: 12px; right: 12px;
            width: 30px; height: 30px;
            border-radius: 50%;
            border: none;
            background: var(--background-dim);
            color: var(--text-muted);
            font-size: 0.88rem;
            cursor: pointer;
            display: flex; align-items: center; justify-content: center;
            transition: background 0.15s;
            line-height: 1;
        }
        #maze-modal-close:hover { background: #c8cdd8; }
        .maze-door-badge {
            background: var(--gold);
            color: var(--text); padding: 5px 14px; border-radius: 20px;
            font-size: 0.82rem; font-weight: 700; display: inline-block; margin-bottom: 14px;
            box-shadow: 0 0 0 3px var(--card-bg), 0 2px 8px rgba(240,180,41,0.38);
            letter-spacing: 0.01em;
        }
        .maze-question-text { font-size: 1.1rem; font-weight: 600; margin-bottom: 16px; line-height: 1.5; }
        .maze-completion { text-align: center; padding: 20px 0; }
        /* Badge reveal: rotating gold aura behind a medallion that springs in */
        .maze-badge-reveal { position: relative; width: 112px; height: 112px; margin: 2px auto 12px; }
        .maze-badge-aura {
            position: absolute; inset: -16px; border-radius: 50%;
            background: conic-gradient(from 0deg,
                rgba(240,180,41,0) 0deg,  rgba(240,180,41,0.55) 42deg,  rgba(240,180,41,0) 84deg,
                rgba(240,180,41,0.32) 150deg, rgba(240,180,41,0) 210deg,
                rgba(240,180,41,0.5) 288deg,  rgba(240,180,41,0) 336deg);
            filter: blur(6px);
            animation: mazeAuraSpin 7s linear infinite;
            opacity: 0;
            transition: opacity 0.6s ease 0.3s;
        }
        @keyframes mazeAuraSpin { to { transform: rotate(360deg); } }
        .maze-badge-medal {
            position: absolute; inset: 0; border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            font-size: 50px;
            background: radial-gradient(circle at 34% 28%, var(--butter), var(--gold) 62%, var(--gold-dark));
            box-shadow: 0 6px 18px rgba(183,121,31,0.45), inset 0 -5px 12px rgba(0,0,0,0.18), inset 0 3px 8px rgba(255,255,255,0.5);
            transform: scale(0);
        }
        .maze-badge-reveal.reveal .maze-badge-aura,
        .maze-badge-reveal.static .maze-badge-aura { opacity: 1; }
        .maze-badge-reveal.reveal .maze-badge-medal { animation: mazeBadgeSpring 0.7s var(--ease-out-back) 0.18s forwards; }
        .maze-badge-reveal.static .maze-badge-medal { transform: scale(1); }
        @keyframes mazeBadgeSpring {
            0%   { transform: scale(0) rotate(-16deg); }
            62%  { transform: scale(1.12) rotate(3deg); }
            100% { transform: scale(1) rotate(0deg); }
        }
        .maze-complete-title { font-family: var(--font-display); font-size: 1.35rem; color: var(--text); margin: 0; }
        .maze-reward-tickers { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; margin-top: 14px; }
        .maze-ticker {
            display: flex; align-items: center; gap: 7px;
            background: var(--gold-light); border: 1.5px solid var(--gold-line);
            border-radius: var(--radius-pill); padding: 7px 16px;
            font-family: var(--font-display); font-weight: 800; font-size: 1.05rem; color: var(--text);
        }
        .maze-ticker-icon { display: inline-flex; font-size: 1.05em; }
        .maze-ticker.counting .maze-ticker-icon { animation: mazeTickerBounce 0.4s var(--ease-standard) infinite; }
        @keyframes mazeTickerBounce {
            0%, 100% { transform: translateY(0) scale(1); }
            40%      { transform: translateY(-5px) scale(1.15); }
        }
        .maze-sound-btn {
            position: absolute; top: 0; right: 0;
            background: none; border: none; cursor: pointer;
            font-size: 1.1rem;
            min-width: 44px; min-height: 44px;
            display: flex; align-items: center; justify-content: center;
            border-radius: 10px;
            opacity: 0.55;
            transition: opacity 0.15s, background 0.15s;
        }
        .maze-sound-btn:hover { opacity: 1; background: rgba(255,255,255,0.12); }
        .maze-sound-btn:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; opacity: 1; }
        .maze-sound-btn:active { transform: scale(0.92); }
        .maze-launch-btn { margin-top: 16px; }
        #maze-skip-btn {
            display: block;
            width: 100%;
            margin-top: 10px;
            padding: 10px 16px;
            background: transparent;
            color: var(--gold-dark); border: 2px solid var(--gold); border-radius: 10px;
            font-size: 0.9rem; font-weight: 700; cursor: pointer;
            transition: background 0.15s;
        }
        #maze-skip-btn:hover { background: var(--gold-light); }
        /* ===== Mission Board ===== */
        .missions-section { margin-top: 20px; }
        .missions-section h4 { margin-bottom: 10px; }
        .mission-list { display: flex; flex-direction: column; gap: 10px; }
        .mission-item { display: flex; align-items: center; gap: 12px; background: var(--card-bg); border-radius: 12px; padding: 12px 16px; border: 2px solid var(--line-dashed); transition: border-color 0.2s; }
        .mission-item.done { border-color: var(--success); background: var(--success-light); }
        .mission-icon { font-size: 1.5rem; flex: 0 0 auto; }
        .mission-body { flex: 1; }
        .mission-name { font-weight: 700; font-size: 0.95rem; }
        .mission-desc { font-size: 0.82rem; color: var(--text-muted); margin-top: 2px; }
        .mission-item.done .mission-desc { color: var(--success); }
        .mission-xp { font-size: 0.82rem; font-weight: 700; color: var(--gold-dark); flex: 0 0 auto; }
        .mission-item.done .mission-xp { color: var(--success); }
        @keyframes missionPop { 0% { transform: scale(1); } 40% { transform: scale(1.04); } 100% { transform: scale(1); } }
        .mission-item.done { animation: missionPop 0.35s var(--ease-standard); }
        /* ===== Speed Burst ===== */
        .speed-main { display: none; }
        .speed-cockpit {
            background: linear-gradient(160deg, var(--navy-900) 0%, var(--navy-800) 100%);
            border-radius: 16px;
            padding: 20px 24px 16px;
            text-align: center;
            margin-bottom: 16px;
            box-shadow: inset 0 1px 0 rgba(255,255,255,0.08), 0 4px 20px rgba(28,35,51,0.22);
        }
        .speed-timer-display { font-size: 3.8rem; font-weight: 800; color: var(--butter); font-family: var(--font-display); letter-spacing: -0.03em; font-variant-numeric: tabular-nums; line-height: 1; margin-bottom: 4px; }
        .speed-timer-display.warning { color: #FCA5A5; animation: timerPulse 0.55s ease-in-out infinite; }
        @keyframes timerPulse {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.08); }
        }
        .speed-correct-count { text-align: center; color: rgba(255,255,255,0.65); font-weight: 700; margin-bottom: 0; font-size: 0.88rem; }
        .speed-question-text { font-size: 1.1rem; font-weight: 600; margin: 12px 0; line-height: 1.5; }
        .speed-completion { display: none; text-align: center; padding: 20px 0; }

        @keyframes coinEarn {
            0%   { transform: scale(1); }
            40%  { transform: scale(1.35); box-shadow: 0 0 0 4px rgba(240,180,41,0.3); }
            100% { transform: scale(1); box-shadow: none; }
        }
        .coin-earn-pulse { animation: coinEarn 0.45s var(--ease-out-back); }

        /* ==================== Village tab ==================== */

        /* Village scene */
        /* Ink-blue frame around the canvas world — reads like a scene pasted
           into the exercise book, and works for every time-of-day sky. */
        .village-scene {
            border-radius: 16px; padding: 14px 14px 48px; margin-bottom: 16px;
            position: relative; overflow: hidden; background: #2A3860;
        }

        /* Coin HUD — overlaid on canvas top-right */
        .village-coin-hud {
            position: absolute; top: 10px; right: 12px;
            background: rgba(24,33,66,0.62); color: var(--butter);
            border-radius: 20px; padding: 4px 10px;
            font-size: 0.85rem; font-weight: 700; pointer-events: none;
            letter-spacing: 0.02em;
        }

        /* Market FAB */
        .market-fab {
            position: absolute; bottom: 14px; right: 12px;
            background: var(--gold); color: var(--text);
            border: none; border-radius: 24px;
            padding: 10px 18px; font-weight: 800; font-size: 0.9rem;
            cursor: pointer; box-shadow: 0 4px 14px rgba(0,0,0,0.28);
            transition: background var(--dur-base), transform var(--dur-fast);
            z-index: 20;
        }
        .market-fab:hover { background: var(--gold-dark); transform: scale(1.04); }

        /* Market bottom sheet — z-index 900 keeps it above village-card (200) but below overlays (1050) */
        .market-sheet {
            display: none; position: fixed; inset: 0; z-index: 900;
            background: rgba(0,0,0,0); transition: background 250ms;
        }
        .market-sheet.open { display: block; background: rgba(0,0,0,0.42); }
        .market-sheet-inner {
            position: absolute; bottom: 56px; left: 0; right: 0;
            background: #f9f5e8; border-radius: 20px 20px 0 0;
            max-height: 65vh; display: flex; flex-direction: column;
            transform: translateY(100%);
            transition: transform 280ms cubic-bezier(0.32,0.72,0,1);
            box-shadow: 0 -4px 24px rgba(0,0,0,0.18);
        }
        .market-sheet.open .market-sheet-inner { transform: translateY(0); }
        .market-sheet-handle {
            width: 40px; height: 4px; border-radius: 2px;
            background: rgba(0,0,0,0.15); margin: 10px auto 0;
            flex-shrink: 0;
        }
        .market-sheet-header {
            display: flex; align-items: center; justify-content: space-between;
            padding: 12px 20px 8px; flex-shrink: 0;
            border-bottom: 1px solid #e8ddc8;
        }
        .market-sheet-title { font-weight: 800; font-size: 1.05rem; color: var(--text); }
        .market-sheet-close {
            background: rgba(0,0,0,0.08); border: none; border-radius: 50%;
            /* flex:0 — the global `button { flex:1 }` rule was stretching this
               into a full-width ellipse across the sheet header */
            flex: 0 0 auto;
            width: 30px; height: 30px; font-size: 0.85rem; cursor: pointer;
            color: var(--text-muted); font-weight: 700; display: flex;
            align-items: center; justify-content: center;
            transition: background var(--dur-fast), transform var(--dur-fast);
        }
        .market-sheet-close:hover { background: rgba(0,0,0,0.15); transform: scale(1.08); }
        .market-sheet-close:active { transform: scale(0.93); }
        .market-sheet-list { overflow-y: auto; padding: 16px 16px 24px; flex: 1; }
        .village-scene-hint {
            font-size: 0.72rem; font-weight: 700; color: rgba(255,255,255,0.78);
            text-align: center; margin-bottom: 8px; letter-spacing: 0.05em;
            text-transform: uppercase; text-shadow: 0 1px 3px rgba(0,0,0,0.5);
        }
        .village-scene-hint.goal { color: #ffe066; text-shadow: 0 1px 4px rgba(0,0,0,0.6); }

        /* Village canvas (isometric renderer) */
        #village-canvas { cursor: pointer; }
        #village-buddy-wrap {
            /* pointer-events on: the buddy responds to pokes (village.js tap handler) */
            position: absolute; pointer-events: auto; cursor: pointer; display: none;
            transition: left 1.5s ease-in-out, top 1.5s ease-in-out;
        }
        #village-tooltip {
            position: absolute; pointer-events: none; display: none;
            background: rgba(20,20,30,0.88); color: #fff;
            padding: 4px 10px; border-radius: 8px;
            font-size: 0.76rem; font-weight: 700; white-space: nowrap;
            transform: translateX(-50%) translateY(-100%);
            z-index: 10; letter-spacing: 0.02em;
        }

        /* Pet speech bubble in village */
        #village-speech-bubble {
            position: absolute; pointer-events: none;
            background: #fff; color: var(--text);
            border-radius: 14px; padding: 6px 12px;
            font-size: 0.78rem; font-weight: 700; white-space: nowrap;
            box-shadow: 0 2px 8px rgba(0,0,0,0.18);
            transform: translateX(-50%) translateY(-100%);
            z-index: 30; display: none;
            animation: bubblePop 0.25s var(--ease-out-back);
        }
        #village-speech-bubble::after {
            content: ''; position: absolute; bottom: -7px; left: 50%;
            transform: translateX(-50%);
            border: 6px solid transparent; border-top-color: #fff; border-bottom: none;
        }
        @keyframes bubblePop {
            from { opacity: 0; transform: translateX(-50%) translateY(-120%) scale(0.8); }
            to   { opacity: 1; transform: translateX(-50%) translateY(-100%) scale(1); }
        }

        /* Shop */
        .building-card {
            display: flex; align-items: center; gap: 14px;
            padding: 14px 16px; border-radius: 12px;
            background: #f9f5e8; border: 1px solid #e8ddc8;
            margin-bottom: 10px; transition: border-color var(--dur-base), opacity var(--dur-base);
        }
        .building-card.teaser { opacity: 0.55; }
        .building-card-emoji { font-size: 2rem; flex-shrink: 0; }
        .building-card-info { flex: 1; min-width: 0; }
        .building-card-name { font-weight: 700; font-size: 0.95rem; color: var(--text); }
        .building-card-desc { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; }
        .building-card-cost { font-size: 0.78rem; font-weight: 700; color: var(--gold-dark); margin-top: 4px; }
        .building-card-locked { font-size: 0.78rem; color: var(--text-muted); margin-top: 2px; }
        .building-card-btn {
            flex-shrink: 0; padding: 8px 14px; border-radius: 20px;
            font-weight: 700; font-size: 0.82rem; cursor: pointer;
            border: none; transition: opacity var(--dur-base);
        }
        .building-card-btn.can-buy { background: var(--gold); color: #fff; }
        .building-card-btn.can-buy:hover { background: var(--gold-dark); }
        .building-card-btn:disabled { background: var(--background-dim); color: var(--text-muted); cursor: not-allowed; opacity: 0.7; }
        .building-owned-badge {
            flex-shrink: 0; padding: 6px 12px; border-radius: 20px;
            background: var(--success-light); color: var(--success);
            font-weight: 700; font-size: 0.82rem;
        }
        .shop-section-label {
            font-size: 0.72rem; font-weight: 800; letter-spacing: 0.07em;
            text-transform: uppercase; color: var(--text-muted);
            margin: 18px 0 10px; padding-bottom: 6px;
            border-bottom: 1.5px solid var(--line-dashed);
        }
        .shop-more-hint {
            font-size: 0.82rem; color: var(--text-muted); text-align: center;
            padding: 10px 0 4px; font-style: italic;
        }

        /* Shared overlay base */
        .village-overlay {
            display: none; position: fixed; inset: 0;
            background: rgba(0,0,0,0.55); z-index: 1050;
            align-items: center; justify-content: center;
            animation: backdropFadeIn 200ms;
        }
        .village-overlay.open { display: flex; }
        .village-overlay-card {
            background: var(--card-bg); max-width: 340px; width: 92%;
            border-radius: 20px; padding: 28px 24px;
            box-shadow: 0 10px 30px rgba(28,35,51,0.18);
            animation: popIn 0.3s ease-out; max-height: 80vh; overflow-y: auto;
        }

        /* Slot picker */
        .slot-picker-title { font-weight: 800; font-size: 1.1rem; margin-bottom: 16px; text-align: center; }
        .slot-picker-grid {
            display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 16px;
        }
        .slot-picker-item {
            aspect-ratio: 1; border-radius: 10px; border: 2px solid var(--line-dashed);
            background: var(--background); display: flex; flex-direction: column;
            align-items: center; justify-content: center; gap: 4px;
            cursor: pointer; padding: 6px; text-align: center;
            transition: border-color var(--dur-base), background var(--dur-base);
        }
        .slot-picker-item:hover { border-color: var(--primary); background: var(--primary-light); }
        .slot-picker-item-emoji { font-size: 1.8rem; line-height: 1; }
        .slot-picker-item-label { font-size: 0.6rem; font-weight: 700; color: var(--text-muted); line-height: 1.1; }
        .slot-picker-empty { text-align: center; color: var(--text-muted); font-size: 0.9rem; padding: 20px 0; }
        .overlay-close-btn {
            display: block; width: 100%; padding: 10px;
            background: var(--background-dim); border: none; border-radius: 12px;
            font-weight: 700; color: var(--text-muted); cursor: pointer; margin-top: 6px;
            transition: background var(--dur-fast), transform var(--dur-fast);
        }
        .overlay-close-btn:hover { background: rgba(0,0,0,0.1); }
        .overlay-close-btn:active { transform: scale(0.97); }

        /* Building info panel */
        .building-info-emoji { font-size: 3.5rem; text-align: center; display: block; margin-bottom: 10px; }
        .building-info-name { font-weight: 800; font-size: 1.15rem; text-align: center; margin-bottom: 6px; }
        .building-info-desc { font-size: 0.88rem; color: var(--text-muted); text-align: center; margin-bottom: 20px; line-height: 1.5; }
        .building-info-move {
            display: block; width: 100%; padding: 10px; margin-bottom: 8px;
            background: var(--background); border: 1.5px solid var(--line-dashed);
            border-radius: 12px; font-weight: 700; color: var(--text-muted); cursor: pointer;
            transition: background var(--dur-fast), border-color var(--dur-fast);
        }
        .building-info-move:hover { background: var(--background-dim); border-color: var(--text-muted); }
        .building-info-move:active { transform: scale(0.97); }

        /* Purchase confirm */
        .confirm-emoji { font-size: 3.5rem; text-align: center; display: block; margin-bottom: 10px; }
        .confirm-name { font-weight: 800; font-size: 1.1rem; text-align: center; margin-bottom: 4px; }
        .confirm-cost { font-size: 0.9rem; color: var(--gold-dark); font-weight: 700; text-align: center; margin-bottom: 6px; }
        .confirm-desc { font-size: 0.82rem; color: var(--text-muted); text-align: center; margin-bottom: 10px; line-height: 1.45; }
        .confirm-balance { font-size: 0.78rem; color: var(--text-muted); text-align: center; margin-bottom: 18px; }

        /* Village complete banner */
        .village-complete-banner {
            background: linear-gradient(135deg, var(--gold-light), #fff9e6);
            border: 1.5px solid rgba(240,180,41,0.45);
            border-radius: 14px; padding: 14px 18px; margin-bottom: 14px;
            text-align: center; font-weight: 800; font-size: 1rem; color: var(--gold-dark);
            letter-spacing: 0.02em;
        }
        .village-complete-banner small {
            display: block; font-weight: 400; font-size: 0.78rem;
            color: var(--text-muted); margin-top: 4px;
        }

        /* ── Fullscreen village ───────────────────────────────────── */
        body.village-active { overflow: hidden; }
        body.village-active #village-card {
            position: fixed;
            inset: 0;
            bottom: 56px;
            z-index: 200;
            border-radius: 0;
            padding: 0;
            margin: 0 !important;
            max-width: none;
            display: flex !important;
            flex-direction: column;
            overflow: hidden;
        }
        body.village-active #village-card > h2,
        body.village-active #village-card > p { display: none; }
        body.village-active #village-complete-banner { margin: 8px 16px; }
        body.village-active .village-scene {
            flex: 1;
            border-radius: 0;
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        body.village-active .market-fab { bottom: 22px; }
        body.village-active .village-coin-hud { top: 14px; right: 16px; }
        body.village-active .tab-bar,
        body.maze-active .tab-bar {
            position: fixed;
            top: auto; bottom: 0; left: 0; right: 0;
            transform: none;
            height: 56px;
            z-index: 201;
            max-width: none;
            margin: 0;
            border-bottom: none;
            border-top: 1px solid rgba(30,42,74,0.08);
            background: rgba(253,251,247,0.85);
            backdrop-filter: blur(14px);
            -webkit-backdrop-filter: blur(14px);
            padding-bottom: env(safe-area-inset-bottom);
        }

        /* ── Nonsuch Mock Exam takeover (no distractions, matches exam conditions) ── */
        body.mockexam-active .arena-header,
        body.mockexam-active .score-board,
        body.mockexam-active .tab-bar,
        body.dailyset-active .arena-header,
        body.dailyset-active .score-board,
        body.dailyset-active .tab-bar { display: none; }

        /* Daily mini-Stage-1: neutral answer lock-in (deliberately not green/red —
           correctness is only revealed in the review) + review answer/tip lines */
        .dailyset-choice-locked { outline: 3px solid var(--primary); background: var(--background-dim); }
        .dailyset-recap { background: var(--gold-light); border: 1.5px solid var(--gold-line); border-radius: 12px; padding: 8px 14px; font-size: 0.9rem; color: var(--gold-dark); }
        .dailyset-review-answer { font-size: 0.88rem; margin-top: 4px; }
        .dailyset-review-strategy { color: var(--text-muted); font-size: 0.84rem; margin-top: 4px; line-height: 1.45; }

        /* ── Fullscreen maze ──────────────────────────────────────── */
        body.maze-active { overflow: hidden; }
        body.maze-active #adventure-card {
            position: fixed;
            inset: 0;
            bottom: 56px;
            z-index: 200;
            border-radius: 0;
            padding: 0;
            margin: 0 !important;
            max-width: none;
            display: flex !important;
            flex-direction: column;
            overflow: hidden;
        }
        body.maze-active #maze-intro { display: none !important; }
        body.maze-active #maze-main {
            flex: 1 1 0;
            display: flex !important;
            flex-direction: column;
            align-items: center;
            gap: 8px;
            padding: 8px 12px 12px;
            min-height: 0;
            overflow: hidden;
        }
        body.maze-active #maze-main > div:first-child > h2 { display: none; }
        body.maze-active .maze-canvas-container {
            flex: 1 1 0;
            max-width: none;
            width: 100%;
            min-height: 0;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        body.maze-active #maze-canvas {
            max-height: 100% !important;
            max-width: 100% !important;
            width: auto !important;
            height: 100% !important;
            aspect-ratio: 1;
            border-radius: 10px !important;
        }

        /* "How to earn coins" guide in the shop */
        .coin-earn-guide {
            background: var(--gold-light); border: 1.5px solid var(--gold-line);
            border-radius: 14px; padding: 10px 14px; margin-bottom: 16px;
            font-size: 0.85rem; color: var(--text); text-align: left;
        }
        .coin-earn-guide summary {
            cursor: pointer; font-weight: 800; color: var(--gold-dark);
            font-family: var(--font-display); font-size: 0.92rem;
        }
        .coin-earn-guide ul { margin: 10px 0 4px; padding-left: 18px; line-height: 1.55; }
        .coin-earn-guide li { margin-bottom: 4px; }
        .coin-earn-guide .guide-note { color: var(--text-muted); font-size: 0.8rem; }

        /* New-player shop CTA */
        .village-new-player-cta {
            background: var(--background-dim); border-radius: 14px;
            padding: 18px 16px; text-align: center; margin-bottom: 18px;
            font-size: 0.88rem; color: var(--text-muted); line-height: 1.5;
        }
        .village-new-player-cta button {
            margin-top: 12px; margin-inline: 4px; padding: 10px 20px; border-radius: 20px;
            background: var(--primary); color: #fff; border: none;
            font-weight: 700; font-size: 0.88rem; cursor: pointer;
        }

        .confirm-yes-btn {
            display: block; width: 100%; padding: 12px; margin-bottom: 8px;
            background: var(--gold); color: #fff; border: none; border-radius: 12px;
            font-weight: 800; font-size: 1rem; cursor: pointer;
        }
        .confirm-yes-btn:hover { background: var(--gold-dark); }

        @keyframes confettiFloat {
            0%   { transform: translate(0, 0) scale(1); opacity: 1; }
            100% { transform: translate(var(--cf-dx, 0px), -130px) scale(0.4); opacity: 0; }
        }

        /* ── Pencil-write animation ──────────────────────────────────── */
        .algebra-block {
            font-family: var(--font-hand);
            font-size: 1.15rem;
            line-height: 1.6;
            white-space: pre-wrap;
        }
        .easy-step-prompt {
            font-family: var(--font-hand);
            font-size: 1.2rem;
            line-height: 1.6;
            font-weight: 400;
        }
        /* Character spans injected by pencilWrite */
        .pw-char { visibility: hidden; }
        .pw-char.pw-visible { visibility: visible; }

        /* Line divs injected by pencilWriteLines (algebra) */
        .alg-line {
            display: block;
            opacity: 0;
            transform: translateX(-6px);
            transition: opacity 220ms ease, transform 220ms ease;
        }
        .alg-line.alg-line-in {
            opacity: 1;
            transform: translateX(0);
        }

        /* Pencil cursor element */
        #pencil-cursor-el {
            position: fixed;
            pointer-events: none;
            width: 28px;
            height: 28px;
            z-index: 9999;
            opacity: 0;
            will-change: transform, left, top;
            transition: opacity 200ms, left 80ms ease, top 80ms ease;
            transform: rotate(-38deg);
            transform-origin: bottom left;
        }
        #pencil-cursor-el.pw-active { opacity: 1; }
        #pencil-cursor-el.pw-lifting {
            transition: opacity 200ms, left 160ms ease-out, top 160ms ease-out;
        }
        #pencil-cursor-el.pw-done { opacity: 0; }
        @keyframes pencilWobble {
            0%, 100% { transform: rotate(-38deg); }
            50%       { transform: rotate(-42deg); }
        }
        #pencil-cursor-el.pw-active {
            animation: pencilWobble 500ms ease-in-out infinite;
        }
        #pencil-cursor-el.pw-done, #pencil-cursor-el.pw-lifting {
            animation: none;
        }

        /* SVG path draw-on */
        @keyframes svgDrawPath {
            to { stroke-dashoffset: 0; }
        }
        @keyframes svgFadeIn {
            to { opacity: 1; }
        }
        .svg-draw-stroke {
            stroke-dashoffset: var(--path-len);
            stroke-dasharray: var(--path-len);
            animation: svgDrawPath var(--draw-dur, 0.5s) ease-in-out forwards;
            animation-delay: var(--draw-delay, 0s);
        }
        .svg-draw-fill {
            opacity: 0;
            animation: svgFadeIn var(--draw-dur, 0.3s) ease-in forwards;
            animation-delay: var(--draw-delay, 0s);
        }

        /* Skip button */
        .pencil-skip-btn {
            display: inline-block;
            margin-left: 12px;
            font-size: 0.72rem;
            color: #aaa;
            cursor: pointer;
            opacity: 0.8;
            user-select: none;
            vertical-align: middle;
            font-family: var(--font-body);
        }
        .pencil-skip-btn:hover { opacity: 1; color: #888; }

        @media (prefers-reduced-motion: reduce) {
            #pencil-cursor-el { display: none !important; }
            .pw-char { visibility: visible !important; }
            .alg-line { opacity: 1 !important; transform: none !important; transition: none !important; }
            .svg-draw-stroke { animation: none !important; stroke-dashoffset: 0 !important; }
            .svg-draw-fill { animation: none !important; opacity: 1 !important; }
        }
        /* ── End pencil-write ────────────────────────────────────────── */

        /* ── Buddy Widget ───────────────────────────────────────────── */
        #buddy-widget {
            position: fixed;
            bottom: 72px;
            right: 16px;
            z-index: 80;
            width: 88px;
            display: none;
            flex-direction: column;
            align-items: center;
        }
        #buddy-widget.buddy-visible { display: flex; }
        /* Clip container forces visible area to 80×80 while the canvas renders at 250×250
           (its natural SIZE_PRESET). CSS transform scales the canvas to fit — ~3× supersampling. */
        #buddy-canvas-clip {
            width: 80px;
            height: 80px;
            overflow: hidden;
            border-radius: 50%;
            filter: drop-shadow(0 2px 6px rgba(0,0,0,0.20));
            flex-shrink: 0;
            position: relative;
        }
        #buddy-canvas {
            display: block;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%) scale(0.32);
        }
        #buddy-bubble {
            position: absolute;
            bottom: 88px;
            right: 0;
            background: #fff;
            border-radius: 12px;
            padding: 6px 10px;
            font-size: 13px;
            font-weight: 600;
            color: #1e293b;
            box-shadow: 0 2px 8px rgba(0,0,0,0.15);
            max-width: 160px;
            text-align: center;
            white-space: nowrap;
            opacity: 0;
            transform: translateY(4px);
            transition: opacity 0.18s ease, transform 0.18s ease;
            pointer-events: none;
        }
        #buddy-bubble.bubble-visible {
            opacity: 1;
            transform: translateY(0);
        }
        #buddy-bubble::after {
            content: '';
            position: absolute;
            bottom: -6px;
            right: 16px;
            width: 0;
            height: 0;
            border-left: 6px solid transparent;
            border-right: 6px solid transparent;
            border-top: 6px solid #fff;
        }
        @media (max-width: 400px) {
            #buddy-widget { width: 64px; bottom: 64px; right: 8px; }
            #buddy-canvas-clip { width: 56px; height: 56px; }
            #buddy-canvas { transform: translate(-50%, -50%) scale(0.224); } /* 56/250 */
            #buddy-bubble { display: none; }
            /* The widget floats fixed above quiz answer choices, which on this
               narrow a screen span nearly the full card width — reserve a gutter
               so its circle never sits on top of option text (see #interaction-area,
               the only container the buddy is shown alongside — Skills practice
               uses a separate #skill-interaction-area and is unaffected). */
            body:has(#buddy-widget.buddy-visible) #interaction-area {
                padding-right: 64px;
            }
        }
        /* ── End Buddy Widget ───────────────────────────────────────── */

        /* ════════════════════════════════════════════════════════════
           ARENA SHELL — unified header, app shell & tactile controls
           ════════════════════════════════════════════════════════════ */
        /* (arena tokens now live in the single :root block at the top) */

        /* -- Card uniformity: every content container gets the same edge -- */
        .card { border: var(--border-subtle); border-radius: var(--radius-card); }

        /* -- Global Arena Header: permanent, non-shifting, sticky anchor -- */
        .arena-header {
            position: sticky;
            top: 0;
            z-index: 60;
            width: 100%;
            max-width: 700px;
            background: rgba(253,251,247,0.92);
            backdrop-filter: blur(14px) saturate(140%);
            -webkit-backdrop-filter: blur(14px) saturate(140%);
            border-radius: var(--radius-card);
            box-shadow: 0 2px 12px rgba(28,35,51,0.08);
            border: var(--border-subtle);
            margin-bottom: 16px;
            padding: 10px 16px;
            text-align: left;
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 10px;
            flex-wrap: wrap;
        }
        .arena-header h1 {
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 1.3rem;
            font-weight: 800;
            margin: 0;
            letter-spacing: 0.01em;
            min-width: 0;
        }
        .arena-header h1::after { display: none; }
        .arena-logo-icon { width: 30px; height: 30px; flex: 0 0 auto; }
        .arena-header p {
            position: absolute;
            width: 1px; height: 1px;
            overflow: hidden;
            clip: rect(0,0,0,0);
            white-space: nowrap;
        }
        /* Right-hand cluster: Sound toggle · Parents link · Log in/out.
           All three share one labeled-pill shape (icon + word) so no control
           is ever an unexplained glyph — same reasoning as the old "⋯ Menu",
           but flat: with only three actions left, a submenu is pure friction. */
        .arena-actions {
            display: flex;
            align-items: center;
            gap: 6px;
            flex: 0 0 auto;
            margin-left: auto;
        }
        .arena-action-btn {
            display: inline-flex;
            align-items: center;
            gap: 6px;
            padding: 7px 12px;
            border-radius: var(--radius-pill);
            background: var(--background);
            color: var(--text-muted);
            border: var(--border-subtle);
            font-family: var(--font-display);
            font-weight: 800;
            font-size: 0.78rem;
            line-height: 1;
            text-decoration: none;
            white-space: nowrap;
            cursor: pointer;
            box-shadow: none;
            transition: background 0.2s, color 0.2s, transform 0.1s;
        }
        .arena-action-btn:hover { background: var(--primary-light); color: var(--primary); transform: translateY(-1px); }
        .arena-action-btn:active { transform: scale(0.96); }
        .arena-action-icon { font-size: 0.92rem; line-height: 1; }
        /* Muted state reads at a glance even icon-only: dimmed + hollow */
        #sound-toggle-btn[aria-pressed="false"] { opacity: 0.62; }
        .arena-auth-btn.is-logged-in:hover { background: var(--error-light); color: var(--error); }

        @media (max-width: 560px) {
            /* Icon-only pills: the title + clipped label keep the accessible
               name, and ~38px squares stay comfortable touch targets. Title
               and logo shrink a step so the whole header holds one row down
               to ~350px; below that the pills wrap right-aligned underneath. */
            .arena-header { padding: 8px 12px; }
            .arena-header h1 { font-size: 1.12rem; gap: 8px; }
            .arena-logo-icon { width: 26px; height: 26px; }
            .arena-actions { gap: 4px; }
            .arena-action-btn { padding: 9px; }
            .arena-action-icon { font-size: 1.05rem; }
            .arena-action-label {
                position: absolute;
                width: 1px; height: 1px;
                overflow: hidden;
                clip: rect(0,0,0,0);
                white-space: nowrap;
            }
        }

        /* -- Score board is now contextual: lives inside the active quiz session -- */
        #topic-practice > .score-board { margin-top: 0; margin-bottom: 20px; }

        /* -- Bottom nav dock: locked bar under the header on desktop,
              floating sticky dock on mobile -- */
        @media (min-width: 801px) {
            .tab-bar { position: sticky; top: calc(var(--arena-header-h) + 8px); z-index: 45; }
            /* Tab bar sits near the top of the page here, not the bottom — opening the "More"
               menu upward (the mobile default) would clip it behind the sticky header. */
            .tab-more-menu {
                bottom: auto;
                top: calc(100% + 8px);
                transform: translateX(-50%) translateY(-6px);
            }
            .tab-more-menu.open { transform: translateX(-50%) translateY(0); }
        }
        @media (max-width: 800px) {
            .tab-bar {
                position: fixed;
                left: 50%;
                transform: translateX(-50%);
                bottom: 10px;
                width: calc(100% - 24px);
                max-width: 460px;
                /* Above #buddy-widget (z-index 80) — position:fixed here opens a new
                   stacking context, so the "More" popup menu nested inside (its own
                   z-index: 70) was being capped at this element's level and losing to
                   the buddy avatar, which floats in the same corner during any active
                   quiz. Raising the whole dock above it fixes the popup, not just the
                   bar itself. */
                z-index: 90;
                padding-bottom: env(safe-area-inset-bottom);
            }
            /* At this width there's only ~366px shared across 6 equal flex:1 items
               (~61px each) — enough for "Skills"/"Quiz"/etc but not for the "🏆 Progress"
               label this trigger swaps to when that tab is active, which needs closer to
               90px. Giving it a bigger share (rather than relying on ellipsis to hide
               almost the whole word) keeps the label legible; the other five tabs give
               up a few px each, which their short labels can absorb. */
            .tab-more-wrap { flex: 1.6; }
            /* Content scrolls behind this floating dock — without a fade, the bar's
               opaque top edge slices straight through whatever line of text happens
               to be underneath it. Fading that edge lets text taper off instead of
               looking hard-clipped mid-line. */
            .tab-bar::before {
                content: '';
                position: absolute;
                left: 0; right: 0;
                bottom: 100%;
                height: 26px;
                background: linear-gradient(to top, rgba(238,241,250,0.9), rgba(238,241,250,0));
                pointer-events: none;
            }
            body { padding-bottom: 88px; }
        }

        /* -- Tactile pill CTAs: uniform shape + press feedback -- */
        .btn-submit, .btn-secondary, .btn-warning, .btn-next, #btn-next-nav, #btn-customize {
            border-radius: var(--radius-pill);
        }
        .btn-secondary {
            box-shadow: 0 3px 0 var(--line-dashed), 0 4px 10px rgba(30,42,74,0.10);
        }
        .btn-secondary:active {
            transform: translateY(2px);
            box-shadow: 0 1px 0 var(--line-dashed), 0 2px 5px rgba(30,42,74,0.08);
        }
        .btn-warning {
            background: linear-gradient(180deg, #F6C64B 0%, var(--gold) 100%);
            box-shadow: 0 4px 0 #C89112, 0 6px 12px rgba(240,180,41,0.32);
        }
        .btn-warning:hover { background: linear-gradient(180deg, #F8D06A 0%, #F2BB35 100%); color: var(--text); }
        .btn-warning:active {
            transform: translateY(2px);
            box-shadow: 0 2px 0 #C89112, 0 3px 6px rgba(240,180,41,0.2);
        }
        .btn-next, #btn-next-nav {
            background: linear-gradient(180deg, #1EA765 0%, var(--success) 100%);
            box-shadow: 0 4px 0 var(--success-dark), 0 6px 12px rgba(23,138,80,0.3);
        }
        .btn-next:active, #btn-next-nav:active {
            transform: translateY(2px);
            box-shadow: 0 2px 0 var(--success-dark), 0 3px 6px rgba(23,138,80,0.2);
        }
        #btn-customize:active { transform: translateY(2px); }


        /* -- Desktop: give the page room to breathe above laptop width -- */
        @media (min-width: 1100px) {
            header, .card, .arena-header, .tab-bar, .score-board { max-width: 780px; }
        }

        /* ── Semantic classes extracted from JS template inline styles ── */
        .btn-flush { margin: 0; }
        .feedback-detail { margin-top: 8px; font-weight: 400; }
        .feedback-strategy { margin-top: 10px; font-weight: 400; font-size: 0.95em; }
        .review-perfect { color: var(--success); font-weight: bold; margin-top: 15px; }
        .review-expected { color: var(--error); }
        .mockexam-review-q { margin-bottom: 6px; }
        .mockexam-readiness-note { margin-top: 6px; }
        .mockexam-caveat-lead { margin-bottom: 10px; }
        .paywall-step-strategy { font-style: italic; }
        .progress-caption-spaced { margin-top: 6px; }
        .nudge-copy { font-weight: 400; margin: 0 0 10px; }
        .context-compact { font-size: 0.88rem; margin-bottom: 10px; }
        .shop-more-hint-lead { margin-bottom: 10px; }
        .skill-tile-done { opacity: 0.6; cursor: default; }

        /* ── A11y / touch floor ── */
        .skip-link {
            position: absolute;
            left: 12px; top: -60px;
            z-index: 2001;
            background: var(--primary);
            color: #fff;
            font-family: var(--font-display);
            font-weight: 700;
            padding: 10px 18px;
            border-radius: var(--radius-pill);
            text-decoration: none;
            transition: top 0.15s var(--ease-standard);
        }
        .skip-link:focus-visible { top: 12px; }
        html { -webkit-tap-highlight-color: transparent; }
        button, a, input, select, .skill-tile, .tab-btn, .option-btn, .swatch-btn {
            touch-action: manipulation;
        }

        /* Drawn gold coin — replaces the 🪙 emoji, which renders as a grey
           monochrome ball on some platforms (looked like a moon in the HUD). */
        .coin-icon {
            display: inline-block;
            width: 0.85em; height: 0.85em;
            border-radius: 50%;
            background: radial-gradient(circle at 35% 30%, #FFE9A0 0%, #F5C231 55%, #D99B14 100%);
            box-shadow: inset 0 0 0 1.5px rgba(158,108,15,0.55), 0 1px 2px rgba(30,42,74,0.25);
            vertical-align: -0.08em;
        }
        .coin-icon-lg {
            width: 2.2rem; height: 2.2rem;
            box-shadow: inset 0 0 0 3px rgba(158,108,15,0.55), 0 2px 6px rgba(30,42,74,0.3);
        }
