/* =========================================================================
   TEST MODE — "EXAM CONSOLE"

   A full visual rebuild of the running-test screen (#test-view). Nothing about
   how the test *works* changes: every class name, id, onclick and JS hook the
   runtime depends on is untouched. This file only owns how it looks.

   Why a separate file rather than edits inside study-features.css: that file
   carries three overlapping generations of the mock-test skin (the same
   selectors re-declared two or three times, each fixing the last). Rather than
   untangle that in place, this layer loads last and takes over the shell — the
   old rules stay as the fallback for anything not restyled here.

   Test mode is deliberately excluded from premium-ui.css, design-system.css and
   light-theme.css (they all guard with body:not(.test-taking-mode)), so this is
   the only stylesheet with an opinion about these surfaces — including its light
   theme, which lives at the bottom of this file as a token swap on
   html.theme-light and nothing more.

   Scoping: every rule is prefixed with .mock-test-view (the running test) or
   .mobile-palette-drawer (the phone palette). .mock-btn and .q-box also appear
   on the result screen and must not be caught.
   ========================================================================= */

.mock-test-view,
.mobile-palette-drawer,
.tm-modal {
    /* Surfaces: four steps, dark to light, so elevation reads without borders
       doing all the work. */
    --tm-bg: #0b0d11;
    --tm-surface: #14171d;
    --tm-surface-2: #1a1e26;
    --tm-surface-3: #222732;

    --tm-line: rgba(255, 255, 255, 0.07);
    --tm-line-2: rgba(255, 255, 255, 0.13);

    --tm-text: #eef1f6;
    --tm-text-2: #a4adbd;
    --tm-text-3: #6b7486;

    /* One accent (teal), plus status colours that only appear when they carry
       meaning: amber = flagged, red = unanswered/urgent, green = correct. */
    --tm-accent: #2ee6c5;
    --tm-accent-dim: rgba(46, 230, 197, 0.14);
    --tm-accent-ink: #04241f;
    --tm-amber: #f7c948;
    --tm-red: #ff5c6a;
    --tm-green: #43dd8b;

    --tm-r-sm: 9px;
    --tm-r: 13px;
    --tm-r-lg: 18px;

    /* One motion curve everywhere. Two durations: 140ms for anything under the
       cursor, 300ms for anything entering the screen. */
    --tm-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
    --tm-fast: 0.14s;
    --tm-slow: 0.3s;

    --tm-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);

    /* Text-size multiplier, set on #test-view by applyTestFontScale(). Only the
       paper itself multiplies by it — the chrome stays put, because scaling the
       timer and the palette would take back the room the question just won. */
    --tm-fs: 1;
}

/* ── SHELL ──────────────────────────────────────────────────────────────── */

.mock-test-view {
    background:
        radial-gradient(1100px 620px at 15% -10%, rgba(46, 230, 197, 0.06), transparent 60%),
        radial-gradient(900px 560px at 105% 0%, rgba(176, 111, 245, 0.05), transparent 62%),
        var(--tm-bg) !important;
    color: var(--tm-text) !important;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    letter-spacing: -0.008em;
}

/* ── HEADER ─────────────────────────────────────────────────────────────── */

.mock-test-view .mock-header {
    position: relative;
    height: 60px;
    padding: 0 18px;
    background: rgba(14, 16, 21, 0.82);
    -webkit-backdrop-filter: saturate(160%) blur(18px);
    backdrop-filter: saturate(160%) blur(18px);
    border-bottom: 1px solid var(--tm-line);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.03), 0 8px 24px rgba(0, 0, 0, 0.35);
    gap: 14px;
}

.mock-test-view .mock-h-left {
    gap: 12px;
    min-width: 0;
}

/* The home glyph was a bare icon with a click handler — no target, no feedback.
   It gets the same 38px hit area as every other control in the bar. */
.mock-test-view .mock-h-left > .fa-home {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    flex-shrink: 0;
    border-radius: var(--tm-r-sm);
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    color: var(--tm-text-2) !important;
    font-size: 0.95rem !important;
    margin-right: 0 !important;
    transition: color var(--tm-fast) var(--tm-ease), background var(--tm-fast) var(--tm-ease), transform var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-h-left > .fa-home:hover {
    color: var(--tm-accent) !important;
    background: var(--tm-surface-3);
    transform: translateY(-1px);
}

.mock-test-view .mock-h-left h3 {
    font-family: 'Archivo', 'Inter', sans-serif;
    font-size: 1.02rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--tm-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 30vw;
}

/* Timer: the number a candidate looks at most, so it gets its own column,
   tabular monospace digits (no width jitter each tick) and a label that stops
   it reading as a stopwatch counting up. */
.mock-test-view .mock-timer-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    min-width: 152px;
    padding: 6px 20px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line-2);
    border-radius: var(--tm-r);
    color: var(--tm-text);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04);
    transition: border-color var(--tm-slow) var(--tm-ease), background var(--tm-slow) var(--tm-ease);
}

.mock-test-view .mock-timer-box .tm-timer-label {
    font-size: 0.56rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--tm-text-3);
    transition: color var(--tm-slow) var(--tm-ease);
}

.mock-test-view .mock-timer-box i {
    display: none;
}

.mock-test-view #test-timer {
    font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 1.24rem;
    font-weight: 700;
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.02em;
    color: var(--tm-text);
}

/* Last 5 minutes, then the last minute. The colour change is the warning; the
   pulse only starts where seconds actually matter. */
.mock-test-view .mock-timer-box.is-warning {
    border-color: color-mix(in srgb, var(--tm-amber) 50%, transparent);
    background: color-mix(in srgb, var(--tm-amber) 9%, transparent);
}

.mock-test-view .mock-timer-box.is-warning #test-timer,
.mock-test-view .mock-timer-box.is-warning .tm-timer-label {
    color: var(--tm-amber);
}

.mock-test-view .mock-timer-box.is-critical {
    border-color: rgba(255, 92, 106, 0.55);
    background: rgba(255, 92, 106, 0.11);
    animation: tmTimerPulse 1.6s var(--tm-ease) infinite;
}

.mock-test-view .mock-timer-box.is-critical #test-timer,
.mock-test-view .mock-timer-box.is-critical .tm-timer-label {
    color: var(--tm-red);
}

@keyframes tmTimerPulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(255, 92, 106, 0.32); }
    55%      { box-shadow: 0 0 0 8px rgba(255, 92, 106, 0); }
}

.mock-test-view .mock-h-right {
    gap: 10px !important;
    flex-shrink: 0;
}

/* Icon-only header controls (pause, fullscreen). */
.mock-test-view .tm-icon-btn {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    padding: 0;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-sm);
    color: var(--tm-text-2);
    font-size: 0.95rem;
    cursor: pointer;
    transition: color var(--tm-fast) var(--tm-ease), background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), transform var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-icon-btn:hover {
    color: var(--tm-text);
    background: var(--tm-surface-3);
    border-color: var(--tm-line-2);
    transform: translateY(-1px);
}

/* Text-size stepper. Same pill shape as the palette's grid/list switch, so the
   two read as the same class of control. */
.mock-test-view .tm-font-switch {
    display: flex;
    flex-shrink: 0;
    gap: 2px;
    padding: 2px;
    border-radius: var(--tm-r-sm);
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
}

