/* ==========================================================================
   Eliza's Math Dashboard — design system
   --------------------------------------------------------------------------
   A clean, modern product UI: an indigo brand, a calm neutral surface palette,
   layered hairline shadows, and consistent radii/spacing tokens. The kid game
   keeps its colorful subject tiles (now refined), while the grown-ups area
   reads like a real analytics dashboard. Fills an iPad-mini screen, app-like.

   Markup is generated in app.js / game.js / grownups.js with fixed class
   names — this file only restyles those classes (no structural assumptions
   were changed). A few legacy custom-property names are kept as aliases
   because some inline styles in the JS still reference them (--good, --bad…).
   ========================================================================== */

/* Inter, self-hosted (public/fonts) so there's no third-party request — better
   privacy for a kids' app and it works fully offline. These are the variable
   woff2 files (latin + latin-ext subsets) covering the whole weight axis. */
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/inter-latinext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  color-scheme: light;

  /* ----- Brand (indigo → violet) ----- */
  --brand-50:  #eef2ff;
  --brand-100: #e0e7ff;
  --brand-400: #818cf8;
  --brand-500: #6366f1;
  --brand-600: #4f46e5;
  --brand-700: #4338ca;
  --brand:      var(--brand-600);
  --brand-soft: var(--brand-50);
  /* Signature gradient — a deep indigo→violet sweep used on every "hero"
     surface (logo, primary button, progress, brand mark) for one cohesive,
     premium accent. Defined once so the whole product reads from one source. */
  --g-brand:      linear-gradient(140deg, #6366f1 0%, #6d40e6 52%, #7c3aed 100%);
  --g-brand-rev:  linear-gradient(140deg, #7c3aed 0%, #6366f1 100%);
  --accent:       #7c3aed;
  --ring: 0 0 0 3px rgba(99, 102, 241, 0.28);

  /* ----- Surfaces & neutrals ----- */
  --bg:            #f4f5fa;
  --bg-soft:       #e9ebf5;
  --surface:       #ffffff;
  --surface-2:     #f7f8fc;
  --border:        #e6e8f1;
  --border-strong: #d6dae8;
  --card: var(--surface);            /* legacy alias used across older rules */

  /* ----- Text ----- */
  --ink:      #0f1629;   /* primary  */
  --ink-soft: #5a6378;   /* secondary */
  --ink-3:    #99a1b5;   /* tertiary / placeholder */

  /* ----- Semantic ----- */
  --good: #15a34a; --good-2: #22c55e; --good-soft: #dcfce7;
  --bad:  #dc2626; --bad-soft: #fee2e2;
  --warn: #d97706; --warn-soft: #fef3c7;
  --amber: #f59e0b;

  /* legacy background aliases (sticky activity header gradient, etc.) */
  --bg-1: var(--bg); --bg-2: var(--bg-soft);

  /* ----- Shadows (soft, layered) -----
     Premium depth = a crisp 1px contact shadow + a wide, very soft ambient
     one. Low opacities so cards feel like they float on light, not smudged. */
  --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.04), 0 2px 6px rgba(15, 23, 42, 0.06);
  --shadow-md: 0 1px 2px rgba(15, 23, 42, 0.05), 0 8px 22px -6px rgba(15, 23, 42, 0.12);
  --shadow-lg: 0 2px 4px rgba(15, 23, 42, 0.05), 0 22px 50px -12px rgba(15, 23, 42, 0.20);
  --shadow-xl: 0 4px 8px rgba(15, 23, 42, 0.06), 0 40px 80px -16px rgba(15, 23, 42, 0.28);
  /* Colored brand glow for hero CTAs/marks */
  --glow-brand: 0 10px 28px -6px rgba(99, 70, 229, 0.45);

  /* ----- Radii ----- */
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 22px;
  --radius: var(--r-xl);             /* legacy alias */

  /* ----- Rhythm (scales gently with the screen) ----- */
  --pad: clamp(16px, 2.6vmin, 30px);
  --gap: clamp(12px, 1.9vmin, 20px);

  --font-ui: 'Inter', ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

/* ==========================================================================
   Dark theme — applied when <html data-theme="dark"> is set (app.js resolves
   the user's choice of System / Light / Dark and toggles this attribute). The
   whole UI is variable-driven, so dark mode is mostly redefining the tokens;
   below the tokens are a few targeted fixes for components that hard-code
   light tints (pills, chips, the content-bank box, grade letters). The printed
   report (.pr-*) is intentionally left light — it's meant for white paper.
   ========================================================================== */
:root[data-theme="dark"] {
  color-scheme: dark;

  --brand-soft: rgba(99, 102, 241, 0.16);
  --ring: 0 0 0 3px rgba(129, 140, 248, 0.40);

  /* Surfaces & neutrals */
  --bg:            #0e1220;
  --bg-soft:       #161b2b;
  --surface:       #191f30;
  --surface-2:     #212a40;
  --border:        #2b3349;
  --border-strong: #3a4259;

  /* Text */
  --ink:      #e8ebf6;
  --ink-soft: #a7b0c6;
  --ink-3:    #717a93;

  /* Semantic — lighter ink + translucent soft fills that sit on dark cards */
  --good: #34d399; --good-2: #34d399; --good-soft: rgba(52, 211, 153, 0.16);
  --bad:  #f87171; --bad-soft:  rgba(248, 113, 113, 0.16);
  --warn: #fbbf24; --warn-soft: rgba(251, 191, 36, 0.16);
  --amber: #fbbf24;

  /* Shadows read as depth on dark, not as a grey haze */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40), 0 1px 3px rgba(0, 0, 0, 0.50);
  --shadow-md: 0 4px 10px rgba(0, 0, 0, 0.45), 0 10px 28px rgba(0, 0, 0, 0.50);
  --shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.60);
  --shadow-xl: 0 30px 70px rgba(0, 0, 0, 0.70);
}

