/* MUSX Quiz player styles — extracted/adapted from mockup.html.
   Scoped under .musx-quiz-shell so we don't bleed into the WP theme.
   Uses design tokens from musx-tokens.css (loaded as a dependency). */

/* ─────────────────────────────────────────────────────────────────── */
/* DESIGN-SYSTEM TYPOGRAPHY MAPPING                                    */
/* Saira for everything that needs to feel earned (titles, score       */
/* numbers, eyebrows). Montserrat (set on body via tokens) for body    */
/* + buttons. Tabular numerics on every score/count display.           */
/* ─────────────────────────────────────────────────────────────────── */
.musx-quiz-shell .musx-intro-title,
.musx-quiz-shell .musx-guide-head,
.musx-quiz-shell .musx-guide-sections-head,
.musx-quiz-shell .musx-section-title-big,
.musx-quiz-shell .musx-score-title,
.musx-quiz-shell .musx-score-number,
.musx-quiz-shell .musx-quiz-header-title,
.musx-quiz-shell .musx-q-text,
.musx-quiz-shell .musx-gate-title {
    font-family: var(--font-display, "Saira", system-ui, sans-serif);
    letter-spacing: var(--tracking-tight, -0.02em);
}
.musx-quiz-shell .musx-score-number,
.musx-quiz-shell .musx-progress-label,
.musx-quiz-shell .musx-q-number,
.musx-quiz-shell .musx-section-num,
.musx-quiz-shell .musx-score-fact {
    font-variant-numeric: tabular-nums;
}
/* Eyebrow / small caps labels (section number, "QUESTION N") */
.musx-quiz-shell .musx-section-num,
.musx-quiz-shell .musx-q-number {
    font-family: var(--font-display, "Saira", system-ui, sans-serif);
    letter-spacing: var(--tracking-cap, 0.12em);
    color: var(--musx-orange);
}


/* On any page hosting a quiz, collapse the theme's page-wrapper padding
   and per-block margins around the shell. The shell sizes itself to
   100vh-header so the player fits a single screen — outer padding from
   .musx-page (32-64px top + bottom) only adds white-band scroll above
   and below the player. The body class is set by MUSX_Renderer when
   the [musx_quiz] shortcode is detected. */
body.page-has-quiz .musx-page {
    padding-top: 0;
    padding-bottom: 0;
    max-width: none;
}
/* Lift the inner .musx-content's max-width constraint (44rem) too — the
   quiz shell is its own 720px-max-width centred element, so the wrapping
   .musx-content must let it span full-width to centre properly. Without
   this the shell pins to the left edge of a 44rem column. */
body.page-has-quiz .musx-content {
    max-width: none;
    margin: 0;
}
/* Only kill the vertical margin theme rule (1em above/below blocks) — must
   NOT clobber margin-left/margin-right: auto on the quiz shell, which is
   what centres the 720px-max-width shell within the now-full-width
   .musx-content. (Previous "margin: 0" override here pinned the shell
   flush-left.) */
body.page-has-quiz .musx-content > * {
    margin-top: 0;
    margin-bottom: 0;
}

.musx-quiz-shell { position: relative; z-index: 1; max-width: 720px; margin: 0 auto; padding: 24px 16px;
    /* Viewport-height minus everything ABOVE the shell, so a short quiz card
       fits in one screen without page scroll. min-height (not height) lets
       longer content grow naturally past the viewport.

       --musx-shell-top is measured and written by sizeShell() in musx-quiz.js
       (re-measured on resize, so a title that wraps to two lines is handled).
       It must be the shell's real document offset, NOT just --musx-header-h:
       quiz pages also render header.musx-page-head above the shell, so
       subtracting only the site header reserved ~110px more than the shell
       actually had and forced a scrollbar on EVERY quiz page regardless of
       content (measured on prod 2026-08-31: shell top 182px, available 699px,
       reserved 809px). The old value stays as the fallback, so the layout is
       unchanged if the script has not run yet or does not run at all. */
    min-height: calc(100vh - var(--musx-shell-top, var(--musx-header-h, 96px)));
    display: flex; flex-direction: column; justify-content: center;
    font-family: var(--font-body, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
    color: #fff;
}

/* Every quiz page: no site footer. The shell reserves the viewport height, so
   a footer below it forced a constant scrollbar on every view (Barry,
   2026-09-03: "try hiding the footer on all quizzes"). The shell's own
   "Back to MUSX" link is the way out. body.page-has-quiz is set server-side
   by MUSX_Renderer for any page carrying the shortcode. */
body.page-has-quiz .musx-footer { display: none !important; }

/* Exam pages: true full-bleed "kiosk" — hide ALL page chrome (WP site header,
   page H1, footer, admin bar) so the exam fills the viewport with no
   distractions. Matches the original Outgrow blank-page UX. Modern browsers
   only (:has support) — IE11/old Safari don't get the cleanup but the exam
   still works. The shell renders its own header (logo + back link), so we
   don't lose navigation by hiding the site header. */
body:has(.musx-quiz-shell.is-exam-mode) .musx-header,
body:has(.musx-quiz-shell.is-exam-mode) .musx-page-head,
body:has(.musx-quiz-shell.is-exam-mode) .musx-footer,
body:has(.musx-quiz-shell.is-exam-mode) #wpadminbar,
body:has(.musx-quiz-shell.is-app-mode) .musx-header,
body:has(.musx-quiz-shell.is-app-mode) .musx-page-head,
body:has(.musx-quiz-shell.is-app-mode) .musx-footer,
body:has(.musx-quiz-shell.is-app-mode) #wpadminbar {
    display: none !important;
}
/* WP injects `html { margin-top: 32px !important }` when admin bar is shown
   — undo so the exam can flush to viewport top. */
html:has(body .musx-quiz-shell.is-exam-mode),
html:has(body .musx-quiz-shell.is-app-mode) {
    margin-top: 0 !important;
}
body:has(.musx-quiz-shell.is-exam-mode),
body:has(.musx-quiz-shell.is-app-mode) {
    margin: 0;
    /* No overflow:hidden — when the shell's content exceeds the viewport
       (small windows, tall question images, etc.) the PAGE should scroll
       naturally, not trap the user in an internal scrollbox. */
}

/* Exam mode — pin the shell to the viewport height (no page scroll) and let
   the question card scroll INTERNALLY if it overflows. Keeps the section
   progress bar + nav bar always visible like a real exam app. */
.musx-quiz-shell.is-exam-mode {
    /* Fills the viewport when content fits (kiosk feel), grows naturally
       when content is taller. Page scrolls if the shell exceeds 100vh — no
       internal card scrollbars on tight viewports. */
    min-height: 100vh;
    justify-content: center;
}
.musx-quiz-shell.is-exam-mode .musx-quiz-container {
    /* Compact padding so a question + image + 4 options can fit a normal
       laptop viewport (~700-800px) without page scroll. */
    padding-top: 30px;
    padding-bottom: 18px;
}

/* Fullscreen mode: shell owns the whole viewport. Same min-height model as
   the kiosk view — no internal scrollbars; content grows naturally and the
   fullscreen viewport scrolls if it has to. */
.musx-quiz-shell:fullscreen,
.musx-quiz-shell:-webkit-full-screen {
    max-width: 100vw;
    width: 100vw;
    min-height: 100vh;
    padding: 0;
    justify-content: center;
    overflow-y: auto;
    background: #0d1326;
}
.musx-quiz-shell:fullscreen .musx-quiz-container,
.musx-quiz-shell:-webkit-full-screen .musx-quiz-container {
    min-height: 100vh;
    border-radius: 0;
    border: 0;
    box-shadow: none;
}
/* Backdrop is fixed inside the fullscreened element — keep it from leaking out. */
.musx-quiz-shell:fullscreen::before,
.musx-quiz-shell:-webkit-full-screen::before {
    position: absolute;
}

/* Full-viewport photo backdrop with 50% darken. Fixed so it stays put when the page scrolls. */
.musx-quiz-shell::before {
    content: '';
    position: fixed; inset: 0;
    /* WebP with a JPEG fallback for anything that cannot take it. The source
       JPEG was 237 KB — the heaviest asset on the site, gating the first screen
       of a quiz on a school connection. WebP at 1400w is 71 KB (-70%), and the
       800w variant serves phones below (2026-08-31). */
    background-image:
        linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
        url('img/musx_girl_piano.jpg');
    background-image:
        linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
        image-set(url('img/musx_girl_piano.webp') type('image/webp'),
                  url('img/musx_girl_piano.jpg')  type('image/jpeg'));
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    z-index: -1;
    pointer-events: none;
}

.musx-quiz-shell * { box-sizing: border-box; }

/* .musx-bg is no longer used — panel styling moved onto .musx-quiz-container so the dark/blur
   sizes to the quiz content, with the photo backdrop showing through around it. */
.musx-bg { display: none; }

.musx-quiz-container {
    position: relative;
    z-index: 1;
    padding: 24px;
    flex-shrink: 0;
    /* Near-solid — the blur is still visible at the edges/around the card but colours inside
       (especially saturated ones like the orange CTA) render true. The 50% darken on the photo
       lives independently in .musx-quiz-shell::before. */
    background: rgba(15, 20, 40, 0.75);
    border-radius: 18px;
    overflow: hidden;
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255,255,255,0.08);
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.35);
}

/* Header layout: flex row so title (left) + logo (centre) + actions (right)
   sit on a single horizontal line. The HTML order is logo→title→actions,
   so `order:` rearranges them visually. Flex is more bulletproof than grid
   for the "always-one-row" guarantee. */
.musx-quiz-header {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 14px;
}
.musx-quiz-header > * { min-width: 0; }
/* Header logo: compact M-icon variant of the MUSX mark. The full
   "INTERNATIONAL / MUSIC EXAMS" wordmark is reserved for the intro splash card.
   32px height keeps it proportional next to the quiz title text. */
.musx-logo {
    order: 2;            /* visually centred between title (left) and actions (right) */
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}
/* Logo: 28px tall, no padding/margin on the img itself — breathing room is
   given by the .musx-logo wrapper + the container's padding-top instead.
   !important defends against theme/page CSS that auto-styles content imgs.
   Source is musx-bowtie.svg (orange-on-transparent vector). Filter recolours
   it white for the dark exam header — works cleanly because the SVG truly
   has no background. */