.mock-test-view .tm-font-btn {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 1px;
    width: 30px;
    height: 32px;
    padding: 0;
    border: none;
    border-radius: 7px;
    background: transparent;
    color: var(--tm-text-2);
    font-family: 'Archivo', 'Inter', sans-serif;
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-font-btn i {
    font-size: 0.62rem;
    font-style: normal;
    font-weight: 800;
}

.mock-test-view .tm-font-btn:hover:not(:disabled) {
    background: var(--tm-surface-3);
    color: var(--tm-text);
}

/* Disabled at the ends of the scale rather than silently doing nothing. */
.mock-test-view .tm-font-btn:disabled {
    opacity: 0.32;
    cursor: default;
}

/* Rough-work button lights up while the pad is open, so it reads as a toggle. */
.mock-test-view #tm-rough-btn.is-on {
    background: var(--tm-accent-dim);
    border-color: rgba(46, 230, 197, 0.35);
    color: var(--tm-accent);
}

.mock-test-view #test-pause-btn.tm-icon-btn {
    color: var(--tm-amber);
    border-color: color-mix(in srgb, var(--tm-amber) 32%, transparent);
    background: color-mix(in srgb, var(--tm-amber) 10%, transparent);
}

.mock-test-view #test-pause-btn.tm-icon-btn:hover {
    background: color-mix(in srgb, var(--tm-amber) 18%, transparent);
}

/* startTest() sets display:block on this button inline, so the label is centred
   with line-height rather than a flex rule the inline style would defeat. */
.mock-test-view .mock-submit-btn {
    height: 38px;
    line-height: 36px;
    padding: 0 20px;
    background: linear-gradient(180deg, #ff6470, #e5384a);
    border: none;
    border-radius: var(--tm-r-sm);
    color: #fff;
    font-size: 0.88rem;
    font-weight: 700;
    box-shadow: 0 4px 14px rgba(229, 56, 74, 0.32);
    transition: transform var(--tm-fast) var(--tm-ease), box-shadow var(--tm-fast) var(--tm-ease), filter var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-submit-btn:hover {
    background: linear-gradient(180deg, #ff6470, #e5384a);
    filter: brightness(1.07);
    transform: translateY(-1px);
    box-shadow: 0 6px 20px rgba(229, 56, 74, 0.42);
}

.mock-test-view .mock-submit-btn:active {
    transform: translateY(0);
}

/* Progress rail: a 2px line along the bottom edge of the header showing how
   much of the paper is answered. Free information in space that was empty. */
.mock-test-view .tm-progress-rail {
    position: absolute;
    left: 0;
    bottom: -1px;
    width: 100%;
    height: 2px;
    background: rgba(255, 255, 255, 0.05);
    overflow: hidden;
}

.mock-test-view .tm-progress-fill {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, var(--tm-accent), #7bf0dc);
    box-shadow: 0 0 10px rgba(46, 230, 197, 0.55);
    border-radius: 0 2px 2px 0;
    transition: width 0.45s var(--tm-ease);
}

/* ── BODY / PANELS ──────────────────────────────────────────────────────── */

.mock-test-view .mock-body {
    padding: 14px;
    gap: 14px;
}

.mock-test-view .mock-left-panel,
.mock-test-view .mock-right-panel {
    background: var(--tm-surface);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-lg);
    box-shadow: var(--tm-shadow), inset 0 1px 0 rgba(255, 255, 255, 0.035);
}

.mock-test-view .mock-q-container {
    padding: 24px 28px 18px !important;
    font-size: 1rem;
    color: var(--tm-text);
    scrollbar-width: thin;
    scrollbar-color: var(--tm-surface-3) transparent;
}

.mock-test-view .mock-q-container::-webkit-scrollbar,
.mock-test-view .mock-rp-grid::-webkit-scrollbar {
    width: 8px;
}

.mock-test-view .mock-q-container::-webkit-scrollbar-thumb,
.mock-test-view .mock-rp-grid::-webkit-scrollbar-thumb {
    background: var(--tm-surface-3);
    border-radius: 8px;
    border: 2px solid transparent;
    background-clip: content-box;
}

.mock-test-view .mock-q-container::-webkit-scrollbar-thumb:hover,
.mock-test-view .mock-rp-grid::-webkit-scrollbar-thumb:hover {
    background: #2e3542;
    background-clip: content-box;
}

/* ── QUESTION ───────────────────────────────────────────────────────────── */

.mock-test-view .tm-qhead {
    display: flex;
    align-items: center;
    gap: 12px;
    padding-bottom: 14px;
    margin-bottom: 18px;
    border-bottom: 1px solid var(--tm-line);
}

.mock-test-view .tm-qnum {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 5px 12px;
    border-radius: 100px;
    background: var(--tm-accent-dim);
    border: 1px solid rgba(46, 230, 197, 0.24);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--tm-accent);
}

.mock-test-view .tm-qnum b {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.92rem;
    letter-spacing: 0;
}

.mock-test-view .tm-qtimer {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin-left: auto;
    padding: 5px 12px;
    border-radius: 100px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    font-size: 0.74rem;
    font-weight: 600;
    color: var(--tm-text-3);
}

.mock-test-view .tm-qtimer i {
    font-size: 0.72rem;
    color: var(--tm-amber);
}

.mock-test-view .tm-qtimer b {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-variant-numeric: tabular-nums;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--tm-text-2);
}

/* The review-mode action pill (Ask AI / star / bookmark) sits in the same row.
   Its inline margin-left:auto has to go, or it fights the timer's for the same
   free space and leaves the timer stranded mid-row. */
.mock-test-view .tm-qhead .test-review-action-wrapper {
    margin-left: 0 !important;
    background: var(--tm-surface-2) !important;
    border-color: var(--tm-line) !important;
}

/* Exam source chip. Review mode only — renderTestQ() lifts the trailing
   "[SSC MTS 08/09/2023 (Shift-01)]" out of the question text in every mode, but
   only puts it back here, on its own row above the question, where it reads as
   provenance instead of as part of the sentence. */
.mock-test-view .tm-meta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}

.mock-test-view .tm-exam-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    max-width: 100%;
    padding: 4px 11px;
    border-radius: 100px;
    background: color-mix(in srgb, var(--tm-amber) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--tm-amber) 32%, transparent);
    color: var(--tm-amber);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mock-test-view .tm-exam-chip i {
    font-size: 0.68rem;
    opacity: 0.8;
}

.mock-test-view .tm-qtext {
    font-size: calc(1.1rem * var(--tm-fs));
    font-weight: 500;
    line-height: 1.65;
    color: var(--tm-text);
    margin-bottom: 20px;
}

/* Question and options fade up only when a NEW question arrives. renderTestQ()
   puts .tm-q-enter on the container for that render and drops it when it is
   redrawing the same question (re-attempt pick, View Solution, Clear, language
   toggle) — those taps used to replay the whole entrance every time. */
.mock-test-view .tm-q-enter .tm-qhead,
.mock-test-view .tm-q-enter .tm-qtext,
.mock-test-view .tm-q-enter .mock-options-container .mock-option-label {
    animation: tmRise var(--tm-slow) var(--tm-ease) both;
}

.mock-test-view .tm-qtext { animation-delay: 0.03s; }
.mock-test-view .mock-options-container .mock-option-label:nth-child(1) { animation-delay: 0.06s; }
.mock-test-view .mock-options-container .mock-option-label:nth-child(2) { animation-delay: 0.1s; }
.mock-test-view .mock-options-container .mock-option-label:nth-child(3) { animation-delay: 0.14s; }
.mock-test-view .mock-options-container .mock-option-label:nth-child(4) { animation-delay: 0.18s; }
.mock-test-view .mock-options-container .mock-option-label:nth-child(n+5) { animation-delay: 0.22s; }

@keyframes tmRise {
    from { opacity: 0; transform: translateY(9px); }
    to   { opacity: 1; transform: none; }
}