/* Accent text that hard-codes the (too-dark-for-dark) brand-700 */
:root[data-theme="dark"] .term-pill.year,
:root[data-theme="dark"] .gp-nav button.active,
:root[data-theme="dark"] .range-tabs button.active { color: #a5b4fc; }
:root[data-theme="dark"] .term-pill.grade { color: #5eead4; }

/* Warm pills (streak / stars / summer) → translucent amber */
:root[data-theme="dark"] .streak-pill,
:root[data-theme="dark"] .stars-pill,
:root[data-theme="dark"] .term-pill.summer {
  background: rgba(251, 191, 36, 0.16); color: #fcd34d; border-color: rgba(251, 191, 36, 0.30);
}

/* Role / status chips */
:root[data-theme="dark"] .chip.role-owner  { background: rgba(124, 58, 237, 0.20); color: #c4b5fd; border-color: rgba(124, 58, 237, 0.40); }
:root[data-theme="dark"] .chip.role-parent { background: rgba(2, 132, 199, 0.20);  color: #7dd3fc; border-color: rgba(2, 132, 199, 0.40); }
:root[data-theme="dark"] .chip.role-child  { background: rgba(34, 197, 94, 0.18);  color: #86efac; border-color: rgba(34, 197, 94, 0.40); }
:root[data-theme="dark"] .chip.warn        { background: rgba(251, 191, 36, 0.16); color: #fcd34d; border-color: rgba(251, 191, 36, 0.40); }

/* Report-card grade letters (lighter so they pop on dark cards) */
:root[data-theme="dark"] .grade.g-a .g-letter { color: #4ade80; }
:root[data-theme="dark"] .grade.g-b .g-letter { color: #a3e635; }
:root[data-theme="dark"] .grade.g-c .g-letter { color: #fbbf24; }
:root[data-theme="dark"] .grade.g-d .g-letter { color: #fb923c; }

/* Content-bank staleness box */
:root[data-theme="dark"] .stale-box.level-fresh { background: rgba(34, 197, 94, 0.10);  border-color: rgba(34, 197, 94, 0.30); }
:root[data-theme="dark"] .stale-box.level-warn  { background: rgba(251, 191, 36, 0.10); border-color: rgba(251, 191, 36, 0.30); }
:root[data-theme="dark"] .stale-box.level-stale { background: rgba(248, 113, 113, 0.10); border-color: rgba(248, 113, 113, 0.30); }
:root[data-theme="dark"] .sb-badge.fresh { background: rgba(34, 197, 94, 0.22);  color: #86efac; }
:root[data-theme="dark"] .sb-badge.warn  { background: rgba(251, 191, 36, 0.22); color: #fcd34d; }
:root[data-theme="dark"] .sb-badge.stale { background: rgba(248, 113, 113, 0.22); color: #fca5a5; }

/* Inline error banner */
:root[data-theme="dark"] .auth-err { color: #fca5a5; border-color: rgba(248, 113, 113, 0.40); }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body { height: 100%; margin: 0; overscroll-behavior: none; }

body {
  font-family: var(--font-ui);
  /* Inter's stylistic sets: single-storey a, rounded numerals, tabular slashes
     — small touches that make the type look intentionally designed. */
  font-feature-settings: 'cv05' 1, 'cv11' 1, 'ss01' 1;
  color: var(--ink);
  background:
    radial-gradient(1200px 680px at 100% -10%, rgba(124, 58, 237, 0.12), transparent 58%),
    radial-gradient(1000px 640px at -12% 2%, rgba(99, 102, 241, 0.09), transparent 56%),
    radial-gradient(900px 700px at 50% 120%, rgba(20, 184, 166, 0.05), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  user-select: none;
  touch-action: manipulation;
}

/* Quiet, modern scrollbars for the dashboard areas */
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: #c2c7d8; background-clip: content-box; }

:focus-visible { outline: none; box-shadow: var(--ring); }

/* ----------  App shell  ---------- */
.app {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  gap: var(--gap);
  padding: max(var(--pad), env(safe-area-inset-top))
           max(var(--pad), env(safe-area-inset-right))
           max(var(--pad), env(safe-area-inset-bottom))
           max(var(--pad), env(safe-area-inset-left));
}

/* Kid mode (body.kid): lock the whole UI to exactly one screenful so Eliza
   never scrolls. The app is pinned to the viewport height and the scrollable
   question card absorbs any overflow internally, while the progress bar,
   feedback line and the "Next →" action button stay pinned and always visible.
   The grown-up dashboards keep min-height (they scroll on purpose). */
body.kid { overflow: hidden; }
body.kid .app { height: 100dvh; min-height: 0; }

/* …except on phones. A phone (narrow portrait, or short landscape) simply
   doesn't have the height the one-screenful lock assumes — pinning there
   CLIPPED content (the home cards' "Start" button, quiz choices) instead of
   showing it. On phones the kid UI still fills the screen, but anything that
   genuinely can't fit scrolls into reach instead of being cut off. Tablets
   and desktop keep the no-scroll lock. */
@media (max-width: 560px), (orientation: landscape) and (max-height: 560px) {
  body.kid { overflow: auto; }
  body.kid .app { height: auto; min-height: 100dvh; }
}

/* The kid quiz sizes to the available HEIGHT (dvh), not just width/vmin, so the
   prompt, answer box and especially the math keypad shrink to fit a short
   viewport (Safari chrome + the iPad dock eat vertical space) — the whole
   question, keypad and all, always fits one screen with no scrolling. The max
   values keep it big and comfortable on a tall screen. */
body.kid .quiz { gap: clamp(8px, 1.5dvh, 18px); }
body.kid .qcard { padding: clamp(12px, 2.4dvh, 30px); gap: clamp(10px, 1.8dvh, 22px); }
body.kid .prompt.equation { font-size: clamp(26px, 6.2dvh, 70px); }
body.kid .prompt.words { font-size: clamp(16px, 3dvh, 30px); }
body.kid .answer-display { font-size: clamp(22px, 4.6dvh, 52px); padding: 4px 20px; }
body.kid .keypad { gap: clamp(5px, 1.2dvh, 14px); }
body.kid .key { padding: clamp(6px, 1.35dvh, 18px) 0; font-size: clamp(17px, 3dvh, 32px); }
/* Box-builder cells shrink with height too */
body.kid .box { width: clamp(16px, min(4.4vmin, 4dvh), 40px); height: clamp(16px, min(4.4vmin, 4dvh), 40px); }
/* Reading/English: cap the passage so the question + choices + Next always fit */
body.kid .passage { max-height: clamp(120px, 26dvh, 280px); }
body.kid .choice { padding: clamp(9px, 1.7dvh, 17px) clamp(16px, 2.6vmin, 20px); }

/* ----------  Top bar  ---------- */
.topbar {
  display: flex;
  align-items: center;
  gap: clamp(10px, 1.6vmin, 16px);
  flex: 0 0 auto;
}
.greeting { flex: 1 1 auto; min-width: 0; }
.greeting h1 {
  margin: 0;
  font-size: clamp(20px, 4.2vmin, 34px);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.greeting .date {
  margin: 3px 0 0;
  font-size: clamp(12px, 2.1vmin, 16px);
  color: var(--ink-soft);
  font-weight: 500;
}

.screen-title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: clamp(19px, 3.6vmin, 28px);
  font-weight: 700;
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  gap: 10px;
}
.screen-title .st-emoji { font-size: 1.05em; }

.spacer { flex: 1 1 auto; }

/* Brand lockup used in the grown-ups header */
.brandbar { display: flex; align-items: center; gap: 12px; min-width: 0; }
.brandbar-mark {
  width: clamp(38px, 6vmin, 46px); height: clamp(38px, 6vmin, 46px);
  display: grid; place-items: center;
  border-radius: 13px;
  font-size: clamp(20px, 3.4vmin, 26px);
  background: var(--g-brand);
  box-shadow: var(--glow-brand), inset 0 1px 0 rgba(255, 255, 255, 0.30), inset 0 0 0 1px rgba(255, 255, 255, 0.08);
}
.brandbar-text { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.brandbar-name { font-weight: 700; font-size: clamp(16px, 2.8vmin, 20px); letter-spacing: -0.01em; }
.brandbar-sub { font-size: clamp(11px, 1.9vmin, 13px); color: var(--ink-soft); font-weight: 500; }

/* Icon buttons (header account/back, modal close) */
.iconbtn {
  flex: 0 0 auto;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  width: clamp(40px, 6.6vmin, 48px);
  height: clamp(40px, 6.6vmin, 48px);
  border-radius: 13px;
  font-size: clamp(17px, 2.8vmin, 21px);
  font-family: inherit;
  cursor: pointer;
  display: grid;
  place-items: center;
  box-shadow: var(--shadow-sm);
  transition: transform 0.12s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease;
}
@media (hover: hover) { .iconbtn:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); } }
.iconbtn:active { transform: scale(0.94); }
.iconbtn.gear { font-size: clamp(16px, 2.5vmin, 20px); }
.iconbtn.back { border-radius: 13px; }

/* Stars pill (kid header) */
.stars {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  background: linear-gradient(150deg, #fffaf0, #fff3da);
  border: 1px solid #fde9c2;
  color: #b45309;
  border-radius: 999px;
  padding: clamp(8px, 1.5vmin, 11px) clamp(13px, 2.2vmin, 18px);
  box-shadow: var(--shadow-sm);
  font-size: clamp(15px, 2.6vmin, 20px);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.stars .star-icon { font-size: 1.05em; line-height: 1; }
.stars.bump { animation: bump 0.4s ease; }
@keyframes bump { 0%,100%{transform:scale(1);} 40%{transform:scale(1.18);} }

/* ----------  Screen root  ---------- */
.screen-root { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }

/* ----------  Dashboard tile grid (kid home)  ---------- */
.grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 1fr;
}
/* Landscape column counts for the kid grids are handled by the symmetric
   "no dead space" system at the end of this file (keyed on data-count). */

.tile {
  position: relative;
  border: none;
  border-radius: var(--r-xl);
  padding: clamp(12px, 2.4vmin, 24px);
  color: #fff;
  font-family: inherit;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 1.4vmin, 14px);
  background: linear-gradient(155deg, var(--c1), var(--c2));
  box-shadow: 0 10px 24px var(--shadow, rgba(2, 6, 23, 0.16)), inset 0 1px 0 rgba(255, 255, 255, 0.22);
  transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
  opacity: 0;
  transform: translateY(14px) scale(0.97);
  animation: pop 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
  animation-delay: var(--delay, 0s);
}
/* soft top sheen for a premium, app-icon feel */
.tile::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0) 42%);
  pointer-events: none;
}
.tile:active { transform: scale(0.96); filter: brightness(1.04); }
@media (hover: hover) {
  .tile:not(.locked):hover { transform: translateY(-4px); box-shadow: 0 18px 36px var(--shadow, rgba(2, 6, 23, 0.22)), inset 0 1px 0 rgba(255, 255, 255, 0.22); }
}

.tile .icon {
  width: clamp(48px, 11vmin, 92px);
  height: clamp(48px, 11vmin, 92px);
  display: grid;
  place-items: center;
  border-radius: 22px;
  background: rgba(255, 255, 255, 0.20);
  border: 1px solid rgba(255, 255, 255, 0.28);
  font-size: clamp(26px, 6vmin, 50px);
  line-height: 1;
  box-shadow: inset 0 1px 4px rgba(255, 255, 255, 0.4);
}
.tile .label {
  font-size: clamp(15px, 2.7vmin, 25px);
  font-weight: 600;
  letter-spacing: 0.1px;
  text-align: center;
}

/* Locked (not today's) tiles — calm, not harsh */
.tile.locked {
  filter: saturate(0.55) brightness(0.99);
  opacity: 0.5;
  box-shadow: var(--shadow-sm);
  cursor: default;
}
.tile.locked .lock {
  position: absolute; top: 12px; right: 14px;
  font-size: clamp(13px, 2.2vmin, 18px); opacity: 0.95;
}

/* Today's glowing pick + bonus ribbon */
.tile.active-glow { animation: pop 0.5s cubic-bezier(0.22,1,0.36,1) forwards, glow 2s ease-in-out infinite; }
.tile .today-badge,
.tile .bonus-ribbon {
  position: absolute; top: 12px;
  background: rgba(255, 255, 255, 0.96);
  color: var(--c2);
  font-weight: 700;
  font-size: clamp(11px, 1.8vmin, 14px);
  padding: 4px 11px;
  border-radius: 999px;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.12);
}
.tile .today-badge { left: 12px; }
.tile .bonus-ribbon { right: 12px; }
@keyframes glow {
  0%,100% { box-shadow: 0 10px 24px var(--shadow), 0 0 0 0 rgba(255,255,255,0.0), inset 0 1px 0 rgba(255,255,255,.22); }
  50%     { box-shadow: 0 14px 30px var(--shadow), 0 0 0 6px rgba(255,255,255,0.34), inset 0 1px 0 rgba(255,255,255,.22); }
}
@keyframes pop { to { opacity: 1; transform: translateY(0) scale(1); } }

/* ----------  Subject screen: set cards  ---------- */
.sets {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(2, 1fr);
  grid-auto-rows: 1fr;
}
.set-card {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  cursor: pointer;
  padding: clamp(16px, 2.8vmin, 28px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(7px, 1.4vmin, 12px);
  box-shadow: var(--shadow-sm);
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
}
@media (hover: hover) { .set-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--border-strong); } }
.set-card:active { transform: scale(0.98); }
.set-card .set-icon {
  font-size: clamp(26px, 5vmin, 42px); line-height: 1;
  width: clamp(54px, 9vmin, 76px); height: clamp(54px, 9vmin, 76px);
  display: grid; place-items: center; border-radius: 18px;
  background: var(--brand-soft); color: var(--brand-700);
}
.set-card .set-name { font-size: clamp(16px, 2.7vmin, 24px); font-weight: 700; letter-spacing: -0.01em; text-align: center; }
.set-card .set-desc { font-size: clamp(12px, 2vmin, 16px); color: var(--ink-soft); text-align: center; }
.set-card .set-status { margin-top: 2px; font-size: clamp(12px, 2vmin, 15px); font-weight: 600; color: var(--ink-soft); }
.set-card.done { border-color: rgba(34, 197, 94, 0.55); background: linear-gradient(180deg, #f6fefa, var(--surface)); }
.set-card.done .set-status { color: var(--good); }
.set-card .done-check { position: absolute; top: 12px; right: 14px; font-size: clamp(15px, 2.4vmin, 20px); }

/* ----------  Quiz screen  ---------- */
.quiz { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; gap: var(--gap); }
.progress { flex: 0 0 auto; display: flex; align-items: center; gap: 14px; }
.progress .bar {
  flex: 1 1 auto;
  height: clamp(10px, 1.6vmin, 14px);
  background: var(--bg-soft);
  border-radius: 999px;
  overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06);
}
.progress .bar > i {
  display: block; height: 100%; width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--brand-500), var(--accent));
  box-shadow: 0 0 12px -2px rgba(124, 58, 237, 0.5);
  transition: width 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
.progress .count { flex: 0 0 auto; font-weight: 700; color: var(--ink-soft); font-size: clamp(14px, 2.4vmin, 19px); font-variant-numeric: tabular-nums; }

.qcard {
  flex: 1 1 auto;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  padding: clamp(16px, 3vmin, 32px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 2.4vmin, 24px);
  overflow-y: auto;
}
.prompt { text-align: center; font-weight: 600; line-height: 1.25; color: var(--ink); }
.prompt.equation { font-size: clamp(34px, 8vmin, 74px); font-weight: 700; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.prompt.words { font-size: clamp(19px, 3.6vmin, 30px); max-width: 24ch; color: var(--ink); }
.prompt .blank {
  display: inline-block; min-width: 1.4em;
  border-bottom: 4px solid var(--brand-500);
  color: var(--brand-600);
}

/* Answer entry: display + keypad */
.answer-display {
  font-size: clamp(28px, 6.6vmin, 56px);
  font-weight: 800;
  min-width: 2.6em;
  min-height: 1.3em;
  padding: 6px 24px;
  text-align: center;
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 140% at 50% 0%, var(--brand-soft), transparent 70%),
    var(--surface-2);
  color: var(--brand-700);
  border: 1px solid var(--brand-100);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  box-shadow: inset 0 1px 3px rgba(15, 23, 42, 0.06);
}
.answer-display.empty { color: var(--ink-3); border-color: var(--border-strong); background: var(--surface-2); }

.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(8px, 1.6vmin, 14px); width: min(380px, 88%); }
/* Tactile, slightly raised keys with a top sheen — satisfying to tap and a
   step up from flat buttons. */
.key {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: inherit;
  font-size: clamp(22px, 4.4vmin, 32px);
  font-weight: 700;
  padding: clamp(11px, 2.2vmin, 18px) 0;
  background: linear-gradient(180deg, var(--surface), var(--surface-2));
  color: var(--ink);
  cursor: pointer;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  transition: transform 0.1s ease, background 0.1s ease, box-shadow 0.1s ease, border-color 0.1s ease;
}
@media (hover: hover) { .key:hover { box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.6); border-color: var(--border-strong); transform: translateY(-1px); } }
.key:active { transform: scale(0.94); background: var(--bg-soft); box-shadow: inset 0 2px 5px rgba(15, 23, 42, 0.10); }
.key.enter { background: linear-gradient(150deg, var(--good-2), var(--good)); color: #fff; border: none; box-shadow: 0 8px 18px -4px rgba(22, 163, 74, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.3); }
.key.del { background: var(--surface); color: var(--bad); }

/* Box-builder grid */
.boxwrap { display: flex; flex-direction: column; align-items: center; gap: clamp(12px, 2vmin, 18px); width: 100%; }
.boxgrid { display: grid; gap: clamp(5px, 1vmin, 8px); justify-content: center; }
.box {
  width: clamp(20px, 4.4vmin, 40px);
  height: clamp(20px, 4.4vmin, 40px);
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--border-strong);
  cursor: pointer;
  transition: transform 0.08s ease, background 0.08s ease, border-color 0.08s ease;
}
.box:active { transform: scale(0.9); }
.box.filled { background: var(--g-brand); border-color: var(--brand-700); }
.box.filled.frac { background: linear-gradient(150deg, #fbbf24, #f97316); border-color: #f97316; }
.boxcount { font-size: clamp(15px, 2.6vmin, 22px); font-weight: 700; color: var(--ink-soft); }
.boxbtns { display: flex; gap: clamp(8px, 1.6vmin, 14px); flex-wrap: wrap; justify-content: center; }

/* ----------  Buttons  ---------- */
.btn {
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: inherit;
  font-size: clamp(15px, 2.6vmin, 18px);
  font-weight: 600;
  padding: clamp(11px, 1.9vmin, 15px) clamp(18px, 3vmin, 26px);
  cursor: pointer;
  transition: transform 0.1s ease, box-shadow 0.12s ease, background 0.12s ease, border-color 0.12s ease, filter 0.12s ease;
}
.btn:active { transform: scale(0.97); }
.btn.primary { background: var(--g-brand); color: #fff; box-shadow: var(--glow-brand), inset 0 1px 0 rgba(255, 255, 255, 0.18); }
@media (hover: hover) { .btn.primary:hover { filter: brightness(1.05) saturate(1.05); box-shadow: 0 14px 32px -6px rgba(99, 70, 229, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.18); transform: translateY(-1px); } }
.btn.secondary { background: var(--surface); color: var(--ink); border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
@media (hover: hover) { .btn.secondary:hover { border-color: #c7cce0; box-shadow: var(--shadow-md); } }
.btn.ghost { background: transparent; color: var(--ink-soft); }
@media (hover: hover) { .btn.ghost:hover { background: var(--bg-soft); color: var(--ink); } }

/* Feedback banner */
.feedback { flex: 0 0 auto; min-height: 1.2em; text-align: center; font-size: clamp(18px, 3.4vmin, 27px); font-weight: 700; }

/* Always-visible action slot at the bottom of a quiz. The "Next →" button after
   a wrong answer lives here — OUTSIDE the scrollable question card — so it can
   never be pushed off-screen. Empty between answers (collapses to nothing). */
.quiz-action { flex: 0 0 auto; display: flex; justify-content: center; }
.quiz-action:empty { display: none; }
.quiz-action .btn { min-width: clamp(200px, 60%, 320px); animation: continue-pop 0.22s cubic-bezier(0.18, 1.4, 0.4, 1) both; }
@keyframes continue-pop { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
.feedback.good { color: var(--good); }
.feedback.bad { color: var(--bad); }
.shake { animation: shake 0.4s ease; }
@keyframes shake { 0%,100%{transform:translateX(0);} 20%{transform:translateX(-8px);} 40%{transform:translateX(8px);} 60%{transform:translateX(-6px);} 80%{transform:translateX(6px);} }

/* ----------  Celebration overlay  ---------- */
.celebrate {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background: rgba(244, 245, 250, 0.78);
  backdrop-filter: blur(6px);
  z-index: 20;
}
.celebrate .card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: clamp(24px, 4vmin, 44px);
  text-align: center;
  box-shadow: var(--shadow-xl);
  display: flex; flex-direction: column; gap: clamp(10px, 2vmin, 18px);
  align-items: center; max-width: min(420px, 90vw);
}
.celebrate .big { font-size: clamp(40px, 9vmin, 80px); }
.celebrate .score { font-size: clamp(26px, 5vmin, 44px); font-weight: 800; letter-spacing: -0.02em; }
.celebrate .sub { color: var(--ink-soft); font-size: clamp(15px, 2.6vmin, 19px); }
.celebrate .actions { display: flex; gap: 12px; flex-wrap: wrap; justify-content: center; }

.confetti { position: absolute; top: -10px; font-size: 22px; animation: fall 1.6s linear forwards; }
@keyframes fall { to { transform: translateY(120vh) rotate(540deg); opacity: 0; } }

/* ==========================================================================
   Epic "day complete" victory — a full-screen, you-beat-the-game takeover the
   moment Math + Reading + English are ALL done for the day. Its own animated
   background (deep indigo→violet), a slowly spinning sunburst, a pulsing glow,
   a shower of confetti and a floating trophy. Lives above everything (z 200).
   ========================================================================== */
.epic {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  overflow: hidden; padding: 24px;
  background: radial-gradient(125% 125% at 50% 0%, #4f46e5 0%, #6d28d9 34%, #1e1b4b 72%, #0b0f1f 100%);
  animation: epic-in 0.45s ease both;
}
.epic.out { animation: epic-out 0.32s ease forwards; }
@keyframes epic-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes epic-out { to { opacity: 0; transform: scale(1.05); } }

/* Rotating sunburst rays */
.epic-rays {
  position: absolute; left: 50%; top: 42%; width: 240vmax; height: 240vmax;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(from 0deg, rgba(255, 255, 255, 0.06) 0deg 7deg, transparent 7deg 16deg);
  animation: epic-spin 24s linear infinite; pointer-events: none;
}
@keyframes epic-spin { to { transform: translate(-50%, -50%) rotate(360deg); } }

/* Soft pulsing color glow behind the card */
.epic-glow {
  position: absolute; left: 50%; top: 46%; width: 70vmin; height: 70vmin;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(251, 191, 36, 0.30), transparent 62%);
  filter: blur(10px); pointer-events: none;
  animation: epic-pulse 2.6s ease-in-out infinite;
}
@keyframes epic-pulse { 0%,100% { opacity: 0.55; transform: translate(-50%,-50%) scale(0.92); } 50% { opacity: 1; transform: translate(-50%,-50%) scale(1.08); } }

/* Confetti rain layer */
.epic-confetti { position: absolute; inset: 0; pointer-events: none; }
.epic-bit { position: absolute; top: -7%; will-change: transform, opacity; animation: epic-fall linear forwards; filter: drop-shadow(0 2px 3px rgba(0,0,0,0.2)); }
@keyframes epic-fall { to { transform: translateY(118vh) rotate(600deg); opacity: 0.85; } }

/* The trophy / score card */
.epic-card {
  position: relative; z-index: 1; text-align: center; color: #fff;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: clamp(24px, 4vmin, 44px); max-width: min(440px, 92vw);
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.20);
  border-radius: 28px;
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: 0 44px 100px -24px rgba(0, 0, 0, 0.65), inset 0 1px 0 rgba(255, 255, 255, 0.22);
  animation: epic-pop 0.6s cubic-bezier(0.18, 1.5, 0.4, 1) 0.08s both;
}
@keyframes epic-pop { from { opacity: 0; transform: translateY(34px) scale(0.85); } to { opacity: 1; transform: none; } }

.epic-badge {
  font-size: clamp(11px, 1.9vmin, 13px); font-weight: 800; letter-spacing: 0.16em; text-transform: uppercase;
  color: #fde68a; border: 1px solid rgba(253, 230, 138, 0.45); border-radius: 999px;
  padding: 5px 15px; background: rgba(253, 230, 138, 0.12);
}
.epic-trophy {
  font-size: clamp(64px, 16vmin, 124px); line-height: 1;
  filter: drop-shadow(0 12px 26px rgba(251, 191, 36, 0.55));
  animation: epic-trophy 2.4s ease-in-out infinite;
}
@keyframes epic-trophy { 0%,100% { transform: translateY(0) rotate(-4deg); } 50% { transform: translateY(-12px) rotate(4deg); } }

.epic-title {
  font-size: clamp(36px, 8.4vmin, 66px); font-weight: 900; letter-spacing: -0.02em; line-height: 1;
  background: linear-gradient(100deg, #fde68a 0%, #ffffff 25%, #a5b4fc 50%, #ffffff 75%, #fde68a 100%);
  background-size: 220% auto; -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: epic-shine 3s linear infinite;
}
@keyframes epic-shine { to { background-position: 220% center; } }
.epic-sub  { font-size: clamp(14px, 2.6vmin, 18px); font-weight: 700; opacity: 0.96; }
.epic-name { font-size: clamp(13px, 2.3vmin, 16px); opacity: 0.85; }

.epic-stats { display: flex; gap: 10px; margin: 8px 0 4px; flex-wrap: wrap; justify-content: center; }
.epic-stat {
  background: rgba(255, 255, 255, 0.10); border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 16px; padding: 10px 16px; min-width: 86px;
}
.epic-stat b { display: block; font-size: clamp(18px, 3.4vmin, 26px); font-weight: 900; font-variant-numeric: tabular-nums; }
.epic-stat b span { font-size: 0.6em; opacity: 0.7; }
.epic-stat small { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; opacity: 0.75; }
.epic-btn { margin-top: 8px; min-width: 200px; }

@media (prefers-reduced-motion: reduce) {
  .epic, .epic-card, .epic-trophy, .epic-title, .epic-rays, .epic-glow, .epic-bit { animation: none !important; }
}

/* ----------  Toast  ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: max(24px, env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(30px);
  background: #111827;
  color: #fff;
  padding: 13px 22px;
  border-radius: 14px;
  font-weight: 600;
  font-size: clamp(14px, 2.4vmin, 17px);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
  z-index: 60;
  max-width: 86vw;
  text-align: center;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ----------  Modal / sheet  ---------- */
.overlay {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, 0.42);
  backdrop-filter: blur(5px);
  display: grid; place-items: center;
  padding: 16px;
  z-index: 80;
}
.overlay[hidden] { display: none; }
.sheet {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  width: min(640px, 96vw);
  max-height: 92dvh;
  overflow-y: auto;
  padding: clamp(20px, 3vmin, 32px);
  box-shadow: var(--shadow-xl);
}
.sheet h2 { margin: 0 0 4px; font-size: clamp(21px, 3.6vmin, 28px); font-weight: 700; letter-spacing: -0.02em; }
.sheet .muted { color: var(--ink-soft); font-size: clamp(13px, 2.2vmin, 16px); margin: 0 0 14px; }
.sheet .close-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 8px; }

/* ----------  Segmented range tabs (report time range)  ---------- */
.range-tabs {
  display: inline-flex; gap: 3px; margin: 4px 0 16px;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  padding: 4px; border-radius: 999px;
  flex-wrap: wrap;
}
.range-tabs button {
  border: none; font-family: inherit; font-weight: 600;
  font-size: clamp(13px, 2.1vmin, 15px);
  padding: 8px 16px; border-radius: 999px;
  background: transparent; color: var(--ink-soft);
  cursor: pointer; transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease;
}
.range-tabs button:hover { color: var(--ink); }
.range-tabs button.active { background: var(--surface); color: var(--brand-700); box-shadow: var(--shadow-sm); }

/* Range row + previous/next year stepper (keeps the tab bar a fixed size) */
.range-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 16px; }
.range-row .range-tabs { margin: 0; }
.year-stepper {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 6px; box-shadow: var(--shadow-sm);
}
.ys-btn {
  border: none; background: var(--bg-soft); color: var(--ink);
  width: 30px; height: 30px; border-radius: 999px; cursor: pointer;
  font-size: 12px; display: grid; place-items: center; font-family: inherit;
  transition: background 0.14s ease, color 0.14s ease;
}
@media (hover: hover) { .ys-btn:hover:not([disabled]) { background: var(--brand-soft); color: var(--brand-700); } }
.ys-btn[disabled] { opacity: 0.35; cursor: default; }
.ys-label { font-weight: 600; font-size: clamp(13px, 2.1vmin, 15px); color: var(--ink); min-width: 104px; text-align: center; font-variant-numeric: tabular-nums; }
:root[data-theme="dark"] .ys-btn:hover:not([disabled]) { color: #a5b4fc; }

/* ----------  Assessment panel (weak/strong summary)  ----------
   The report's "executive summary" — given a touch more presence (a soft brand
   wash + card shadow) so it reads as the headline insight, not a side note. */
.assess {
  position: relative;
  background:
    radial-gradient(120% 140% at 0% 0%, var(--brand-soft), transparent 42%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: 18px 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-sm);
}
.assess-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 12px; }
.assess-title { font-weight: 800; font-size: clamp(15px, 2.4vmin, 17px); letter-spacing: -0.02em; }
.assess-range { font-size: clamp(11px, 1.8vmin, 12px); color: var(--ink-soft); font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }
.assess-empty { color: var(--ink-soft); font-size: clamp(13px, 2.1vmin, 14px); margin: 4px 0 0; }
.assess-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .assess-grid { grid-template-columns: 1fr; } }
.assess-block { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-md); padding: 12px 13px; }
.assess-block.thin { margin-top: 12px; }
.ab-title { font-weight: 700; font-size: clamp(13px, 2.1vmin, 14px); margin-bottom: 9px; }
.ab-sub { font-weight: 500; color: var(--ink-soft); font-size: 0.82em; }
.ab-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.ab-body { font-size: clamp(12px, 2vmin, 13px); color: var(--ink); line-height: 1.55; }
.ab-hint { color: var(--ink-soft); font-size: 0.92em; margin-top: 6px; }
.assess-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px; border-radius: 999px;
  font-size: clamp(12px, 2vmin, 13px); font-weight: 600;
  border: 1px solid var(--border-strong);
}
.assess-chip .ac-acc { font-variant-numeric: tabular-nums; font-weight: 700; }
.assess-chip.focus { background: var(--bad-soft); border-color: transparent; color: var(--bad); }
.assess-chip.strong { background: var(--good-soft); border-color: transparent; color: var(--good); }
.assess-none { font-size: clamp(12px, 2vmin, 13px); color: var(--ink-soft); }
.assess-plan {
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
  font-size: clamp(13px, 2.1vmin, 14px); line-height: 1.55; color: var(--ink);
}
.assess-plan .ap-label {
  display: inline-block; font-weight: 700; color: var(--brand-700);
  text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.82em; margin-right: 6px;
}
:root[data-theme="dark"] .assess-plan .ap-label { color: #a5b4fc; }

/* ----------  Stat / KPI cards  ----------
   Analytics-style metric cards: a colored accent rail on the leading edge, a
   bold tabular number, and a quiet uppercase label. Reads instantly as a real
   reporting dashboard. */
.stat-cards { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 18px; }
.stat-cards .sc {
  position: relative;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 15px 16px 14px 18px;
  overflow: hidden;
  transition: transform 0.14s ease, box-shadow 0.14s ease;
}
.stat-cards .sc::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(var(--brand-500), var(--accent));
  opacity: 0.85;
}
.stat-cards .sc.good::before { background: var(--good); }
.stat-cards .sc.bad::before  { background: var(--bad); }
@media (hover: hover) { .stat-cards .sc:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } }
.stat-cards .sc .n { font-size: clamp(23px, 4.2vmin, 32px); font-weight: 800; letter-spacing: -0.025em; line-height: 1.05; font-variant-numeric: tabular-nums; }
.stat-cards .sc .l { font-size: clamp(10.5px, 1.8vmin, 12px); color: var(--ink-soft); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; margin-top: 7px; }
.stat-cards .sc.good .n { color: var(--good); }
.stat-cards .sc.bad .n { color: var(--bad); }
@media (max-width: 460px) { .stat-cards { grid-template-columns: repeat(2, 1fr); } }

/* ----------  Tables  ---------- */
table.breakdown { width: 100%; border-collapse: collapse; font-size: clamp(13px, 2.1vmin, 15px); }
table.breakdown th, table.breakdown td { padding: 11px 12px; text-align: left; border-bottom: 1px solid var(--border); }
table.breakdown thead th {
  color: var(--ink-soft); font-weight: 600;
  font-size: clamp(11px, 1.8vmin, 12px); text-transform: uppercase; letter-spacing: 0.04em;
  border-bottom: 1px solid var(--border-strong);
}
table.breakdown tbody tr { transition: background 0.12s ease; }
@media (hover: hover) { table.breakdown tbody tr:hover { background: var(--surface-2); } }
table.breakdown tbody tr:last-child td { border-bottom: none; }
table.breakdown td.num, table.breakdown th.num { text-align: right; font-variant-numeric: tabular-nums; }
table.breakdown .subj { font-weight: 600; display: flex; align-items: center; gap: 9px; }

/* ----------  Settings rows + toggle  ---------- */
.controls { margin-top: 20px; display: flex; flex-direction: column; gap: 12px; }
.control-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-lg); padding: 14px 16px;
  box-shadow: var(--shadow-sm);
}
.control-row .ct { font-weight: 600; }
.control-row .cd { color: var(--ink-soft); font-size: clamp(12px, 2vmin, 14px); margin-top: 2px; }
.switch { position: relative; width: 50px; height: 30px; flex: 0 0 auto; }
.switch input { display: none; }
.switch .track { position: absolute; inset: 0; background: var(--border-strong); border-radius: 999px; transition: background 0.2s; }
.switch .thumb { position: absolute; top: 3px; left: 3px; width: 24px; height: 24px; background: #fff; border-radius: 50%; transition: left 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,0.25); }
.switch input:checked + .track { background: var(--good-2); }
.switch input:checked + .track + .thumb { left: 23px; }

/* ----------  Pills (streak / stars in report)  ---------- */
.streak-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--warn-soft); color: #b45309; font-weight: 600;
  padding: 7px 14px; border-radius: 999px; font-size: clamp(13px, 2.2vmin, 16px);
  border: 1px solid #fde9c2;
}

/* ----------  Game timer  ---------- */
.timer { flex: 0 0 auto; font-size: clamp(22px, 4.4vmin, 36px); font-weight: 800; color: var(--brand-700); text-align: center; font-variant-numeric: tabular-nums; }
.timer.low { color: var(--bad); }

@media (prefers-reduced-motion: reduce) { .tile, .confetti { animation: none !important; opacity: 1; transform: none; } }

/* ==========================================================================
   Accounts: sign-in, forced password change, account menu, forms
   ========================================================================== */
.auth { flex: 1 1 auto; min-height: 0; display: grid; place-items: center; padding: var(--pad); }
.auth-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl);
  padding: clamp(30px, 4.4vmin, 48px) clamp(26px, 4vmin, 44px) clamp(24px, 3.4vmin, 36px);
  width: min(420px, 94vw);
  display: flex; flex-direction: column; gap: clamp(11px, 2vmin, 16px);
  text-align: center;
  overflow: hidden;
}
/* A faint brand sheen behind the logo gives the card a sense of depth/light. */
.auth-card::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(150% 70% at 50% -10%, rgba(124, 58, 237, 0.09), transparent 60%);
}
.auth-card > * { position: relative; }
/* brand mark presented as a polished app-icon chip with a soft halo */
.auth-logo {
  width: clamp(68px, 12vmin, 84px); height: clamp(68px, 12vmin, 84px);
  margin: 0 auto 4px;
  display: grid; place-items: center;
  font-size: clamp(34px, 6vmin, 44px);
  border-radius: 23px;
  background: var(--g-brand);
  box-shadow:
    0 16px 36px -8px rgba(99, 70, 229, 0.55),
    0 0 0 6px rgba(99, 102, 241, 0.08),
    inset 0 1px 0 rgba(255, 255, 255, 0.32);
}
.auth-card h1 { margin: 0; font-size: clamp(25px, 5vmin, 35px); font-weight: 800; letter-spacing: -0.025em; }
.auth-sub { margin: 0 0 6px; color: var(--ink-soft); font-size: clamp(13px, 2.4vmin, 16px); }
.auth-foot { margin: 4px 0 0; color: var(--ink-3); font-size: clamp(11px, 1.9vmin, 13px); font-weight: 500; letter-spacing: 0.01em; }
/* Trust row — small subject pills that signal a real, curriculum-backed product */
.auth-trust {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 7px;
  margin-top: clamp(12px, 2.2vmin, 18px);
  padding-top: clamp(14px, 2.4vmin, 20px);
  border-top: 1px solid var(--border);
}
.auth-trust .tp {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: clamp(11px, 1.9vmin, 13px); font-weight: 600; color: var(--ink-soft);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 5px 11px; border-radius: 999px;
}
.auth-trust .tp .tpi { font-size: 1.05em; line-height: 1; }
.auth-curric { margin: 10px 0 0; font-size: clamp(10.5px, 1.8vmin, 12px); color: var(--ink-3); font-weight: 600; letter-spacing: 0.02em; }
.auth-err { background: var(--bad-soft); color: #991b1b; border-radius: var(--r-md); padding: 11px 14px; font-size: clamp(13px, 2.2vmin, 15px); font-weight: 600; border: 1px solid #fecaca; }

/* Form fields */
.field { display: flex; flex-direction: column; gap: 6px; text-align: left; }
/* `display:flex` above would otherwise beat the [hidden] attribute, leaving a
   hidden field (e.g. the parent's kid checklist) visible — keep hidden hidden. */
.field[hidden] { display: none; }
.field > span { font-size: clamp(12px, 2vmin, 14px); font-weight: 600; color: var(--ink-soft); }
.field input, .field select {
  font-family: inherit;
  font-size: clamp(15px, 2.6vmin, 17px);
  padding: clamp(11px, 1.8vmin, 14px) 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--ink);
  width: 100%;
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
.field input::placeholder { color: var(--ink-3); }
.field input:focus, .field select:focus { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }
.field .readonly { font-size: clamp(14px, 2.4vmin, 16px); padding: clamp(11px, 1.8vmin, 14px) 14px; border-radius: var(--r-md); background: var(--surface-2); border: 1px solid var(--border); color: var(--ink-soft); font-weight: 600; }
.form { display: flex; flex-direction: column; gap: 12px; }

/* Modern select caret */
.field select, .child-pick {
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%235a6378' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 36px;
}

.btn.big { font-size: clamp(16px, 2.8vmin, 19px); padding: clamp(13px, 2.2vmin, 17px); margin-top: 4px; }
.btn.danger { color: var(--bad); }
.btn.secondary.danger, .btn.ghost.danger { color: var(--bad); }
.btn.tiny { font-size: clamp(12px, 1.9vmin, 14px); padding: 8px 13px; border-radius: var(--r-sm); box-shadow: none; }
.btn.tiny.secondary { box-shadow: var(--shadow-sm); }
.btn[disabled] { opacity: 0.4; cursor: default; }

.menu-list { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.menu-list .btn { width: 100%; }

/* Appearance (theme) selector in the account menu */
.menu-theme { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 16px; }
.menu-theme-label { font-size: clamp(12px, 2vmin, 14px); font-weight: 600; color: var(--ink-soft); }
.theme-seg {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px;
  background: var(--bg-soft); border: 1px solid var(--border);
  padding: 4px; border-radius: 999px;
}
.theme-seg button {
  border: none; font-family: inherit; font-weight: 600;
  font-size: clamp(13px, 2.1vmin, 15px);
  padding: 9px 6px; border-radius: 999px;
  background: transparent; color: var(--ink-soft); cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease, box-shadow 0.14s ease;
}
@media (hover: hover) { .theme-seg button:hover { color: var(--ink); } }
.theme-seg button.active { background: var(--surface); color: var(--brand-700); box-shadow: var(--shadow-sm); }
:root[data-theme="dark"] .theme-seg button.active { color: #a5b4fc; }

/* ==========================================================================
   Grown-ups: nav, report head, report-card grades, manage users
   ========================================================================== */
.gp { display: flex; flex-direction: column; gap: var(--gap); }

/* Primary navigation as clean underline tabs */
.gp-nav { display: flex; gap: 4px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.gp-nav button {
  border: none; background: transparent;
  font-family: inherit; font-weight: 600;
  font-size: clamp(14px, 2.3vmin, 16px);
  padding: 11px 14px; border-radius: 0;
  color: var(--ink-soft); cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color 0.14s ease, border-color 0.14s ease;
}
.gp-nav button:hover { color: var(--ink); }
.gp-nav button.active { color: var(--brand-700); border-bottom-color: var(--brand); }

.dash-title { font-size: clamp(19px, 3.6vmin, 26px); font-weight: 800; letter-spacing: -0.02em; margin: 4px 0 12px; }

/* ----------  Collapsible report sections  ----------
   Bold full-width header buttons with a rotating arrow chip; the body below
   folds away. Used by Assessment, Original Assessment, Math, Reading, English. */
.sec-toggle {
  display: flex; align-items: center; gap: 10px; width: 100%;
  background: none; border: none; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.sec-toggle .sec-arrow {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--r-sm);
  background: var(--surface-2); border: 1px solid var(--border-strong);
  color: var(--brand-700); font-size: 16px; line-height: 1; font-weight: 800;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s ease, border-color 0.15s ease;
}
:root[data-theme="dark"] .sec-toggle .sec-arrow { color: #a5b4fc; }
.sec-toggle[aria-expanded="false"] .sec-arrow { transform: rotate(-90deg); }
@media (hover: hover) { .sec-toggle:hover .sec-arrow { border-color: var(--brand-500); } }
.sec-toggle .sec-title { font-weight: 800; font-size: clamp(15px, 2.4vmin, 17px); letter-spacing: -0.02em; }
.sec-toggle.big .sec-title { font-size: clamp(16px, 2.7vmin, 21px); letter-spacing: -0.025em; }
.sec-title .domain-sub { color: var(--ink-soft); font-weight: 500; font-size: clamp(12px, 2vmin, 14px); }
.sec-toggle .sec-meta { margin-left: auto; flex: 0 0 auto; font-size: clamp(11px, 1.8vmin, 12px); color: var(--ink-soft); font-weight: 600; text-align: right; }
.sec-toggle[aria-expanded="true"] { margin-bottom: 12px; }
.domain-section > .sec-toggle[aria-expanded="true"] { margin-bottom: 16px; padding-bottom: 13px; border-bottom: 1px solid var(--border); }

.report-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding-bottom: 14px; border-bottom: 1px solid var(--border); }
.rh-left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.rh-right { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.child-name { font-size: clamp(18px, 3.4vmin, 24px); font-weight: 700; letter-spacing: -0.01em; }
.child-pick {
  font-family: inherit; font-weight: 600;
  font-size: clamp(14px, 2.4vmin, 17px);
  padding: 9px 36px 9px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--border-strong);
  background-color: var(--surface);
  color: var(--ink); cursor: pointer;
  transition: border-color 0.14s ease, box-shadow 0.14s ease;
}
.child-pick:focus { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }
.stars-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: linear-gradient(150deg, #fffaf0, #fff3da); color: #b45309; font-weight: 700;
  padding: 7px 14px; border-radius: 999px; font-size: clamp(14px, 2.4vmin, 17px);
  border: 1px solid #fde9c2; font-variant-numeric: tabular-nums;
}

/* The Print / Export button keeps the brand glow that .btn.tiny strips. */
.export-btn.btn.tiny { box-shadow: var(--glow-brand), inset 0 1px 0 rgba(255, 255, 255, 0.18); }

/* Print / Export menu: stacked choices with an icon, a bold name and a hint. */
.export-menu .btn {
  display: flex; align-items: center; gap: 12px;
  justify-content: flex-start; text-align: left;
}
.export-menu .em-icon { font-size: 24px; flex: 0 0 auto; }
.export-menu .em-text { display: flex; flex-direction: column; line-height: 1.3; min-width: 0; }
.export-menu .em-sub { font-size: 12.5px; font-weight: 500; color: var(--ink-soft); }
.export-menu .btn:disabled { opacity: 0.55; cursor: not-allowed; }

/* ----------  Kid chooser (multi-child landing)  ---------- */
.kid-chooser { padding: 8px 0 4px; }
.kc-title { font-size: clamp(20px, 4vmin, 28px); font-weight: 800; letter-spacing: -0.02em; margin: 4px 0 2px; }
.kc-sub { margin: 0 0 16px; }
.kid-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 14px; }
.kid-card {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 22px 16px; cursor: pointer; text-align: center;
  border-radius: var(--r-lg); border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-sm);
  transition: border-color 0.14s ease, box-shadow 0.14s ease, transform 0.08s ease;
}
.kid-card:hover { border-color: var(--brand-500); box-shadow: var(--ring); transform: translateY(-2px); }
.kid-card:focus-visible { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }
.kid-avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 999px;
  background: linear-gradient(150deg, var(--brand-500), var(--accent)); color: #fff;
  font-weight: 800; font-size: 22px; letter-spacing: 0.02em;
}
.kid-name { font-weight: 700; font-size: clamp(15px, 2.6vmin, 18px); }
.kid-cta { color: var(--brand-700); font-weight: 600; font-size: clamp(12px, 2vmin, 14px); }

/* Parent → kid link checklist in the user form. One tappable row per kid. */
.kid-checks { display: flex; flex-direction: column; gap: 8px; }
.kid-check {
  display: flex; align-items: center; gap: 10px;
  padding: 11px 14px; border-radius: var(--r-md);
  border: 1px solid var(--border-strong); background: var(--surface);
  font-weight: 600; cursor: pointer; user-select: none;
}
.kid-check input { width: 18px; height: 18px; flex: none; accent-color: var(--brand-500); }
.kid-check span { min-width: 0; overflow-wrap: anywhere; }

/* Read-only "which kids" tags in the Manage users table. */
.kid-tags { display: flex; flex-wrap: wrap; gap: 5px; }
.kid-tag {
  display: inline-flex; align-items: center;
  padding: 3px 9px; border-radius: 999px;
  background: var(--bg-soft); color: var(--ink-soft);
  border: 1px solid var(--border); font-size: clamp(11px, 1.9vmin, 13px); font-weight: 600;
}

/* ----------  Term / school-year context bar  ---------- */
.term-bar { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 4px; }
.term-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--bg-soft); color: var(--ink-soft); font-weight: 600;
  padding: 6px 12px; border-radius: 999px; font-size: clamp(12px, 2vmin, 14px);
  border: 1px solid var(--border);
}
.term-pill.year { color: var(--brand-700); }
.term-pill.summer { background: #fff3da; color: #b45309; border-color: #fde9c2; }
.term-pill.grade { color: #0d9488; }

/* ----------  Owner: content-bank staleness box  ---------- */
.stale-box {
  margin: 12px 0 4px; padding: 14px 16px;
  border-radius: var(--r-lg); border: 1px solid var(--border);
  background: var(--surface); box-shadow: var(--shadow-sm);
}
.stale-box.loading-box { color: var(--ink-soft); font-size: clamp(13px, 2.1vmin, 15px); }
.stale-box.level-fresh { border-color: #bbf7d0; background: #f0fdf4; }
.stale-box.level-warn  { border-color: #fde68a; background: #fffbeb; }
.stale-box.level-stale { border-color: #fecaca; background: #fef2f2; }
.sb-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.sb-title { font-weight: 700; font-size: clamp(14px, 2.4vmin, 17px); letter-spacing: -0.01em; }
.sb-badge { font-size: 12px; font-weight: 700; padding: 3px 10px; border-radius: 999px; }
.sb-badge.fresh { background: #dcfce7; color: #15803d; }
.sb-badge.warn  { background: #fef3c7; color: #b45309; }
.sb-badge.stale { background: #fee2e2; color: #b91c1c; }
.sb-body { margin-top: 6px; color: var(--ink-soft); font-size: clamp(13px, 2.1vmin, 15px); }
.sb-reasons { margin: 10px 0 0; padding-left: 20px; display: flex; flex-direction: column; gap: 6px; }
.sb-reasons li { font-size: clamp(13px, 2.1vmin, 15px); color: var(--ink); }
.sb-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.sb-hint { color: var(--ink-soft); font-size: 12px; }
.sb-prompt {
  display: none; margin: 10px 0 0; padding: 12px;
  background: var(--bg-soft); border: 1px solid var(--border); border-radius: var(--r-md);
  font-size: 12px; white-space: pre-wrap; word-break: break-word; color: var(--ink);
}
.sb-prompt.show { display: block; }

.section-title { margin: 18px 0 10px; font-size: clamp(10.5px, 1.7vmin, 12px); font-weight: 700; color: var(--ink-soft); letter-spacing: 0.06em; text-transform: uppercase; }

/* Report-card grade tiles with a colored top accent */
.grades { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
@media (max-width: 620px) { .grades { grid-template-columns: repeat(3, 1fr); } }
.grade {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-top: 3px solid var(--border-strong);
  border-radius: var(--r-md);
  padding: 14px 10px; text-align: center;
  transition: transform 0.14s ease, box-shadow 0.14s ease;
}
@media (hover: hover) { .grade:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); } }
.grade .g-top { display: flex; align-items: center; justify-content: center; gap: 6px; }
.grade .g-emoji { font-size: clamp(17px, 2.8vmin, 22px); }
.grade .g-letter { font-size: clamp(22px, 4.4vmin, 32px); font-weight: 800; letter-spacing: -0.02em; }
.grade .g-label { font-size: clamp(12px, 2vmin, 14px); font-weight: 600; margin-top: 5px; }
.grade .g-meta { font-size: clamp(10px, 1.8vmin, 12px); color: var(--ink-soft); margin-top: 2px; }
.grade.g-a { border-top-color: #22c55e; } .grade.g-a .g-letter { color: #15a34a; }
.grade.g-b { border-top-color: #84cc16; } .grade.g-b .g-letter { color: #65a30d; }
.grade.g-c { border-top-color: #f59e0b; } .grade.g-c .g-letter { color: #d97706; }
.grade.g-d { border-top-color: #fb923c; } .grade.g-d .g-letter { color: #ea580c; }
.grade.g-f { border-top-color: #f43f5e; } .grade.g-f .g-letter { color: var(--bad); }
.grade.g-none { opacity: 0.75; } .grade.g-none .g-letter { color: var(--ink-3); }

.control-row .danger { color: var(--bad); }

/* Manage users */
.users-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-bottom: 4px; }
.users-head .muted { color: var(--ink-soft); font-size: clamp(13px, 2.2vmin, 15px); max-width: 60ch; margin: 0; }
.users-table td { vertical-align: middle; }
.users-table th.ta-right { text-align: right; }
.u-sub { color: var(--ink-soft); font-size: clamp(11px, 1.9vmin, 13px); font-weight: 500; margin-top: 2px; }
.u-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* Role / status chips */
.chip {
  display: inline-block; font-size: clamp(11px, 1.8vmin, 12px); font-weight: 600;
  padding: 3px 10px; border-radius: 999px;
  background: var(--bg-soft); color: var(--ink-soft);
  border: 1px solid var(--border); margin-right: 4px;
}
.chip.role-owner  { background: var(--brand-50); color: #6d28d9; border-color: #ddd6fe; }
.chip.role-parent { background: #e0f2fe; color: #0369a1; border-color: #bae6fd; }
.chip.role-child  { background: var(--good-soft); color: #15803d; border-color: #bbf7d0; }
.chip.warn        { background: var(--warn-soft); color: #b45309; border-color: #fde68a; }

.loading { color: var(--ink-soft); font-weight: 600; padding: 28px 0; text-align: center; }
.empty-note {
  color: var(--ink-soft);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
  padding: 26px; text-align: center;
  font-size: clamp(14px, 2.4vmin, 17px);
}

/* Small helper text under a form field (e.g. password requirements). */
.field-hint {
  margin: -2px 0 2px; color: var(--ink-soft);
  font-size: clamp(12px, 2vmin, 13px); line-height: 1.4;
}

/* Privacy / retention summary card. */
.privacy-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(16px, 2.4vmin, 22px);
}
.privacy-card h3 { margin: 0 0 10px; }

/* ==========================================================================
   Owner: activity log (chronological feed) + account detail
   ========================================================================== */
.muted-cell { color: var(--ink-soft); font-size: clamp(12px, 2vmin, 14px); }

.act-summary { margin-bottom: 16px; }
.act-summary .sc .n { font-size: clamp(16px, 3vmin, 22px); }

/* Activity day navigator */
.act-daybar { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.act-dayheading { margin: 0; font-size: clamp(17px, 3.2vmin, 22px); font-weight: 800; letter-spacing: -0.01em; }
.act-daynav { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.day-pick {
  font-family: inherit; font-weight: 600;
  font-size: clamp(13px, 2.2vmin, 15px);
  padding: 8px 12px; border-radius: var(--r-md);
  border: 1px solid var(--border-strong);
  background-color: var(--surface); color: var(--ink); cursor: pointer;
}
.day-pick:focus { outline: none; border-color: var(--brand-500); box-shadow: var(--ring); }

.act-filters { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.act-filters .child-pick { font-size: clamp(13px, 2.2vmin, 15px); padding: 9px 34px 9px 13px; }

.act-day { margin-bottom: 16px; }
.act-day-head {
  position: sticky; top: 0; z-index: 1;
  font-weight: 700; color: var(--ink-soft);
  font-size: clamp(12px, 2vmin, 14px); text-transform: uppercase; letter-spacing: 0.04em;
  padding: 8px 2px; margin-bottom: 4px;
  background: var(--bg);
}
.act-timeline { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.act-item {
  display: flex; gap: 12px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg);
  padding: 12px 14px; box-shadow: var(--shadow-sm);
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
}
@media (hover: hover) { .act-item:hover { transform: translateY(-1px); box-shadow: var(--shadow-md); border-color: var(--border-strong); } }
.act-icon {
  flex: 0 0 auto; font-size: clamp(15px, 2.6vmin, 18px);
  width: 38px; height: 38px; border-radius: 12px;
  display: grid; place-items: center;
  background: var(--brand-soft);
  border: 1px solid var(--border);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.act-main { min-width: 0; flex: 1 1 auto; }
.act-line { font-size: clamp(13px, 2.2vmin, 15px); line-height: 1.5; }
.act-verb { font-weight: 600; }
.act-detail { color: var(--ink-soft); }
.act-detail::before { content: "· "; }
.act-time { color: var(--ink-3); font-size: clamp(11px, 1.9vmin, 13px); margin-top: 3px; }
.act-end { text-align: center; color: var(--ink-3); font-size: clamp(12px, 2vmin, 14px); padding: 14px 0; }
.code-hint {
  text-align: left; background: #0f172a; color: #e2e8f0;
  border-radius: var(--r-md); padding: 14px 16px; margin: 10px 0 0;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: clamp(12px, 2vmin, 14px); white-space: pre-wrap; overflow-x: auto;
  border: 1px solid #1e293b;
}
.act-migrate p { margin: 0 0 8px; }

/* Account detail modal */
.ad-head { display: flex; align-items: center; gap: 8px; margin: 2px 0 14px; }
.ad-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 18px; margin-bottom: 8px; }
@media (max-width: 480px) { .ad-meta { grid-template-columns: 1fr; } }
.ad-kv { display: flex; justify-content: space-between; gap: 10px; border-bottom: 1px solid var(--border); padding: 8px 0; font-size: clamp(13px, 2.2vmin, 15px); }
.ad-kv .k { color: var(--ink-soft); font-weight: 500; }
.ad-kv .v { font-weight: 600; text-align: right; }
.ad-actions { margin: 10px 0 4px; }
.ad-actions .btn { width: 100%; }

/* ==========================================================================
   Printable report card (PDF). Hidden on screen; shown only when printing.
   ========================================================================== */
.print-area { display: none; }

@media print {
  .app, .toast, .overlay, .devbar { display: none !important; }
  .print-area { display: block !important; }
  html, body { background: #fff !important; }
  @page { margin: 14mm; }
}

.print-area, .pr-sheet { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.pr-sheet { font-family: var(--font-ui); color: #0f1629; max-width: 720px; margin: 0 auto; padding: 8px 4px; }
.pr-head { text-align: center; border-bottom: 3px solid var(--brand-600); padding-bottom: 12px; margin-bottom: 14px; }
.pr-brand { font-size: 14px; letter-spacing: 1px; color: var(--brand-700); font-weight: 700; }
.pr-title { font-size: 30px; font-weight: 800; letter-spacing: -0.02em; margin: 2px 0; }
.pr-sub { display: flex; justify-content: center; gap: 14px; flex-wrap: wrap; color: #5a6378; font-size: 13px; }
.pr-sub .pr-name { color: #0f1629; font-weight: 700; }

.pr-pills { display: flex; justify-content: center; gap: 10px; margin: 0 0 14px; }
.pr-pill { font-weight: 700; font-size: 13px; padding: 5px 14px; border-radius: 999px; background: #fff7ed; color: #c2410c; border: 1px solid #fed7aa; }

.pr-assess { border: 1px solid #eceefa; background: #f7f8fc; border-radius: 14px; padding: 12px 14px; margin: 0 0 16px; }
.pr-assess-title { font-weight: 800; font-size: 14px; color: #0f1629; margin-bottom: 8px; }
.pr-assess-row { display: flex; gap: 10px; font-size: 12.5px; line-height: 1.5; color: #1f2738; margin-top: 4px; }
.pr-assess-label { flex: 0 0 130px; font-weight: 700; color: #5a6378; }

.pr-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 16px; }
.pr-stat { background: #f7f8fc; border-radius: 14px; padding: 12px; text-align: center; border: 1px solid #eceefa; }
.pr-stat .n { font-size: 26px; font-weight: 800; letter-spacing: -0.02em; }
.pr-stat .l { font-size: 11px; color: #5a6378; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }
.pr-stat.good .n { color: #15a34a; }
.pr-stat.bad .n { color: #dc2626; }

.pr-section { font-size: 15px; color: #0f1629; font-weight: 700; margin: 16px 0 8px; }
.pr-note { color: #5a6378; font-size: 13px; line-height: 1.5; margin: 0 0 12px; }

.pr-grades { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; }
.pr-grade { border: 1px solid #e5e7eb; border-top: 3px solid #e5e7eb; border-radius: 14px; padding: 10px 6px; text-align: center; }
.pr-g-top { display: flex; align-items: center; justify-content: center; gap: 5px; }
.pr-g-letter { font-size: 24px; font-weight: 800; letter-spacing: -0.02em; }
.pr-g-label { font-size: 12px; font-weight: 600; margin-top: 3px; }
.pr-g-meta { font-size: 10px; color: #5a6378; margin-top: 2px; }
.pr-grade.g-a { border-top-color: #22c55e; } .pr-grade.g-a .pr-g-letter { color: #15a34a; }
.pr-grade.g-b { border-top-color: #84cc16; } .pr-grade.g-b .pr-g-letter { color: #65a30d; }
.pr-grade.g-c { border-top-color: #f59e0b; } .pr-grade.g-c .pr-g-letter { color: #d97706; }
.pr-grade.g-d { border-top-color: #fb923c; } .pr-grade.g-d .pr-g-letter { color: #ea580c; }
.pr-grade.g-f { border-top-color: #f43f5e; } .pr-grade.g-f .pr-g-letter { color: #dc2626; }
.pr-grade.g-none .pr-g-letter { color: #5a6378; }

.pr-table { width: 100%; border-collapse: collapse; font-size: 14px; margin-top: 4px; }
.pr-table th, .pr-table td { padding: 9px 10px; text-align: left; border-bottom: 1px solid #eee; }
.pr-table th { color: #5a6378; font-weight: 600; background: #f7f8fc; text-transform: uppercase; font-size: 11px; letter-spacing: 0.04em; }
.pr-table td.num, .pr-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.pr-table tbody tr:nth-child(even) { background: #fbfaff; }

.pr-foot { margin-top: 18px; padding-top: 10px; border-top: 1px solid #eee; text-align: center; color: #99a1b5; font-size: 12px; }

/* ==========================================================================
   Mode picker (kid home: Math vs Reading)
   ========================================================================== */
.mode-grid {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  grid-auto-rows: 1fr;
}
@media (orientation: portrait) and (max-width: 560px) { .mode-grid { grid-template-columns: 1fr; } }
.mode-card {
  position: relative;
  border: none;
  border-radius: var(--r-xl);
  padding: clamp(22px, 4vmin, 40px);
  color: #fff;
  font-family: inherit;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(10px, 1.8vmin, 18px);
  background:
    radial-gradient(120% 90% at 18% 8%, rgba(255, 255, 255, 0.22), transparent 46%),
    linear-gradient(155deg, var(--c1), var(--c2));
  box-shadow: 0 18px 38px -10px var(--shadow, rgba(2, 6, 23, 0.30)), inset 0 1px 0 rgba(255, 255, 255, 0.28), inset 0 0 0 1px rgba(255, 255, 255, 0.10);
  transition: transform 0.18s cubic-bezier(0.22, 1, 0.36, 1), box-shadow 0.18s ease, filter 0.18s ease;
  opacity: 0;
  transform: translateY(14px) scale(0.97);
  animation: pop 0.5s cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.mode-card::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0) 38%);
  pointer-events: none;
}
/* Oversized translucent glyph in the corner — gives the big card depth and a
   designed, "this space is on purpose" feel instead of a flat color block. */
.mode-watermark {
  position: absolute; right: -6%; bottom: -8%;
  font-size: clamp(120px, 34vmin, 280px);
  line-height: 1; opacity: 0.12;
  transform: rotate(-12deg);
  pointer-events: none; filter: saturate(0) brightness(0) invert(1);
}
.mode-card:nth-child(2) { animation-delay: 0.08s; }
.mode-card:nth-child(3) { animation-delay: 0.16s; }
.mode-card:active { transform: scale(0.97); filter: brightness(1.04); }
@media (hover: hover) {
  .mode-card:hover { transform: translateY(-6px); box-shadow: 0 28px 54px -12px var(--shadow, rgba(2, 6, 23, 0.40)), inset 0 1px 0 rgba(255, 255, 255, 0.28), inset 0 0 0 1px rgba(255, 255, 255, 0.10); }
  .mode-card:hover .mode-go { background: #fff; color: var(--c2); }
  .mode-card:hover .mg-arrow { transform: translateX(3px); }
}
.mode-emoji {
  width: clamp(64px, 14vmin, 120px);
  height: clamp(64px, 14vmin, 120px);
  display: grid; place-items: center;
  border-radius: 28px;
  background: rgba(255, 255, 255, 0.22);
  border: 1px solid rgba(255, 255, 255, 0.30);
  font-size: clamp(34px, 8vmin, 64px);
  line-height: 1;
  box-shadow: inset 0 1px 6px rgba(255, 255, 255, 0.45), 0 8px 18px -6px rgba(0, 0, 0, 0.18);
}
.mode-name { font-size: clamp(22px, 4.4vmin, 36px); font-weight: 800; letter-spacing: -0.02em; }
.mode-sub { font-size: clamp(13px, 2.3vmin, 17px); font-weight: 500; opacity: 0.94; text-align: center; max-width: 22ch; }
/* Clear call-to-action chip so each card resolves with purpose */
.mode-go {
  margin-top: clamp(6px, 1.4vmin, 12px);
  display: inline-flex; align-items: center; gap: 7px;
  font-size: clamp(13px, 2.2vmin, 16px); font-weight: 700; letter-spacing: 0.01em;
  color: #fff;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.34);
  padding: clamp(8px, 1.5vmin, 11px) clamp(16px, 2.4vmin, 22px);
  border-radius: 999px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
  transition: background 0.16s ease, color 0.16s ease;
}
.mg-arrow { display: inline-block; transition: transform 0.16s ease; }

/* Per-section daily progress on the mode cards */
.mode-status {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: clamp(12px, 2vmin, 15px); font-weight: 700;
  color: #fff; opacity: 0.92;
  background: rgba(0, 0, 0, 0.14);
  padding: 5px 12px; border-radius: 999px;
  font-variant-numeric: tabular-nums;
}
.mode-status.done { background: rgba(255, 255, 255, 0.26); }
.mode-status .ms-check { font-weight: 900; }
/* A finished section gets a gold ring + corner check so "done" reads instantly */
.mode-card.complete { box-shadow: 0 18px 38px -10px var(--shadow), inset 0 0 0 3px rgba(255, 255, 255, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.28); }
.mode-badge {
  position: absolute; top: 14px; right: 14px;
  width: 30px; height: 30px; border-radius: 50%;
  display: grid; place-items: center;
  background: #fff; color: #16a34a; font-weight: 900; font-size: 16px;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.18);
}

/* Portrait phones: the three big "poster" cards are taller than a phone screen
   can stack, which clipped the Start button. Re-flow each card into a compact
   horizontal row — emoji | name/sub/progress | Start — so all three sections
   fit one screen with every control visible. (This block must come AFTER the
   base .mode-card rules above: same specificity, so source order decides.) */
@media (orientation: portrait) and (max-width: 560px) {
  .mode-grid { grid-auto-rows: auto; align-content: start; }
  .mode-card {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas:
      "emoji name   go"
      "emoji sub    go"
      "emoji status go";
    align-items: center;
    justify-items: start;
    column-gap: 14px;
    row-gap: 5px;
    padding: 16px;
    text-align: left;
  }
  .mode-emoji { grid-area: emoji; width: 58px; height: 58px; font-size: 30px; border-radius: 18px; }
  .mode-name { grid-area: name; font-size: 21px; }
  .mode-sub { grid-area: sub; font-size: 13px; text-align: left; max-width: none; }
  .mode-status { grid-area: status; font-size: 12px; margin-top: 2px; }
  .mode-go { grid-area: go; justify-self: end; margin-top: 0; padding: 9px 14px; font-size: 13px; }
  .mode-watermark { font-size: 110px; right: -10%; bottom: -28%; }
  /* The corner ✓ badge would collide with the Start chip in this row layout —
     the gold ring + "Done today" pill already say "complete". */
  .mode-card .mode-badge { display: none; }
}

/* Daily plan hint + section-complete banners (kid home screens) */
.day-plan, .done-banner {
  flex: 0 0 auto;
  border-radius: var(--r-lg);
  padding: clamp(11px, 1.9vmin, 15px) clamp(14px, 2.4vmin, 18px);
  font-weight: 600;
  font-size: clamp(13px, 2.2vmin, 16px);
  margin-bottom: var(--gap);
}
.day-plan {
  background: var(--surface); border: 1px solid var(--border);
  color: var(--ink-soft); box-shadow: var(--shadow-sm);
}
.done-banner {
  background: linear-gradient(135deg, var(--good-soft), var(--surface));
  border: 1px solid rgba(34, 197, 94, 0.35);
  color: var(--good); font-weight: 700;
  box-shadow: var(--shadow-sm);
}
/* ----------  "Achievement Unlocked" banner (whole day complete)  ----------
   A game-style gold trophy banner with a flowing metallic sheen, a sweeping
   glint, a bobbing trophy and twinkling sparkles. Looks the same (and pops) in
   light or dark mode because the gold is self-contained. Purely visual — no
   stats — just the "you beat the day" wow. */
.achv {
  position: relative; overflow: hidden;
  flex: 0 0 auto;
  display: flex; align-items: center; gap: clamp(12px, 2vmin, 18px);
  padding: clamp(13px, 2.1vmin, 18px) clamp(16px, 2.6vmin, 24px);
  margin-bottom: var(--gap);
  border-radius: var(--r-xl);
  background: linear-gradient(110deg, #b45309 0%, #f59e0b 24%, #fde68a 48%, #f59e0b 72%, #b45309 100%);
  background-size: 220% auto;
  border: 1px solid rgba(255, 255, 255, 0.45);
  box-shadow: 0 16px 38px -12px rgba(245, 158, 11, 0.65), 0 0 0 1px rgba(180, 83, 9, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.6);
  animation: achv-pop 0.6s cubic-bezier(0.18, 1.45, 0.4, 1) both, achv-flow 7s linear infinite;
}
@keyframes achv-pop  { from { opacity: 0; transform: translateY(-14px) scale(0.96); } to { opacity: 1; transform: none; } }
@keyframes achv-flow { to { background-position: 220% center; } }

/* Diagonal glint that sweeps across now and then */
.achv-shine {
  position: absolute; top: 0; left: -45%; width: 38%; height: 100%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, 0.65), transparent);
  transform: skewX(-18deg); pointer-events: none;
  animation: achv-sweep 3.6s ease-in-out infinite;
}
@keyframes achv-sweep { 0%, 18% { left: -50%; } 62%, 100% { left: 135%; } }

.achv-medal {
  flex: 0 0 auto; font-size: clamp(32px, 6.4vmin, 50px); line-height: 1; z-index: 1;
  filter: drop-shadow(0 4px 9px rgba(91, 45, 6, 0.4));
  animation: achv-medal 2.4s ease-in-out infinite;
}
@keyframes achv-medal { 0%, 100% { transform: rotate(-7deg) translateY(0); } 50% { transform: rotate(7deg) translateY(-4px); } }

.achv-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; z-index: 1; }
.achv-kicker {
  font-size: clamp(10px, 1.7vmin, 12px); font-weight: 800; letter-spacing: 0.16em;
  text-transform: uppercase; color: #7c2d12;
}
.achv-title { font-size: clamp(19px, 3.3vmin, 28px); font-weight: 900; letter-spacing: -0.01em; line-height: 1.05; color: #3b2406; }
.achv-desc  { font-size: clamp(12px, 2vmin, 15px); font-weight: 600; color: #5c3a0c; }

/* Twinkling sparkles scattered over the banner */
.achv-spark { position: absolute; z-index: 1; pointer-events: none; font-size: clamp(11px, 2vmin, 16px); animation: achv-twinkle 1.8s ease-in-out infinite; }
.achv-spark.sp1 { top: 14%; right: 16%; animation-delay: 0.0s; }
.achv-spark.sp2 { bottom: 16%; right: 30%; animation-delay: 0.5s; }
.achv-spark.sp3 { top: 22%; right: 42%; animation-delay: 1.0s; font-size: clamp(9px, 1.6vmin, 13px); }
@keyframes achv-twinkle { 0%, 100% { opacity: 0.25; transform: scale(0.8) rotate(0deg); } 50% { opacity: 1; transform: scale(1.15) rotate(15deg); } }

@media (prefers-reduced-motion: reduce) {
  .achv, .achv-shine, .achv-medal, .achv-spark { animation: none !important; }
  .achv { background-position: 50% center; }
}

/* Subject/skill tile finished for the day */
.tile.tile-complete { box-shadow: 0 10px 24px var(--shadow, rgba(2,6,23,.16)), inset 0 0 0 3px rgba(255,255,255,.5), inset 0 1px 0 rgba(255,255,255,.22); }

/* ---- Bonus-star tile states (shared by all three section homes) ---- */
.tile.bonus-done { opacity: 1; filter: none; cursor: default; box-shadow: 0 10px 24px var(--shadow), inset 0 0 0 3px rgba(255,255,255,.55), inset 0 1px 0 rgba(255,255,255,.22); }
.tile.bonus-locked { cursor: pointer; } /* tappable to show the hint, but visibly dimmed via .locked */
.tile.bonus-locked .label, .tile.bonus-locked .icon { filter: grayscale(0.1); }

/* ---- Bonus round: "get 3 right" header + progress dots ---- */
.bonus-head {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.bonus-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: linear-gradient(150deg, #fffaf0, #fff3da);
  border: 1px solid #fde9c2; color: #b45309;
  font-weight: 800; font-size: clamp(13px, 2.2vmin, 16px);
  padding: 6px 13px; border-radius: 999px;
}
.bonus-goal { font-weight: 700; color: var(--ink-soft); font-size: clamp(13px, 2.2vmin, 16px); }
.bonus-dots { display: inline-flex; gap: 7px; margin-left: auto; }
.bonus-dot {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--bg-soft); border: 2px solid var(--border-strong);
  transition: background 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
}
.bonus-dot.on { background: var(--amber); border-color: var(--amber); transform: scale(1.08); box-shadow: 0 0 10px -2px rgba(245, 158, 11, 0.6); }

/* ==========================================================================
   Reading: dashboard banner, passage box, multiple-choice answers
   ========================================================================== */
.reading-banner {
  flex: 0 0 auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: clamp(10px, 1.8vmin, 14px) clamp(14px, 2.4vmin, 18px);
  margin-bottom: var(--gap);
  color: var(--ink-soft);
  font-weight: 600;
  font-size: clamp(13px, 2.3vmin, 16px);
  box-shadow: var(--shadow-sm);
}
.reading-grid { grid-template-columns: repeat(2, 1fr); }
/* (landscape columns handled by the symmetric grid system at end of file) */

/* The passage / context box sits at the top of the question card */
.qcard.reading { justify-content: flex-start; gap: clamp(12px, 2vmin, 20px); }
.passage {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 4px solid var(--brand-500);
  border-radius: var(--r-md);
  padding: clamp(12px, 2.2vmin, 20px);
  text-align: left;
  font-size: clamp(15px, 2.5vmin, 19px);
  line-height: 1.55;
  color: var(--ink);
  max-height: 38vh;
  overflow-y: auto;
}
.passage p { margin: 0; }
.passage-title { font-weight: 800; letter-spacing: -0.01em; margin-bottom: 6px; font-size: 1.05em; }

.prompt.rq-prompt { max-width: 38ch; font-size: clamp(17px, 3vmin, 24px); font-weight: 700; }

.choices { display: flex; flex-direction: column; gap: clamp(8px, 1.5vmin, 12px); width: min(560px, 100%); }
.choice {
  border: 1px solid var(--border-strong);
  background: var(--surface);
  color: var(--ink);
  font-family: inherit;
  font-size: clamp(15px, 2.6vmin, 19px);
  font-weight: 600;
  text-align: left;
  padding: clamp(12px, 2.1vmin, 17px) clamp(16px, 2.6vmin, 20px);
  border-radius: var(--r-md);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform 0.1s ease, box-shadow 0.12s ease, border-color 0.12s ease, background 0.12s ease;
}
@media (hover: hover) { .choice:not([disabled]):hover { border-color: var(--brand-500); background: var(--brand-soft); box-shadow: var(--shadow-md); transform: translateY(-1px); } }
.choice:not([disabled]):active { transform: scale(0.985); }
.choice[disabled] { cursor: default; }
.choice.correct { border-color: var(--good-2); background: var(--good-soft); color: #14532d; box-shadow: 0 6px 16px -6px rgba(22, 163, 74, 0.40); }
.choice.wrong { border-color: var(--bad); background: var(--bad-soft); color: #7f1d1d; }

/* ==========================================================================
   Dashboard: per-domain (Math / Reading) report sections
   ========================================================================== */
.domain-section {
  margin-bottom: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: clamp(18px, 2.6vmin, 26px);
  box-shadow: var(--shadow-md);
}
.domain-title {
  margin: 0 0 16px; padding-bottom: 13px;
  border-bottom: 1px solid var(--border);
  font-size: clamp(16px, 2.7vmin, 21px); font-weight: 800; letter-spacing: -0.025em;
}
.domain-title .domain-sub { color: var(--ink-soft); font-weight: 500; font-size: clamp(12px, 2vmin, 14px); }
/* First section label sits right under the title — trim its top gap */
.domain-section .stat-cards { margin-top: 2px; }

/* ==========================================================================
   Owner "Test as" switcher bar (only shown to owners / impersonation sessions)
   ========================================================================== */
.devbar {
  position: fixed;
  left: max(12px, env(safe-area-inset-left));
  bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 55;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 9px;
  background: rgba(15, 23, 42, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  box-shadow: var(--shadow-lg);
  backdrop-filter: blur(6px);
}
.devbar .devbar-label { color: #cbd5e1; font-size: 12px; font-weight: 700; padding: 0 4px; white-space: nowrap; }
.devbar button {
  border: 1px solid transparent;
  background: rgba(255, 255, 255, 0.10);
  color: #e2e8f0;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  padding: 7px 11px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease, transform 0.1s ease;
}
.devbar button:hover { background: rgba(255, 255, 255, 0.18); }
.devbar button:active { transform: scale(0.95); }
.devbar button.active { background: #fff; color: #0f172a; }
@media (max-width: 420px) { .devbar .devbar-label { display: none; } }

/* When the bar is on screen (body.has-devbar — set by app.js), reserve its
   height at the bottom of the page so it floats over empty space, never over
   the last row of content / a button someone is trying to tap. */
body.has-devbar .app {
  padding-bottom: calc(max(var(--pad), env(safe-area-inset-bottom)) + 58px);
}

/* Phones: a floating translucent pill over a scrolling page reads as a glitch —
   content slides through and around it. Dock it flush to the bottom edge as a
   solid, full-width switcher bar instead (like a tab bar), so scrolling under
   it looks deliberate and nothing shows through. Applies in both orientations:
   narrow portrait and short landscape. */
@media (max-width: 560px), (orientation: landscape) and (max-height: 560px) {
  .devbar {
    left: 0; right: 0; bottom: 0;
    justify-content: center;
    gap: 8px;
    border-radius: 0;
    border: none;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    background: #0f172a; /* fully opaque — no content bleeding through */
    backdrop-filter: none;
    padding: 8px max(10px, env(safe-area-inset-right))
             max(8px, env(safe-area-inset-bottom))
             max(10px, env(safe-area-inset-left));
  }
  .devbar .devbar-label { display: none; }
  body.has-devbar .app {
    padding-bottom: calc(max(8px, env(safe-area-inset-bottom)) + 62px);
  }
}

/* ==========================================================================
   Phones in landscape (short + wide)
   --------------------------------------------------------------------------
   The kid game is pinned to a single screenful (body.kid never scrolls). On a
   tablet that's easy, but a phone in landscape is only ~330–430px TALL — far
   too short to stack the prompt, the answer box AND a four-row keypad without
   the keypad getting clipped off the bottom. The previous layout always stacked
   vertically, which is exactly what was getting cut off on an iPhone.

   The fix: on short-but-wide screens, spend the spare WIDTH instead of fighting
   for height. The numeric quiz turns into a calculator (prompt + answer on the
   left, a full-height keypad on the right) and reading questions sit the passage
   beside the question + answers. Tablets in landscape are ≥ ~768px tall, so the
   max-height ceiling leaves the iPad/desktop layout completely untouched.

   The :has() selectors degrade gracefully — a browser without :has() simply
   ignores these rules and keeps the existing vertical stack, so nothing breaks.
   ========================================================================== */
@media (orientation: landscape) and (max-height: 560px) {
  /* Reclaim vertical rhythm so the question card wins the available space. */
  body.kid .app   { gap: clamp(6px, 1.4vh, 12px); }
  body.kid .qcard { padding: clamp(8px, 2vh, 20px) clamp(12px, 2.6vw, 26px); }

  /* (The "sets" picker's landscape columns are handled by the symmetric grid
     system at the end of this file.) */

  /* ---- Numeric questions → calculator layout (prompt/answer | keypad) ---- */
  .qcard:has(.keypad) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: 1fr auto;
    align-items: center;
    justify-items: center;
    column-gap: clamp(16px, 4vw, 40px);
    row-gap: clamp(6px, 1.6vh, 14px);
  }
  .qcard:has(.keypad) .prompt         { grid-column: 1; grid-row: 1; align-self: end; margin: 0; }
  .qcard:has(.keypad) .answer-display { grid-column: 1; grid-row: 2; align-self: start; }
  .qcard:has(.keypad) .keypad {
    grid-column: 2; grid-row: 1 / span 2;
    width: min(44vw, 290px); height: 100%;
    grid-auto-rows: 1fr;        /* keys grow to fill the height → big tap targets */
  }

  /* ---- Reading / choice questions with a passage → side-by-side ---- */
  .qcard.reading:has(.passage) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
    grid-template-rows: auto minmax(0, 1fr);
    column-gap: clamp(14px, 3vw, 30px);
    row-gap: clamp(8px, 1.6vh, 14px);
    align-content: stretch;
  }
  .qcard.reading:has(.passage) .passage {
    grid-column: 1; grid-row: 1 / span 2;
    max-height: none; height: 100%;
  }
  .qcard.reading:has(.passage) .prompt  { grid-column: 2; grid-row: 1; }
  .qcard.reading:has(.passage) .choices {
    grid-column: 2; grid-row: 2;
    width: 100%; align-self: stretch; overflow-y: auto;
  }

  /* ---- Choice questions WITHOUT a passage (assessment, word study) ----
     Stacked single-column choices need more height than a landscape phone
     has. Two columns spend the spare width instead, so all four choices sit
     on screen at once. */
  .qcard.reading:not(:has(.passage)) .choices {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: clamp(8px, 1.6vh, 12px);
    width: 100%;
    overflow-y: auto;
  }

  /* Compact the headers so the question keeps the height. The kid topbar drops
     its subtitle line; the assessment keeps its save pill but slims down. */
  body.kid .topbar { gap: 10px; }
  body.kid .greeting h1 { font-size: 17px; }
  body.kid .greeting .date { display: none; }
  .assess-top .save-pill { padding: 6px 11px; font-size: 11px; }
  body.kid .progress .bar { height: 8px; }
}

/* ==========================================================================
   Narrow phones (portrait) — keep the grown-ups dashboard from overflowing
   --------------------------------------------------------------------------
   The report breakdown and "Manage users" tables have up to five columns. On a
   ~360px-wide phone that's wider than the screen, which pushed content off the
   edge ("cut off"). Two safeguards: every data table now lives in a horizontal
   scroll wrapper (.table-scroll) so it can never break the page layout, and on
   small screens the cells get tighter padding and are allowed to wrap.
   ========================================================================== */
.table-scroll {
  /* Let a wide table scroll sideways on its own instead of shoving the whole
     page off-screen. On roomy screens the table fits and this never engages. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior-x: contain;
  margin: 0 -2px;          /* tiny bleed so the scroll edge isn't flush to text */
  padding: 0 2px;
}

@media (max-width: 480px) {
  /* Give the tables more room by trimming the section + cell padding. */
  .domain-section { padding: 16px 14px; }
  table.breakdown th, table.breakdown td { padding: 9px 8px; }
  table.breakdown .subj { gap: 7px; }
  /* Long usernames / emails wrap instead of forcing the table wider. */
  .users-table td, .users-table th { overflow-wrap: anywhere; }
  .u-sub { overflow-wrap: anywhere; }
}

/* ==========================================================================
   Symmetric kid grids — never leave a "dead space"
   --------------------------------------------------------------------------
   The subject/skill grids change size by grade: Grade 1 math shows 2 subjects
   plus the bonus = 3 buttons; Grade 4 shows 6. We keep them balanced — an even
   count fills the row, and a lone odd button stretches to fill the row instead
   of leaving a gap. `data-count` (the number of buttons) is set in the JS.

   Portrait: two columns; a lone last button spans the full width.
   Landscape (short + wide): a 12-track grid so 3-, 4- and "3 + 2 wide"-button
   rows all come out even, with no empty columns.
   ========================================================================== */

/* Portrait — a lone last button stretches across both columns. */
.grid > *:last-child:nth-child(odd),
.reading-grid > *:last-child:nth-child(odd),
.sets > *:last-child:nth-child(odd) { grid-column: 1 / -1; }

@media (orientation: landscape) {
  /* 12 tracks divide evenly by 2, 3, 4 and 6 — every layout we produce fits. */
  .grid, .reading-grid, .sets { grid-template-columns: repeat(12, 1fr); }
  .grid > *, .reading-grid > *, .sets > * { grid-column: span 4; } /* default: 3 across */

  /* 4 buttons → 4 across (each spans 3). */
  .grid[data-count="4"] > *,
  .reading-grid[data-count="4"] > *,
  .sets[data-count="4"] > * { grid-column: span 3; }

  /* 5 buttons → 3 across, then 2 half-width buttons fill the last row. */
  .grid[data-count="5"] > *:nth-child(n+4),
  .reading-grid[data-count="5"] > *:nth-child(n+4) { grid-column: span 6; }
  /* 3 and 6 buttons use the default 3-across (one or two even rows). */
}

/* ==========================================================================
   Onboarding placement assessment
   --------------------------------------------------------------------------
   Starts with a video-game title screen — "WELCOME <NAME>" + a giant pulsing
   START button — built on the .epic victory layers (rays/glow/confetti).
   The questions reuse the quiz/choices styling, add the corner "Saved ✓"
   auto-save pill, a calm neutral selected-choice state (a placement test
   shouldn't read as right/wrong) and a big wordless → arrow to advance.
   ========================================================================== */

/* ---- Welcome title screen ---- */
.welcome-card { gap: clamp(8px, 1.8vmin, 16px); }
.welcome-mascot {
  font-size: clamp(56px, 13vmin, 110px); line-height: 1;
  filter: drop-shadow(0 12px 26px rgba(251, 191, 36, 0.45));
  animation: epic-trophy 2.4s ease-in-out infinite;
}
.welcome-hi {
  font-size: clamp(15px, 2.8vmin, 21px); font-weight: 900;
  letter-spacing: 0.5em; text-indent: 0.5em; text-transform: uppercase;
  color: #c7d2fe;
}
.welcome-name {
  font-size: clamp(46px, 11vmin, 96px);
  text-transform: uppercase;
  overflow-wrap: anywhere;
}
.welcome-sub { font-size: clamp(15px, 2.8vmin, 19px); font-weight: 700; color: rgba(255, 255, 255, 0.94); }
.welcome-start {
  margin-top: clamp(8px, 2vmin, 18px);
  border: 0; cursor: pointer; font-family: inherit;
  font-size: clamp(24px, 5vmin, 38px); font-weight: 900;
  letter-spacing: 0.12em; text-indent: 0.12em;
  color: #1e1b4b;
  padding: clamp(16px, 3vmin, 26px) clamp(42px, 9vmin, 80px);
  border-radius: 999px;
  background: linear-gradient(180deg, #fde68a, #fbbf24 55%, #f59e0b);
  box-shadow: 0 18px 44px -10px rgba(251, 191, 36, 0.8), inset 0 2px 0 rgba(255, 255, 255, 0.65);
  animation: start-pulse 1.5s ease-in-out infinite;
  transition: filter 0.12s ease;
}
.welcome-start:active { animation: none; transform: scale(0.94); }
@media (hover: hover) { .welcome-start:hover { filter: brightness(1.07); } }
@keyframes start-pulse {
  0%, 100% { transform: scale(1);    box-shadow: 0 18px 44px -10px rgba(251, 191, 36, 0.8),  inset 0 2px 0 rgba(255, 255, 255, 0.65); }
  50%      { transform: scale(1.06); box-shadow: 0 26px 64px -8px  rgba(251, 191, 36, 0.95), inset 0 2px 0 rgba(255, 255, 255, 0.65); }
}

/* ---- Question screens ---- */
.assess-top .greeting h1 { font-size: clamp(18px, 3.6vmin, 28px); }

.save-pill {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 7px;
  padding: clamp(7px, 1.4vmin, 10px) clamp(11px, 1.9vmin, 15px);
  border-radius: 999px;
  font-size: clamp(12px, 2vmin, 14px); font-weight: 700;
  background: var(--good-soft); color: var(--good);
  border: 1px solid rgba(34, 197, 94, 0.35);
  box-shadow: var(--shadow-sm);
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.save-pill .save-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.save-pill[data-state="saving"] { background: var(--warn-soft); color: #b45309; border-color: #fde68a; }
.save-pill[data-state="saving"] .save-dot { animation: save-pulse 0.9s ease-in-out infinite; }
.save-pill[data-state="error"] { background: var(--bg-soft); color: var(--ink-soft); border-color: var(--border); }
@keyframes save-pulse { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
:root[data-theme="dark"] .save-pill { background: rgba(34, 197, 94, 0.16); }

/* Neutral "chosen" state for an assessment answer (no green/red). */
.choice.chosen { border-color: var(--brand-500); background: var(--brand-soft); color: var(--brand-700); box-shadow: var(--ring); }
/* Wordless "next" arrow shown once an answer is picked. */
.assess-next { font-size: clamp(26px, 5vmin, 38px); line-height: 1; }
.assess-loading { padding: clamp(40px, 12vmin, 90px) 0; }
@media (prefers-reduced-motion: reduce) {
  .save-pill[data-state="saving"] .save-dot,
  .welcome-mascot, .welcome-start { animation: none; }
}

/* ==========================================================================
   "Original Assessment" panel (the frozen placement result, owner + parent)
   ========================================================================== */
.orig-assess {
  background:
    radial-gradient(120% 140% at 100% 0%, var(--brand-soft), transparent 42%),
    var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: 18px 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-sm);
}
.oa-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.oa-title { font-weight: 800; font-size: clamp(15px, 2.4vmin, 17px); letter-spacing: -0.02em; }
.oa-when { font-size: clamp(11px, 1.8vmin, 12px); color: var(--ink-soft); font-weight: 600; }
.oa-sub { color: var(--ink-soft); font-size: clamp(12px, 2vmin, 14px); margin: 6px 0 12px; line-height: 1.5; }
.oa-empty { color: var(--ink-soft); font-size: clamp(13px, 2.1vmin, 14px); margin: 8px 0 0; line-height: 1.55; }
.oa-overall { font-size: clamp(13px, 2.1vmin, 15px); font-weight: 600; color: var(--ink); margin-bottom: 10px; }
.oa-overall b { font-variant-numeric: tabular-nums; }
.oa-rows { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.oa-row {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r-md); padding: 10px 14px;
}
.oa-subj { font-weight: 700; min-width: 8.5em; }
.oa-placed { color: var(--ink-soft); font-size: clamp(12px, 2vmin, 14px); flex: 1 1 auto; }
.oa-placed b { color: var(--brand-700); }
:root[data-theme="dark"] .oa-placed b { color: #a5b4fc; }
.oa-now-inline { color: var(--ink-3); font-weight: 600; }
.oa-score { font-weight: 800; font-variant-numeric: tabular-nums; }
.oa-pct { color: var(--ink-soft); font-weight: 600; font-size: 0.85em; }
.orig-assess .btn.tiny { margin-top: 2px; }
.oa-detail { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 10px; }
.oa-detail-row { display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap; }
.oa-bands { display: flex; flex-wrap: wrap; gap: 6px; }
.oa-band {
  font-size: clamp(11px, 1.9vmin, 13px); font-weight: 700;
  padding: 3px 9px; border-radius: 999px; font-variant-numeric: tabular-nums;
  border: 1px solid var(--border-strong); background: var(--surface);
}
.oa-band.pass { background: var(--good-soft); color: var(--good); border-color: transparent; }
.oa-band.fail { background: var(--bad-soft); color: var(--bad); border-color: transparent; }
:root[data-theme="dark"] .oa-band.pass { background: rgba(34,197,94,.16); color: #86efac; }
:root[data-theme="dark"] .oa-band.fail { background: rgba(248,113,113,.16); color: #fca5a5; }
