/* Maths Made Easy — light themes.
 *
 * Two production themes, written from scratch. The dev-review preview themes in
 * dev-themes.css are untouched: they are temporary, dark-only, gated behind
 * DEVELOPER_REVIEW_MODE and not deployed. Nothing here derives from them.
 *
 * A theme is a complete redefinition of the colour-bearing custom properties.
 * There are 33 of them across style.css and math-theme.css (some are declared
 * in both), and every one is set below, plus --surface and --accent, which are
 * used with hardcoded fallbacks but declared nowhere, and the three .fx-flow
 * surface tokens. The six geometry/typography properties (--radius,
 * --radius-sm, --font, --font-display, --safe-top, --safe-bottom) are
 * deliberately NOT touched: this is a colour change, not a layout change.
 *
 * THE TRAP, AND WHY EVERY TOKEN MATTERS
 *   The dark theme builds depth out of translucent WHITE over a dark ground:
 *   --surface-a05 through --surface-a12, --bg-card, --bg-card-hover and
 *   --gradient-surface are all rgba(255,255,255,...). Every one of those is
 *   invisible on a light background. They are re-expressed here as translucent
 *   INK over light, which is the same idea inverted. Missing even one leaves an
 *   element that simply disappears.
 *
 * CONTRAST
 *   Every accent below was measured against both its own background and the
 *   card colour, and clears WCAG 2.1 SC 1.4.11 (3:1 for graphics and UI) with
 *   margin; text and muted text clear SC 1.4.3 (4.5:1). Measurements are in the
 *   report accompanying this change.
 */

/* ══════════════════════════════════════════════════════════════════════════
   Theme A — Daylight.  Cool, bright, the specified blue/sky palette.
   ══════════════════════════════════════════════════════════════════════════ */