/* ── OPTIONS ────────────────────────────────────────────────────────────── */

.mock-test-view .mock-options-container {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.mock-test-view .mock-option-label {
    position: relative;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 18px;
    margin-bottom: 0;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r);
    color: var(--tm-text-2);
    font-size: calc(0.98rem * var(--tm-fs));
    line-height: 1.55;
    overflow: hidden;
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease), transform var(--tm-fast) var(--tm-ease), box-shadow var(--tm-fast) var(--tm-ease);
}

/* A rail that grows from the left edge on hover — cheaper to read than moving
   the whole row, and it stays as the accent marker in the selected state. */
.mock-test-view .mock-option-label::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--tm-accent);
    transform: scaleY(0);
    transform-origin: center;
    transition: transform var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-option-label:hover {
    background: var(--tm-surface-3);
    border-color: var(--tm-line-2);
    color: var(--tm-text);
    transform: translateX(2px);
}

.mock-test-view .mock-option-label:hover::before {
    transform: scaleY(0.55);
}

.mock-test-view .mock-option-label:active {
    transform: translateX(2px) scale(0.995);
}

.mock-test-view .mock-option-label.selected {
    background: linear-gradient(90deg, rgba(46, 230, 197, 0.13), rgba(46, 230, 197, 0.05));
    border-color: rgba(46, 230, 197, 0.45);
    color: var(--tm-text);
    box-shadow: 0 0 0 1px rgba(46, 230, 197, 0.13), 0 6px 18px rgba(0, 0, 0, 0.28);
}

.mock-test-view .mock-option-label.selected::before {
    transform: scaleY(1);
}

.mock-test-view .opt-circle {
    width: 30px;
    height: 30px;
    margin-right: 0;
    flex-shrink: 0;
    border-radius: 10px;
    border: 1px solid var(--tm-line-2);
    background: var(--tm-surface-3);
    color: var(--tm-text-3);
    font-family: 'Archivo', 'Inter', sans-serif;
    font-size: calc(0.82rem * var(--tm-fs));
    font-weight: 700;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-option-label:hover .opt-circle {
    color: var(--tm-text-2);
    border-color: rgba(255, 255, 255, 0.2);
}

.mock-test-view .mock-option-label.selected .opt-circle {
    background: var(--tm-accent);
    border-color: var(--tm-accent);
    color: var(--tm-accent-ink);
    box-shadow: 0 0 14px rgba(46, 230, 197, 0.34);
    animation: tmPop 0.26s var(--tm-ease);
}

@keyframes tmPop {
    0%   { transform: scale(0.82); }
    60%  { transform: scale(1.09); }
    100% { transform: scale(1); }
}

.mock-test-view .opt-text {
    padding-top: 3px;
}

/* Review states. The base rules in study-features.css use !important, so these
   have to as well. */
.mock-test-view .mock-option-label.opt-correct {
    background: linear-gradient(90deg, rgba(67, 221, 139, 0.14), rgba(67, 221, 139, 0.04)) !important;
    border-color: rgba(67, 221, 139, 0.45) !important;
    color: var(--tm-text) !important;
}

.mock-test-view .mock-option-label.opt-correct::before {
    background: var(--tm-green);
    transform: scaleY(1);
}

.mock-test-view .mock-option-label.opt-correct .opt-circle {
    background: var(--tm-green) !important;
    border-color: var(--tm-green) !important;
    color: #04241a !important;
}

.mock-test-view .mock-option-label.opt-wrong {
    background: linear-gradient(90deg, rgba(255, 92, 106, 0.14), rgba(255, 92, 106, 0.04)) !important;
    border-color: rgba(255, 92, 106, 0.45) !important;
    color: var(--tm-text) !important;
}

.mock-test-view .mock-option-label.opt-wrong::before {
    background: var(--tm-red);
    transform: scaleY(1);
}

.mock-test-view .mock-option-label.opt-wrong .opt-circle {
    background: var(--tm-red) !important;
    border-color: var(--tm-red) !important;
    color: #fff !important;
}

/* ── SOLUTION ───────────────────────────────────────────────────────────── */

/* togglePreviewSolution() scrolls this into view on the frame after it renders;
   the slide gives the scroll something to arrive at instead of the block just
   existing. */
.mock-test-view .tm-solution {
    animation: tmSlideDown 0.34s var(--tm-ease) both;
}

/* Already on screen before this redraw (e.g. a second re-attempt pick) — it
   just stays put. renderTestQ() sets .tm-sol-kept. */
.mock-test-view .tm-sol-kept .tm-solution {
    animation: none;
}

@keyframes tmSlideDown {
    from { opacity: 0; transform: translateY(-10px); }
    to   { opacity: 1; transform: none; }
}

.mock-test-view .question-figure {
    margin: 4px 0 18px;
    padding: 14px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r);
}

/* The drawer's copy of the display controls. It only exists for phones; the
   drawer itself is display:none above 768px, but being explicit costs nothing
   and stops it flashing during a resize. */
.mob-display-row {
    display: none;
}

/* ── ROUGH WORK — PEN PAD ───────────────────────────────────────────────── */

/* Tablet only. .tm-can-draw is set on #test-view by syncRoughAvailability()
   from one matchMedia, so the button, the pad and the W shortcut all appear and
   disappear together — no second breakpoint here to fall out of sync with it. */
.mock-test-view:not(.tm-can-draw) #tm-rough-btn,
.mock-test-view:not(.tm-can-draw) .tm-rough {
    display: none !important;
}

/* position:fixed, not absolute: it is dragged anywhere on the screen, including
   over the palette, so it must not be trapped by any panel's bounds. */
.mock-test-view .tm-rough {
    position: fixed;
    z-index: 40;
    display: flex;
    flex-direction: column;
    background: var(--tm-surface);
    border: 1px solid var(--tm-line-2);
    border-radius: var(--tm-r);
    box-shadow: 0 22px 60px rgba(0, 0, 0, 0.55);
    overflow: hidden;
    animation: tmRise 0.22s var(--tm-ease) both;
    /* The pad is a drawing surface; a browser pan/zoom gesture starting on it
       is never what was meant. */
    touch-action: none;
    -webkit-user-select: none;
    user-select: none;
}

/* No transition while dragging — the pad has to sit under the stylus, not lag
   a frame behind it. */
.mock-test-view .tm-rough.is-dragging {
    animation: none;
    box-shadow: 0 26px 70px rgba(0, 0, 0, 0.6);
}

.mock-test-view .tm-rough-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-shrink: 0;
    padding: 7px 7px 7px 11px;
    background: var(--tm-surface-3);
    border-bottom: 1px solid var(--tm-line);
    cursor: grab;
    touch-action: none;
}

.mock-test-view .tm-rough.is-dragging .tm-rough-head {
    cursor: grabbing;
}

.mock-test-view .tm-rough-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.65rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--tm-text-3);
    white-space: nowrap;
}

.mock-test-view .tm-rough-title i {
    font-size: 0.72rem;
    opacity: 0.55;
}

.mock-test-view .tm-rough-tools {
    display: flex;
    gap: 3px;
}

/* 34px targets: this is a touch device by definition, and these sit next to a
   drag handle where a mis-hit moves the window instead. */
.mock-test-view .tm-rough-tool {
    display: grid;
    place-items: center;
    width: 34px;
    height: 30px;
    padding: 0;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--tm-text-3);
    font-size: 0.82rem;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-rough-tool:hover {
    background: var(--tm-surface-2);
    color: var(--tm-text);
}

.mock-test-view .tm-rough-tool.is-on {
    background: var(--tm-accent-dim);
    color: var(--tm-accent);
}