.musx-quiz-shell .musx-logo img {
    display: block !important;
    height: 28px !important;
    max-height: 28px !important;
    max-width: none !important;
    width: auto !important;
    padding: 0 !important;
    margin: 0 !important;
    filter: brightness(0) invert(1);
}
.musx-quiz-shell .musx-logo {
    padding: 6px 0;   /* a touch of vertical breathing inside the grid cell */
}

/* Quiz title that persists in the header — populated in renderShell from the bank name
   (e.g. "Grade One Rhythm"). Sits in the left column.
   Truncates with ellipsis on narrow viewports so it never wraps the header onto two rows. */
.musx-quiz-header-title {
    order: 1;
    flex: 1 1 0;     /* fills left side; flex allows the title to shrink */
    min-width: 0;    /* required so ellipsis works inside a flex track */
    margin: 0;
    color: #fff;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: 0.2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* On the intro splash the title already lives big on the white card — hide the
   header version so we don't repeat it. */
.musx-shell-intro .musx-quiz-header-title { display: none; }
@media (max-width: 540px) {
    /* On phones the header is tight; drop the title to one of two states:
       small (when it fits) or hidden completely on the smallest screens. */
    .musx-quiz-header-title { font-size: 13px; margin: 0 8px; }
}
@media (max-width: 380px) {
    .musx-quiz-header-title { display: none; }
}
.musx-header-actions { order: 3; flex: 1 1 0; display: flex; justify-content: flex-end; align-items: center; gap: 16px; }
.musx-fs-btn { background: transparent; border: 1px solid rgba(255,255,255,.3); color: #fff; padding: 6px 10px; border-radius: 6px; cursor: pointer; font-size: 14px; }
.musx-fs-btn:hover { background: rgba(255,255,255,.1); }
.musx-back-link { color: rgba(255,255,255,.7); font-size: 13px; text-decoration: none; }
.musx-back-link:hover { color: #fff; }

.musx-progress-row { display:flex; align-items:center; gap: 12px; margin-bottom: 16px; }
/* Honour the hidden attribute — display:flex above would otherwise win. */
.musx-progress-row[hidden] { display: none; }
.musx-progress-track { flex: 1; height: 6px; background: rgba(255,255,255,.1); border-radius: 3px; overflow: hidden; }
.musx-progress-fill {
    height: 100%; background: var(--musx-orange);
    border-radius: 999px;
    box-shadow: 0 0 12px rgba(254, 80, 0, 0.55);
    transition: width var(--dur-slow, 420ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1));
}
.musx-progress-label { font-size: 12px; color: rgba(255,255,255,.7); white-space: nowrap; }
/* Exam mode — a segmented progress bar, one segment per section, so a 100-question
   exam shows "Section 2 of 7" rather than a daunting "12 of 100". */
.musx-progress-track.musx-progress-segmented { display: flex; gap: 4px; background: transparent; overflow: visible; }
.musx-progress-seg { flex: 1; height: 6px; background: rgba(255,255,255,.1); border-radius: 3px; overflow: hidden; }
.musx-progress-seg-fill {
    height: 100%; width: 0; background: var(--musx-orange);
    border-radius: 999px;
    box-shadow: 0 0 8px rgba(254, 80, 0, 0.55);
    transition: width var(--dur-slow, 420ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1));
}

/* Streak chip — sits left of the progress track. Brand-orange tint at low opacity
   so it draws the eye without competing with the question content. The pulse class
   is applied for ~600ms on increment via a class-toggle trick. */
.musx-streak-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: rgba(255,107,43,.18);
    color: #FFB48A;
    border: 1px solid rgba(255,107,43,.32);
    border-radius: 999px;
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.musx-streak-chip[hidden] { display: none; }
.musx-streak-pulse { animation: musx-streak-pulse-kf .55s ease-out; }
@keyframes musx-streak-pulse-kf {
    0%   { transform: scale(1);    box-shadow: 0 0 0 0 rgba(255,107,43,.4); }
    35%  { transform: scale(1.18); box-shadow: 0 0 0 6px rgba(255,107,43,0); }
    100% { transform: scale(1);    box-shadow: 0 0 0 0 rgba(255,107,43,0); }
}
@media (prefers-reduced-motion: reduce) {
    .musx-streak-pulse { animation: none; }
}

.musx-quiz-card {
    background: rgba(255,255,255,0.05);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
    border-radius: 16px; padding: 18px; border: 1px solid rgba(255,255,255,.1);
    min-height: 320px;
}

/* Intro view — Outgrow-style white splash card. The container goes light during this state
   (see .musx-shell-intro overrides below), then transitions back to the dark quiz UI on Start. */
.musx-intro-view { text-align: center; padding: 24px 16px 8px; }
/* Force-center the wordmark logo — !important defends against theme/Divi
   rules that float images left by default on content pages. */
.musx-quiz-shell .musx-intro-view img.musx-intro-logo-img,
.musx-quiz-shell .musx-gate-view img.musx-intro-logo-img {
    display: block !important;
    width: 280px;
    max-width: 80%;
    height: auto;
    margin-left: auto !important;
    margin-right: auto !important;
    margin-bottom: 28px;
    float: none !important;
}
.musx-intro-title { font-size: 28px; font-weight: 700; line-height: 1.2; margin-bottom: 18px; color: var(--ink-800); }
.musx-intro-meta { font-size: 17px; font-weight: 600; color: #6c7280; margin-bottom: 4px; }
.musx-intro-desc { font-size: 16px; line-height: 1.55; color: #6c7280; margin-bottom: 28px; max-width: 460px; margin-left: auto; margin-right: auto; }
.musx-intro-tipline { font-size: 15px; font-weight: 600; margin: -18px auto 28px; max-width: 460px; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.musx-intro-tipline > span { display: inline-flex; align-items: center; gap: 8px; }
.musx-tipline-right { color: #15803d; }   /* 4.7:1 on white */
.musx-tipline-wrong { color: #b91c1c; }   /* 6.0:1 on white */
.musx-tipline-dot { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 50%; color: #fff; font-style: normal; font-size: 12px; font-weight: 800; line-height: 1; flex: 0 0 20px; }
.musx-tipline-right .musx-tipline-dot { background: #22c55e; }
.musx-tipline-wrong .musx-tipline-dot { background: #ef4444; }
/* CTA fill inside the quiz player.
   The player's filled buttons carry white text at NORMAL text sizes — START is
   18px/600, .musx-next-btn 16px/600 — so brand #fe5000 (3.30:1) fails AA; it only
   passes as "large text" at >=18.66px bold, which the theme's own
   .wp-block-button__link (18.72px/700) does meet, which is why site buttons keep
   the brand orange and these do not.
   Rebound on the SHELL, not :root: theme.css and musx-tokens.css both set --cta-bg
   on :root, so a :root override here would be settled by stylesheet load order.
   Scoping it to the shell is decided by specificity instead, and cannot bleed out. */
.musx-quiz-shell {
    --cta-bg:       var(--musx-orange-aa, #cc3e00);        /* 4.93:1 */
    --cta-bg-hover: var(--musx-orange-aa-hover, #b03600);  /* 6.22:1 — darkens, never lightens */
}
.musx-start-btn, .musx-section-btn {
    background: var(--cta-bg); color: var(--cta-fg, #fff);
    border: 0; border-radius: var(--r-lg, 16px);
    padding: 16px 56px; font: inherit; font-size: 18px;
    font-weight: var(--fw-semibold, 600); letter-spacing: 0;
    cursor: pointer;
    box-shadow: var(--shadow-cta);
    transition: background var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1)),
                box-shadow var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1)),
                transform var(--dur-fast, 120ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1));
    min-height: 48px;
}
.musx-start-btn:hover, .musx-section-btn:hover {
    background: var(--cta-bg-hover);
    box-shadow: var(--shadow-cta-hover);
}
.musx-start-btn:active, .musx-section-btn:active { transform: scale(.97); }

/* Exam cover — guidelines + section breakdown on the intro splash. */
.musx-intro-guidelines { max-width: 560px; margin: 4px auto 30px; }
.musx-guide-head { font-size: 22px; font-weight: 700; color: var(--ink-800); margin-bottom: 14px; }
.musx-guide-rules { font-size: 15px; line-height: 1.7; color: #6c7280; margin-bottom: 22px; }
.musx-guide-sections-head { font-size: 16px; font-weight: 700; color: var(--ink-800); margin-bottom: 8px; }
.musx-guide-sections { font-size: 15px; line-height: 1.75; color: #6c7280; }
.musx-guide-section { font-variant-numeric: tabular-nums; }
@media (max-width: 480px) {
    .musx-guide-head { font-size: 19px; }
    .musx-guide-rules, .musx-guide-sections { font-size: 14px; }
}

/* Section interstitial — shown before each exam section (the 7 marked categories). */
.musx-section-view { text-align: center; padding: 48px 16px 32px; }
.musx-section-num { font-size: 14px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--musx-orange); margin-bottom: 14px; }
.musx-section-title-big { font-size: 34px; font-weight: 800; line-height: 1.15; color: #fff; margin-bottom: 10px; }
.musx-section-count { font-size: 16px; color: #6c7280; margin-bottom: 30px; }
@media (max-width: 480px) {
    .musx-intro-logo-img { width: 220px; margin-bottom: 20px; }
    .musx-intro-title    { font-size: 22px; }
    .musx-intro-desc     { font-size: 15px; }
    .musx-section-view      { padding: 32px 16px 24px; }
    .musx-section-title-big { font-size: 26px; }
}

/* White-splash state — when the intro view is active, the entire panel flips to a clean
   white card on the photo backdrop. Everything else (header, dark card, frosted glass)
   is suppressed until Start is clicked. */
.musx-shell-intro .musx-quiz-container {
    background: #fff;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: 0;
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.18);
}
.musx-shell-intro .musx-quiz-card {
    background: transparent;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: 0;
    padding: 0;
    min-height: 0;
}
.musx-shell-intro .musx-quiz-header { display: none; }

.musx-q-number { font-size: 13px; color: rgba(255,255,255,.5); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 4px; }

/* Slide-up transition between questions — leave lifts up + fades, enter rises from below. */
@keyframes musx-q-leave-anim {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-16px); }
}
@keyframes musx-q-enter-anim {
    from { opacity: 0; transform: translateY(20px); }
    to   { opacity: 1; transform: translateY(0); }
}
.musx-q-leave { animation: musx-q-leave-anim 140ms ease-in   forwards; }
.musx-q-enter { animation: musx-q-enter-anim 220ms ease-out  forwards; }
/* Respect users who've asked OS-level for reduced motion. */
@media (prefers-reduced-motion: reduce) {
    .musx-q-leave, .musx-q-enter { animation: none !important; }
}
.musx-q-text { font-size: 20px; font-weight: 600; line-height: 1.3; margin-bottom: 6px; }
/* Debug badge — bank key + question id, used to identify questions across shuffled attempts. Remove when done debugging. */
.musx-q-debug { font-size: 11px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: rgba(255,255,255,.45); margin-bottom: 12px; user-select: all; }

/* The WRAP owns the height, because it is the flex item. Put the height on a
   descendant instead and the wrap stays shrinkable (`flex: 0 1 auto`, min-height 0)
   while the child keeps a fixed height — so in a short flex column the child
   overflows the wrap and lands on top of the answer options. Sizing the wrap and
   letting the picture fill it at 100% makes that overlap structurally impossible. */
.musx-q-image-wrap {
    margin-bottom: 20px; text-align: center; display: flex; justify-content: center;
}
/* Size ONLY when there is actually an image. The wrap is always in the template and
   emptied per question (renderQuestion), so an unconditional height reserves ~200px
   of blank space on every question whose options carry the images instead. */
/* NO PERCENTAGE HEIGHTS ANYWHERE IN THIS BOX.
   A percentage height only resolves against a parent with a definite height, and
   Safari does not reliably grant that to a replaced element inside <picture> — it
   falls back to the image's intrinsic height, which either spills onto the answer
   options (the original report) or gets clipped once we added overflow:hidden (the
   crop Barry saw next). Giving the wrap, the <picture> and the <img> the SAME
   absolute height removes the dependency completely: the box is identical in every
   engine, and object-fit:contain letterboxes the image inside it — so nothing
   overflows and nothing is cropped. overflow:hidden stays as an inert backstop. */
.musx-q-image-wrap:has(picture) {
    height: min(200px, 22vh);
    flex: 0 0 auto;
    align-items: center;
    overflow: hidden;
}
/* No :has() (older Safari/Firefox ESR): collapse the empty wrap so it can't leave a
   gap, and let the picture's own height carry the reservation instead. */
@supports not selector(:has(picture)) {
    .musx-q-image-wrap:empty { display: none; }
    .musx-q-image-wrap picture { height: min(200px, 22vh); }
}

/* THE BOX MUST BE ON <picture>, NOT ON <img>.
   makePictureEl() builds <picture><source><img class="musx-q-image"></picture>, so
   <picture> is the flex/grid item — and left as its default `display:inline` it has
   no box of its own until the image decodes. The img's `width:100%` then resolves
   against a zero-width parent, so the image renders collapsed and visibly snaps to
   full size the moment it loads. Sizing <picture> reserves the space up front, which
   is what actually removes the jump (the fixed height on .musx-q-image below never
   could, because the width was the collapsed dimension). Fixed 2026-07-26. */
.musx-quiz-shell picture { display: block; }
.musx-q-image-wrap picture {
    width: 100%; max-width: 320px;
    height: min(200px, 22vh);         /* same absolute value, not 100% */
    /* AND kill the stray line box. Something in the cascade gives <source> a
       non-none display, which opens a ~24px line box at the top of the <picture>
       and pushes the block-level <img> down by exactly that much — measured on
       prod. The image then hangs 24px below its own box, which is precisely the
       strip overflow:hidden was cropping (the `ff` dynamic marking, in Barry's
       report). line-height:0 removes the line box; hiding <source> is belt. */
    line-height: 0;
    font-size: 0;
    display: block;
}
.musx-q-image-wrap picture > source { display: none; }
/* Same stray line box as the question image (see above): without line-height
   0 + a hidden <source>, the <img> sat 25px below the top of the cell and the
   picture ran 48px taller than the image (desktop, 2026-09-03). */
.musx-option-card picture { display: block; width: 100%; line-height: 0; font-size: 0; }
.musx-option-card picture > source { display: none; }

/* Fixed dimensions reserve space before the image loads — prevents layout jump (CLS). */
.musx-q-image {
    width: 100%; max-width: 320px; height: min(200px, 22vh);
    /* Viewport-adaptive: capped at 200px on tall screens, scales down on
       short ones so a question + image + options can fit in 100vh without
       requiring page scroll. */
    height: min(200px, 22vh);
    object-fit: contain; object-position: center;
    background: #fff; padding: 10px; border-radius: 12px;
    box-sizing: border-box; margin: 0 auto; display: block;
}

.musx-options-grid { display: grid; gap: 8px; margin-bottom: 12px; }
.musx-grid-images      { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 10px; }
/* Desktop: cap the 2×2 image grid so an image question fits the viewport-tall
   shell like every other question type. Uncapped at 688px the cells were
   339×212 and the card ran to 838px on a 900px window, so the scrollbar thumb
   jumped between questions (measured 2026-09-03). 500px → cells 245×133. */
@media (min-width: 701px) {
    .musx-grid-images { max-width: 500px; margin-left: auto; margin-right: auto; }
    .musx-grid-images .musx-option-card { padding: 8px; }
}
/* Binary (True/False, Yes/No, Higher/Lower) — exactly two large side-by-side buttons. */
.musx-grid-binary      { grid-template-columns: repeat(2, minmax(0,1fr)); gap: 14px; }
.musx-grid-binary .musx-option-card {
    padding: 22px 16px;
    justify-content: center;
    text-align: center;
    font-size: 22px;
    font-weight: 700;
    letter-spacing: 0.5px;
}
.musx-grid-binary .musx-option-label { text-transform: uppercase; }
@media (max-width: 480px) {
    .musx-grid-binary .musx-option-card { padding: 18px 12px; font-size: 19px; }
}
/* Long-text options: auto-fill 2 columns when there's room (~240px min per cell),
   collapse to 1 column on narrow screens. Saves vertical space on 4-option questions. */
.musx-grid-text        { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
/* Short text labels (e.g. note names, time signatures) tile so the quiz fits on one screen. */
.musx-grid-text-short  { grid-template-columns: repeat(4, minmax(0,1fr)); gap: 8px; }
@media (max-width: 480px) {
    .musx-grid-text-short { grid-template-columns: repeat(3, minmax(0,1fr)); }
}

/* Musical accidentals (♭ ♯ ♮) — system fonts render these as typographic glyphs that
   look amateur (flat shapes instead of round, undersized, wrong proportions). Noto Music
   is an engraver-quality face that draws them as proper notation symbols. Loaded as a
   3-glyph subset via the renderer's wp_enqueue_style. Fallback chain keeps things
   working if the CDN is blocked. */
.musx-acc {
    font-family: "Noto Music", "Bravura Text", "Petaluma Script",
                 "Apple SD Gothic Neo", "Segoe UI Symbol", sans-serif;
    /* Music fonts only ship a single regular weight; bold makes them render as a
       fallback face. Keep weight at 400 so we always get the real engraver glyph. */
    font-weight: 400;
    /* Sized to read alongside a capital letter. Mostly baseline-aligned, but the sharp
       gets a small upward nudge because Noto Music's ♯ has a typographic descender
       (the lower diagonal stroke drops below the glyph's baseline) — with pure baseline
       alignment it ends up sitting visibly lower than the flat/natural. */
    font-size: 1.3em;
    line-height: 1;
    vertical-align: baseline;
    margin: 0 0.04em 0 0.02em;
}
/* Per-glyph baseline correction. The JS wrapper adds .musx-acc-flat / -sharp / -natural
   so we can tune each independently if the rendering ever diverges. */
.musx-acc-sharp   { vertical-align: 0.16em; }   /* Noto Music's ♯ and ♭ sit on a descender; lift so the glyph's foot meets the letter's baseline (Barry, 18 Sep 2026) */
.musx-acc-flat    { vertical-align: 0.1em; }
.musx-acc-natural { vertical-align: 0.16em; }
.musx-acc-dsharp  { vertical-align: 0.05em; font-size: 1.6em; }   /* Noto Music's 𝄪 is drawn small; scale it to read beside the letter */   /* 𝄪 is a wide low glyph; a touch smaller keeps the line height */
.musx-acc-dflat   { vertical-align: 0.1em; }
/* Roman numerals as numerals: a serif face so I, II, IV, V are not read as letters. */
.musx-roman { font-family: Georgia, "Times New Roman", serif; font-weight: 700; letter-spacing: 0.02em; }

.musx-option-card {
    position: relative;
    background: var(--exam-card, rgba(255,255,255,.06));
    border: 1px solid var(--exam-card-border, rgba(255,255,255,.14));
    border-radius: var(--r-lg, 16px);
    padding: 14px 16px;
    cursor: pointer;
    color: #fff;
    text-align: left;
    font: inherit;
    transition: background var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
                border-color var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1)),
                transform var(--dur-fast, 120ms) var(--ease-out, cubic-bezier(0.22, 1, 0.36, 1));
    display: flex; align-items: center; gap: 14px;
}
.musx-grid-images .musx-option-card { flex-direction: column; align-items: center; }
.musx-grid-text-short .musx-option-card { padding: 14px 10px; justify-content: center; text-align: center; font-size: 18px; font-weight: var(--fw-semibold, 600); }
.musx-option-card:hover:not(:disabled) {
    background: var(--exam-card-strong, rgba(255,255,255,.10));
    transform: translateY(-1px);
}
.musx-option-card:active:not(:disabled) { transform: scale(.98); }
.musx-option-card:disabled { cursor: default; opacity: 0.85; }
.musx-option-card.musx-correct { background: rgba(43, 182, 115, .18); border-color: var(--success, #2bb673); }
.musx-option-card.musx-wrong   { background: rgba(214, 49, 75, .16); border-color: var(--danger, #d6314b); }
/* Exam mode — the chosen option locks in neutrally; an exam shows no right/wrong. */
.musx-option-card.musx-chosen  { background: rgba(254, 80, 0, .16); border-color: var(--musx-orange, #fe5000); }
/* Tap acknowledged, verdict in flight: lit like a chosen card, never dimmed. */
.musx-option-card.musx-pending { background: rgba(254, 80, 0, .16); border-color: var(--musx-orange, #fe5000); opacity: 1; }

/* Scales with the option-card width via aspect-ratio (no CLS, no fixed pixel height).
   On mobile we go closer to square so the white card fills the cramped option tile. */
.musx-option-image { width: 100%; aspect-ratio: 16 / 10; object-fit: contain; background: #fff; padding: 0; border-radius: 8px; box-sizing: border-box; }
@media (max-width: 480px) {
    .musx-option-image { aspect-ratio: 4 / 3; }
    /* Pin the panel to the top of the viewport on mobile — no vertical centering, no
       wasted background-photo space above. Shell padding stays small for breathing room. */
    .musx-quiz-shell { justify-content: flex-start; min-height: auto; padding: 12px; }
    /* Tighter padding + smaller question header image so the Skip/Next row stays on-screen.
       Top padding matches sides — gap between progress bar and inner card is minimised. */
    .musx-quiz-container { padding: 14px; display: flex; flex-direction: column; }
    .musx-progress-row { margin-bottom: 6px; }
    .musx-quiz-card { padding: 14px; }
    /* Mobile: one value, applied to all three boxes for the same reason as above. */
    .musx-q-image-wrap:has(picture),
    .musx-q-image-wrap picture,
    .musx-q-image { height: min(150px, 22vh); }
    .musx-q-text { font-size: 18px; }
    /* Mobile: move the header (logo + Back) below the quiz card so the question takes
       the top of the viewport (thumb-reachable content, chrome out of the way). */
    .musx-quiz-header { order: 99; margin-top: 14px; margin-bottom: 0; opacity: 0.75; }
    /* Tight grey card on mobile — white notation runs to the grey edge, only padding
       below for the "Option N" label. */
    .musx-grid-images .musx-option-card { padding: 0 0 8px 0; gap: 6px; }
}
.musx-option-label { font-size: 16px; }
.musx-grid-images .musx-option-label { text-align: center; font-size: 14px; }

.musx-status-badge {
    position: absolute; top: 8px; right: 8px;
    width: 22px; height: 22px; border-radius: 50%;
    display: none;
}
.musx-option-card.musx-correct .musx-status-badge,
.musx-option-card.musx-wrong   .musx-status-badge { display: block; }
.musx-option-card.musx-correct .musx-status-badge::before { content: '✓'; color: #22c55e; font-size: 18px; }
.musx-option-card.musx-wrong   .musx-status-badge::before { content: '✕'; color: #ef4444; font-size: 18px; }

.musx-feedback-bar { padding: 10px 12px; border-radius: 10px; font-size: 14px; min-height: 22px; }
.musx-feedback-bar.musx-fb-correct { background: rgba(34,197,94,.15); color: #86efac; }
.musx-feedback-bar.musx-fb-wrong   { background: rgba(239,68,68,.15); color: #fca5a5; }
.musx-feedback-bar.musx-fb-skip    { background: rgba(255,255,255,.08); color: rgba(255,255,255,.7); }
/* When a tip is shown the feedback bar goes off-screen (still announced). */
.musx-quiz-shell .musx-feedback-bar.musx-fb-quiet {
    position: absolute; width: 1px; height: 1px; min-height: 0;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* The tip: the rule behind the answer, under the feedback bar after a wrong answer. */
.musx-quiz-shell .musx-tip {
    margin-top: 0; padding: 12px 14px 12px 16px; border-radius: 10px;
    background: rgba(255,255,255,.07); border-left: 3px solid var(--musx-orange, #fe5000);
    color: rgba(255,255,255,.88); font-size: 15px; line-height: 1.5; text-align: left;
}
.musx-quiz-shell.is-app-mode .musx-tip { margin: 10px 0 0; font-size: 15px; }

.musx-bottom-row { display:flex; justify-content:flex-end; gap: 10px; margin-top: 14px; }
.musx-bottom-row[hidden] { display: none; }
/* .musx-skip-btn rules removed 2026-08-31 — the Skip button is no longer in the
   bottom row (renderShell ships Next only), so nothing could ever match them. */
.musx-next-btn {
    padding: 10px 18px; border-radius: 10px; cursor: pointer; font: inherit; font-weight: 600;
}
.musx-next-btn {
    background: var(--cta-bg, var(--musx-orange-aa, #cc3e00)); color: var(--cta-fg, #fff); border: 0;
    box-shadow: var(--shadow-cta);
    border-radius: var(--r-lg, 16px);
    transition: background var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1)),
                box-shadow var(--dur-base, 220ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1)),
                transform var(--dur-fast, 120ms) var(--ease-out, cubic-bezier(0.22,1,0.36,1));
}
.musx-next-btn:hover { background: var(--cta-bg-hover); box-shadow: var(--shadow-cta-hover); }
.musx-next-btn:active { transform: scale(.97); }
.musx-next-btn:disabled { background: rgba(255,107,43,.3); cursor: default; }
.musx-next-btn:hover:not(:disabled) { background: #ff7836; }

/* Score view */
.musx-score-view { text-align: center; }
.musx-score-ring-wrap { position: relative; width: 160px; height: 160px; margin: 8px auto 16px; }

/* MUSX assessment bands — vocabulary from /rules/ (Distinction / Honours / Merit /
   Participation). For now the score-view styling is uniform brand orange + white;
   the four-colour-per-band system is parked until we ship the multi-attempt
   chart (a future "your work so far" view where band colours act as a legend).
   Until that exists, four ring colours just confuse the single-quiz reading. */
.musx-ring-fill { stroke: var(--musx-orange); }
.musx-score-title { color: #ffffff; font-size: 28px; font-weight: 800; margin-top: 4px; letter-spacing: 0.5px; }

.musx-score-fact { font-size: 13px; color: rgba(255,255,255,.6); margin: 8px 0 24px; font-variant-numeric: tabular-nums; }
.musx-score-ring-wrap svg { transform: rotate(-90deg); }
.musx-ring-bg   { fill: none; stroke: rgba(255,255,255,.1); stroke-width: 12; }
.musx-ring-fill { fill: none; stroke: var(--musx-orange); stroke-width: 12; stroke-linecap: round; transition: stroke-dashoffset 1.4s ease; }
.musx-score-number { position: absolute; inset: 0; display:flex; align-items:center; justify-content: center; font-size: 36px; font-weight: 900; }
.musx-score-number span { font-size: 16px; opacity: .6; margin-left: 4px; }
.musx-score-title { font-size: 24px; font-weight: 700; margin-bottom: 4px; }
.musx-score-subtitle { color: rgba(255,255,255,.7); margin-bottom: 22px; }

/* Band-only reveal: the raw mark stays hidden behind the email capture. The big letter
   inside the ring (D / H / M / P) is the visual reveal. Sized large + colour-matched
   to the band so it reads at a glance without leaking the precise score. */
/* musx-band-initial removed — the big "D" inside the ring read like an academic
   "D-grade" (= fail in many marking systems). The band name printed below the
   ring ("Distinction" / "Honours" / "Merit" / "Participation") carries the
   message; the ring is now purely decorative in band-reveal mode. Selectors
   kept here as a no-op so old cached templates don't break. */
/* In band mode the score title becomes the hero — bump its size so the band name is unmistakable. */
.musx-reveal-band .musx-score-title { font-size: 34px; margin-top: 12px; }
.musx-reveal-band .musx-score-subtitle { max-width: 360px; margin-left: auto; margin-right: auto; }

/* Positive observations list — bulleted with a soft separator. Single column, centered.
   Items only ever surface when favourable, so the list either has 1–3 items or is hidden. */
/* Ancestor-qualified (0,3,0) on purpose: the theme's `.musx-content ul, ol`
   sets padding-left:1.5em at (0,2,0), which beat the bare class here. The ul's
   own box stayed centred, so nothing looked broken — but its CONTENT box was
   inset 24px on the left and 0 on the right, pushing every centred chip 12px
   right of the ring and the title. Measured, not eyeballed (Barry, 6 Sep). */
.musx-quiz-shell .musx-score-view .musx-score-observations {
    list-style: none; padding: 0; margin: 4px 0 18px;
    display: flex; flex-direction: column; gap: 6px;
}
.musx-score-observations li {
    font-size: 14px;
    color: rgba(255,255,255,.82);
    background: rgba(255,255,255,.04);
    border: 1px solid rgba(255,255,255,.08);
    border-radius: 999px;
    padding: 8px 16px;
    display: inline-block;
    align-self: center;
    font-variant-numeric: tabular-nums;
}

/* Email form — premium light card on the dark quiz page. We tried tinted dark inputs
   for several versions and they always read as murky on a dark panel. Flipping to a
   bright white card with soft-grey inputs feels much closer to the iPhone-sign-in
   aesthetic Barry asked for, and sidesteps every browser's autofill paint quirk
   (the autofill blue overlay sits comfortably on a light field). */
.musx-email-form {
    background: #ffffff;
    border: 1px solid rgba(0,0,0,.06);
    border-radius: 18px;
    padding: 28px 26px 24px;
    margin-bottom: 12px;
    text-align: left;
    box-shadow: 0 12px 40px rgba(0,0,0,.32);
    color: #1a1f3a;
}
.musx-email-form h3 {
    color: #1a1f3a;
    font-size: 18px;
    font-weight: 700;
    margin: 0 0 6px;
    line-height: 1.3;
    /* Defeat theme h3 styles. Divi (and many themes) force uppercase + letter-spacing
       on heading elements site-wide. The form heading should read as a natural sentence. */
    text-transform: none;
    letter-spacing: 0;
    font-family: var(--font-body, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
}
.musx-email-form p {
    color: rgba(26,31,58,.65);
    font-size: 14px;
    line-height: 1.45;
    margin: 0 0 20px;
}

/* Inputs — soft grey fill, no visible border at rest. The fill gives instant visual
   contrast against the white card without the noise of a stroke. Focus reveals the
   brand-orange border + a soft orange halo. */
/* Note on selector + !important: Divi (the active theme) applies its own form padding
   via lower-specificity selectors that nonetheless match `input` and beat a plain
   .musx-input rule on cascade order. Bumping specificity by scoping to .musx-email-form
   .musx-input AND marking padding !important is what it takes to make Divi keep its
   hands off these particular fields. Same trick used elsewhere in this file for the
   autofill overrides. */
.musx-email-form .musx-input {
    display: block;
    width: 100%;
    padding: 22px 24px !important;
    margin-bottom: 18px;
    background: #f4f5f9;
    border: 1.5px solid transparent;
    border-radius: 12px;
    color: #1a1f3a;
    font-family: var(--font-body, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif);
    font-size: 16px;            /* 16px prevents iOS Safari from auto-zooming on focus */
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1.25;
    box-sizing: border-box;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
    -webkit-appearance: none;
    appearance: none;
}
/* First + last name row: 50/50 split with comfortable gap. On narrow phones
   the gap collapses and fields stack so the touch targets stay readable. */
.musx-name-row { display: flex; gap: 14px; }
.musx-name-row .musx-input { flex: 1 1 0; min-width: 0; }
@media (max-width: 420px) {
    .musx-name-row { flex-direction: column; gap: 0; }
}

.musx-input::placeholder { color: rgba(26,31,58,.72); font-weight: 400; }  /* .42 measured 2.54:1 on the field ground */
.musx-input:hover { background: #eef0f6; }
.musx-input:focus {
    outline: none;
    background: #ffffff;
    border-color: var(--musx-orange);
    box-shadow: 0 0 0 4px rgba(255,107,43,.14);
}

/* Autofill overrides — match the grey fill so the field doesn't repaint a noisy
   Chrome/Safari blue when the browser autofills the email. Inset shadow technique
   wins over Safari's gradient, transition is parked long enough never to fire. */
.musx-input:-webkit-autofill,
.musx-input:-webkit-autofill:hover,
.musx-input:-webkit-autofill:focus,
.musx-input:-webkit-autofill:active,
.musx-input:autofill,
.musx-input:autofill:hover,
.musx-input:autofill:focus,
.musx-input:autofill:active {
    -webkit-text-fill-color: #1a1f3a !important;
    color: #1a1f3a !important;
    -webkit-box-shadow: 0 0 0 1000px #f4f5f9 inset !important;
    box-shadow: 0 0 0 1000px #f4f5f9 inset !important;
    background-color: #f4f5f9 !important;
    background-image: none !important;
    background-clip: content-box !important;
    -webkit-background-clip: content-box !important;
    caret-color: #1a1f3a !important;
    transition: background-color 600000s 0s, color 600000s 0s, -webkit-text-fill-color 600000s 0s !important;
    animation: none !important;
}

/* Submit — full-width, generous padding, soft orange drop shadow so it floats slightly
   off the white card. Active state nudges it down 1px for tactile feedback. */
.musx-cert-btn {
    display: block;
    width: 100%;
    padding: 16px 20px;
    margin-top: 4px;
    background: var(--musx-orange);
    color: #fff;
    border: 0;
    border-radius: 12px;
    cursor: pointer;
    font: inherit;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.01em;
    box-shadow: 0 6px 18px rgba(255,107,43,.32);
    transition: background .15s ease, transform .08s ease, box-shadow .15s ease;
}
.musx-cert-btn:hover:not(:disabled) { background: #FF8048; box-shadow: 0 8px 22px rgba(255,107,43,.42); }
.musx-cert-btn:active:not(:disabled) { transform: translateY(1px); box-shadow: 0 3px 10px rgba(255,107,43,.28); }
.musx-cert-btn:disabled { cursor: default; opacity: .9; }
.musx-cert-btn-sent { background: #22c55e !important; box-shadow: 0 6px 18px rgba(34,197,94,.32) !important; }

.musx-form-status { margin-top: 10px; font-size: 13px; color: #dc2626; min-height: 16px; line-height: 1.4; }

/* Per-question results view removed 2026-08-31 — the review lives in the
   result email and the dashboard (email-capture lead magnet), so the
   in-player screen was unreachable dead code. */

.musx-loading { text-align: center; padding: 40px; color: rgba(255,255,255,.7); }

/* Mobile */
@media (max-width: 600px) {
    .musx-quiz-shell { padding: 12px 8px; }
    .musx-q-text { font-size: 18px; }
    .musx-grid-images { grid-template-columns: repeat(2, 1fr); }
}

/* ── Paid practice-exam gate (WS3) — shown on the white splash before a paid exam ───── */
.musx-gate-view {
    text-align: center;
    padding: 36px 20px 28px;
}
/* Gate is a utility screen — shrink the splash-sized logo to keep the whole
   gate within 100vh on normal viewports. The intro splash keeps the big 280px. */
.musx-gate-view .musx-intro-logo-img {
    width: 180px;
    margin-bottom: 20px;
}
.musx-gate-title { font-size: 26px; font-weight: 800; line-height: 1.2; color: var(--ink-800); margin-bottom: 10px; }
.musx-gate-desc {
    font-size: 16px; line-height: 1.55; color: #6c7280;
    max-width: 400px; margin: 0 auto 20px;
}
/* Scoped + !important on the box model: Divi styles bare <input> elements
   (float / display / width) with rules that beat a plain single-class
   selector — the same fight the email-form inputs had. This keeps the code
   field centred. */
.musx-quiz-shell .musx-gate-view input.musx-gate-input {
    display: block !important;
    float: none !important;
    width: 100% !important;
    max-width: 320px !important;
    margin: 0 auto !important;
    box-sizing: border-box;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 21px; font-weight: 600; text-align: center;
    letter-spacing: 2px; text-transform: uppercase;
    padding: 15px 16px;
    background: #f4f5f9; color: #1a1f3a;
    border: 2px solid transparent; border-radius: 12px;
    transition: border-color .15s ease, background .15s ease, box-shadow .15s ease;
    -webkit-appearance: none; appearance: none;
}
.musx-gate-input::placeholder { color: rgba(26,31,58,.38); font-weight: 400; letter-spacing: 1px; }
.musx-gate-input:focus {
    outline: none; background: #fff; border-color: var(--musx-orange);
    box-shadow: 0 0 0 4px rgba(255,107,43,.14);
}
.musx-gate-btn {
    display: block; margin: 16px auto 0;
    background: var(--musx-orange); color: #fff; border: 0; border-radius: 10px;
    padding: 15px 40px; font: inherit; font-size: 17px; font-weight: 700;
    letter-spacing: .3px; cursor: pointer;
    box-shadow: 0 6px 18px rgba(255,107,43,.30);
    transition: background .15s ease, transform .08s ease;
}
.musx-gate-btn:hover:not(:disabled) { background: #ff7836; transform: translateY(-1px); }
.musx-gate-btn:disabled { opacity: .6; cursor: default; }
.musx-gate-status { margin-top: 16px; font-size: 14px; min-height: 20px; line-height: 1.4; }
.musx-gate-status.musx-gate-ok  { color: #1a7f37; font-weight: 600; }
.musx-gate-status.musx-gate-err { color: #c0392b; }
@media (max-width: 480px) {
    .musx-gate-title { font-size: 22px; }
    .musx-gate-desc  { font-size: 15px; }
}

/* "Don't have a code? → store" link on the gate. Selling moved to /store/. */
.musx-gate-storelink {
    display: inline-block; margin-top: 22px;
    font-size: 14px; color: #6c7280; text-decoration: none;
    border-bottom: 1px solid #d4d4d8; padding-bottom: 1px;
}
.musx-gate-storelink:hover { color: var(--musx-orange); border-color: var(--musx-orange); }

/* "Tell your teacher" — result-screen card (student-sent mailto).
   Matches the result-email block: faint orange surface, orange left rule. */
.musx-teacher-slot { margin-top: 18px; }
.musx-teacher-card {
  padding: 16px 18px;
  /* EXPLICIT light surface — do NOT reintroduce var(--musx-orange-tint) here.
     Inside the quiz shell that token resolves to rgba(254,80,0,.08): near
     transparent over the dark page, so this card's dark body text measured
     2.27:1 (WCAG AA wants 4.5) and Barry reported it unreadable. The card is
     designed to sit as a light card under the light cert form, mirroring the
     result-email block. Fixed 2026-07-27. */
  background: #fff1ea;
  border: 1px solid #ffd9c4;
  border-left: 4px solid var(--musx-orange, #fe5000);
  border-radius: 10px;
  text-align: left;
}
.musx-teacher-eyebrow {
  font-family: 'Saira', 'Montserrat', -apple-system, sans-serif;
  font-size: 10px; letter-spacing: 1.8px; text-transform: uppercase;
  /* Darker than brand #fe5000, which measures 2.99:1 on #fff1ea. The button
     and the left rule keep the true brand orange — this is a 10px label. */
  font-weight: 700; color: #c23a00; margin-bottom: 6px;  /* 4.9:1 */
}
.musx-teacher-copy { margin: 0 0 12px; font-size: 14px; color: #3d4457; line-height: 1.5; }  /* 8.8:1 */
.musx-teacher-add-form { display: flex; gap: 8px; flex-wrap: wrap; }
/* Ancestor + element so it outranks the theme's input[type=email] rule, whose
   --paper token painted this field near-black in dark mode (Barry, 4 Sep 2026). */
.musx-teacher-card input.musx-teacher-add-input {
  flex: 1 1 200px; min-width: 0; padding: 11px 13px; font-size: 15px;
  border: 1.5px solid var(--musx-orange-soft, #ffd9c4); border-radius: 8px;
  background: #fff; color: #1a1a2e; outline: none;
}
.musx-teacher-card input.musx-teacher-add-input:focus { border-color: var(--musx-orange, #fe5000); }
.musx-teacher-btn {
  display: inline-block; padding: 11px 22px;
  background: var(--musx-orange, #fe5000); color: #fff; text-decoration: none;
  border: 0; border-radius: 8px; cursor: pointer;
  font-family: 'Saira', sans-serif; font-weight: 700; font-size: 14px; letter-spacing: .3px;
  transition: background .15s ease;
}
.musx-teacher-btn:hover { background: var(--musx-orange-hover, #e64600); color: #fff; }
.musx-teacher-note { margin-top: 10px; font-size: 12px; color: #5b6478; line-height: 1.5; }  /* 5.4:1 */

/* Visually-hidden labels for the capture fields (they were placeholder-only). */
.musx-vh { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
           overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }

/* Notation is the one image students must actually read; the 320px cap is
   right for a phone and wasteful on a desktop card (measured 320x189 in a
   638px card). Step it up above the tablet breakpoint. */
/* Desktop: widen the notation box to 460px.
   The three coupled boxes (wrap / <picture> / <img>) must move together — see the
   NO PERCENTAGE HEIGHTS note above. ONLY max-width changes here: the absolute
   height stays, so the CLS reservation and the object-fit letterboxing both
   survive. 460px is not a new number — musx-quiz.js already ships
   sizes="(min-width: 760px) 460px, 320px", so until now the browser downloaded the
   960w candidate sized for a 460px box and then painted it at 320px.
   Was: .musx-q-img, .musx-question-img, .musx-img-wrap img — three classes the
   player has never rendered, so this rule matched nothing (found 2026-08-31). */
@media (min-width: 760px) {
    .musx-q-image-wrap picture,
    .musx-q-image { max-width: 460px; }
}

/* ───────────────────────────────────────────────────────────────────
   Token isolation for the player's LIGHT card (2026-08-31).

   The quiz card is hard-coded `background:#fff` and does not (yet)
   participate in the site's light/dark system. But it *inherits* the
   theme's tokens — and in dark mode theme.css redefines --ink-800 to
   #e9e8f0 (near-white, correct for dark grounds). The result was the
   quiz title rendering near-white on the white card: 1.22:1, the
   product's own name effectively invisible (found 2026-08-31).

   Until the player joins the theme system, it pins the light-ground
   values for the tokens it consumes, so a white card always gets ink
   text no matter what the page theme is doing.
   ─────────────────────────────────────────────────────────────────── */
.musx-quiz-shell,
.musx-quiz-container {
    --ink-800: #1a1a2e;
    --ink-900: #0f0f1f;
    --neutral-600: #4b5470;
    --neutral-500: #6c7591;
    --musx-orange-ink: #b83a00;
}

/* Phones get the 800w piano backdrop — 31 KB instead of 71 KB. */
@media (max-width: 700px) {
    .musx-quiz-shell::before {
        background-image:
            linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)),
            image-set(url('img/musx_girl_piano-800.webp') type('image/webp'),
                      url('img/musx_girl_piano.jpg')      type('image/jpeg'));
    }
}


/* ═══════════════════════════════════════════════════════════════════
   APP MODE — the phone skin (2026-09-03).
   Applied by musx-quiz.js when the viewport is ≤700px (`.is-app-mode` on
   the shell). Purely presentational: every node below already exists and
   behaves exactly as on desktop. Spec: _meta/mobile-quiz-skin-spec-2026-09-03.md
   Design source: Claude Design "Music quiz mobile app" handoff.
   ─────────────────────────────────────────────────────────────────── */

/* Desktop-only bits that app mode introduces: keep them inert elsewhere. */
.musx-header-count { display: none; }
.musx-app-footer   { display: none; }
.musx-swipe { display: block; }

/* ── Shell / container ─────────────────────────────────────────────── */
/* Full-bleed: the theme's content column pads the shell 20px each side, which
   showed as darker bands beside the navy. Centre on the parent, not 100vw. */
body:has(.musx-quiz-shell.is-app-mode) { background: #1a1a2e; }
.musx-quiz-shell.is-app-mode {
    max-width: none; width: 100vw; margin: 0 calc(50% - 50vw); padding: 0 !important;
    min-height: 100vh; min-height: 100dvh;     /* dvh: the browser toolbar */
    justify-content: flex-start;
    background: #1a1a2e;
    font-family: var(--font-body, 'Montserrat', system-ui, sans-serif);
    color: #fff;
}
.musx-quiz-shell.is-app-mode::before { display: none; }   /* no photo backdrop */
.musx-quiz-shell.is-app-mode .musx-quiz-container {
    width: 100%; max-width: 480px; margin: 0 auto;
    min-height: 100vh; min-height: 100dvh;
    display: flex; flex-direction: column;
    border: 0; border-radius: 0; box-shadow: none;
    background: transparent;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    overflow: visible;
    padding: calc(env(safe-area-inset-top, 0px) + 20px) clamp(16px, 5vw, 24px)
             calc(env(safe-area-inset-bottom, 0px) + 10px);
}
.musx-quiz-shell.is-app-mode.musx-shell-intro .musx-quiz-container {
    background: transparent; box-shadow: none;
}
.musx-quiz-shell.is-app-mode .musx-quiz-card {
    background: transparent; border: 0; padding: 0; min-height: 0;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    flex: 1 1 auto; display: flex; flex-direction: column;
}
.musx-quiz-shell.is-app-mode .musx-intro-view,
.musx-quiz-shell.is-app-mode .musx-question-view,
.musx-quiz-shell.is-app-mode .musx-score-view {
    flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0;
}
.musx-quiz-shell.is-app-mode .musx-quiz-card > [hidden] { display: none !important; }

/* ── Header row: bowtie · title · "n / total" ──────────────────────── */
.musx-quiz-shell.is-app-mode .musx-quiz-header {
    order: 0; margin: 0; opacity: 1; gap: 12px;
}
.musx-quiz-shell.is-app-mode .musx-logo { order: 0; padding: 0; }
.musx-quiz-shell.is-app-mode .musx-logo img {
    height: 22px !important; max-height: 22px !important;
}
.musx-quiz-shell.is-app-mode .musx-quiz-header-title {
    order: 1; display: block; flex: 1 1 auto; min-width: 0; margin: 0;
    font-size: 15px; font-weight: 600; color: #fff;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.musx-quiz-shell.is-app-mode .musx-header-actions { order: 2; flex: 0 0 auto; gap: 0; }
.musx-quiz-shell.is-app-mode .musx-header-count {
    display: block;
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-weight: 600; font-size: 14px; color: rgba(255,255,255,.72);
    font-variant-numeric: tabular-nums;
}
.musx-quiz-shell.is-app-mode .musx-fs-btn,
.musx-quiz-shell.is-app-mode .musx-quiz-header .musx-back-link { display: none; }

/* ── Progress: thin bar, no label, no chip (chip lives in the footer) ── */
.musx-quiz-shell.is-app-mode .musx-progress-row { margin: 16px 0 0; gap: 0; }
.musx-quiz-shell.is-app-mode .musx-progress-row .musx-streak-chip,
.musx-quiz-shell.is-app-mode .musx-progress-label { display: none; }
.musx-quiz-shell.is-app-mode .musx-progress-track { height: 4px; }
.musx-quiz-shell.is-app-mode .musx-progress-seg   { height: 4px; }

/* ── Question ──────────────────────────────────────────────────────── */
.musx-quiz-shell.is-app-mode .musx-swipe {
    flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0;
    touch-action: pan-y; user-select: none; -webkit-user-select: none;
    will-change: transform;
    transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1);
}
.musx-quiz-shell.is-app-mode .musx-q-number { display: none; }
.musx-quiz-shell.is-app-mode .musx-q-text {
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-weight: 600; font-size: clamp(21px, 6vw, 26px);
    line-height: 1.2; letter-spacing: -0.02em;
    padding-top: 22px; margin: 0;
}
/* Full-bleed white notation band: cancels the container's side padding. */
.musx-quiz-shell.is-app-mode .musx-q-image-wrap {
    margin: 16px calc(-1 * clamp(16px, 5vw, 24px)) 0;
    width: auto; max-width: none;
    height: clamp(100px, 20vh, 180px);
    background: #fff; border-radius: 0;
    padding: 8px 10px;
    display: flex; align-items: center; justify-content: center;
    overflow: hidden; flex: 0 0 auto;
}
.musx-quiz-shell.is-app-mode .musx-q-image-wrap:empty { display: none; }
.musx-quiz-shell.is-app-mode .musx-q-image-wrap picture {
    width: auto; max-width: 100%; height: 100%;
    display: flex; align-items: center; justify-content: center;
}
.musx-quiz-shell.is-app-mode .musx-q-image {
    width: auto; max-width: 100%; height: 100%; max-height: 100%;
    padding: 0; margin: 0; border-radius: 0; background: #fff;
    object-fit: contain;
}
.musx-quiz-shell.is-app-mode .musx-options-grid { margin: 16px 0 0; gap: 10px; }
.musx-quiz-shell.is-app-mode .musx-grid-images { gap: 16px; }
.musx-quiz-shell.is-app-mode .musx-grid-text-short { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.musx-quiz-shell.is-app-mode .musx-grid-text { grid-template-columns: 1fr; }
.musx-quiz-shell.is-app-mode .musx-option-card {
    background: rgba(255,255,255,.06);
    border: 1px solid rgba(255,255,255,.12);
    border-radius: 12px; min-height: 52px; padding: 12px 14px;
    justify-content: center; text-align: center;
    font-size: clamp(17px, 4.5vw, 20px); font-weight: 600;
    gap: 8px; box-shadow: none;
    transition: box-shadow 220ms cubic-bezier(0.22,1,0.36,1),
                border-color 220ms cubic-bezier(0.22,1,0.36,1),
                transform 120ms cubic-bezier(0.22,1,0.36,1);
}
.musx-quiz-shell.is-app-mode .musx-option-label { font-size: inherit; }
.musx-quiz-shell.is-app-mode .musx-option-card:hover:not(:disabled) {
    background: rgba(255,255,255,.06); transform: none;      /* no sticky hover on touch */
}
.musx-quiz-shell.is-app-mode .musx-option-card:active:not(:disabled) { transform: scale(.97); }
.musx-quiz-shell.is-app-mode .musx-option-card:disabled { opacity: 1; }
/* Text answers: state is a 2px inset ring, never a tinted fill, and the other
   options are never dimmed (both rejected in design review). */
.musx-quiz-shell.is-app-mode .musx-option-card.musx-correct {
    background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.12);
    box-shadow: inset 0 0 0 2px #2bb673;
}
.musx-quiz-shell.is-app-mode .musx-option-card.musx-wrong {
    background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.12);
    box-shadow: inset 0 0 0 2px #d6314b;
}
/* Exam mode: the chosen option locks in neutrally (no right/wrong) — orange ring. */
.musx-quiz-shell.is-app-mode .musx-option-card.musx-chosen {
    background: rgba(254,80,0,.10); border-color: rgba(255,255,255,.12);
    box-shadow: inset 0 0 0 2px #fe5000;
}
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card.musx-chosen {
    background: #fff; border-color: #fe5000; box-shadow: 0 0 10px 1px rgba(255,255,255,.55);
}
/* Image answers: white cell, 2px navy border in EVERY state (no layout shift),
   colour swap + soft white glow on state. */
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card {
    background: #fff; border: 2px solid #1a1a2e; border-radius: 12px;
    padding: 0; gap: 0; aspect-ratio: 4 / 3; overflow: hidden;
    min-height: 0;
}
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card:hover:not(:disabled) { background: #fff; }
/* line-height/font-size 0 + hidden <source>: kills the stray line box that
   otherwise pushes the <img> ~24px down inside the cell (measured 28px). */
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card picture {
    display: block; width: 100%; height: 100%; line-height: 0; font-size: 0;
}
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card picture > source { display: none; }
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-image {
    width: 100%; height: 100%; aspect-ratio: auto;
    object-fit: contain; padding: 6px; border-radius: 0; background: #fff;
}
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-label { display: none; }
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card.musx-correct {
    background: #fff; border-color: #2bb673; box-shadow: 0 0 10px 1px rgba(255,255,255,.55);
}
.musx-quiz-shell.is-app-mode .musx-grid-images .musx-option-card.musx-wrong {
    background: #fff; border-color: #d6314b; box-shadow: 0 0 10px 1px rgba(255,255,255,.55);
}
/* Filled 22px badge, top-right, white glyph. */
.musx-quiz-shell.is-app-mode .musx-status-badge {
    top: 6px; right: 6px; width: 22px; height: 22px;
    align-items: center; justify-content: center;
    box-shadow: 0 1px 4px rgba(0,0,0,.25); z-index: 1;
}
.musx-quiz-shell.is-app-mode .musx-option-card.musx-correct .musx-status-badge { display: flex; background: #2bb673; }
.musx-quiz-shell.is-app-mode .musx-option-card.musx-wrong   .musx-status-badge { display: flex; background: #d6314b; }
.musx-quiz-shell.is-app-mode .musx-option-card.musx-correct .musx-status-badge::before,
.musx-quiz-shell.is-app-mode .musx-option-card.musx-wrong   .musx-status-badge::before {
    color: #fff; font-size: 13px; font-weight: 700; line-height: 1;
}
/* Feedback text stays in the DOM for screen readers (role=status), off-screen. */
.musx-quiz-shell.is-app-mode .musx-feedback-bar {
    position: absolute; width: 1px; height: 1px; min-height: 0;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* Bottom row: the Continue pill only after a wrong answer (a correct one
   auto-advances). */
.musx-quiz-shell.is-app-mode .musx-bottom-row {
    justify-content: center; margin: 12px 0 14px; min-height: 44px; flex: 0 0 auto;
}
.musx-quiz-shell.is-app-mode .musx-next-btn {
    display: none; align-items: center; justify-content: center;
    background: rgba(255,255,255,.08); border: 1px solid rgba(255,255,255,.16);
    border-radius: 999px; color: #fff; font-size: 14px; font-weight: 600;
    padding: 10px 22px; min-height: 44px; box-shadow: none;
}
.musx-quiz-shell.is-app-mode .musx-bottom-row.musx-row-continue .musx-next-btn { display: inline-flex; }
.musx-quiz-shell.is-app-mode .musx-next-btn:hover:not(:disabled) { background: rgba(255,255,255,.14); }

/* ── Footer: streak chip · exit link ───────────────────────────────── */
.musx-quiz-shell.is-app-mode .musx-app-footer {
    display: flex; align-items: center; flex: 0 0 auto;
    margin-top: auto; padding: 8px 0 0;           /* Continue pill sat on the rule (Barry, 3 Sep) */
    border-top: 1px solid rgba(255,255,255,.1);
}
.musx-quiz-shell.is-app-mode .musx-app-footer .musx-streak-chip { margin-right: auto; }
.musx-quiz-shell.is-app-mode .musx-app-exit {
    margin-left: auto; display: inline-block;
    font-size: 13px; font-weight: 600; color: rgba(255,255,255,.52);
    text-decoration: none; padding: 10px 0;                 /* ≥40px target, footer reserve trimmed */
}
.musx-quiz-shell.is-app-mode .musx-app-exit:hover { color: #fff; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-app-exit { display: none; }

/* ── Intro ─────────────────────────────────────────────────────────── */
.musx-quiz-shell.is-app-mode .musx-intro-view {
    text-align: left; padding: clamp(28px, 8vh, 56px) 0 8px;
}
.musx-quiz-shell.is-app-mode .musx-intro-view img.musx-intro-logo-img {
    order: 0; width: clamp(120px, 32vw, 170px); max-width: none;
    margin-left: 0 !important; margin-right: auto !important;
    margin-bottom: auto !important;                          /* pushes text down */
}
.musx-quiz-shell.is-app-mode .musx-intro-meta {
    order: 1; display: flex; flex-direction: column; gap: 10px; margin: 24px 0 0;
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-weight: 600; font-size: clamp(11px, 3vw, 12px);
    letter-spacing: .12em; text-transform: uppercase; color: rgba(255,255,255,.72);
}
.musx-quiz-shell.is-app-mode .musx-eyebrow-sub {
    letter-spacing: .02em; text-transform: none; color: rgba(255,255,255,.52);
}
.musx-quiz-shell.is-app-mode .musx-intro-title {
    order: 2; color: #fff;
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-weight: 700; font-size: clamp(32px, 10vw, 44px);
    line-height: 1.05; letter-spacing: -0.02em; margin: 16px 0 18px;
}
.musx-quiz-shell.is-app-mode .musx-intro-desc {
    order: 3; font-size: clamp(15px, 4vw, 17px); line-height: 1.5;
    color: rgba(255,255,255,.72); max-width: none; margin: 0 0 16px;
}
.musx-quiz-shell.is-app-mode .musx-intro-tipline { order: 3; margin: -8px 0 16px; }
.musx-quiz-shell.is-app-mode .musx-tipline-right { color: #86efac; }
.musx-quiz-shell.is-app-mode .musx-tipline-wrong { color: #fca5a5; }
.musx-quiz-shell.is-app-mode .musx-intro-chips { order: 4; display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 28px; }
.musx-quiz-shell.is-app-mode .musx-intro-chips[hidden] { display: none; }
.musx-quiz-shell.is-app-mode .musx-intro-chip {
    padding: 6px 12px; border-radius: 999px;
    background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.12);
    font-size: 13px; font-weight: 600; color: rgba(255,255,255,.72);
    font-variant-numeric: tabular-nums;
}
.musx-quiz-shell.is-app-mode .musx-intro-guidelines { order: 5; max-width: none; margin: 0 0 24px; }
.musx-quiz-shell.is-app-mode .musx-guide-head,
.musx-quiz-shell.is-app-mode .musx-guide-sections-head { color: #fff; }
.musx-quiz-shell.is-app-mode .musx-guide-rules,
.musx-quiz-shell.is-app-mode .musx-guide-sections { color: rgba(255,255,255,.72); }
.musx-quiz-shell.is-app-mode .musx-start-btn {
    order: 6; width: 100%; min-height: 52px; padding: 14px 20px;
    border-radius: 16px; font-size: clamp(16px, 4.5vw, 18px);
    box-shadow: 0 4px 14px rgba(254,80,0,.32), inset 0 1px 0 rgba(255,255,255,.2);
}
/* Exam cover: the guidelines + section list already overflow a phone, so the
   quiz cover's lower-half composition (top padding, logo auto-margin) only adds
   blank space above the wordmark. Start at the top and set the lists tighter. */
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-intro-view { padding-top: 4px; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-intro-view img.musx-intro-logo-img {
    margin-top: 0 !important; margin-bottom: 18px !important;
}
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-intro-meta  { margin-top: 0; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-intro-title { font-size: clamp(26px, 8vw, 36px); margin: 10px 0 14px; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-intro-guidelines { margin-bottom: 18px; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-guide-head { font-size: 18px; margin-bottom: 8px; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-guide-rules,
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-guide-sections { font-size: 14px; line-height: 1.5; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-guide-rules { margin-bottom: 14px; }
.musx-quiz-shell.is-app-mode.is-exam-mode .musx-guide-sections-head { font-size: 15px; margin-bottom: 6px; }
/* The paid-exam code gate keeps its light card, on the navy page. */
.musx-quiz-shell.is-app-mode .musx-gate-view {
    background: #fff; border-radius: 18px; margin-top: 24px;
}

/* ── Result ────────────────────────────────────────────────────────── */
.musx-quiz-shell.is-app-mode .musx-score-view {
    align-items: center; padding-top: clamp(24px, 6vh, 48px);
}
.musx-quiz-shell.is-app-mode .musx-score-ring-wrap {
    width: clamp(120px, 32vw, 160px); height: clamp(120px, 32vw, 160px); margin: 0 auto 14px;
}
.musx-quiz-shell.is-app-mode .musx-score-ring-wrap svg { width: 100%; height: 100%; }
.musx-quiz-shell.is-app-mode .musx-score-title,
.musx-quiz-shell.is-app-mode.musx-reveal-band .musx-score-title,
.musx-quiz-shell.is-app-mode.musx-reveal-full .musx-score-title {
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-weight: 700; font-size: clamp(26px, 7vw, 34px);
    letter-spacing: -0.02em; line-height: 1.1; margin-top: 0;
}
.musx-quiz-shell.is-app-mode .musx-score-subtitle { font-size: 15px; margin-bottom: 16px; }
.musx-quiz-shell.is-app-mode .musx-email-form {
    width: 100%; max-width: none; border-radius: 18px;
    padding: 22px 20px 20px; margin: 8px 0 0; text-align: left;
    box-shadow: 0 12px 40px rgba(0,0,0,.32);
}
.musx-quiz-shell.is-app-mode .musx-email-form .musx-input {
    padding: 14px 16px !important;        /* the sheet's own padding is !important */
    border-radius: 12px; font-size: 16px;    /* 16px: no iOS zoom */
    line-height: 1.3; height: auto; min-height: 0;
}
/* First + last stay side by side on phones (the desktop sheet stacks them
   under 420px); at 298px of card width each field is ~140px, enough for the
   placeholder. */
.musx-quiz-shell.is-app-mode .musx-name-row { flex-direction: row; gap: 10px; }
.musx-quiz-shell.is-app-mode .musx-name-row .musx-input { margin: 0 0 12px; }
.musx-quiz-shell.is-app-mode .musx-cert-btn {
    min-height: 54px; padding: 14px 20px !important; font-size: 16px; line-height: 1.3; border-radius: 16px;
}
.musx-quiz-shell.is-app-mode .musx-prediction-slot,
.musx-quiz-shell.is-app-mode .musx-teacher-slot { width: 100%; }

@media (prefers-reduced-motion: reduce) {
    .musx-quiz-shell.is-app-mode .musx-swipe { transition: none !important; transform: none !important; }
    .musx-quiz-shell.is-app-mode .musx-option-card { transition: none; }
}

/* ── Identify-once (4 Sep 2026) ──────────────────────────────────────
   A returner's form is one tap: name + email stay in the DOM, prefilled and
   hidden; the button names the masked address. First-timers see the extra
   line about the dashboard. */
.musx-email-form .musx-form-dash { font-size: 13px; line-height: 1.45; color: rgba(26,31,58,.6); margin: -6px 0 14px; }
.musx-email-form.musx-form-returner .musx-name-row,
.musx-email-form.musx-form-returner .musx-input-email,
.musx-email-form.musx-form-returner .musx-form-dash,
.musx-email-form.musx-form-returner .musx-input-role.musx-role-remembered { display: none; }

.musx-teacher-card input.musx-teacher-add-input {
    background: #ffffff; color: #1a1f3a; border-color: #e6dccf; color-scheme: light;
}
.musx-teacher-card input.musx-teacher-add-input::placeholder { color: rgba(26,31,58,.55); }
.musx-teacher-card { color-scheme: light; }

/* The prediction meter is server-rendered inline-styled HTML built for EMAIL,
   where there is no stylesheet. Dropped into the page it inherits the theme's
   `.musx-content td { border: 1px solid …; padding: 10px 16px }`, which drew a
   line around every cell of the progress bar and inflated an 8px bar to ~40px.
   The inline styles carry background and width, so only these two need
   neutralising — and only here, so the emailed copy is untouched. */
.musx-prediction-slot table { border-collapse: collapse; }
.musx-prediction-slot td {
    border: 0 !important;
    padding: 0 !important;
    background-clip: padding-box;
}

/* ── "One area to work on" tip (6 Sep 2026) ──────────────────────────
   Light card on the navy result screen, same reasoning as .musx-teacher-card:
   a tinted token over this ground measures ~2.27:1 and is unreadable. Two
   tiers share the shell; 'focus' takes the orange left rule (there is
   something to fix), 'next' stays quiet blue-grey (there is not). */
.musx-tip-card {
  margin-top: 12px; padding: 16px 18px;
  background: #f2f4f9; border: 1px solid #dfe3ee;
  border-left: 4px solid #6c7591;
  border-radius: 10px; text-align: left; color-scheme: light;
}
/* Focus keeps the NEUTRAL ground and signals urgency through the rule, eyebrow
   and button only. It sits between the prediction meter and the teacher card,
   both of which are #fff1ea — three tinted cards in a row read as one
   undifferentiated orange block (the "box within a box" note, 3 Sep). */
.musx-tip-card--focus { border-left-color: var(--musx-orange, #fe5000); }
.musx-tip-eyebrow {
  font-family: 'Saira', 'Montserrat', -apple-system, sans-serif;
  font-size: 10px; letter-spacing: 1.8px; text-transform: uppercase;
  font-weight: 700; color: #4b5470; margin-bottom: 6px;          /* 7.4:1 on #f2f4f9 */
}
.musx-tip-card--focus .musx-tip-eyebrow { color: #c23a00; }      /* 4.9:1 on #fff1ea */
.musx-tip-copy { margin: 0 0 12px; font-size: 14px; color: #3d4457; line-height: 1.5; }
.musx-tip-btn {
  display: inline-block; padding: 11px 22px; border-radius: 8px; text-decoration: none;
  background: #4b5470; color: #fff;
  font-family: 'Saira', sans-serif; font-weight: 700; font-size: 14px; letter-spacing: .3px;
  transition: background .15s ease;
}
.musx-tip-btn:hover { background: #3d4457; color: #fff; }
.musx-tip-card--focus .musx-tip-btn { background: var(--musx-orange, #fe5000); }
.musx-tip-card--focus .musx-tip-btn:hover { background: var(--musx-orange-hover, #e64600); }
.musx-quiz-shell.is-app-mode .musx-tip-slot { width: 100%; }

/* Teacher note: Send (mailto) + Copy side by side; Copy is the Android-safe path. */
.musx-teacher-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 8px; }
.musx-teacher-btn--ghost { background: transparent; color: var(--musx-orange-ink, #b83a00); border: 1.5px solid var(--musx-orange, #fe5000); cursor: pointer; font: inherit; }
.musx-teacher-btn--ghost:hover { background: var(--musx-orange, #fe5000); color: #fff; }

/* The role selector is hidden by attribute on banks without capture_role, but
   the .musx-input display rule above outranked the UA [hidden] style, so it
   showed on every bank (Barry's screenshot, 4 Sep 2026). */
.musx-email-form .musx-input[hidden] { display: none !important; }

/* ── Optional teacher email on the capture form (6 Sep 2026) ─────────
   Separated from the required fields by a full-bleed hairline so it reads as
   a second, lesser ask rather than a fourth hurdle. "Optional" LEADS the
   label (Barry's call) — the same marker the post-submit card now carries,
   so both asks are visibly optional. Nothing here may ever block a submit. */
.musx-email-form .musx-form-teacher {
    border-top: 1px solid #ecedf2;
    margin: 16px -26px 14px;      /* the card's own 26px side padding */
    padding: 14px 26px 0;
}
.musx-form-teacher-label { display: flex; align-items: baseline; gap: 8px; margin: 0 0 8px; flex-wrap: wrap; }
.musx-form-teacher-opt {
    font-family: var(--font-display, 'Saira', system-ui, sans-serif);
    font-size: 10px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase;
    color: var(--musx-orange-ink, #b83a00);   /* 4.9:1 on the white card */
}
.musx-form-teacher-label label { font-size: 14px; font-weight: 600; color: #1a1f3a; }
/* separator between the OPTIONAL chip and the label, so the pair reads as one
   line ("Optional · Tell your teacher") rather than two loose items. */
.musx-form-teacher-sep { color: rgba(26,31,58,.35); font-size: 13px; line-height: 1; }
.musx-email-form .musx-form-teacher .musx-input { margin-bottom: 8px; }
.musx-form-teacher-help { font-size: 12px; line-height: 1.5; color: rgba(26,31,58,.55); margin: 0 !important; }
/* App mode: the sheet pads 20px, so the hairline pulls to that instead. */
.musx-quiz-shell.is-app-mode .musx-email-form .musx-form-teacher { margin: 14px -20px 12px; padding: 14px 20px 0; }
/* A returner keeps the teacher ask — it is the whole point of the merge that
   everyone sees it, and their name/email are already known. :not([hidden]) is
   load-bearing: without it this display:block outranks the UA [hidden] rule and
   the block stays on screen after submit. Same trap as .musx-input[hidden]
   below, which bit on 4 Sep. */
.musx-email-form.musx-form-returner .musx-form-teacher:not([hidden]) { display: block; }

/* Teacher promo — shown INSTEAD of the teacher-email block when the visitor
   answers "teacher" on the role select. Same hairline-and-inset shape as the
   block it replaces, so the form does not jump when they swap.
   `:not([hidden])` is load-bearing here for the same reason as the rule above:
   a bare `display:block` outranks the UA `[hidden]` rule, and the promo would
   then be permanently visible to students too. */
.musx-email-form .musx-teacher-promo {
    border-top: 1px solid #ecedf2;
    margin: 16px -26px 14px;
    padding: 14px 26px 0;
}
.musx-email-form.musx-form-returner .musx-teacher-promo:not([hidden]) { display: block; }
.musx-teacher-promo-lead {
    font-size: 12.5px; line-height: 1.55; color: rgba(26,31,58,.66);
    margin: 0 0 8px !important;
}
.musx-teacher-promo-lead strong { color: #1a1f3a; font-weight: 700; }
.musx-teacher-promo-link {
    display: inline-block; margin-top: 2px;
    font-size: 13px; font-weight: 700; text-decoration: none;
    color: var(--musx-orange-ink, #b83a00);   /* 5.2:1 on the white card */
}
.musx-teacher-promo-link:hover { text-decoration: underline; }
.musx-quiz-shell.is-app-mode .musx-email-form .musx-teacher-promo { margin: 14px -20px 12px; padding: 14px 20px 0; }

.musx-email-form .musx-form-teacher[hidden] { display: none !important; }

/* Ungated result (4 Sep 2026): the exact percentage sits in the ring. */
.musx-reveal-full .musx-score-title { margin-top: 10px; }
.musx-quiz-shell.is-app-mode .musx-score-number { font-size: clamp(26px, 8vw, 36px); }



/* "Did you mean …@gmail.com?" under an email field (18 Oct 2026). Ancestor-
   qualified so the host form's input rules cannot reach the button. Orange is the
   a darker ink than --musx-orange-aa: #cc3e00 measures 4.47:1 on the peach teacher
   card (#fff1ea), under AA; #a33200 is 6.3:1 there and 7.0:1 on white. */
.musx-quiz-shell .musx-email-suggest { font-size: 13px; line-height: 1.45; color: #1a1f3a; margin: 0 0 10px !important; }
.musx-quiz-shell .musx-email-suggest[hidden] { display: none; }
.musx-quiz-shell .musx-email-suggest strong { font-weight: 700; display: inline-block; max-width: 100%; overflow-wrap: anywhere; }
.musx-quiz-shell .musx-email-suggest .musx-email-suggest-yes {
    appearance: none; background: none; border: 0; padding: 0 2px; margin: 0; min-height: 0; width: auto;
    font: inherit; font-weight: 700; color: #a33200; text-decoration: underline;
    text-underline-offset: 2px; cursor: pointer; box-shadow: none;
}
.musx-quiz-shell .musx-email-suggest .musx-email-suggest-yes:hover,
.musx-quiz-shell .musx-email-suggest .musx-email-suggest-yes:focus-visible { color: #7d2600; }