html[data-theme="light-day"] {
  /* ground and surfaces */
  --bg-deep: #f8fafc;
  --bg-mid: #eaf0f8;
  --bg-card: #ffffff;
  --bg-card-hover: #f1f5f9;

  /* Translucent ink, not translucent white — see THE TRAP above. */
  --surface-a05: rgba(23, 32, 51, 0.035);
  --surface-a06: rgba(23, 32, 51, 0.05);
  --surface-a08: rgba(23, 32, 51, 0.07);
  --surface-a10: rgba(23, 32, 51, 0.1);
  --surface-a12: rgba(23, 32, 51, 0.14);

  /* Shadows on light must be far softer or everything looks bruised. */
  --shadow-a20: rgba(23, 32, 51, 0.08);
  --shadow-a25: rgba(23, 32, 51, 0.12);
  --shadow: 0 10px 30px rgba(23, 32, 51, 0.1);
  --shadow-glow: 0 0 30px rgba(37, 99, 235, 0.12);

  /* text */
  --text: #172033;
  --text-muted: #55637d;

  /* section accents, all darkened from their dark-theme values so they hold
     contrast against white rather than glowing on it.
     --accent-tutorial was #2563eb, which clears 4.5:1 on plain white but only
     reaches 4.19:1 once it sits on its own pale tint — and that is where it is
     actually used, for the trial banner link, the tutorial cross-links and the
     Listen button. Measured on the rendered page, not against white. */
  --accent-tutorial: #1d4ed8;
  --accent-practice: #15803d;
  --accent-test: #92400e;   /* labels the plan badge: was 4.12:1 on it */
  --accent-games: #7c3aed;
  --accent-progress: #be1858;

  /* accent alphas track the primary */
  --accent-a15: rgba(37, 99, 235, 0.12);
  --accent-a20: rgba(37, 99, 235, 0.16);
  --accent-a35: rgba(37, 99, 235, 0.28);
  --accent-a40: rgba(37, 99, 235, 0.32);
  --accent-a50: rgba(37, 99, 235, 0.42);

  /* brand gradient, darkened so it reads as a shape on white */
  --gradient-brand: linear-gradient(135deg, #3b6fd4 0%, #7c5cd6 45%, #d64a7a 100%);
  --gradient-surface: linear-gradient(145deg, rgba(23, 32, 51, 0.05), rgba(23, 32, 51, 0.015));

  /* math-theme.css tokens.
     --accent-gold was #b45309: 4.12:1 on the grey plan badge it labels, so
     just short. Darkened until that real pairing clears 4.5. */
  --accent-gold: #92400e;
  --accent-cyan: #0e7490;
  --accent-math: #2563eb;
  --gradient-hero: linear-gradient(145deg, rgba(37, 99, 235, 0.1) 0%, rgba(124, 58, 237, 0.06) 45%, rgba(2, 132, 199, 0.05) 100%);
  --math-grid-color: rgba(37, 99, 235, 0.06);
  --math-grid-major: rgba(37, 99, 235, 0.11);

  /* Pip. His SVG reads these, so he retunes with the theme rather than
     staying a dark-theme character sitting on a white page. */
  --pip-grad-start: #3b6fd4;
  --pip-grad-mid: #7c5cd6;
  --pip-grad-end: #d64a7a;
  --pip-accent: #b45309;
  --pip-face: #0b1020;

  /* Tokens that are USED with a hardcoded dark fallback but never defined on
     :root, so a light theme would not reach them. Found by auditing every
     var() in the CSS against the :root declarations, not by eye — the
     milestone card was measurably still #1a1f3a on a light page. */
  --surface: #ffffff;
  --accent: #2563eb;

  color-scheme: light;
}

/* ══════════════════════════════════════════════════════════════════════════
   Theme B — Sunrise.  Warm: terracotta primary, teal secondary.
   A genuinely different hue family from Daylight, not a re-tint of it.
   ══════════════════════════════════════════════════════════════════════════ */
html[data-theme="light-warm"] {
  --bg-deep: #fdfbf7;
  --bg-mid: #f6efe4;
  --bg-card: #ffffff;
  --bg-card-hover: #faf5ed;

  --surface-a05: rgba(43, 29, 18, 0.035);
  --surface-a06: rgba(43, 29, 18, 0.05);
  --surface-a08: rgba(43, 29, 18, 0.07);
  --surface-a10: rgba(43, 29, 18, 0.1);
  --surface-a12: rgba(43, 29, 18, 0.14);

  --shadow-a20: rgba(43, 29, 18, 0.08);
  --shadow-a25: rgba(43, 29, 18, 0.12);
  --shadow: 0 10px 30px rgba(43, 29, 18, 0.1);
  --shadow-glow: 0 0 30px rgba(194, 65, 12, 0.12);

  --text: #2b1d12;
  --text-muted: #6b5442;

  /* Darkened for the same reason as Daylight's: measured on its own tint. */
  --accent-tutorial: #9a3412;
  --accent-practice: #0f766e;
  --accent-test: #854d0e;   /* as Daylight: was 4.04:1 on the plan badge */
  --accent-games: #9333ea;
  --accent-progress: #be123c;

  --accent-a15: rgba(194, 65, 12, 0.12);
  --accent-a20: rgba(194, 65, 12, 0.16);
  --accent-a35: rgba(194, 65, 12, 0.28);
  --accent-a40: rgba(194, 65, 12, 0.32);
  --accent-a50: rgba(194, 65, 12, 0.42);

  --gradient-brand: linear-gradient(135deg, #3b6fd4 0%, #7c5cd6 45%, #d64a7a 100%);
  --gradient-surface: linear-gradient(145deg, rgba(43, 29, 18, 0.05), rgba(43, 29, 18, 0.015));

  --accent-gold: #854d0e;   /* as Daylight: measured on the plan badge */
  --accent-cyan: #0f766e;
  --accent-math: #c2410c;
  --gradient-hero: linear-gradient(145deg, rgba(194, 65, 12, 0.1) 0%, rgba(161, 98, 7, 0.06) 45%, rgba(15, 118, 110, 0.05) 100%);
  --math-grid-color: rgba(194, 65, 12, 0.06);
  --math-grid-major: rgba(194, 65, 12, 0.11);

  --pip-grad-start: #3b6fd4;
  --pip-grad-mid: #7c5cd6;
  --pip-grad-end: #d64a7a;
  --pip-accent: #b45309;
  --pip-face: #0b1020;

  /* Tokens that are USED with a hardcoded dark fallback but never defined on
     :root, so a light theme would not reach them. Found by auditing every
     var() in the CSS against the :root declarations, not by eye — the
     milestone card was measurably still #1a1f3a on a light page. */
  --surface: #ffffff;
  --accent: #c2410c;

  color-scheme: light;
}

/* The lesson flow scopes its own surface tokens to .fx-flow rather than :root,
   and three of them are hardcoded translucent WHITE. On a light page those
   render as nothing at all, so every phase card loses its ground. They are
   re-expressed here as translucent ink, matching the rest of the theme. */
html[data-theme="light-day"] .fx-flow {
  --fx-surface: rgba(23, 32, 51, 0.045);
  --fx-surface-2: rgba(23, 32, 51, 0.075);
  --fx-line: rgba(23, 32, 51, 0.12);
}

html[data-theme="light-warm"] .fx-flow {
  --fx-surface: rgba(43, 29, 18, 0.045);
  --fx-surface-2: rgba(43, 29, 18, 0.075);
  --fx-line: rgba(43, 29, 18, 0.12);
}

/* The decorative maths background is drawn for a dark sky; on light it turns
   into muddy smears. Dim it rather than removing it, so the page keeps its
   texture without fighting the content. */
html[data-theme^="light-"] .bg-math-rays,
html[data-theme^="light-"] .bg-math-ring,
html[data-theme^="light-"] .bg-math-symbol,
html[data-theme^="light-"] .bg-math-geo {
  opacity: 0.22;
}

/* Buttons that assumed a dark page put near-black text on a bright fill.
   That still holds on light, so only the ghost variants need a nudge. */
html[data-theme^="light-"] .cert-btn--ghost,
html[data-theme^="light-"] .game-play-btn--secondary {
  color: var(--text-muted);
  border-color: var(--surface-a12);
}

/* ══════════════════════════════════════════════════════════════════════════
   PAINTED COLOUR THAT NEVER CAME FROM A TOKEN

   Everything above re-points tokens. None of it reaches a rule that writes a
   colour literally, and the audit that signed off these themes only compared
   declared tokens against :root — so it reported "no missing variables" while
   the page rendered almost entirely dark. What follows was found instead by
   rendering all nine screens under both light themes, sampling the pixels of
   each render against the theme's own --bg-deep, and walking every element for
   computed colour, rather than by reading the stylesheets again.

   Each block below names what was measured. Dark-theme rendering is untouched:
   every selector here is scoped to html[data-theme^="light-"].
   ══════════════════════════════════════════════════════════════════════════ */

/* THE WASH. body's background-image ends with
     linear-gradient(180deg, #050818 0%, #080d24 40%, var(--bg-deep) 100%)
   — only the LAST stop was ever tokenised. On a light theme the page therefore
   stays near-black from the top down to 40% and only then fades to the light
   ground, which is the diagonal-looking dark wash. Measured: 48 of 48
   background samples on every light screen were darker than --bg-deep, the
   worst by 0.92 luminance, sampling rgb(8,14,40) where #f8fafc was expected.

   The four accent washes above it are tuned to glow on black; on white they go
   muddy. Both are restated here in the theme's own hues. */
html[data-theme="light-day"] body {
  background-image:
    radial-gradient(ellipse 120% 80% at 50% -40%, rgba(37, 99, 235, 0.1), transparent 55%),
    radial-gradient(ellipse 80% 60% at 100% 20%, rgba(124, 58, 237, 0.07), transparent 50%),
    radial-gradient(ellipse 70% 55% at 0% 80%, rgba(14, 116, 144, 0.07), transparent 50%),
    radial-gradient(ellipse 50% 40% at 80% 90%, rgba(180, 83, 9, 0.05), transparent 45%),
    linear-gradient(180deg, #ffffff 0%, #f2f6fb 45%, var(--bg-deep) 100%);
}

html[data-theme="light-warm"] body {
  background-image:
    radial-gradient(ellipse 120% 80% at 50% -40%, rgba(194, 65, 12, 0.09), transparent 55%),
    radial-gradient(ellipse 80% 60% at 100% 20%, rgba(161, 98, 7, 0.07), transparent 50%),
    radial-gradient(ellipse 70% 55% at 0% 80%, rgba(15, 118, 110, 0.07), transparent 50%),
    radial-gradient(ellipse 50% 40% at 80% 90%, rgba(147, 51, 234, 0.05), transparent 45%),
    linear-gradient(180deg, #ffffff 0%, #fbf6ee 45%, var(--bg-deep) 100%);
}

/* The blurred ambient orbs are mid-tone and 70px-blurred, sized to glow on a
   dark sky. Over a light one they read as smudges of haze, which is the second
   half of what the fog looked like. Kept, but well back. */
html[data-theme^="light-"] .bg-orb {
  opacity: 0.16;
}

/* THE MODAL. math-theme.css paints .modal with a literal dark navy gradient
   and a 0.65-alpha black shadow, and style.css has its own literal beneath it.
   Neither is a token, so a light theme never reached them: the tutorial topics
   list rendered dark-navy while its text stayed at --text, which is near-black
   ink on these themes. That is the dark-on-dark report, and it is the same
   shape of bug as the --surface/--accent phantoms. */
html[data-theme^="light-"] .modal {
  background: linear-gradient(165deg, #ffffff 0%, var(--bg-card-hover) 100%);
  box-shadow:
    0 32px 90px var(--shadow-a25),
    0 0 0 1px var(--surface-a12);
}

/* The scrim stays dark on purpose: it is what separates the dialog from the
   page, and it needs to on a light ground too. Only lightened enough that the
   page reads as present behind it rather than switched off. */
html[data-theme^="light-"] .modal::backdrop {
  background: rgba(23, 32, 51, 0.45);
}

/* THE TOAST. Literal rgba(20, 24, 48, 0.95) with a white hairline. Measured at
   1.08:1 against --text on Sunrise, which is illegible: badge unlocks and
   Pip's nudges were dark ink on a dark slab. */
html[data-theme^="light-"] .reward-toast {
  background: rgba(255, 255, 255, 0.97);
  border-color: var(--surface-a12);
  box-shadow: 0 12px 40px var(--shadow-a25);
}

/* Lesson-flow phase cards carry a literal black drop shadow and the figures a
   literal rgba(0,0,0,0.16) ground — six phase cards' worth of dark bruising
   down the tutorial page. */
html[data-theme^="light-"] .fx-phase {
  box-shadow: 0 10px 30px var(--shadow-a20);
}

html[data-theme^="light-"] .fx-figure {
  background: var(--surface-a05);
}

/* THE GAME. The arena opts out of the page entirely: body.game-page is a
   literal #0d0520 and .game-arena a literal purple-black gradient, so the game
   stayed dark under both light themes while its text followed the theme. */
html[data-theme^="light-"] body.game-page {
  background: var(--bg-deep);
}

html[data-theme^="light-"] .game-arena {
  background: linear-gradient(165deg, #ffffff 0%, var(--bg-mid) 45%, var(--bg-deep) 100%);
}

html[data-theme^="light-"] .game-arena__glow {
  opacity: 0.18;
}

/* GRADIENT-CLIPPED HEADINGS. Every large title paints a white-to-pale gradient
   into the glyphs and sets color:transparent. On a light ground that is white
   text on white — the titles measured 1.00:1, i.e. invisible. --gradient-brand
   is already re-pointed above, so the ones that use it recover on their own;
   these are the ones with the gradient written out in place. */
html[data-theme^="light-"] .header__title,
html[data-theme^="light-"] .auth-card__title,
html[data-theme^="light-"] .tutorial__title,
html[data-theme^="light-"] .game-intro__title,
html[data-theme^="light-"] .reward-milestone__lead,
html[data-theme^="light-"] .test-score__marks strong {
  background: var(--gradient-brand);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* The floating symbols default to color: var(--bg-card), which is white here,
   so four of the twelve vanished and the rest went pale. Re-tinted to ink so
   the texture survives; opacity is already pulled back above. */
html[data-theme^="light-"] .bg-math-symbol {
  color: var(--text-muted);
  text-shadow: none;
}

/* ── RECESSED SURFACES ─────────────────────────────────────────────────────
   Thirty-seven rules across nine stylesheets ground a panel with a literal
   background: rgba(0, 0, 0, α). On a dark page that is a subtle recess. On a
   light one it is a grey slab: alpha 0.2 renders #cccccc and alpha 0.45
   renders #8c8c8c, which is why the badges looked faded and the buttons washed
   out. The text over them still clears WCAG, so this is not a legibility
   failure, but it is the wrong surface everywhere it appears.

   Enumerated rather than guessed: the list comes from scanning the committed
   stylesheets for that exact declaration, so it covers rules on screens this
   audit never opened. Each is re-pointed to the translucent-ink token nearest
   its original alpha, which is what the rest of the theme already uses.
   ──────────────────────────────────────────────────────────────────────── */

/* α 0.14 - 0.20 */
html[data-theme^="light-"] .fx-q,
html[data-theme^="light-"] .fx-figure,
html[data-theme^="light-"] .fx-order__line,
html[data-theme^="light-"] .frac-bar,
html[data-theme^="light-"] .frac-card,
html[data-theme^="light-"] .example-box,
html[data-theme^="light-"] .compare-numbers__card,
html[data-theme^="light-"] .groups-demo__group,
html[data-theme^="light-"] .fdp-card,
html[data-theme^="light-"] .fdp-trio,
html[data-theme^="light-"] .ratio-beads,
html[data-theme^="light-"] .shape-card,
html[data-theme^="light-"] .unit-pair,
html[data-theme^="light-"] .bottle-demo__bottle,
html[data-theme^="light-"] .test-q__option,
html[data-theme^="light-"] .rewards-badge,
html[data-theme^="light-"] .rewards-avatar {
  background: var(--surface-a06);
}

/* α 0.22 - 0.25 */
html[data-theme^="light-"] .audio-panel__btn,
html[data-theme^="light-"] .frac-stack,
html[data-theme^="light-"] .pv-chart,
html[data-theme^="light-"] .pct-grid,
html[data-theme^="light-"] .clock-face__dial,
html[data-theme^="light-"] .practice-q__btn,
html[data-theme^="light-"] .test-score__solutions-btn,
html[data-theme^="light-"] .rewards-stat,
html[data-theme^="light-"] .download-card__steps,
html[data-theme^="light-"] .role-student-card,
html[data-theme^="light-"] .progress-topic {
  background: var(--surface-a08);
}

/* α 0.28 - 0.30 */
html[data-theme^="light-"] .col-math,
html[data-theme^="light-"] .auth-demo[open] {
  background: var(--surface-a10);
}

/* α 0.35 - 0.45 */
html[data-theme^="light-"] .game-exit,
html[data-theme^="light-"] .game-intro__rules,
html[data-theme^="light-"] .game-stat,
html[data-theme^="light-"] .game-results__card,
html[data-theme^="light-"] .rewards-hero__bar {
  background: var(--surface-a12);
}

/* Entry fields are the exception: they were rgba(0, 0, 0, 0.32), which on a
   light page is a mid grey that reads as disabled rather than editable. They
   get the card colour and a visible edge instead. */
html[data-theme^="light-"] .fx-numinput__box,
html[data-theme^="light-"] .fx-fracinput__box,
html[data-theme^="light-"] .auth-field__input:focus {
  background: var(--bg-card);
  border-color: var(--surface-a12);
}

/* Billing uses its own navy literals rather than black, which is why a scan
   for rgba(0,0,0,α) alone did not find them: the account page and the pricing
   panel stayed dark slabs under both light themes. The upgrade panel is on the
   test screen too, so a trial student meets it without visiting billing. */
html[data-theme^="light-"] .pricing-card,
html[data-theme^="light-"] .account-card,
html[data-theme^="light-"] .success-card {
  background: var(--bg-card);
  border-color: var(--surface-a12);
}

html[data-theme^="light-"] .pricing-card--featured {
  background: linear-gradient(160deg, var(--bg-card) 0%, var(--bg-card-hover) 100%);
}

html[data-theme^="light-"] .license-input {
  background: var(--bg-card);
  border-color: var(--surface-a12);
}

/* Billing also writes its body text as #c8d4f0, a pale blue-grey meant for a
   navy card. Against the white card above it measured 1.49:1 — the plan
   features, the account rows and the licence table were all near-invisible.
   The white on the filled buttons is correct and stays. */
html[data-theme^="light-"] .pricing-card__features li,
html[data-theme^="light-"] .pricing-license-note,
html[data-theme^="light-"] .account-row,
html[data-theme^="light-"] .license-table th,
html[data-theme^="light-"] .license-table td {
  color: var(--text);
}

/* The error alert is #ff9090 on a 10%-red wash: fine on navy, 1.89:1 on a
   light one, which is the least legible thing to render illegibly. */
html[data-theme^="light-"] .billing-alert--error {
  color: #b91c1c;
  background: rgba(185, 28, 28, 0.08);
}

/* The numbered step bullet paints color:#04102c onto the accent disc — near
   black on a strong blue, 3.64:1. White on that disc measures 5.17:1. */
html[data-theme^="light-"] .fx-steps__n {
  color: #ffffff;
}

/* The tier names and the Complete pill in the Progress modal were written for
   a dark panel: #e8a870, #d6dcea and #ffd98a on a light card, with a #4ade80
   pill. The silver name measured barely above the background. Re-inked here
   for the light panel; the medals themselves keep their own colours. */
html[data-theme^="light-"] .rewards-tier--bronze .rewards-tier__name { color: #9a4f12; }
html[data-theme^="light-"] .rewards-tier--silver .rewards-tier__name { color: #4b5566; }
html[data-theme^="light-"] .rewards-tier--gold .rewards-tier__name { color: #8a5a00; }

html[data-theme^="light-"] .rewards-tier__done {
  color: #166534;
  background: rgba(22, 101, 52, 0.12);
}

/* ══════════════════════════════════════════════════════════════════════════
   The theme picker itself.
   ══════════════════════════════════════════════════════════════════════════ */
.theme-picker {
  position: relative;
  flex-shrink: 0;
  margin-right: 0.5rem;
}

.theme-picker__btn {
  font: inherit;
  font-size: 0.85rem;
  font-weight: 700;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 12px;
  border-radius: 10px;
  color: var(--text-muted);
  background: var(--surface-a08);
  border: 1px solid var(--surface-a12);
}

.theme-picker__btn:hover { color: var(--text); }

.theme-picker__swatch {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  border: 1px solid var(--surface-a12);
  background: var(--gradient-brand);
}

.theme-picker__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 60;
  min-width: 178px;
  padding: 6px;
  border-radius: 12px;
  background: var(--bg-card);
  border: 1px solid var(--surface-a12);
  box-shadow: var(--shadow);
}

.theme-picker__menu[hidden] { display: none; }

.theme-picker__option {
  font: inherit;
  font-size: 0.85rem;
  width: 100%;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border: 0;
  border-radius: 8px;
  cursor: pointer;
  text-align: left;
  color: var(--text);
  background: none;
}

.theme-picker__option:hover { background: var(--surface-a08); }

.theme-picker__option[aria-checked="true"] {
  background: var(--accent-a15);
  font-weight: 700;
}

.theme-picker__dot {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid var(--surface-a12);
}

.theme-picker__dot--dark { background: linear-gradient(135deg, #0a1030, #6c9eff); }
.theme-picker__dot--light-day { background: linear-gradient(135deg, #f8fafc 45%, #2563eb); }
.theme-picker__dot--light-warm { background: linear-gradient(135deg, #fdfbf7 45%, #c2410c); }

@media (prefers-reduced-motion: reduce) {
  .theme-picker__btn,
  .theme-picker__option { transition: none; }
}