/* --tm-ink is read back by drawRoughStroke(), so the pen colour is defined once
   here and follows the theme with everything else. */
.mock-test-view #tm-rough-canvas {
    --tm-ink: #e8ecf4;
    flex: 1;
    min-height: 0;
    width: 100%;
    display: block;
    background: var(--tm-surface-2);
    cursor: crosshair;
    touch-action: none;
}

.mock-test-view #tm-rough-canvas.is-erasing {
    cursor: cell;
}

/* Resize corner. Drawn rather than native: CSS resize gives a 6px hit area, and
   the whole point of this pad is that it is used with a stylus. */
.mock-test-view .tm-rough-grip {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 26px;
    height: 26px;
    cursor: nwse-resize;
    touch-action: none;
    background:
        linear-gradient(135deg, transparent 52%, var(--tm-text-3) 52%, var(--tm-text-3) 60%, transparent 60%,
            transparent 70%, var(--tm-text-3) 70%, var(--tm-text-3) 78%, transparent 78%);
    opacity: 0.55;
}

.mock-test-view .tm-rough-grip:hover {
    opacity: 0.9;
}

/* ── ACTION BAR ─────────────────────────────────────────────────────────── */

.mock-test-view .mock-action-row {
    gap: 10px;
    padding: 14px 20px;
    border-top: 1px solid var(--tm-line);
    background: rgba(255, 255, 255, 0.012) !important;
}

.mock-test-view .mock-btn {
    height: 42px;
    padding: 0 20px;
    border-radius: var(--tm-r-sm);
    font-size: 0.9rem;
    font-weight: 600;
    transition: transform var(--tm-fast) var(--tm-ease), background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease), box-shadow var(--tm-fast) var(--tm-ease), filter var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-btn:active {
    transform: translateY(1px);
}

/* One filled button per row. Save & Next is taken on almost every question;
   Mark for Review and Clear are occasional, so they step back to a tinted and
   a plain ghost instead of three competing solid blocks. */
.mock-test-view .mock-btn.m-save {
    background: linear-gradient(180deg, #3df0d0, #16c4a6);
    color: var(--tm-accent-ink);
    font-weight: 700;
    box-shadow: 0 4px 16px rgba(22, 196, 166, 0.3);
}

.mock-test-view .mock-btn.m-save:hover {
    background: linear-gradient(180deg, #3df0d0, #16c4a6);
    filter: brightness(1.06);
    transform: translateY(-1px);
    box-shadow: 0 6px 22px rgba(22, 196, 166, 0.4);
}

.mock-test-view .mock-btn.m-review {
    background: color-mix(in srgb, var(--tm-amber) 11%, transparent);
    border: 1px solid color-mix(in srgb, var(--tm-amber) 34%, transparent);
    color: var(--tm-amber);
}

.mock-test-view .mock-btn.m-review:hover {
    background: color-mix(in srgb, var(--tm-amber) 20%, transparent);
    border-color: color-mix(in srgb, var(--tm-amber) 55%, transparent);
    transform: translateY(-1px);
}

.mock-test-view .mock-btn.m-clear {
    background: transparent;
    border: 1px solid var(--tm-line-2);
    color: var(--tm-text-3);
}

.mock-test-view .mock-btn.m-clear:hover {
    background: var(--tm-surface-2);
    color: var(--tm-text);
    transform: translateY(-1px);
}

/* ── PREV / NEXT ────────────────────────────────────────────────────────── */

.mock-test-view .mock-nav-row {
    padding: 4px 20px 16px;
}

.mock-test-view .mock-nav-btn {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    height: 40px;
    padding: 0 20px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-sm);
    color: var(--tm-text-2);
    font-size: 0.88rem;
    font-weight: 600;
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease), transform var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-nav-btn:hover {
    background: var(--tm-surface-3);
    border-color: var(--tm-line-2);
    color: var(--tm-text);
}

.mock-test-view #prev-btn:hover { transform: translateX(-2px); }
.mock-test-view #next-btn:hover { transform: translateX(2px); }

.mock-test-view .mock-nav-btn i {
    font-size: 0.72rem;
    opacity: 0.75;
}

/* ── QUESTION PALETTE ───────────────────────────────────────────────────── */

.mock-test-view .mock-right-panel {
    width: 306px;
    flex-shrink: 0;
}

.mock-test-view .mock-rp-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 13px 14px;
    background: transparent;
    border-bottom: 1px solid var(--tm-line);
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-align: left;
    color: var(--tm-text-3);
}

.mock-test-view .tm-rp-title,
.mobile-palette-drawer .tm-rp-title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── GRID / LIST SWITCH ─────────────────────────────────────────────────── */

.mock-test-view .tm-view-switch,
.mobile-palette-drawer .tm-view-switch {
    display: flex;
    flex-shrink: 0;
    gap: 2px;
    padding: 2px;
    margin-left: auto;
    border-radius: 9px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
}

.mock-test-view .tm-view-btn,
.mobile-palette-drawer .tm-view-btn {
    display: grid;
    place-items: center;
    width: 26px;
    height: 22px;
    padding: 0;
    border: none;
    border-radius: 7px;
    background: transparent;
    color: var(--tm-text-3);
    font-size: 0.72rem;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-view-btn:hover,
.mobile-palette-drawer .tm-view-btn:hover {
    color: var(--tm-text-2);
}

.mock-test-view .tm-view-btn.active,
.mobile-palette-drawer .tm-view-btn.active {
    background: var(--tm-accent);
    color: var(--tm-accent-ink);
}

/* ── PALETTE LIST VIEW ──────────────────────────────────────────────────── */

/* Both containers are always in the DOM and always populated by
   renderMockGrid(); the switch only decides which one is displayed, so status
   updates and filters never have to know which view is on screen. */
.mock-rp-list {
    display: none;
    flex-direction: column;
    gap: 5px;
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: 10px;
    scrollbar-width: thin;
    scrollbar-color: var(--tm-surface-3) transparent;
}

.mock-right-panel.list-mode .mock-rp-grid {
    display: none;
}

.mock-right-panel.list-mode .mock-rp-list {
    display: flex;
}

.mock-test-view .mock-rp-list::-webkit-scrollbar {
    width: 8px;
}

.mock-test-view .mock-rp-list::-webkit-scrollbar-thumb {
    background: var(--tm-surface-3);
    border-radius: 8px;
    border: 2px solid transparent;
    background-clip: content-box;
}

.mock-rp-list .tm-list-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 7px 9px;
    border-radius: 10px;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease);
}

.mock-rp-list .tm-list-row:hover {
    background: var(--tm-surface-2);
}

.mock-rp-list .tm-list-row.is-active {
    background: var(--tm-accent-dim);
    border-color: rgba(46, 230, 197, 0.35);
}

/* The number tile keeps its grid-view status colour, just at a fixed size — the
   status must read the same in both views or the switch becomes a translation. */
.mock-rp-list .tm-list-row .q-box {
    width: 28px;
    height: 28px;
    aspect-ratio: auto;
    flex-shrink: 0;
    border-radius: 8px;
    font-size: 0.74rem;
}

.mock-rp-list .tm-list-row:hover .q-box {
    transform: none;
    box-shadow: none;
}

.mock-rp-list .tm-list-text {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 0.76rem;
    line-height: 1.42;
    color: var(--tm-text-2);
    word-break: break-word;
}

.mock-rp-list .tm-list-row.is-active .tm-list-text {
    color: var(--tm-text);
}

/* Answered / total, so the count is readable without adding up five legend
   chips. Fed by updateGridUI(). */
.mock-test-view .tm-answered-chip {
    padding: 3px 10px;
    border-radius: 100px;
    background: var(--tm-accent-dim);
    border: 1px solid rgba(46, 230, 197, 0.22);
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0;
    color: var(--tm-accent);
}

.mock-test-view .mock-legend-grid {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    gap: 4px !important;
    padding: 12px !important;
    border-bottom: 1px solid var(--tm-line) !important;
    background: transparent !important;
    font-size: 0.72rem !important;
    color: var(--tm-text-2) !important;
}

.mock-test-view .mock-legend-grid .l-item {
    gap: 9px;
    padding: 6px 7px !important;
    border-radius: var(--tm-r-sm);
    line-height: 1.25;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-legend-grid .l-item:hover {
    background: var(--tm-surface-2);
    color: var(--tm-text);
}

.mock-test-view .mock-legend-grid .q-box {
    width: 26px;
    height: 26px;
    flex-shrink: 0;
    border-radius: 8px;
    font-size: 0.74rem;
}

.mock-test-view .mock-rp-grid {
    grid-template-columns: repeat(5, 1fr);
    gap: 9px;
    padding: 16px 14px;
    scrollbar-width: thin;
    scrollbar-color: var(--tm-surface-3) transparent;
}

.mock-test-view .q-box,
.mobile-palette-drawer .q-box {
    width: auto;
    height: auto;
    aspect-ratio: 1 / 1;
    display: grid;
    place-items: center;
    border-radius: 10px;
    border: 1px solid var(--tm-line);
    background: var(--tm-surface-2);
    color: var(--tm-text-3);
    font-family: 'Archivo', 'Inter', sans-serif;
    font-size: 0.82rem;
    font-weight: 700;
    transition: transform var(--tm-fast) var(--tm-ease), box-shadow var(--tm-fast) var(--tm-ease), background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .mock-rp-grid .q-box:hover,
.mobile-palette-drawer .mob-q-grid .q-box:hover {
    transform: translateY(-2px) scale(1.06);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
    z-index: 1;
}

/* Status colours. Flat fills with a matching hairline — the old palette mixed
   saturated fills with darker borders of a different hue, which read as noise
   at tile size. */
.mock-test-view .q-box.not-visited,
.mobile-palette-drawer .q-box.not-visited {
    background: var(--tm-surface-2);
    border-color: var(--tm-line);
    color: var(--tm-text-3);
}

.mock-test-view .q-box.not-answered,
.mobile-palette-drawer .q-box.not-answered {
    background: rgba(255, 92, 106, 0.16);
    border-color: rgba(255, 92, 106, 0.42);
    color: #ff8b95;
}

.mock-test-view .q-box.answered,
.mobile-palette-drawer .q-box.answered {
    background: linear-gradient(180deg, #3df0d0, #16c4a6);
    border-color: transparent;
    color: var(--tm-accent-ink);
    box-shadow: 0 2px 10px rgba(22, 196, 166, 0.28);
}

.mock-test-view .q-box.review,
.mobile-palette-drawer .q-box.review {
    background: linear-gradient(180deg, #ffd75e, #eeb320);
    border-color: transparent;
    color: #2b1f00;
    box-shadow: 0 2px 10px rgba(238, 179, 32, 0.26);
}

.mock-test-view .q-box.answered-review,
.mobile-palette-drawer .q-box.answered-review {
    background: linear-gradient(180deg, #c084fb, #9b4fe8);
    border-color: transparent;
    color: #fff;
    box-shadow: 0 2px 10px rgba(155, 79, 232, 0.3);
}

.mock-test-view .q-box.correct,
.mobile-palette-drawer .q-box.correct {
    background: linear-gradient(180deg, #56e79b, #2cba71);
    border-color: transparent;
    color: #04241a;
}

.mock-test-view .q-box.wrong,
.mobile-palette-drawer .q-box.wrong {
    background: linear-gradient(180deg, #ff7480, #e5384a);
    border-color: transparent;
    color: #fff;
}

/* Current question: a ring outside the tile rather than a 2px border, which
   shifted every neighbour by a pixel each time it moved. */
.mock-test-view .mock-rp-grid .q-box.active-q,
.mobile-palette-drawer .mob-q-grid .q-box.active-q {
    /* The old rule painted a white 2px border here; it is not in any of the
       properties below, so it has to be turned off explicitly or it shows
       through underneath the ring. */
    border-width: 1px;
    border-color: transparent;
    box-shadow: 0 0 0 2px var(--tm-surface), 0 0 0 4px var(--tm-accent), 0 4px 14px rgba(46, 230, 197, 0.3);
    transform: scale(1.04);
}

.mock-test-view .mock-rp-grid .q-box.active-q.not-visited,
.mobile-palette-drawer .mob-q-grid .q-box.active-q.not-visited {
    color: var(--tm-text);
}

/* Legend chips are counters, not tiles — the hover lift and the active ring
   would be lying about what they do. */
.mock-test-view .mock-legend-grid .q-box:hover {
    transform: none;
    box-shadow: none;
}

/* ── REVIEW-MODE EXTRAS ─────────────────────────────────────────────────── */

.mock-test-view #post-test-filters {
    padding: 12px 14px !important;
    gap: 7px !important;
    background: transparent !important;
    border-bottom: 1px solid var(--tm-line) !important;
}

.mock-test-view .rf-btn {
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-sm);
    color: var(--tm-text-3);
    font-size: 0.75rem !important;
    font-weight: 600;
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .rf-btn:hover {
    background: var(--tm-surface-3);
    color: var(--tm-text-2);
}

.mock-test-view #dynamic-reattempt-box {
    padding: 12px 14px !important;
    border-top: 1px solid var(--tm-line) !important;
    background: transparent !important;
}

.mock-test-view .compact-scoreboard-btn {
    height: 42px;
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-sm);
    color: var(--tm-text-2);
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .compact-scoreboard-btn:hover {
    background: var(--tm-surface-3);
    border-color: rgba(46, 230, 197, 0.35);
    color: var(--tm-accent);
    box-shadow: none;
}

/* ── SECTIONS ───────────────────────────────────────────────────────────────
   Only a sectional paper — a full-length mock — ever reveals this strip;
   testSections.js sets display on #tm-section-bar and a chapter test never
   calls it, so nothing below touches the console a daily student sees.

   The strip sits between the header and the workspace: a part is a bigger unit
   than a question, so it reads above the paper rather than beside it. Three
   states, and the difference between them has to survive a glance — the open
   part is the only one wearing the accent, the parts still to come are quiet
   outlines, and a closed part is dimmed and carries a lock. */

.mock-test-view .tm-section-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 18px;
    background: rgba(16, 19, 25, 0.72);
    border-bottom: 1px solid var(--tm-line);
    flex-shrink: 0;
}

.mock-test-view .tm-sec-tabs {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
}

.mock-test-view .tm-sec-tabs::-webkit-scrollbar {
    display: none;
}

.mock-test-view .tm-sec-tab {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding: 8px 15px;
    border-radius: var(--tm-r-sm);
    border: 1px solid var(--tm-line-2);
    background: var(--tm-surface-2);
    color: var(--tm-text-2);
    font-family: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    letter-spacing: -0.005em;
    cursor: pointer;
    transition: color var(--tm-fast) var(--tm-ease),
        background var(--tm-fast) var(--tm-ease),
        border-color var(--tm-fast) var(--tm-ease),
        transform var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-sec-tab:hover:not(:disabled) {
    color: var(--tm-text);
    border-color: rgba(46, 230, 197, 0.4);
    transform: translateY(-1px);
}

.mock-test-view .tm-sec-tab.is-active {
    background: var(--tm-accent);
    border-color: var(--tm-accent);
    color: var(--tm-accent-ink);
    box-shadow: 0 6px 18px rgba(46, 230, 197, 0.22);
}

.mock-test-view .tm-sec-tab.is-closed {
    background: transparent;
    border-color: var(--tm-line);
    color: var(--tm-text-3);
}

/* A part that has not started is reachable in a free-navigation paper and shut
   in a locked one. Both look the same until you try, so the disabled state has
   to say so without a click. */
.mock-test-view .tm-sec-tab:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.mock-test-view .tm-sec-count {
    font-size: 0.7rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    padding: 2px 7px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
    color: inherit;
}

.mock-test-view .tm-sec-tab.is-active .tm-sec-count {
    background: rgba(4, 36, 31, 0.22);
}

.mock-test-view .tm-sec-lock {
    font-size: 0.66rem;
    opacity: 0.7;
}

/* Banking a part is irreversible, so it is styled as a deliberate action —
   amber, the console's "you flagged this" colour — and never as the accent,
   which is reserved for where you are. */
.mock-test-view .tm-sec-submit {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    padding: 8px 16px;
    border-radius: var(--tm-r-sm);
    border: 1px solid rgba(247, 201, 72, 0.45);
    background: rgba(247, 201, 72, 0.12);
    color: var(--tm-amber);
    font-family: inherit;
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease);
}

.mock-test-view .tm-sec-submit:hover {
    background: rgba(247, 201, 72, 0.2);
    color: #ffd970;
}

/* The palette shows one part at a time, so the numbers restart at 1 — this band
   is what says at 1 of what. */
.mock-test-view .tm-palette-sec {
    padding: 10px 14px 0;
    font-size: 0.68rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--tm-accent);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Section scoping for the palette.
   !important because filterByLegend() and applyFiltersToGrid() write the inline
   display of every tile: the two rules compose, and a tile shows only when the
   filter allows it AND it belongs to the open part. */
.mock-test-view .q-box.sec-hidden,
.mock-test-view .tm-list-row.sec-hidden,
.mobile-palette-drawer .q-box.sec-hidden,
.mobile-palette-drawer .tm-list-row.sec-hidden {
    display: none !important;
}

/* ── MOBILE ─────────────────────────────────────────────────────────────── */

@media (max-width: 768px) {
    /* The strip is the one piece of chrome that may not shrink to fit: four
       parts do not fold onto a phone, so it scrolls sideways and the submit
       control drops out of the row rather than squeezing the tabs. */
    .mock-test-view .tm-section-bar {
        padding: 8px 10px;
        gap: 8px;
    }

    .mock-test-view .tm-sec-tab {
        padding: 7px 12px;
        font-size: 0.76rem;
    }

    .mock-test-view .tm-sec-submit {
        padding: 7px 10px;
        font-size: 0.7rem;
    }

    .mock-test-view .mock-header {
        height: 56px;
        padding: 0 10px;
        gap: 8px;
    }

    .mock-test-view .mock-h-left > .fa-home {
        width: 34px;
        height: 34px;
    }

    .mock-test-view .mock-timer-box {
        min-width: 0;
        padding: 5px 12px;
    }

    .mock-test-view .mock-timer-box .tm-timer-label {
        display: none;
    }

    .mock-test-view #test-timer {
        font-size: 1.06rem;
    }

    .mock-test-view .mock-h-right {
        gap: 6px !important;
    }

    .mock-test-view .tm-icon-btn {
        width: 34px;
        height: 34px;
        font-size: 0.88rem;
    }

    /* Header budget at 375px: home 34 + timer ~85 + lang 72 + rough 34 +
       pause 34 + palette 34, plus gaps and padding, is already the whole row.
       The two set-once preferences move to the drawer and fullscreen goes —
       the test enters fullscreen by itself on start, and on a phone that button
       is the least-used thing in the bar. */
    .mock-test-view .mock-header .tm-font-switch,
    .mock-test-view .mock-header .tm-theme-btn,
    .mock-test-view .tm-fullscreen-btn {
        display: none !important;
    }

    .mobile-palette-drawer .mob-display-row {
        display: flex;
        align-items: center;
        gap: 10px;
        flex-shrink: 0;
        padding: 10px 12px;
        border-top: 1px solid var(--tm-line);
        font-size: 0.64rem;
        font-weight: 700;
        letter-spacing: 0.09em;
        text-transform: uppercase;
        color: var(--tm-text-3);
    }

    .mobile-palette-drawer .mob-display-row > span {
        margin-right: auto;
    }

    .mobile-palette-drawer .tm-font-switch {
        display: flex;
        gap: 2px;
        padding: 2px;
        border-radius: var(--tm-r-sm);
        background: var(--tm-surface-2);
        border: 1px solid var(--tm-line);
    }

    .mobile-palette-drawer .tm-font-btn {
        display: flex;
        align-items: baseline;
        justify-content: center;
        gap: 1px;
        width: 28px;
        height: 28px;
        padding: 0;
        border: none;
        border-radius: 7px;
        background: transparent;
        color: var(--tm-text-2);
        font-family: 'Archivo', 'Inter', sans-serif;
        font-size: 0.82rem;
        font-weight: 700;
        cursor: pointer;
    }

    .mobile-palette-drawer .tm-font-btn i {
        font-size: 0.58rem;
        font-style: normal;
        font-weight: 800;
    }

    .mobile-palette-drawer .tm-font-btn:disabled {
        opacity: 0.32;
    }

    .mobile-palette-drawer .tm-icon-btn {
        display: grid;
        place-items: center;
        width: 32px;
        height: 32px;
        padding: 0;
        border-radius: var(--tm-r-sm);
        background: var(--tm-surface-2);
        border: 1px solid var(--tm-line);
        color: var(--tm-text-2);
        font-size: 0.86rem;
        cursor: pointer;
    }

    /* The responsive layer styles .mobile-grid-btn directly with !important. */
    .mock-test-view .mobile-grid-btn {
        width: 34px !important;
        height: 34px !important;
        padding: 0 !important;
        background: var(--tm-surface-2) !important;
        border: 1px solid var(--tm-line) !important;
        border-radius: var(--tm-r-sm) !important;
        color: var(--tm-accent) !important;
        font-size: 0.95rem !important;
        margin-left: 0 !important;
    }

    .mock-test-view .mock-body {
        padding: 10px;
    }

    .mock-test-view .mock-left-panel {
        border-radius: var(--tm-r) !important;
    }

    .mock-test-view .mock-q-container {
        padding: 16px 16px 12px !important;
    }

    .mock-test-view .tm-qtext {
        font-size: calc(1.02rem * var(--tm-fs));
        line-height: 1.6;
    }

    .mock-test-view .mock-option-label {
        padding: 12px 14px;
        font-size: calc(0.94rem * var(--tm-fs));
    }

    .mock-test-view .mock-action-row {
        padding: 10px 12px;
        gap: 8px;
    }

    .mock-test-view .mock-btn {
        flex: 1;
        height: 40px;
        padding: 0 8px;
        font-size: 0.82rem;
    }

    .mock-test-view .mock-nav-row {
        padding: 2px 12px 12px;
    }

    .mock-test-view .mock-nav-btn {
        height: 38px;
        padding: 0 16px;
        font-size: 0.84rem;
    }

    /* Palette drawer */
    .mobile-palette-drawer {
        background: var(--tm-surface) !important;
        border-left: 1px solid var(--tm-line) !important;
        box-shadow: -18px 0 48px rgba(0, 0, 0, 0.55) !important;
    }

    /* Title, view switch and close all share a ~300px row here, so the tracking
       comes down until "QUESTION PALETTE" fits without ellipsing. */
    .mobile-palette-drawer .mob-drawer-header {
        background: transparent !important;
        border-bottom: 1px solid var(--tm-line) !important;
        padding: 14px 12px !important;
        font-size: 0.64rem !important;
        font-weight: 700 !important;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: var(--tm-text-3) !important;
    }

    .mobile-palette-drawer .mob-drawer-close {
        display: grid;
        place-items: center;
        width: 30px;
        height: 30px;
        border-radius: 8px;
        background: var(--tm-surface-2);
        color: var(--tm-text-2) !important;
        font-size: 0.9rem !important;
    }

    .mobile-palette-drawer .mob-legend {
        background: transparent !important;
        border-bottom: 1px solid var(--tm-line) !important;
        padding: 10px !important;
        gap: 3px !important;
        font-size: 0.68rem !important;
        color: var(--tm-text-3) !important;
    }

    .mobile-palette-drawer .mob-legend .l-item {
        padding: 5px 6px;
        border-radius: 8px;
    }

    .mobile-palette-drawer .mob-legend .l-item .q-box {
        width: 22px !important;
        height: 22px !important;
        aspect-ratio: auto;
        border-radius: 7px !important;
    }

    .mobile-palette-drawer .mob-q-grid {
        gap: 8px !important;
    }

    /* .mob-grid-scroll already owns the scrolling and the padding in the
       drawer, so the list inside it must not add a second scroller. */
    .mobile-palette-drawer .mock-rp-list {
        padding: 0;
        overflow: visible;
    }

    .mobile-palette-drawer.list-mode .mob-q-grid {
        display: none;
    }

    .mobile-palette-drawer.list-mode .mock-rp-list {
        display: flex;
    }

    .mobile-palette-drawer .mob-drawer-header {
        gap: 8px;
    }

    .mobile-palette-drawer .mob-submit-box {
        background: transparent !important;
        border-top: 1px solid var(--tm-line) !important;
    }

    .mobile-palette-drawer .mob-submit-box button {
        height: 46px;
        border-radius: var(--tm-r-sm) !important;
        background: linear-gradient(180deg, #ff6470, #e5384a) !important;
        color: #fff !important;
        box-shadow: 0 4px 16px rgba(229, 56, 74, 0.32);
    }

    .mobile-palette-overlay {
        background: rgba(0, 0, 0, 0.62) !important;
        -webkit-backdrop-filter: blur(3px);
        backdrop-filter: blur(3px);
    }
}

/* ── SUBMIT DIALOG ──────────────────────────────────────────────────────── */

/* Lives outside #test-view at body level, so it carries .tm-modal to pick the
   token block up. Same surfaces as the exam shell — it is the last thing the
   student sees before the paper closes and it should not look like it came from
   a different app. */
.tm-modal {
    align-items: center;
    justify-content: center;
    background: rgba(6, 8, 12, 0.66);
    -webkit-backdrop-filter: blur(6px);
    backdrop-filter: blur(6px);
}

.tm-modal .tm-modal-card {
    width: min(460px, 92vw);
    padding: 26px 26px 22px;
    background: var(--tm-surface);
    border: 1px solid var(--tm-line);
    border-radius: var(--tm-r-lg);
    box-shadow: var(--tm-shadow);
    color: var(--tm-text);
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    animation: tmRise 0.26s var(--tm-ease) both;
}

.tm-modal .tm-modal-head {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-bottom: 20px;
}

.tm-modal .tm-modal-head > i {
    display: grid;
    place-items: center;
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    border-radius: var(--tm-r);
    background: color-mix(in srgb, var(--tm-amber) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--tm-amber) 32%, transparent);
    color: var(--tm-amber);
    font-size: 1.05rem;
}

.tm-modal .tm-modal-head h2 {
    margin: 0 0 3px;
    font-family: 'Archivo', 'Inter', sans-serif;
    font-size: 1.16rem;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--tm-text);
}

.tm-modal .tm-modal-head p {
    margin: 0;
    font-size: 0.85rem;
    line-height: 1.45;
    color: var(--tm-text-3);
}

.tm-modal .tm-submit-stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin-bottom: 14px;
}

.tm-modal .tm-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    padding: 12px 4px 10px;
    border-radius: var(--tm-r);
    background: var(--tm-surface-2);
    border: 1px solid var(--tm-line);
}

.tm-modal .tm-stat b {
    font-family: 'JetBrains Mono', ui-monospace, monospace;
    font-size: 1.02rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--tm-text);
}

.tm-modal .tm-stat span {
    font-size: 0.62rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--tm-text-3);
    text-align: center;
}

/* Only the two numbers that should change a decision get a colour. Answered and
   time left are context, not alarms. */
.tm-modal .tm-stat.is-answered b { color: var(--tm-accent); }
.tm-modal .tm-stat.is-unanswered b { color: var(--tm-red); }
.tm-modal .tm-stat.is-marked b { color: var(--tm-amber); }

.tm-modal .tm-submit-warn {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 10px 13px;
    margin-bottom: 20px;
    border-radius: var(--tm-r);
    background: color-mix(in srgb, var(--tm-red) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--tm-red) 30%, transparent);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--tm-red);
}

.tm-modal .tm-submit-warn i {
    flex-shrink: 0;
}

.tm-modal .tm-modal-actions {
    display: flex;
    gap: 10px;
}

.tm-modal .tm-modal-btn {
    flex: 1;
    height: 44px;
    border-radius: var(--tm-r-sm);
    border: 1px solid transparent;
    font-family: inherit;
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
    transition: background var(--tm-fast) var(--tm-ease), border-color var(--tm-fast) var(--tm-ease), color var(--tm-fast) var(--tm-ease), transform var(--tm-fast) var(--tm-ease), filter var(--tm-fast) var(--tm-ease);
}

.tm-modal .tm-modal-btn:active {
    transform: translateY(1px);
}

/* "Keep Solving" is the safe option and gets the calm treatment; submitting is
   irreversible, so it is the one that has to be chosen deliberately. */
.tm-modal .tm-modal-btn.is-ghost {
    background: var(--tm-surface-2);
    border-color: var(--tm-line-2);
    color: var(--tm-text-2);
}

.tm-modal .tm-modal-btn.is-ghost:hover {
    background: var(--tm-surface-3);
    color: var(--tm-text);
}

.tm-modal .tm-modal-btn.is-primary {
    background: linear-gradient(180deg, #ff6470, #e5384a);
    color: #fff;
    box-shadow: 0 4px 14px rgba(229, 56, 74, 0.3);
}

.tm-modal .tm-modal-btn.is-primary:hover {
    filter: brightness(1.07);
}

@media (max-width: 480px) {
    .tm-modal .tm-submit-stats {
        grid-template-columns: repeat(2, 1fr);
    }

    .tm-modal .tm-modal-actions {
        flex-direction: column-reverse;
    }
}

/* ── LIGHT THEME ────────────────────────────────────────────────────────── */

/* Driven by the app-wide toggle (togglePremiumTheme in bootstrap.js), which
   stamps html.theme-light. Because every surface above resolves from the token
   block, this is mostly a token swap — the handful of rules after it are the
   places where a literal colour was unavoidable, plus two overrides for
   light-theme.css rules that reach into the panel during review mode.
   Accent-ink stays dark: the teal and amber fills keep dark text in both
   themes, which is what makes them legible. */
html.theme-light .mock-test-view,
html.theme-light .mobile-palette-drawer,
html.theme-light .tm-modal {
    --tm-bg: #e9edf4;
    --tm-surface: #ffffff;
    /* Dark mode gets its separation from surfaces being LIGHTER than the panel,
       and a 4% step is plenty against near-black. On white the same step has to
       run the other way and it has to be bigger, or an option row and the card
       it sits on are the same colour. */
    --tm-surface-2: #eaeef5;
    --tm-surface-3: #dbe2ec;

    --tm-line: rgba(15, 23, 42, 0.13);
    --tm-line-2: rgba(15, 23, 42, 0.22);

    --tm-text: #111721;
    --tm-text-2: #4b5565;
    --tm-text-3: #78849a;

    --tm-accent: #0aa78b;
    --tm-accent-dim: rgba(10, 167, 139, 0.12);
    --tm-amber: #a9750a;
    --tm-red: #d92f42;
    --tm-green: #14894f;

    --tm-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
}

html.theme-light .mock-test-view {
    background:
        radial-gradient(1100px 620px at 15% -10%, rgba(10, 167, 139, 0.09), transparent 60%),
        radial-gradient(900px 560px at 105% 0%, rgba(124, 92, 240, 0.07), transparent 62%),
        var(--tm-bg) !important;
}

html.theme-light .mock-test-view .mock-header {
    background: rgba(255, 255, 255, 0.86);
    box-shadow: 0 1px 0 rgba(15, 23, 42, 0.02), 0 6px 20px rgba(15, 23, 42, 0.06);
}

html.theme-light .mock-test-view .tm-progress-rail {
    background: rgba(15, 23, 42, 0.08);
}

/* The section strip and its count pills are the only two surfaces above that
   name a colour instead of a token — both are translucent over the page, and
   translucent white does not survive the swap. */
html.theme-light .mock-test-view .tm-section-bar {
    background: rgba(255, 255, 255, 0.72);
}

html.theme-light .mock-test-view .tm-sec-count {
    background: rgba(15, 23, 42, 0.07);
}

html.theme-light .mock-test-view .tm-sec-tab.is-active .tm-sec-count {
    background: rgba(255, 255, 255, 0.3);
}

html.theme-light .mock-test-view .tm-progress-fill {
    background: linear-gradient(90deg, #0aa78b, #2ee6c5);
    box-shadow: 0 0 8px rgba(10, 167, 139, 0.4);
}

/* The dark theme's inset white top-highlight reads as a smudge on white. */
html.theme-light .mock-test-view .mock-left-panel,
html.theme-light .mock-test-view .mock-right-panel,
html.theme-light .mock-test-view .mock-timer-box {
    box-shadow: var(--tm-shadow);
}

html.theme-light .mock-test-view .mock-action-row {
    background: rgba(15, 23, 42, 0.015) !important;
}

/* The two status tints that were built for a dark ground: a 16% red wash and a
   pale red number vanish on white, so both go darker and denser. */
html.theme-light .mock-test-view .q-box.not-answered,
html.theme-light .mobile-palette-drawer .q-box.not-answered {
    background: rgba(217, 47, 66, 0.12);
    border-color: rgba(217, 47, 66, 0.38);
    color: #c22436;
}

/* Options and the Prev/Next pair sit directly on the white card, where the
   token border alone was not enough to make them read as pressable. Both get a
   defined edge; the nav buttons also take the darker text, since a ghost button
   on white was reading as disabled. */
/* These borders are the one place the theme stops being a straight token swap.
   --tm-line is tuned to separate the white card from the page behind it, which
   only needs a whisper; an option row and a nav button sit ON the white card and
   have to read as pressable, so they take a hairline at roughly 2:1 against it
   instead. Anything lighter and they disappear the way they did before. */
html.theme-light .mock-test-view .mock-option-label {
    background: #e8edf5;
    border-color: rgba(15, 23, 42, 0.3);
}

html.theme-light .mock-test-view .mock-option-label:hover {
    background: #dee5f0;
    border-color: rgba(15, 23, 42, 0.42);
}

html.theme-light .mock-test-view .opt-circle {
    background: #ffffff;
    border-color: rgba(15, 23, 42, 0.28);
    color: #4b5565;
}

html.theme-light .mock-test-view .mock-nav-btn {
    background: #eef2f8;
    border-color: rgba(15, 23, 42, 0.34);
    color: var(--tm-text);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05);
}

html.theme-light .mock-test-view .mock-nav-btn:hover {
    background: #e2e9f3;
    border-color: rgba(15, 23, 42, 0.48);
}

html.theme-light .mock-test-view .mock-option-label.selected {
    background: linear-gradient(90deg, rgba(10, 167, 139, 0.14), rgba(10, 167, 139, 0.05));
    border-color: rgba(10, 167, 139, 0.5);
    box-shadow: 0 0 0 1px rgba(10, 167, 139, 0.14), 0 4px 14px rgba(15, 23, 42, 0.08);
}

html.theme-light .mock-test-view .mock-option-label.selected .opt-circle {
    box-shadow: 0 0 10px rgba(10, 167, 139, 0.3);
}

html.theme-light .mock-test-view .mock-rp-list .tm-list-row.is-active {
    border-color: rgba(10, 167, 139, 0.4);
}

/* Dark ink on light paper. drawRoughStroke() reads --tm-ink back off the
   canvas, so the pen colour is only ever declared here. */
html.theme-light .mock-test-view #tm-rough-canvas {
    --tm-ink: #16202e;
}

html.theme-light .mock-test-view .tm-rough {
    box-shadow: 0 18px 44px rgba(15, 23, 42, 0.18);
}

/* light-theme.css restyles .mock-btn and .rf-btn with !important under
   body:not(.test-taking-mode) — a guard that stops applying the moment review
   mode drops that class off <body>, at which point it repaints the palette's
   own buttons. #test-view outranks it. */
html.theme-light #test-view .mock-btn,
html.theme-light #test-view .rf-btn {
    background: var(--tm-surface-2) !important;
    border: 1px solid var(--tm-line) !important;
    color: var(--tm-text-2) !important;
}

html.theme-light #test-view .mock-btn.m-save {
    background: linear-gradient(180deg, #2ee6c5, #0aa78b) !important;
    border: none !important;
    color: var(--tm-accent-ink) !important;
}

/* A 10% amber wash reads as "disabled" on white the way it reads as "tinted"
   on near-black, so the light variant carries more of both. */
html.theme-light #test-view .mock-btn.m-review {
    background: color-mix(in srgb, var(--tm-amber) 15%, transparent) !important;
    border: 1px solid color-mix(in srgb, var(--tm-amber) 45%, transparent) !important;
    color: var(--tm-amber) !important;
}

html.theme-light .mock-test-view .tm-exam-chip {
    background: color-mix(in srgb, var(--tm-amber) 13%, transparent);
    border-color: color-mix(in srgb, var(--tm-amber) 40%, transparent);
}

/* Same reasoning as the nav buttons: a ghost on white reads as disabled. */
html.theme-light #test-view .mock-btn.m-clear {
    background: transparent !important;
    border: 1px solid rgba(15, 23, 42, 0.3) !important;
    color: var(--tm-text-2) !important;
}

/* ── REDUCED MOTION ─────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
    .mock-test-view .tm-qhead,
    .mock-test-view .tm-qtext,
    .mock-test-view .mock-options-container .mock-option-label,
    .mock-test-view .mock-option-label.selected .opt-circle,
    .mock-test-view .mock-timer-box.is-critical,
    .mock-test-view .tm-solution {
        animation: none !important;
    }

    .mock-test-view *,
    .mobile-palette-drawer * {
        transition-duration: 0.01ms !important;
    }
}
