/* Practice Tests. Phone first. Three age themes set by html[data-grade-band]. */

:root {
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --base: 16px;
  --radius: 6px;
  --btn-h: 44px;
  --gutter: 16px;
  --maxw: 760px;

  --bg: #e7ebf1;             /* page, one step darker 2026-10-25 (was #f4f6f9) so cards stand out */
  --surface: #ffffff;
  --text: #17202e;
  --muted: #5b6575;
  --line: #b7c0cd;           /* card edges, mid tone 2026-10-25 (was #d3d9e2) */
  --primary: #1f3a68;
  --primary-text: #ffffff;
  --accent: #5b6b82;
  --chip: #eef1f6;
  --chip-on: #1f3a68;
  --chip-on-text: #ffffff;
  --good: #146c3a;
  --good-bg: #e6f4ec;
  --bad: #a52a1f;
  --bad-bg: #fbece9;
  --warn: #8a4b00;
  --focus: #1a73e8;
  --select: #1a5fd0;         /* chosen answer, the same blue in every band (ruling 15) */
  --select-bg: #eaf1fd;
  --shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 1px 3px rgba(16, 24, 40, 0.08);
  --lift: 0 2px 8px rgba(16, 24, 40, 0.10);   /* soft shadow under cards and answer buttons (2026-10-25) */
  --heading-weight: 650;
  --q-font: "Atkinson Hyperlegible", system-ui, sans-serif;
  --q-ink: #0b2350;
  --q-bg: #eef3fc;
  --q-edge: #1a5fd0;
}
.progress-table td.good { color: var(--good); font-weight: 600; }
.progress-table td.bad { color: var(--bad); font-weight: 600; }
.progress-table tr.is-current td { background: var(--select-bg); }

/* Grades 1 to 3: large type, round corners, warm and bright, playful but tidy. */
html[data-grade-band="k3"] {
  --font: ui-rounded, "Nunito", "Segoe UI Rounded", "Arial Rounded MT Bold", system-ui, sans-serif;
  --base: 20px;
  --radius: 18px;
  --btn-h: 56px;
  --bg: #fcefcc;             /* 2026-10-25, was #fff8e1 */
  --surface: #ffffff;
  --text: #2b2118;
  --muted: #6b5a48;
  --line: #e0bd7a;           /* was #f1d9a6 */
  --primary: #b53a27;        /* coral, darkened 2026-10-24 and again 2026-10-25 for 4.5:1 on the deeper page (was #e2553f, then #c8432f) */
  --primary-text: #ffffff;
  --accent: #1f68a6;         /* sky, darkened 2026-10-24 and 2026-10-25 for 4.5:1 (was #2f8fd8, then #2272b5) */
  --chip: #fff1c7;           /* warm yellow */
  --chip-on: #1f68a6;
  --primary-dark: #8a2b1c;    /* the 3D edge under coral buttons, below the 2026-10-25 coral */
  --chip-on-text: #ffffff;
  --good: #176a36;           /* 2026-10-25 for 4.5:1 on every look's page (was #1d7a3e) */
  --good-bg: #e3f6e8;
  --bad: #b23a2a;
  --bad-bg: #fdebe7;
  --shadow: 0 3px 0 var(--tint, rgba(226, 85, 63, 0.18));
  --heading-weight: 800;
}

/* Grades 4 to 6: bright but tidy. */
html[data-grade-band="g46"] {
  --base: 18px;
  --radius: 12px;
  --btn-h: 48px;
  --bg: #e0f2ee;             /* 2026-10-25, was #f1faf8 */
  --surface: #ffffff;
  --text: #1c2430;
  --muted: #56606e;
  --line: #9fcfc5;           /* was #c9e4df */
  --primary: #0c7068;        /* teal, 2026-10-25 for 4.5:1 on the deeper page (was #0f7c74) */
  --primary-text: #ffffff;
  --accent: #a1500b;         /* orange, darkened 2026-10-24 and 2026-10-25 (was #e07a1f, then #b35a0e) */
  --chip: #e5f4f1;
  --chip-on: #6a3d7a;        /* plum */
  --chip-on-text: #ffffff;
  --good: #136b3a;
  --good-bg: #e4f5ea;
  --bad: #a8321f;
  --bad-bg: #fcebe7;
  --heading-weight: 750;
}

/* Grades 7 to 12: navy, grey and white, formal. */
html[data-grade-band="g712"] {
  --base: 16px;
  --radius: 6px;
  --btn-h: 44px;
  --bg: #e7ebf1;
  --primary: #1f3a68;        /* navy */
  --chip-on: #1f3a68;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: var(--base);
  line-height: 1.5;
  overflow-x: hidden;
}
[hidden] { display: none !important; }
img { max-width: 100%; height: auto; }

h1, h2, h3 { line-height: 1.25; font-weight: var(--heading-weight); margin: 0 0 0.5em; }
h1 { font-size: 1.6em; }
h2 { font-size: 1.2em; margin-top: 1.3em; }
h3 { font-size: 1em; }
p { margin: 0 0 0.75em; }
.muted { color: var(--muted); font-weight: 500; }
.small { font-size: 0.85em; }
.break { overflow-wrap: anywhere; }
.center { text-align: center; }
.good { color: var(--good); font-weight: 600; }
.bad { color: var(--bad); }
.hint { color: var(--muted); font-size: 0.9em; margin: 0.5em 0; font-weight: 500; }
.big-line { font-size: 1.2em; font-weight: 600; }

/* Layout */
.view, .topbar-inner {
  max-width: var(--maxw);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}
.view { padding-top: 20px; padding-bottom: 48px; outline: none; }
h1:focus { outline: none; }

.card {
  background: var(--surface);
  border: 1.5px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  margin: 0 0 16px;
  box-shadow: var(--shadow), var(--lift);
}
.row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 10px 0; }
.row.center { justify-content: center; }
.row input[type="text"], .row input[type="email"] { flex: 1 1 200px; min-width: 0; }

/* Header */
.topbar { background: var(--surface); border-bottom: 1px solid var(--line); }
.topbar-inner {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px;
  padding-top: 8px; padding-bottom: 8px;
}
.brand { font-weight: var(--heading-weight); color: var(--primary); text-decoration: none; margin-right: auto; }
.who { margin: 0; font-size: 0.9em; }
.acting-tag { color: var(--warn); font-weight: 600; }
.tools { display: flex; flex-wrap: wrap; gap: 6px; }

/* Message bar */
.msg {
  display: flex; align-items: flex-start; gap: 10px;
  width: calc(100% - 2 * var(--gutter));
  max-width: calc(var(--maxw) - 2 * var(--gutter));
  margin: 12px auto 0;
  padding: 10px 14px;
  background: var(--bad-bg);
  border: 1px solid var(--bad);
  color: var(--text);
  border-radius: var(--radius);
}
.msg[data-kind="ok"], .msg[data-kind="info"] { background: var(--good-bg); border-color: var(--good); }
.msg-text { margin: 0; flex: 1; font-weight: 500; }
.msg-close {
  border: 0; background: transparent; font-size: 1.4em; line-height: 1; cursor: pointer;
  min-width: 44px; min-height: 44px; margin: -10px -10px -10px 0; color: inherit;
  border-radius: var(--radius);
}

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--btn-h);
  padding: 8px 18px;
  font: inherit; font-weight: 600;
  color: var(--primary);
  background: var(--surface);
  border: 2px solid var(--primary);
  border-radius: var(--radius);
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  touch-action: manipulation;
}
.btn.primary { background: var(--primary); color: var(--primary-text); }
.btn.big { min-height: calc(var(--btn-h) + 8px); padding: 10px 24px; font-size: 1.05em; }
.btn.small { min-height: 44px; padding: 6px 12px; font-size: 0.85em; }
.btn.warn { border-color: var(--bad); color: var(--bad); }
.btn.warn.armed { background: var(--bad); color: #ffffff; }
.btn:disabled, .btn[disabled] { opacity: 0.45; cursor: not-allowed; }
.btn:not(:disabled):hover { filter: brightness(0.95); }
.btn.inactive { opacity: 0.45; }
.need-answer { border-radius: 14px; box-shadow: 0 0 0 4px #e8820c; animation: need-pulse 0.6s ease-in-out 2; }
.need-line { color: var(--warn); font-weight: 600; margin: 6px 0; }
@keyframes need-pulse { 0%, 100% { box-shadow: 0 0 0 4px #e8820c; } 50% { box-shadow: 0 0 0 9px rgba(232, 130, 12, 0.35); } }
@media (prefers-reduced-motion: reduce) { .need-answer { animation: none; } }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* Form fields */
input[type="text"], input[type="email"], input[type="number"], select {
  font: inherit;
  min-height: var(--btn-h);
  padding: 8px 12px;
  border: 2px solid var(--line);
  border-radius: var(--radius);
  background: #ffffff;
  color: var(--text);
  max-width: 100%;
}
input:focus-visible, select:focus-visible { border-color: var(--focus); }
.field { display: flex; flex-direction: column; gap: 4px; margin: 0 0 12px; }
.field label { font-weight: 600; font-size: 0.9em; }
.grade-input { width: 5.5em; }
fieldset.options { border: 1px solid var(--line); border-radius: var(--radius); padding: 10px 14px; margin: 0 0 12px; }
.opt { display: flex; align-items: center; gap: 10px; min-height: 44px; }
.opt input { width: 22px; height: 22px; }

/* Chips */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px;
  padding: 6px 14px;
  font: inherit; font-size: 0.95em;
  color: var(--text);
  background: var(--chip);
  border: 2px solid transparent;
  border-radius: 999px;
  cursor: pointer;
  text-align: left;
  max-width: 100%;
  overflow-wrap: anywhere;
}
html[data-grade-band="g712"] .chip { border-radius: var(--radius); }
.chip[aria-pressed="true"] { background: var(--chip-on); color: var(--chip-on-text); }
.chip[aria-pressed="true"]::before { content: "\2713"; font-weight: 700; }
.chip.partial { border-color: var(--chip-on); }
.chip.topic-chip { font-weight: 700; }
.chip.choice-chip { font-weight: 600; }
.chip-sel { cursor: default; background: var(--surface); border-color: var(--line); padding: 2px 4px 2px 12px; min-height: 40px; font-size: 0.85em; }
.chip-x {
  border: 0; background: transparent; color: inherit; font-size: 1.25em; line-height: 1;
  min-width: 36px; min-height: 36px; border-radius: 999px; cursor: pointer;
}
.chip-x:hover { background: var(--chip); }
.tag {
  display: inline-block; font-size: 0.72em; font-weight: 700; padding: 2px 8px;
  border-radius: 999px; background: var(--chip); color: var(--muted); white-space: nowrap;
}
.tag-match { background: var(--good-bg); color: var(--good); }
.tag-own { background: var(--chip); color: var(--text); }

/* Builder */
.summary {
  position: sticky; top: 0; z-index: 5;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 12px;
  margin: 0 0 12px;
  box-shadow: var(--shadow);
  max-height: 90px; overflow-y: auto;   /* ruling 12 */
}
.summary-title { font-weight: 700; margin: 0; }
.summary .chips { margin: 4px 0 0; gap: 6px; }
.summary .chip-sel { min-height: 36px; }
.link-btn {
  font: inherit; font-weight: 600; color: var(--select); background: transparent; border: 0;
  text-decoration: underline; cursor: pointer; min-height: 44px; padding: 0 6px;
}
.block { display: block; }
.confirm { display: inline-flex; flex-wrap: wrap; gap: 6px; }
.added-line { margin: 10px 0 0; }
.added-line:empty { display: none; }
.round-err:empty { display: none; }
.round-err { margin-top: 10px; font-weight: 600; }
/* Ruling 25: the course chip shows the short label and the NYS name under it, both at body size. */
.chip.course-chip { font-size: 1em; }
.course-text { display: flex; flex-direction: column; }
.course-nys { font-weight: 400; }
.chapter {
  background: var(--surface); border: 1.5px solid var(--line); box-shadow: var(--lift); border-radius: var(--radius);
  margin: 0 0 10px;
}
.chapter > summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  min-height: 48px; padding: 10px 14px; cursor: pointer; font-weight: 600; list-style: none;
}
.chapter > summary::-webkit-details-marker { display: none; }
.chapter > summary::before { content: "+"; font-weight: 700; width: 1em; color: var(--accent); }
.chapter[open] > summary::before { content: "\2212"; }
.ch-name { flex: 1; }
.count { font-size: 0.8em; color: var(--good); white-space: nowrap; }
.chapter-body { padding: 0 14px 12px; }
.topic { border-top: 1px dashed var(--line); padding-top: 8px; margin-top: 8px; }
.start-row { margin: 24px 0; display: flex; flex-direction: column; align-items: stretch; gap: 6px; }

/* Mix slider: left number multiple choice, right number short answer */
.mix { margin: 8px 0 4px; }
.mix-labels { display: flex; justify-content: space-between; gap: 10px; font-weight: 600; flex-wrap: wrap; }
.mix-num.right { text-align: right; margin-left: auto; }
input[type="range"] {
  width: 100%; height: 44px; margin: 4px 0; background: transparent;
  -webkit-appearance: none; appearance: none; cursor: pointer;
}
input[type="range"]::-webkit-slider-runnable-track {
  height: 12px; border-radius: 999px;
  background: linear-gradient(to right, var(--primary) var(--fill, 70%), var(--accent) var(--fill, 70%));
}
input[type="range"]::-moz-range-track { height: 12px; border-radius: 999px; background: var(--accent); }
input[type="range"]::-moz-range-progress { height: 12px; border-radius: 999px; background: var(--primary); }
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 32px; height: 32px; margin-top: -10px;
  border-radius: 50%; background: #ffffff; border: 3px solid var(--text);
}
input[type="range"]::-moz-range-thumb {
  width: 28px; height: 28px; border-radius: 50%; background: #ffffff; border: 3px solid var(--text);
}

/* Home */
.home-actions { display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 16px; }
@media (min-width: 560px) { .home-actions { grid-template-columns: 1fr 1fr; } }

/* Building */
.progress-line { font-weight: 600; font-size: 1.1em; }
.spinner {
  width: 44px; height: 44px; margin: 16px auto; border-radius: 50%;
  border: 5px solid var(--chip); border-top-color: var(--primary);
  animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Test */
.test-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.test-head h1 { margin-bottom: 0.15em; }
/* 2026-10-26: on a phone the title ("English Language Arts" at grades 1-3 type) pushed Leave past the right edge;
   the title column may shrink and the buttons wrap under it, so the page never scrolls sideways. */
.test-head { flex-wrap: wrap; }
.test-head > div { flex: 1 1 12em; min-width: 0; }
.test-head h1 { overflow-wrap: anywhere; }
.progress { margin: 10px 0 16px; }
.bar { height: 10px; background: var(--chip); border-radius: 999px; overflow: hidden; }
.bar span { display: block; height: 100%; width: 0; background: var(--primary); transition: width 0.3s ease; }
.progress-text { margin: 4px 0 0; font-weight: 600; font-size: 0.9em; color: var(--muted); }
/* The question and its choices are what the eye should find (Dr. M, 2026-10-16): their own typeface,
   larger, a deep ink colour, and a tinted panel; the counters and labels around them step back. */
.q-num { font-size: 0.78em; color: var(--muted); margin: 0 0 0.4em; font-weight: 600; letter-spacing: 0.02em; }
/* Reports 33-40 (2026-10-30): the topic above each question, the topics a test covers, the correct answer at the end. */
.q-topic { margin: -0.2em 0 0.5em; }
.covers { margin: 6px 0 10px; }
.covers summary { cursor: pointer; }
.covers ul { margin: 6px 0 0; padding-left: 1.2em; }
.right-answer { font-weight: 600; margin: 8px 0; }
.stem {
  font-family: var(--q-font); font-size: 1.32em; line-height: 1.45; font-weight: 600; color: var(--q-ink);
  background: var(--q-bg); border-left: 5px solid var(--q-edge); border-radius: var(--radius);
  padding: 14px 16px; margin: 0 0 14px;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.choice { font-family: var(--q-font); font-size: 1.15em; font-weight: 500; color: var(--q-ink); }
.choices { display: flex; flex-direction: column; gap: 10px; margin: 10px 0; }
.choice {
  display: flex; align-items: center; gap: 12px; width: 100%;
  min-height: var(--btn-h);
  padding: 10px 14px;
  font: inherit; text-align: left; color: var(--text);
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--lift);
  cursor: pointer;
}
.choice .letter {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  width: 1.9em; height: 1.9em; border-radius: 50%; background: var(--chip); font-weight: 700;
}
.choice-text { flex: 1; overflow-wrap: anywhere; }
.choice[aria-checked="true"] { border-color: var(--select); background: var(--select-bg); box-shadow: inset 0 0 0 1px var(--select); }
.choice[aria-checked="true"] .letter { background: var(--select); color: #ffffff; }
/* Only after checking: green for right, red for not right. */
.choice.is-right { border-color: var(--good); background: var(--good-bg); box-shadow: inset 0 0 0 1px var(--good); }
.choice.is-right .letter { background: var(--good); color: #ffffff; }
.choice.is-wrong { border-color: var(--bad); background: var(--bad-bg); box-shadow: inset 0 0 0 1px var(--bad); }
.choice.is-wrong .letter { background: var(--bad); color: #ffffff; }
.choice:disabled { cursor: default; }
.choice.tried { opacity: 0.45; background: var(--bg); text-decoration: line-through; }
.choice.tried .tag { text-decoration: none; }
.sa-box { display: flex; flex-direction: column; gap: 4px; margin: 10px 0; }
.sa-input { width: 100%; font-size: 1.05em; }
.given { font-weight: 600; overflow-wrap: anywhere; }
.result { font-size: 1.1em; }
.saved { color: var(--muted); font-weight: 600; }
.explain { display: grid; gap: 10px; margin: 10px 0; }
.explain > div { border-left: 4px solid var(--accent); padding: 6px 12px; background: var(--bg); border-radius: 0 var(--radius) var(--radius) 0; }
.explain .explain-rule { border-left-color: var(--primary); }
.explain h3 { font-size: 0.9em; margin: 0 0 0.2em; }
.explain p { margin: 0; }
.retry { border-top: 1px solid var(--line); margin-top: 12px; padding-top: 10px; }
.retry-title { font-weight: 700; margin-bottom: 0.3em; }
.nav-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; margin: 12px 0 24px; }
.nav-row .hint { flex-basis: 100%; }
@media (min-width: 700px) {
  .nav-row { justify-content: flex-end; }
  .nav-row .hint { flex-basis: auto; margin-right: auto; }
}

/* Score */
.score { font-size: 3em; font-weight: 800; margin: 12px 0; color: var(--primary); }
.score-zoom { animation: score-zoom 1.4s ease-in-out 1; }
@keyframes score-zoom {
  0% { transform: scale(0.6); opacity: 0; }
  45% { transform: scale(1.15); opacity: 1; }
  70% { transform: scale(0.95); }
  100% { transform: scale(1); }
}
html[data-effects="off"] .score-zoom { animation: none; }
/* Score page (2026-10-25): confetti thinner over the score card at the top of the column, full strength
   below it and, on wide screens, at the sides. canvas-confetti draws on one fixed canvas appended to <body>;
   a browser without :has() or mask simply shows full confetti. */
html:has(.score) body > canvas {
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.25) 0, rgba(0, 0, 0, 0.25) 470px, #000 560px),
    linear-gradient(to right, #000 calc(50% - 400px), transparent calc(50% - 370px), transparent calc(50% + 370px), #000 calc(50% + 400px));
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.25) 0, rgba(0, 0, 0, 0.25) 470px, #000 560px),
    linear-gradient(to right, #000 calc(50% - 400px), transparent calc(50% - 370px), transparent calc(50% + 370px), #000 calc(50% + 400px));
}
.pop { animation: pop 0.45s ease-out 1; }
@keyframes pop { 0% { transform: scale(0.6); opacity: 0; } 60% { transform: scale(1.15); opacity: 1; } 100% { transform: scale(1); } }
html[data-effects="off"] .pop { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .score-zoom, .spinner, .pop { animation: none; }
  .bar span { transition: none; }
}

/* Review */
.round-box { text-align: center; }
.round-box .btn { width: 100%; }
@media (min-width: 560px) { .round-box .btn { width: auto; } }

/* Upload */
.file-btn { position: relative; overflow: hidden; }
.file-btn input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; font-size: 0; }
.file-btn:focus-within { outline: 3px solid var(--focus); outline-offset: 2px; }
.note { font-size: 0.9em; color: var(--muted); border-left: 4px solid var(--line); padding-left: 10px; }
.thumbs { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin: 10px 0; }
.thumb { position: relative; margin: 0; width: 96px; }
.thumb img { width: 96px; height: 120px; object-fit: cover; border-radius: var(--radius); border: 1px solid var(--line); display: block; }
.thumb .chip-x { position: absolute; top: 2px; right: 2px; background: var(--surface); box-shadow: var(--shadow); }

/* Print options */
.pdf-out { margin-top: 12px; }

/* Admin */
.user-name { margin: 0; }
.history { margin-top: 8px; }
.table { width: 100%; border-collapse: collapse; font-size: 0.9em; margin: 8px 0; table-layout: fixed; }
.table th, .table td { text-align: left; padding: 6px 6px; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; vertical-align: top; }
.table th { font-weight: 700; color: var(--muted); }
.add-user { margin-top: 16px; }

/* Sign in */
.gbtn { display: flex; justify-content: center; min-height: 44px; margin: 16px 0; }
.dev-login { margin-top: 20px; padding-top: 14px; border-top: 1px dashed var(--line); text-align: left; }
.dev-login label { font-weight: 600; font-size: 0.9em; }

/* Grades 1 to 3: small decorations drawn in CSS, no mascot. */
html[data-grade-band="k3"] h1::before {
  content: ""; display: inline-block; width: 0.7em; height: 0.7em; margin-right: 0.35em;
  background: var(--accent); border-radius: 50%;
  box-shadow: 0.9em 0 0 -0.1em var(--dot, #f6c445), 1.6em 0 0 -0.2em var(--primary);
  vertical-align: 0.05em; margin-right: 1.9em;
}
html[data-grade-band="k3"] .card { border-width: 2px; }
html[data-grade-band="k3"] .choice:not([aria-checked="true"]) .letter { background: var(--chip); }
html[data-grade-band="k3"] .btn.primary { box-shadow: 0 4px 0 var(--primary-dark, #b53e2c); }
html[data-grade-band="k3"] .btn.primary:active:not(:disabled) { transform: translateY(2px); box-shadow: 0 2px 0 var(--primary-dark, #b53e2c); }
html[data-grade-band="k3"] .progress .bar { height: 14px; }
html[data-grade-band="k3"] .bar span { background: var(--bar, linear-gradient(90deg, var(--primary), #f6c445)); }

/* Grades 4 to 6 */
html[data-grade-band="g46"] h1 { color: var(--primary); }
html[data-grade-band="g46"] .bar span { background: var(--bar, linear-gradient(90deg, var(--primary), var(--accent))); }

/* Grades 7 to 12: plain and formal */
html[data-grade-band="g712"] .card { box-shadow: 0 1px 4px rgba(16, 24, 40, 0.08); }
html[data-grade-band="g712"] .score { color: var(--text); }

/* Progress page (cards for phones) */
.prog p { margin: 4px 0; }
.prog-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; flex-wrap: wrap; }
.prog-q { border-bottom: 1px solid var(--line); padding: 8px 2px; }
.prog-q p { margin: 2px 0; }
.prog-q.is-current { background: var(--select-bg); }
.prog-q .good { color: var(--good); font-weight: 700; }
.prog-q .bad { color: var(--bad); font-weight: 700; }
.prog-q .now { color: var(--select); font-weight: 700; }
/* Question by question as a table (owner 2026-10-27). Wide screens: a real table with a coloured edge per result;
   phones: each row folds into a block, every cell led by its label. */
.prog-counts { font-weight: 700; margin: 10px 0 6px; }
.prog-table { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.prog-table th { text-align: left; font-size: 0.85em; color: var(--muted); padding: 8px 10px; border-bottom: 2px solid var(--line); background: var(--chip); }
.prog-table td { padding: 8px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
.prog-table tr.prog-row > td:first-child { border-left: 5px solid var(--line); }
.prog-table tr.prog-row.r-good > td:first-child { border-left-color: var(--good); }
.prog-table tr.prog-row.r-bad > td:first-child { border-left-color: var(--bad); }
.prog-table tr.prog-row.r-now > td:first-child { border-left-color: var(--select); }
.prog-table tr.is-current td { background: var(--select-bg); }
.prog-table .good { color: var(--good); font-weight: 700; }
.prog-table .bad { color: var(--bad); font-weight: 700; }
.prog-table .now { color: var(--select); font-weight: 700; }
@media (max-width: 640px) {
  .prog-table, .prog-table tbody, .prog-table tr, .prog-table td { display: block; width: 100%; }
  .prog-table { border: 0; background: transparent; }
  .prog-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .prog-table tr.prog-row { background: var(--surface); border: 1px solid var(--line); border-left: 6px solid var(--line); border-radius: var(--radius); margin: 0 0 10px; padding: 4px 0; }
  .prog-table tr.prog-row.r-good { border-left-color: var(--good); }
  .prog-table tr.prog-row.r-bad { border-left-color: var(--bad); }
  .prog-table tr.prog-row.r-now { border-left-color: var(--select); }
  .prog-table tr.prog-row > td:first-child { border-left: 0; }
  .prog-table td { border: 0; padding: 3px 12px; display: grid; grid-template-columns: 8.5em 1fr; gap: 8px; }
  .prog-table td::before { content: attr(data-label); color: var(--muted); font-size: 0.85em; font-weight: 600; }
}

.topic-search { width: 100%; min-height: var(--btn-h); padding: 8px 12px; font: inherit; border: 2px solid var(--line); border-radius: var(--radius); background: var(--surface); color: var(--text); }
.topic-search:focus { outline: 3px solid var(--focus); outline-offset: 2px; }
.search-note { margin: 6px 0 10px; }

/* Requests to join */
.req-mark { display: inline-flex; width: 1.6em; height: 1.6em; border-radius: 50%; align-items: center; justify-content: center; font-weight: 800; background: var(--chip); }
.req.pending .req-mark { background: var(--warn); color: #fff; }
.req.accepted .req-mark { background: var(--good); color: #fff; }
.req.rejected .req-mark { background: var(--bad); color: #fff; }
.linkish { background: none; border: 0; padding: 0; font: inherit; color: inherit; text-align: left; cursor: pointer; text-decoration: underline dotted; }
.early-line { margin: 6px 0 0; }
.kid-row input.kid-name { flex: 1 1 10em; }

textarea { font: inherit; }

/* Regents questions: the printed images, and four numbered answer buttons */
.stem-media { padding: 10px; background: #ffffff; }
.stem-media img { display: block; width: 100%; height: auto; margin: 0 0 10px; border-radius: 4px; }
.stem-media img.regents-ctx { border: 1px solid var(--line); }
.regents-src { font-family: var(--font); font-size: 0.72rem; font-weight: 500; color: var(--muted); margin: 0; }
/* 2026-11-02: at iPhone width the D button ran past the right edge (repeat(4, 1fr) never shrinks a column under its
   content, and 14 px side padding plus the 2.4em letter was wider than a quarter of the card); with "First try" beside
   the letter the page scrolled sideways by 68 px. Columns may now shrink, the padding is small, and the tag goes under
   the letter. */
.choices.numbered { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.choices.numbered .choice { justify-content: center; flex-direction: column; gap: 4px; min-width: 0; padding: 8px 4px; }
.choices.numbered .tag { white-space: normal; text-align: center; padding: 2px 4px; max-width: 100%; }
.choices.numbered .letter { width: 2.4em; height: 2.4em; font-size: 1.1em; max-width: 100%; }

/* "How hard?": a colour per level, and a clear "Choose one" until a level is picked */
.level-chip { border: 2px solid transparent; font-weight: 700; }
.level-chip.level-basic { background: #e3f6e8; border-color: #1d7a3e; color: #14532d; }
.level-chip.level-advanced { background: #f1e8fb; border-color: #7b3fc4; color: #4c1d95; }
.level-chip.level-regents { background: #e7eefb; border-color: #1f3a68; color: #1f3a68; }
.level-chip.level-basic[aria-pressed="true"] { background: #1d7a3e; color: #ffffff; }
.level-chip.level-advanced[aria-pressed="true"] { background: #7b3fc4; color: #ffffff; }
.level-chip.level-regents[aria-pressed="true"] { background: #1f3a68; color: #ffffff; }
.level-row.unset { outline: 3px dashed var(--warn); outline-offset: 6px; border-radius: 12px; }
.level-need { color: var(--warn); font-weight: 700; margin: 0 0 8px; }

/* ----- Flashcards (2026-10-17) ----- */
.deck { perspective: 1200px; margin: 12px 0; }
.flashcard { position: relative; width: 100%; min-height: 260px; cursor: pointer; touch-action: pan-y; user-select: none; -webkit-user-select: none; transition: transform 0.25s ease, opacity 0.25s ease; outline-offset: 4px; }
.flashcard.fly-right { transform: translateX(120%) rotate(8deg); opacity: 0; }
.flashcard.fly-left { transform: translateX(-120%) rotate(-8deg); opacity: 0; }
.flip-inner { position: relative; width: 100%; min-height: 260px; transform-style: preserve-3d; transition: transform 0.45s ease; }
.flashcard.flipped .flip-inner { transform: rotateY(180deg); }
.face { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; gap: 10px; padding: 22px; border-radius: 16px; background: var(--surface, #fff); border: 2px solid var(--line, #ccc); box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08); backface-visibility: hidden; -webkit-backface-visibility: hidden; overflow: auto; }
.face.back { transform: rotateY(180deg); border-color: var(--accent); }
.face-label { margin: 0; font-size: 0.85em; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--accent); }
.face .stem { font-size: 1.15em; margin: 0; }
.card-choices { margin: 0; padding-left: 1.2em; }
.card-answer { font-size: 1.4em; font-weight: 700; margin: 0; }
.card-rule { margin: 0; }
.grade-row { display: flex; gap: 12px; justify-content: center; margin: 8px 0 4px; flex-wrap: wrap; }
.grade-row .result { width: 100%; text-align: center; margin: 0; }
.grade-row .explain { width: 100%; }
.btn.grade-no, .btn.grade-yes { color: #fff; border: 0; min-width: 44%; display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
.btn.grade-no { background: #c62828; }
.btn.grade-yes { background: #2e7d32; }
.btn.grade-no:disabled, .btn.grade-yes:disabled { opacity: 0.45; }
.btn .mark { font-weight: 900; font-size: 1.1em; }
.hint.center { text-align: center; }
@media (prefers-reduced-motion: reduce) {
  .flip-inner, .flashcard { transition: none; }
}

/* ----- Game: pop the balloon (2026-10-17) ----- */
.game-question .stem { font-size: 1.15em; margin: 0; }
.sky { position: relative; height: clamp(260px, calc(100vh - 470px), 520px); margin: 10px 0; border-radius: 16px; background: linear-gradient(#dff1ff, #f7fbff); overflow: hidden; border: 1px solid var(--line, #ccc); }
.balloon { position: absolute; left: 0; top: 0; margin: 0; border: 0; padding: 10px 12px 22px; color: #1b1b1b; background: var(--c); border-radius: 50% 50% 50% 50% / 45% 45% 55% 55%; box-shadow: inset -10px -14px 0 rgba(0, 0, 0, 0.08); display: flex; align-items: center; justify-content: center; text-align: center; cursor: pointer; will-change: transform; font: inherit; }
.balloon::after { content: ""; position: absolute; left: 50%; bottom: -24px; width: 2px; height: 24px; background: #777; transform: translateX(-50%); }
.balloon-text { font-weight: 700; font-size: 1em; line-height: 1.2; overflow-wrap: anywhere; }
.balloon.pop { animation: pop 0.35s ease forwards; }
.balloon.shake { animation: shake 0.4s ease; }
.balloon.dim { opacity: 0.45; cursor: default; }
.sky-done { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; margin: 0; font-weight: 700; }
@keyframes pop { to { opacity: 0; filter: blur(2px); } }
@keyframes shake { 0%, 100% { margin-left: 0; } 25% { margin-left: -8px; } 75% { margin-left: 8px; } }
@media (prefers-reduced-motion: reduce) { .balloon.pop, .balloon.shake { animation: none; } .balloon.pop { opacity: 0; } }
/* ----- Games: garden, feed, river, picture (2026-10-29) ----- */
/* The scene sits between the question and the choices, so nothing covers the question. Movement only with
   .moving (motion allowed); without it every change happens at once. */
.stage { margin: 10px 0 0; --stage-h: min(34vh, 300px); }
/* At 100% the bar's rider sits past the bar's end and pushed an iPhone page 5px sideways (walk 2026-10-29). */
.scene-game .progress, .arcade-game .progress { margin-right: 12px; }
/* Every game (owner, 2026-10-29: his children found no way back inside a game): on a phone each new question moves the
   page up, and on a computer a tall play area makes the page scroll, so the head with "Leave" stays at the top of the
   screen, on the page colour. On a phone it is one short row. */
.play-game > .test-head { position: sticky; top: 0; z-index: 20; align-items: center; background: var(--bg);
  margin: 0 calc(-1 * var(--gutter)); padding: 6px var(--gutter); box-shadow: 0 4px 6px -5px rgba(0, 0, 0, 0.35); }
@media (max-width: 699px) {
  .play-game > .test-head { flex-wrap: nowrap; }
  .play-game > .test-head h1 { font-size: 1.3em; }
  .play-game > .test-head [data-slot="meta"] { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
/* Phones: a smaller scene, so a long question, the scene and the choices fit on one screen. */
@media (max-width: 699px) { .stage { --stage-h: 24vh; } }
.stage-svg { display: block; margin: 0 auto; height: auto; border-radius: 16px; border: 1px solid var(--line, #ccc); }
.feed-field { border-radius: 16px; border: 1px solid var(--line, #ccc); overflow: hidden; }
.stage-line { margin: 6px 0 0; text-align: center; font-weight: 700; min-height: 1.3em; }
.picks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin: 12px 0; }
.pick { display: flex; align-items: center; gap: 8px; min-height: 56px; margin: 0; padding: 10px 12px; border: 2px solid var(--line); border-radius: 14px; background: var(--surface); color: var(--text); font: inherit; font-weight: 700; text-align: left; cursor: pointer; box-shadow: var(--lift); min-width: 0; }
.pick:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.pick-icon { flex: none; font-size: 1.5em; line-height: 1; }
.pick-text { flex: 1; min-width: 0; overflow-wrap: anywhere; line-height: 1.25; }
.pick[aria-disabled="true"] { cursor: default; }
.pick.dim { opacity: 0.4; box-shadow: none; }
.pick.right { border-color: var(--good); background: var(--good-bg); opacity: 1; }
.pick.shake { animation: shake 0.4s ease; }
.pick-garden { border-color: #8ce99a; }
.pick-river { border-color: #a5d8ff; }
.pick-picture { border-color: #d0bfff; }
.pick-feed { border-color: #ffd8a8; }
html[data-dark="1"] .pick-garden, html[data-dark="1"] .pick-river, html[data-dark="1"] .pick-picture, html[data-dark="1"] .pick-feed { border-color: var(--line); }
@media (max-width: 360px) { .picks { grid-template-columns: 1fr; } }
/* Garden: a seed in each bed; a finished question opens its flower. */
.bed .plant, .bed .drops { transform-box: fill-box; transform-origin: 50% 100%; }
.bed .plant { transform: scale(0); }
.bed.grown .plant { transform: scale(1); }
.bed.grown .seed, .bed .drops, .bed .ring { opacity: 0; }
.bed.next .ring { opacity: 1; }
.moving .bed .plant { transition: transform 0.7s cubic-bezier(.3, 1.5, .5, 1) 0.45s; }
.moving .bed.water .drops { animation: drops 0.6s ease-in 1; }
@keyframes drops { 0% { opacity: 1; transform: translateY(-6px); } 100% { opacity: 0; transform: translateY(22px); } }
/* River: stones already crossed look wet and dark; the next stone is ringed. */
.stone.passed .top { fill: #adb5bd; }
.stone.next .top { fill: #fff3bf; stroke: #f59f00; stroke-width: 1.5; }
/* The stone the animal stands on is drawn bigger with a dark rim, so the animal is clearly ON it (outside read 2026-10-29). */
.stone.here { transform-box: fill-box; transform-origin: 50% 50%; transform: scale(1.45); }
.stone.here .top { fill: #e9ecef; stroke: #495057; stroke-width: 1.2; }
/* Feed the animal. */
.feed-field { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; min-height: 150px; padding: 8px 8px 6px; background: linear-gradient(#e7f5ff 0 55%, #b2f2bb 55%); }
html[data-dark="1"] .feed-field { background: linear-gradient(#24324a 0 55%, #2b4a35 55%); }
.feed-spot { position: relative; }
.feed-animal { display: inline-block; font-size: 84px; line-height: 1.05; transform-origin: 50% 90%; }
.feed-say { position: absolute; left: 100%; top: 0; margin-left: -6px; padding: 4px 10px; border-radius: 14px; background: #fff; color: #17202e; border: 2px solid var(--line); font-weight: 700; white-space: nowrap; opacity: 0; }
.feed-say.on { opacity: 1; }
.feed-tummy { min-height: 1.4em; font-size: 14px; line-height: 1.3; text-align: center; max-width: 100%; overflow-wrap: anywhere; color: var(--text); }
.feed-tummy.none { visibility: hidden; }
.feed-eaten-label { font-weight: 700; }
.feed-eaten-items { opacity: 0.6; font-size: 13px; letter-spacing: -1px; }
/* Confetti stays behind the question, the scene and the buttons in these games (outside read 2026-10-29): the
   confetti canvas sits on the body, the page content above it. */
body:has(.scene-game) > canvas { z-index: 0 !important; }
.feed-fly { position: fixed; z-index: 50; font-size: 1.5em; line-height: 1; pointer-events: none; }
@media (max-width: 699px) { .feed-field { min-height: 0; height: 24vh; } .feed-animal { font-size: min(64px, 11vh); } }
/* Picture: the parts not yet earned are hidden; the newest one pops in. */
.layer { opacity: 0; }
.layer.on { opacity: 1; }
.pic-back { opacity: 1; } /* fully opaque: confetti behind the page must not show through the picture */
.moving .layer.new { animation: part-in 0.6s cubic-bezier(.3, 1.4, .5, 1); transform-box: fill-box; transform-origin: 50% 50%; }
@keyframes part-in { 0% { opacity: 0; transform: scale(0.6); } 100% { opacity: 1; transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .moving .bed .plant, .moving .bed.water .drops, .moving .layer.new, .pick.shake { transition: none; animation: none; } }
/* ----- Arcade games: Sky Blast, Keeper Clash, Net Splash (2026-10-29) -----
   The choices are buttons that move over a drawn play area (rockets, the corners of a goal or hoops, fish). The
   words are always dark on a light patch, at least as large as the balloon text. Movement only with .moving. */
.arena { background: #1b1b3a; touch-action: manipulation; height: clamp(300px, calc(100vh - 380px), 560px); }
.arena-art { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.arc {
  position: absolute; left: 0; top: 0; margin: 0; padding: 0; border: 0; background: none; font: inherit; color: #17202e;
  cursor: pointer; will-change: transform; display: flex; flex-direction: column; align-items: center; z-index: 2;
}
.arc:focus-visible { outline: 3px solid var(--focus, #ffd166); outline-offset: 3px; }
.arc[aria-disabled="true"] { cursor: default; }
.arc-text {
  display: block; width: 100%; padding: 8px 10px; font-weight: 800; font-size: 1em; line-height: 1.2; text-align: center;
  overflow-wrap: anywhere; background: #fff; border-radius: 12px; border: 3px solid var(--c);
}
.arc.dim { opacity: 0.4; }
.arc.dim .arc-text { border-style: dashed; }
.arc.shake { animation: shake 0.4s ease; }
.sky.arena .sky-done { color: #fff; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); font-size: 1.2em; padding: 0 16px; text-align: center; z-index: 3; }
.arena-goal .sky-done, .arena-hoop .sky-done { color: #13241a; text-shadow: 0 0 4px #fff, 0 0 8px #fff; }
body:has(.arcade-game) > canvas { z-index: 0 !important; }
/* Sky Blast: a rocket is a nose cone, a body with the words, fins and a flame. */
.arc-fireworks .rk-nose { width: 100%; aspect-ratio: 1.5 / 1; margin-bottom: -1px; background: var(--c); clip-path: polygon(50% 0, 62% 14%, 76% 38%, 90% 70%, 100% 100%, 0 100%, 10% 70%, 24% 38%, 38% 14%); }
/* The body is the rocket's own colour (all pale enough for dark words, 7:1 or more); a white window would read as a label. */
.arc-fireworks .arc-text { position: relative; z-index: 1; background: var(--c); border: 0; border-radius: 0 0 6px 6px; box-shadow: inset -7px 0 0 rgba(0, 0, 0, 0.08); padding: 10px 8px; min-height: 84px; display: flex; align-items: center; justify-content: center; }
/* Two side fins: small triangles beside the lower body (the shape between them has no height). */
.arc-fireworks .rk-fins { position: relative; z-index: 0; width: 130%; height: 40px; margin-top: -40px; background: var(--c); filter: brightness(0.85); clip-path: polygon(0 100%, 12% 0, 12% 100%, 88% 100%, 88% 0, 100% 100%); }
.arc-fireworks .rk-flame { width: 16px; height: 22px; margin-top: 0; border-radius: 50% 50% 50% 50% / 30% 30% 70% 70%; background: radial-gradient(circle at 50% 30%, #fff3bf, #ffa94d 55%, #ff6b6b); }
.moving .arc-fireworks .rk-flame { animation: flame 0.18s ease-in-out infinite alternate; transform-origin: 50% 0; }
@keyframes flame { from { transform: scaleY(0.75); } to { transform: scaleY(1.15); } }
.arc-fireworks.dim .rk-flame { visibility: hidden; }
.moving .arc-fireworks.fizzle { transition: transform 0.6s ease-in, opacity 0.6s; }
.moving .arc-fireworks.fizzle .rk-nose, .moving .arc-fireworks.fizzle .arc-text { animation: fizzle 0.6s ease-in 1 forwards; }
@keyframes fizzle { 0% { transform: rotate(0); } 40% { transform: rotate(-8deg); } 100% { transform: rotate(10deg) translateY(4px); } }
.arc-fireworks.right { visibility: hidden; }
.burst { position: absolute; width: 0; height: 0; z-index: 3; pointer-events: none; }
.burst i { position: absolute; left: -5px; top: -5px; width: 10px; height: 10px; border-radius: 50%; transform: translate(var(--dx), var(--dy)); }
.moving .burst i { animation: spark 1s cubic-bezier(.2, .7, .3, 1) forwards; }
@keyframes spark { 0% { transform: translate(0, 0) scale(1.4); opacity: 1; } 70% { opacity: 1; } 100% { transform: translate(var(--dx), calc(var(--dy) + 18px)) scale(0.5); opacity: 0; } }
/* Keeper Clash: targets on the goal, a goalkeeper on the line, the ball on its spot; hoops and a blocker on the court. */
.arc-goal .arc-text { border-radius: 999px; border-width: 4px; box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.55); }
.moving .arc-goal:not(.dim):not(.right) .arc-text { animation: aim 1.4s ease-in-out infinite; }
@keyframes aim { 50% { box-shadow: 0 0 0 9px rgba(255, 255, 255, 0.35); } }
.arc-goal.right .arc-text, .arc-hoop.right .arc-text { border-color: var(--good, #146c3a); border-style: solid; }
.arc-hoop .arc-text { border-radius: 6px; border: 3px solid #495057; box-shadow: inset 0 0 0 3px #fff, inset 0 0 0 5px #fa5252; padding: 10px 12px; }
.arc-hoop .hoop-rim { width: 44%; height: 26px; margin-top: -2px; border: 4px solid #f76707; border-top-width: 5px; border-radius: 0 0 40% 40%;
  background: repeating-linear-gradient(60deg, transparent 0 5px, rgba(255, 255, 255, 0.9) 5px 7px), repeating-linear-gradient(-60deg, transparent 0 5px, rgba(255, 255, 255, 0.9) 5px 7px); }
.keeper { position: absolute; left: 0; top: 0; width: clamp(54px, 12vw, 80px); z-index: 1; pointer-events: none; transition: transform 0.35s ease-out; will-change: transform; }
.moving .keeper { transition: transform 0.3s ease-out; }
.keeper svg { display: block; width: 100%; height: auto; }
.shot-ball { position: absolute; left: 0; top: 0; width: 32px; height: 32px; font-size: 28px; line-height: 32px; text-align: center; z-index: 2; pointer-events: none; }
.arena.scored .arena-art { animation: net-shake 0.5s ease 1; }
@keyframes net-shake { 30% { transform: translateY(3px); } 60% { transform: translateY(-2px); } }
/* Net Splash: a fish is a coloured body with the words, an eye and a tail; the net waits on the bank. A fish faces
   left (tail on the right); .left puts the tail on the left, for a fish swimming to the right. */
.arc-fish { flex-direction: row; }
.arc-fish .arc-text { order: 1; border-radius: 50%; background: var(--c); border: 3px solid rgba(0, 0, 0, 0.2); padding: 12px 26px 12px 42px; }
.arc-fish.left .arc-text { padding: 12px 42px 12px 26px; }
.arc-fish .fish-tail { order: 2; flex: none; width: 26px; height: 34px; margin-left: -4px; background: var(--c); clip-path: polygon(0 50%, 100% 0, 78% 50%, 100% 100%); }
.arc-fish .fish-eye { position: absolute; left: 22px; top: 50%; width: 9px; height: 9px; margin-top: -10px; border-radius: 50%; background: #17202e; box-shadow: 0 0 0 2px #fff; }
.arc-fish.left { flex-direction: row-reverse; }
.arc-fish.left .fish-tail { margin-left: 0; margin-right: -4px; transform: scaleX(-1); }
.arc-fish.left .fish-eye { left: auto; right: 22px; }
.moving .arc-fish:not(.dim):not(.right) .fish-tail { animation: wag 0.5s ease-in-out infinite alternate; transform-origin: 0 50%; }
.moving .arc-fish.left:not(.dim):not(.right) .fish-tail { animation-name: wag-left; transform-origin: 100% 50%; }
@keyframes wag { from { transform: scaleY(0.8) skewY(-8deg); } to { transform: scaleY(1) skewY(8deg); } }
@keyframes wag-left { from { transform: scaleX(-1) scaleY(0.8) skewY(-8deg); } to { transform: scaleX(-1) scaleY(1) skewY(8deg); } }
.arc-fish.right { opacity: 0; transition: opacity 0.2s 0.6s; }
.fish-net { position: absolute; right: 10px; top: 2px; width: 60px; height: 44px; z-index: 2; pointer-events: none; border: 3px solid #8d5524; border-top-width: 4px; border-radius: 4px 4px 50% 50%;
  background: repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.85) 0 2px, transparent 2px 7px), repeating-linear-gradient(-45deg, rgba(255, 255, 255, 0.85) 0 2px, transparent 2px 7px), rgba(255, 255, 255, 0.2); }
.fish-net::before { content: ""; position: absolute; right: 100%; top: -6px; width: 34px; height: 4px; background: #8d5524; transform: rotate(-20deg); transform-origin: 100% 50%; }
.fish-net-count { position: absolute; left: 50%; bottom: -26px; transform: translateX(-50%); min-width: 26px; padding: 0 6px; border-radius: 999px; background: #fff; color: #17202e; font-weight: 800; font-size: 0.85em; text-align: center; }
.splash { position: absolute; width: 0; height: 0; z-index: 1; pointer-events: none; }
.splash::before, .splash::after { content: ""; position: absolute; left: -30px; top: -10px; width: 60px; height: 20px; border-radius: 50%; border: 3px solid #e7f5ff; }
.moving .splash::before { animation: ripple 0.8s ease-out forwards; }
.moving .splash::after { animation: ripple 0.8s ease-out 0.15s forwards; opacity: 0; }
@keyframes ripple { from { transform: scale(0.4); opacity: 1; } to { transform: scale(1.6); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .arcade-game .arc, .arcade-game .burst i, .arcade-game .keeper, .arcade-game .rk-flame, .arcade-game .fish-tail, .arcade-game .arc-text, .arcade-game .splash::before, .arcade-game .splash::after, .arena.scored .arena-art { animation: none !important; transition: none !important; }
}
.card-question { margin: 0; font-size: 0.95em; color: var(--muted, #555); }
.game-hint { margin: 10px 0 0; font-weight: 700; }
.game-hint.bad { color: var(--bad, #b3261e); }
.game-hint:empty { display: none; }

/* Report this question (2026-10-18) */
.report { margin-top: 12px; }
.report-form { border: 1px solid var(--line, #ccc); border-radius: 10px; padding: 10px 12px; margin: 0; display: grid; gap: 8px; }
.report-form legend { font-weight: 600; padding: 0 4px; }
.report-reason { display: flex; align-items: center; gap: 8px; min-height: 36px; }
.report-note { width: 100%; box-sizing: border-box; }
.report-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.report-q img { max-width: 100%; }
.ref-tables { margin: 8px 0 12px; }
.badge { display: inline-block; min-width: 1.4em; margin-left: 6px; padding: 0 6px; border-radius: 999px; background: #c62828; color: #fff; font-weight: 700; font-size: 0.85em; line-height: 1.5; text-align: center; }
.book-picker { margin: 8px 0 12px; }
.chapter > summary { flex-wrap: wrap; }
.book-tag { order: 3; flex-basis: 100%; padding-left: calc(1em + 10px); font-size: 0.8em; color: var(--muted, #667); font-weight: 400; margin-top: -4px; }
.term-chips { margin-top: 6px; }
.book-q { margin: 0; font-weight: 600; }
/* Book list (2026-10-29): the book chips and the "My book is not listed" form inside the same card. */
.book-chips { margin-top: 6px; }
.book-ask { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.book-ask input[type="text"] { width: 100%; }
.book-note { margin: 14px 0 4px; font-size: 0.72rem; }
.book-req-titles { margin: 4px 0; }
.grade-switch { margin: 4px 0 8px; }
.grade-switch > summary { cursor: pointer; list-style: none; min-height: 44px; display: flex; align-items: center; }
.grade-switch > summary::-webkit-details-marker { display: none; }
.grade-switch.other { border: 2px solid var(--accent); border-radius: 12px; padding: 4px 12px 8px; background: var(--card, #fff); }
.grade-body { display: grid; gap: 8px; }
.grade-other { min-height: 44px; font: inherit; max-width: 16em; }

/* Leave a test, deck or game (2026-10-18): every answer is already saved. */
.test-head .leave-btn { flex: none; }
/* Owner, 2026-10-31: parents did not see that they can leave. Its own colour beside PDF, the same in every look. */
.btn.leave-btn { background: #b4470f; border-color: #b4470f; color: #ffffff; }
.test-head { column-gap: 8px; }

/* Flashcards: terms and definitions (2026-10-18) */
.card-term { font-size: 1.9em; font-weight: 800; text-align: center; margin: 0.6em 0; overflow-wrap: anywhere; }
.face.term .card-answer { font-size: 1.25em; line-height: 1.35; }
.explain-wait { display: flex; align-items: center; gap: 0.4em; }
.explain-wait .pencil { display: inline-block; animation: write 0.9s ease-in-out infinite alternate; }
@keyframes write { from { transform: rotate(-12deg) translateX(-2px); } to { transform: rotate(8deg) translateX(3px); } }

/* Fun for grades 1 to 4 (2026-10-18): praise that floats up, a wobble on a miss, stars on the score page,
   and a rocket riding the progress bar. All off with Effects off or reduced motion. */
.float-word {
  position: fixed; left: 50%; bottom: 22%; z-index: 50; pointer-events: none;
  font-size: 2rem; font-weight: 900; color: var(--primary); white-space: nowrap;
  text-shadow: 0 2px 0 #fff, 0 0 12px rgba(255, 255, 255, 0.9);
  animation: float-up 1.5s ease-out forwards;
}
.float-word.streak { color: #e8590c; font-size: 2.3rem; }
@keyframes float-up {
  0% { transform: translate(-50%, 20px) scale(0.6); opacity: 0; }
  20% { transform: translate(-50%, 0) scale(1.15); opacity: 1; }
  70% { opacity: 1; }
  100% { transform: translate(-50%, -110px) scale(1); opacity: 0; }
}
.wobble { animation: wobble 0.5s ease-in-out; }
@keyframes wobble { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(-2deg); } 40% { transform: rotate(2deg); } 60% { transform: rotate(-1.2deg); } 80% { transform: rotate(1deg); } }
.stars { font-size: 2.6rem; letter-spacing: 0.15em; margin: 0.2em 0 0.4em; line-height: 1; }
.stars .star { color: #d9d9d9; display: inline-block; }
.stars .star.on { color: #f6b400; text-shadow: 0 2px 0 #c98a00; animation: star-in 0.5s cubic-bezier(.3,1.6,.5,1) both; animation-delay: calc(0.3s + var(--i) * 0.25s); }
@keyframes star-in { from { transform: scale(0) rotate(-120deg); opacity: 0; } to { transform: scale(1) rotate(0); opacity: 1; } }
:is(html[data-young="1"], html[data-theme])[data-effects="on"] .progress .bar { overflow: visible; position: relative; }
:is(html[data-young="1"], html[data-theme])[data-effects="on"] .progress .bar span { position: relative; border-radius: 999px; }
:is(html[data-young="1"], html[data-theme])[data-effects="on"] .progress .bar span::after {
  content: var(--rider, "🚀"); position: absolute; right: -0.9em; top: 50%; transform: translateY(-55%) rotate(45deg);
  font-size: 1.25rem; line-height: 1;
}
@media (prefers-reduced-motion: reduce) {
  .float-word, .wobble, .stars .star.on, .explain-wait .pencil { animation: none; }
}
html[data-effects="off"] .float-word, html[data-effects="off"] .stars .star.on { animation: none; }

/* Grades 1 to 4, round two (owner, 2026-10-18: more often, bigger). */
html[data-young="1"] .float-word { font-size: 2.6rem; }
html[data-young="1"] .float-word.streak { font-size: 3rem; }
.float-word.gentle { color: #1c7ed6; font-size: 2rem !important; }
.float-word.milestone { color: #ae3ec9; bottom: 40%; }
.hello-pet { display: inline-block; font-size: 1.3em; animation: wave 1.6s ease-in-out infinite; transform-origin: 70% 90%; }
@keyframes wave { 0%, 60%, 100% { transform: rotate(0); } 10%, 30% { transform: rotate(-14deg); } 20%, 40% { transform: rotate(12deg); } }
html[data-young="1"] .flashcard.flipped .face.back { animation: pop 0.35s ease-out; }

#kid-sky { position: fixed; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; display: none; }
html[data-young="1"][data-effects="on"] body:is([data-view="home"], [data-view="score"], [data-view="review"]) #kid-sky { display: block; }
#kid-sky span { position: absolute; bottom: -60px; left: calc(4% + var(--i) * 9.5%); font-size: calc(22px + (var(--i) * 7px) % 20px); opacity: 0.35;
  animation: drift calc(14s + var(--i) * 1.7s) linear infinite; animation-delay: calc(var(--i) * -2.3s); }
@keyframes drift { from { transform: translate(0, 0) rotate(-6deg); } 50% { transform: translate(18px, -55vh) rotate(6deg); } to { transform: translate(-10px, -115vh) rotate(-6deg); } }
main, #view, .topbar, #msg { position: relative; z-index: 1; }

/* Review animals: a naughty one points at each mistake, a happy one sleeps on each right answer. */
.review-item.has-critter { position: relative; margin-top: 46px; overflow: visible; }
.critter { position: absolute; top: -40px; right: 10px; display: flex; align-items: flex-end; gap: 4px; z-index: 2; pointer-events: none; }
.critter-face { display: grid; place-items: center; width: 62px; height: 62px; font-size: 40px; line-height: 1; border-radius: 50%;
  background: var(--c); box-shadow: 0 3px 0 rgba(0, 0, 0, 0.18), 0 0 0 4px #fff; }
.critter.naughty { flex-direction: row; }
.critter.naughty .critter-face { animation: cheeky 1.4s ease-in-out infinite; }
.critter-point { font-size: 30px; align-self: flex-end; margin-bottom: -18px; animation: point 0.8s ease-in-out infinite alternate; order: 2; }
.critter-say { order: -1; align-self: center; background: #fff; color: #c92a2a; font-weight: 800; font-size: 0.85rem; padding: 4px 9px;
  border-radius: 14px; border: 2px solid var(--c); white-space: nowrap; margin-right: 2px; }
.critter.naughty.fixed .critter-say { color: #2b8a3e; }
.critter.naughty.fixed .critter-face { animation: hop 0.9s ease-in-out infinite; }
@keyframes cheeky { 0%, 100% { transform: rotate(-8deg); } 50% { transform: rotate(8deg) translateY(-3px); } }
@keyframes point { from { transform: translateY(0); } to { transform: translateY(7px); } }
@keyframes hop { 0%, 100% { transform: translateY(0); } 40% { transform: translateY(-8px); } }
.review-right { border-color: #b2f2bb; background: #f4fff6; }
.critter.sleepy .critter-face { width: 52px; height: 52px; font-size: 32px; animation: breathe 3s ease-in-out infinite; filter: saturate(0.9); }
.zzz { position: absolute; top: -18px; left: -14px; font-weight: 800; color: #4dabf7; font-style: normal; }
.zzz i { position: absolute; font-style: normal; opacity: 0; animation: zz 3s ease-in-out infinite; }
.zzz i:nth-child(1) { font-size: 12px; animation-delay: 0s; }
.zzz i:nth-child(2) { font-size: 16px; animation-delay: 1s; }
.zzz i:nth-child(3) { font-size: 20px; animation-delay: 2s; }
@keyframes zz { 0% { transform: translate(0, 0); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(-16px, -26px); opacity: 0; } }
@keyframes breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.06); } }
.right-head { margin-top: 28px; }
@media (prefers-reduced-motion: reduce) {
  .hello-pet, .critter *, .zzz i, #kid-sky span { animation: none !important; }
  .zzz i { opacity: 1; }
  .zzz i:nth-child(2) { transform: translate(-8px, -12px); } .zzz i:nth-child(3) { transform: translate(-16px, -24px); }
}
html[data-effects="off"] .hello-pet, html[data-effects="off"] .critter *, html[data-effects="off"] .zzz i { animation: none !important; }
html[data-effects="off"] .zzz i { opacity: 1; }

/* Builder steps (owner, 2026-10-18): each part is its own soft panel, every other one a shade darker,
   with a thin rule between. The panel padding replaces the heading's top margin, so the page is no longer. */
.step { padding: 8px 12px 2px; margin: 0 -12px; border-radius: var(--radius); border-top: 1px solid color-mix(in srgb, var(--line) 70%, transparent); }
.step.alt { background: color-mix(in srgb, var(--chip) 60%, transparent); border-top-color: transparent; }
.step + .step.alt, .step.alt + .step { border-top-color: transparent; }
.step > h2:first-child { margin-top: 0; }
.step .chips { margin-bottom: 4px; }
.settings { margin-top: 0; }

/* Start tapped too early: the missing step gets a thick moving rainbow ring until it is chosen. */
.btn.primary.inactive { opacity: 0.55; }
.need-ring { position: relative; z-index: 0; }
.need-ring::before {
  content: ""; position: absolute; inset: -8px; border-radius: calc(var(--radius) + 8px); padding: 7px; z-index: -1; pointer-events: none;
  background: linear-gradient(90deg, #ff4d4d, #ff9f1a, #ffe600, #3ddc84, #2fa8ff, #8a5cff, #ff4dc4, #ff4d4d);
  background-size: 300% 100%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  animation: rainbow 2.2s linear infinite, ring-in 0.5s ease-out;
}
@keyframes rainbow { to { background-position: 300% 0; } }
@keyframes ring-in { from { transform: scale(1.06); opacity: 0; } to { transform: scale(1); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .need-ring::before { animation: none; } }

/* The mix slider: each side named in its own track colour, with a picture of what it looks like. */
.mix-labels { align-items: flex-start; }
.mix-side { display: flex; flex-direction: column; gap: 2px; }
.mix-side.sa { align-items: flex-end; text-align: right; }
.mix-side.mc .mix-num, .mix-side.mc .mix-kind { color: var(--primary); }
.mix-side.sa .mix-num, .mix-side.sa .mix-kind { color: var(--accent); }
.mix-kind { font-size: 0.8em; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }
.mix-pic { display: inline-flex; gap: 3px; font-size: 0.75em; font-weight: 700; }
.mix-pic i { font-style: normal; display: inline-grid; place-items: center; width: 1.6em; height: 1.6em; border-radius: 50%;
  border: 2px solid var(--primary); color: var(--primary); background: var(--surface); }
.mix-pic.type { color: var(--accent); }
.mix-pic.type u { text-decoration: none; border-bottom: 2px dashed var(--accent); padding: 0 6px; }
.mix-side.zero { opacity: 0.45; }
.mix-presets { margin-top: 10px; }
.chip.mini { min-height: 36px; padding: 4px 12px; font-size: 0.9em; }
.mix-kind { display: inline-flex; align-items: center; gap: 5px; }
.mix-presets { margin-top: 8px; margin-bottom: 2px; flex-wrap: nowrap; }
.mix-presets .chip.mini { flex: 1 1 0; justify-content: center; text-align: center; white-space: nowrap; padding: 4px 6px; }
.mix-pic i { width: 1.45em; height: 1.45em; }

/* Reading help (2026-10-18): bigger text, calm screens, and a "Read it to me" button. */
html[data-reading="1"] body { font-size: calc(var(--base) * 1.18); line-height: 1.6; }
html[data-reading="1"] .stem { font-size: 1.15em; }
html[data-reading="1"] #kid-sky { display: none !important; }
html[data-reading="1"] .critter *, html[data-reading="1"] .hello-pet, html[data-reading="1"] .zzz i { animation: none !important; }
html[data-reading="1"] .zzz i { opacity: 1; }
.stem-wrap { display: flex; flex-direction: column; gap: 6px; }
.read-btn { align-self: flex-start; min-height: 40px; padding: 4px 14px; font-weight: 700; }
.read-row { display: flex; justify-content: center; margin: 8px 0 0; }
.reading-help { margin: -4px 0 10px; }
.reading-help summary { cursor: pointer; color: var(--muted); }
.reading-help-body { padding: 6px 0 2px; }
.reading-tag { align-self: center; }
html[data-reading="1"] .progress .bar span::after { display: none; }

/* Short science videos (2026-10-20): "Watch this first" beside a missed question, optional ones at the top of a chapter. */
.reel-btn { display: flex; align-items: center; gap: 0.6em; width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer;
  padding: 10px 14px; border: 2px solid var(--primary); border-radius: var(--radius); background: var(--bg); min-height: 48px; }
.reel-btn:hover, .reel-btn:focus-visible { background: color-mix(in srgb, var(--primary) 12%, var(--bg)); }
.reel-play { flex: none; display: grid; place-items: center; width: 2em; height: 2em; border-radius: 50%; background: var(--primary); color: #fff; font-size: 0.95em; }
.chapter-reels { display: grid; gap: 8px; margin: 4px 0 12px; }
.chapter-reels p { margin: 0; }
.reel-shade { position: fixed; inset: 0; z-index: 1000; background: rgba(0, 0, 0, 0.82); display: grid; place-items: center; padding: 12px; }
.reel-box { display: grid; gap: 10px; justify-items: center; width: min(100%, 460px); }
/* Owner, 2026-10-27: the guess while the video waits, and the one question at its end, sit on the video. */
.reel-stage { position: relative; width: 100%; }
.reel-ask { position: absolute; left: 8px; right: 8px; bottom: 8px; background: #fff; color: #1d2b53; border-radius: 14px; padding: 14px; display: grid; gap: 10px; box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35); max-height: calc(100% - 16px); overflow: auto; }
.reel-ask.top { top: 8px; bottom: auto; padding: 10px 12px; gap: 8px; }
.reel-ask[hidden] { display: none; }
.reel-q { margin: 0; font-size: 1.25rem; font-weight: 700; line-height: 1.35; }
.reel-choices { display: grid; gap: 8px; }
.reel-choices.two { grid-template-columns: 1fr 1fr; }
.reel-choices button { width: 100%; }
.reel-choices button.good-pick { background: #e3f6e8; color: #1b6b34; border-color: currentColor; opacity: 1; }
.reel-choices button.bad-pick { background: #fde7e7; color: #a3221a; border-color: currentColor; opacity: 1; }
.reel-fb { margin: 0; font-size: 1.1rem; font-weight: 700; }
.reel-fb.good { color: #1b6b34; }
.reel-fb.bad { color: #1d2b53; }   /* "Good try!" is said kindly, not in red */
.reel-fb:empty { display: none; }
.reel-box video { width: 100%; max-height: calc(100vh - 110px); max-height: calc(100dvh - 110px); aspect-ratio: 9 / 16; background: #000; border-radius: 12px; object-fit: contain; }

/* Owner's requests of 2026-10-21 */
/* Medium: between the green of Easy and the purple of Hard */
.level-chip.level-medium { background: #fff4d6; border-color: #b7791f; color: #6b4410; }
.level-chip.level-medium[aria-pressed="true"] { background: #b7791f; color: #ffffff; }
/* "Review" a whole chapter, on the chapter row */
.chapter > summary .review-chip { min-height: 36px; padding: 4px 14px; font-size: 0.9em; font-weight: 700; }
/* Two tries: each half in its own colour */
.result.tries .try-1, .result.tries .try-2 { font-weight: 700; }
/* Voice help */
.help-box { margin: 10px 0 0; }
.help-panel { border: 2px dashed var(--line); border-radius: var(--radius); padding: 10px 12px; margin-top: 6px; }
.help-q { margin: 0 0 8px; font-weight: 600; }
/* Two different jobs (2026-10-24): a large microphone button on its own line, then a chat-style typed row. */
.help-say { display: block; width: 100%; font-size: 1.15em; padding: 14px 16px; margin: 8px 0 12px; }
.help-row { display: flex; flex-wrap: nowrap; gap: 8px; align-items: center; margin-bottom: 8px; }
.help-row .help-typed { flex: 1 1 auto; min-width: 0; }
.help-send { flex: 0 0 auto; white-space: nowrap; }
.help-typed { flex: 1 1 12em; min-height: 40px; font: inherit; padding: 4px 8px; }
.help-answer:not(:empty) { margin-top: 10px; }

/* ----- New test page as numbered cards (owner, 2026-10-22; the blend of the two outside readers' choices) ----- */
section { counter-reset: stp; }
[data-need] { counter-increment: stp; position: relative; margin: 0 0 16px !important; padding: 0 14px 12px !important;
  background: var(--surface, #fff) !important; border: 1px solid #d5e4e0 !important; border-radius: 16px !important;
  box-shadow: 0 3px 0 #c6d9d4, 0 8px 18px rgba(16, 70, 62, .08); }
[data-need]:empty { display: none; }
[data-need] > h2:first-of-type { display: flex; align-items: center; gap: 10px; margin: 0 -14px 12px !important; padding: 10px 14px;
  border-radius: 16px 16px 0 0; background: #eaf4f1; color: #16423b; font-size: 1.1em; }
[data-need] > h2:first-of-type::before { content: counter(stp); flex: 0 0 auto; width: 32px; height: 32px; border-radius: 50%;
  display: inline-grid; place-items: center; background: #1f6f63; color: #fff; font-weight: 800; font-size: 17px; }
[data-need][data-done] { border-left: 6px solid #2e9e44 !important; }
[data-need][data-done] > h2:first-of-type::before { content: "\2713"; background: #2e9e44; }
[data-need][data-next] { border: 3px solid #f08c00 !important; box-shadow: 0 0 0 4px #fff1d6, 0 8px 18px rgba(240, 140, 0, .18); }
[data-need][data-next] > h2:first-of-type { background: #f08c00; color: #fff; }
[data-need][data-next] > h2:first-of-type::before { background: #fff; color: #b35f00; }
[data-need][data-next] > h2:first-of-type::after { content: "Do this next"; margin-left: auto; font-size: 0.72em; font-weight: 700;
  background: rgba(255, 255, 255, .25); padding: 3px 10px; border-radius: 999px; white-space: nowrap; }
.mix-labels { flex-wrap: nowrap; }
/* Paper marks */
.paper-link { margin: 4px 0 10px; }
.paper-way { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line); }
.pgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin: 14px 0 8px; }
.pbox { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; min-height: 86px; padding: 6px 4px;
  border-radius: 14px; border: 2px solid #b9d3cd; background: #fff; box-shadow: 0 3px 0 #c6d9d4; font: inherit; color: #1d2b53; cursor: pointer; }
.pbox .pn { font-size: 24px; font-weight: 800; line-height: 1.1; }
.pbox .pt { font-size: 11px; line-height: 1.2; color: #4a5568; text-align: center; overflow: hidden; overflow-wrap: break-word; hyphens: auto; max-width: 100%; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.pbox .pm { margin-top: auto; font-size: 12px; font-weight: 700; color: #2e7d4f; }
.pbox.wrong { background: #fde7e7; border-color: #c62828; box-shadow: 0 1px 0 #c62828; }
.pbox.wrong .pm { color: #c62828; }
.pbox.online { opacity: .7; cursor: default; }
.pcount { font-weight: 700; margin: 8px 0; }
.pcheck { display: flex; gap: 8px; align-items: center; font-weight: 600; margin: 10px 0; }
.pcheck input { width: 22px; height: 22px; }
.pnote { background: #fff8e6; border: 1px solid #f0c36d; border-radius: 12px; padding: 10px 12px; }
.print-which { font-size: 1.05em; margin: 0 0 10px; }
.pbox .pm.untapped { color: #6b7280; font-weight: 600; }

/* ---------- Family plan (2026-10-23) ---------- */
.plan-line { margin: 0 0 12px; }
.plan-card h2 { margin-top: 0; }
.plan-card h3 { margin: 16px 0 4px; font-size: 1em; }
.plan-price { font-size: 1.15em; margin: 4px 0; }
.plan-list { margin: 4px 0 8px; padding-left: 1.2em; }
.plan-list li { margin: 2px 0; }
.plan-box h2 { margin-top: 0; font-size: 1.1em; }
.plan-agree { display: flex; gap: 10px; align-items: flex-start; margin: 16px 0 12px; }
.plan-agree input { width: 22px; height: 22px; flex: none; margin-top: 2px; }
.plan-agree label { line-height: 1.4; }
.plan-buttons { display: flex; flex-direction: column; gap: 10px; margin: 8px 0; }
.plan-buttons .btn[disabled] { opacity: 0.55; cursor: not-allowed; }

/* Admin portal (2026-10-24): tabs, count filters, family cards, confirm box, map */
.admin-portal { max-width: 960px; }
.admin-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 14px; padding: 0 0 10px; border-bottom: 1px solid var(--line); }
.admin-tab { flex: 0 0 auto; min-height: 44px; padding: 8px 14px; font: inherit; font-size: 0.95em; color: var(--text); background: var(--chip); border: 2px solid transparent; border-radius: var(--radius); cursor: pointer; white-space: nowrap; }
.admin-tab[aria-selected="true"] { background: var(--primary); color: var(--primary-text); font-weight: 650; }
.admin-panel[hidden] { display: none; }
.admin-counts { display: grid; grid-template-columns: repeat(auto-fill, minmax(112px, 1fr)); gap: 8px; margin: 0 0 12px; }
.admin-count { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; min-height: 44px; padding: 6px 12px; font: inherit; color: var(--text); background: var(--surface); border: 2px solid var(--line); border-radius: var(--radius); cursor: pointer; text-align: left; }
.admin-count[aria-pressed="true"] { border-color: var(--select); background: var(--select-bg); }
.admin-count-n { font-weight: 700; }
.admin-count-l { font-size: 0.85em; color: var(--muted); }
.admin-search { width: 100%; min-height: 44px; font: inherit; padding: 6px 10px; box-sizing: border-box; }
.admin-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.admin-chip { display: inline-block; padding: 4px 10px; font-size: 0.85em; background: var(--chip); border-radius: 999px; overflow-wrap: anywhere; max-width: 100%; }
.admin-chip.good { background: var(--good-bg); color: var(--good); }
.admin-chip.bad { background: var(--bad-bg); color: var(--bad); }
.admin-chip.warn { background: #fff1d6; color: var(--warn); }
.admin-chip.comp { background: var(--select-bg); color: var(--select); }
.admin-chip.child { border-radius: var(--radius); }
.admin-family.paused { border-left: 4px solid var(--warn); }
.admin-kids { margin: 8px 0; }
.admin-kid { margin: 0 0 8px; }
.admin-kid-actions { display: inline-flex; flex-wrap: wrap; gap: 8px; margin-left: 4px; vertical-align: middle; }
.admin-actions .btn { min-height: 44px; }
.admin-explain { margin: 4px 0; }
.admin-confirm { margin: 10px 0 0; padding: 12px; background: var(--select-bg); border: 1px solid var(--select); border-radius: var(--radius); }
.admin-confirm .field { margin: 8px 0; }
.admin-reason, .admin-days { min-height: 44px; font: inherit; padding: 6px 10px; box-sizing: border-box; width: 100%; }
.admin-days { max-width: 8em; }
.admin-status:empty { display: none; }
.admin-note { margin: 8px 0 0; }
.admin-note:empty { display: none; }
.admin-picker { display: flex; flex-direction: column; gap: 8px; margin: 0 0 16px; }
.admin-pick { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; min-height: 44px; padding: 8px 12px; font: inherit; color: var(--text); background: var(--surface); border: 2px solid var(--line); border-radius: var(--radius); text-align: left; cursor: pointer; }
.admin-pick[aria-pressed="true"] { border-color: var(--select); background: var(--select-bg); }
.admin-scroll { overflow-x: auto; margin: 8px 0 16px; }
.admin-table { table-layout: auto; min-width: 620px; }
.admin-table th, .admin-table td { overflow-wrap: normal; padding: 6px 10px 6px 6px; }
.admin-map { height: 340px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--chip); z-index: 0; }
.admin-map.failed { display: flex; align-items: center; justify-content: center; text-align: center; padding: 16px; }
.admin-map-note:empty { display: none; }
@media (min-width: 700px) { .admin-map { height: 460px; } }

.admin-family .user-name strong { font-size: 1.3em; }
.admin-danger { margin: 8px 0; padding: 8px 12px; border: 2px solid var(--bad); border-radius: var(--radius); }
.admin-danger[hidden] { display: none; }
.admin-danger p { margin: 0; color: var(--bad); }
.admin-confirm.done { background: var(--good-bg); border-color: var(--good); }
.admin-cards { display: none; }
.admin-rowcard { padding: 10px 12px; margin: 0 0 8px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.admin-rowcard p { margin: 2px 0; overflow-wrap: anywhere; }
.admin-first { font-weight: 650; }
@media (max-width: 599px) { .admin-scroll { display: none; } .admin-cards { display: block; margin: 8px 0 16px; } }

/* "My look" for grades 1 to 6 (2026-10-24, docs/PLAN-2026-10-24-themes.md). Set as html[data-theme] only for
   grades 1 to 6 and only for a look other than Classic; the band keeps its sizes and fonts. The same rules
   colour the preview cards in the picker. The answer colours (--select, --good, --bad) never change. */
html[data-theme="wild"], .look-card[data-theme="wild"] {
  --bg: #e6efd2; --line: #a8c27e; --chip: #e3eecb; --primary: #2e6a1e; --primary-dark: #1d4612; --accent: #a94a00;
  --chip-on: #7a3a00; --dot: #f0a32b; --tint: rgba(46, 106, 30, 0.2); --bar: linear-gradient(90deg, #2e6a1e, #f0a32b); --rider: "🦖";
}
html[data-theme="gentle"], .look-card[data-theme="gentle"] {
  --bg: #f4e8d2; --line: #cdb385; --chip: #f3e7cf; --primary: #85561a; --primary-dark: #5f3c10; --accent: #446c30;
  --chip-on: #446c30; --dot: #9cc46a; --tint: rgba(133, 86, 26, 0.18); --bar: linear-gradient(90deg, #85561a, #9cc46a); --rider: "🐘";
}
html[data-theme="rainbow"], .look-card[data-theme="rainbow"] {
  --bg: #f2e3fa; --line: #cba7e2; --chip: #f4e4fb; --primary: #7e3aa6; --primary-dark: #5a2678; --accent: #b8246a;
  --chip-on: #2763a6; --dot: #f783ac; --tint: rgba(126, 58, 166, 0.18); --rider: "🦄";
  --bar: linear-gradient(90deg, #e03131, #f08c00, #f2c94c, #37b24d, #1c7ed6, #7048e8);
}
html[data-theme="ocean"], .look-card[data-theme="ocean"] {
  --bg: #dceff6; --line: #92c5da; --chip: #dbeff7; --primary: #0b5d87; --primary-dark: #073f5c; --accent: #0b6f6b;
  --chip-on: #0b6f6b; --dot: #38c3d6; --tint: rgba(11, 93, 135, 0.18); --bar: linear-gradient(90deg, #0b5d87, #38c3d6); --rider: "🐬";
}
html[data-theme="space"], .look-card[data-theme="space"] {
  --bg: #e5e2f6; --line: #afa6db; --chip: #e6e2f8; --primary: #3a2a8e; --primary-dark: #241a5e; --accent: #8a5a00;
  --chip-on: #1f1c52; --dot: #f6c445; --tint: rgba(58, 42, 142, 0.2); --bar: linear-gradient(90deg, #3a2a8e, #f6c445); --rider: "🚀";
}
html[data-theme="halloween"], .look-card[data-theme="halloween"] {
  --bg: #fce5c9; --line: #e0ae70; --chip: #fde4c4; --primary: #a8420a; --primary-dark: #742c05; --accent: #5b3bbf;
  --chip-on: #4a2a86; --dot: #f59f00; --tint: rgba(168, 66, 10, 0.2); --bar: linear-gradient(90deg, #5b3bbf, #f59f00); --rider: "🎃";
}
/* Halloween unicorns (2026-10-25): a purple, orange and soft pink night look. */
html[data-theme="halloween_unicorns"], .look-card[data-theme="halloween_unicorns"] {
  --bg: #f5e2f0; --line: #d8a3ca; --chip: #f6dff0; --primary: #6a2c9e; --primary-dark: #4a1d70; --accent: #a64200;
  --chip-on: #3d1f6e; --dot: #ff9f43; --tint: rgba(106, 44, 158, 0.2); --rider: "🦄";
  --bar: linear-gradient(90deg, #3d1f6e, #6a2c9e, #f783ac, #f59f00);
}
html[data-theme="christmas"], .look-card[data-theme="christmas"] {
  --bg: #e2efe2; --line: #a2c8a2; --chip: #e1f0e1; --primary: #ad1f29; --primary-dark: #7a141b; --accent: #1d6a33;
  --chip-on: #1d6a33; --dot: #f2c94c; --tint: rgba(173, 31, 41, 0.18); --bar: linear-gradient(90deg, #ad1f29, #1d6a33); --rider: "🦌";
}
html[data-theme="easter"], .look-card[data-theme="easter"] {
  --bg: #f6eed4; --line: #cfbd7c; --chip: #f4eed2; --primary: #7448ad; --primary-dark: #523180; --accent: #3a7845;
  --chip-on: #2c7570; --dot: #f7d26b; --tint: rgba(116, 72, 173, 0.18); --bar: linear-gradient(90deg, #7448ad, #f7d26b); --rider: "🐰";
}
html[data-theme="summer"], .look-card[data-theme="summer"] {
  --bg: #fdf1c7; --line: #ddc464; --chip: #fff0bb; --primary: #bb3a2c; --primary-dark: #852819; --accent: #0a6f88;
  --chip-on: #0a6f88; --dot: #ffd43b; --tint: rgba(187, 58, 44, 0.18); --bar: linear-gradient(90deg, #bb3a2c, #ffd43b); --rider: "☀️";
}
/* The Classic preview card shows the child's band as it is today. */
.look-card[data-theme="classic"][data-band="k3"] { --bg: #fcefcc; --line: #e0bd7a; --chip: #fff1c7; --primary: #b53a27; --accent: #1f68a6; }
.look-card[data-theme="classic"][data-band="g46"] { --bg: #e0f2ee; --line: #9fcfc5; --chip: #e5f4f1; --primary: #0c7068; --accent: #a1500b; }

/* The picker. */
.look-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; margin: 12px 0 8px; }
.look-card {
  display: flex; flex-direction: column; align-items: stretch; gap: 8px; padding: 12px; min-height: 44px; text-align: left;
  background: var(--bg); color: var(--text); border: 2px solid var(--line); border-radius: var(--radius); cursor: pointer;
  font: inherit;
}
.look-card:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.look-card[aria-pressed="true"] { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary); }
.look-emoji { font-size: 1.5em; line-height: 1.1; white-space: nowrap; overflow: hidden; }
.look-name { display: block; background: var(--primary); color: var(--primary-text); font-weight: 700; padding: 4px 10px; border-radius: 999px; text-align: center; }
.look-card[aria-pressed="true"] .look-name::before { content: "\2713  "; }
.look-dots { display: flex; gap: 6px; }
.look-dots i { width: 18px; height: 18px; border-radius: 50%; border: 1px solid rgba(0, 0, 0, 0.15); }
.look-until { display: block; margin: 0; font-size: 0.85em; color: var(--muted); }
.look-line { margin: 0.2em 0 0.6em; }
.look-link.btn { justify-self: start; justify-content: flex-start; min-height: 0; margin: -10px 0 6px; color: var(--muted); }

/* The animal that comes to the child when a test is finished (2026-10-24, docs/PLAN-2026-10-24-arrival-animal.md).
   The stage gives the perspective; the mover travels on the Z axis, so the animal grows as it comes closer. */
.arrival {
  position: fixed; inset: 0; z-index: 60; overflow: hidden; cursor: pointer;
  perspective: 700px; perspective-origin: 50% 35%;
  background: color-mix(in srgb, var(--bg) 55%, transparent);
}
.arrival-ground {
  position: absolute; left: -20%; right: -20%; top: 38%; bottom: 0;
  background: linear-gradient(to bottom, transparent, color-mix(in srgb, var(--chip) 90%, transparent) 45%, var(--chip));
}
.arrival.gait-swim .arrival-ground { background: linear-gradient(to bottom, transparent, rgba(56, 195, 214, 0.35) 40%, rgba(11, 111, 160, 0.35)); }
.arrival.gait-fly .arrival-ground, .arrival.gait-roll .arrival-ground { opacity: 0.7; }
.arrival-mover { position: absolute; left: 50%; bottom: 14vh; width: 0; height: 0; transform-style: preserve-3d; }
.arrival-body { position: absolute; left: 0; bottom: 0; transform-origin: 50% 90%; }
.arrival-face {
  display: block; transform: translateX(-50%); line-height: 1;
  font-size: clamp(120px, 36vw, 220px); filter: drop-shadow(0 6px 4px rgba(0, 0, 0, 0.18));
}
.arrival-shadow {
  position: absolute; left: 0; bottom: -10px; width: clamp(110px, 30vw, 190px); height: 26px; transform: translateX(-50%);
  border-radius: 50%; background: radial-gradient(closest-side, rgba(0, 0, 0, 0.28), transparent);
}
.arrival.gait-fly .arrival-shadow { opacity: 0.5; width: clamp(70px, 18vw, 120px); }
.arrival-say {
  position: absolute; left: 50%; top: 14vh; transform: translate(-50%, 12px); opacity: 0; transition: opacity 0.25s, transform 0.25s;
  background: #fff; color: var(--text); border: 3px solid var(--primary); border-radius: 18px;
  padding: 8px 18px; font-weight: 800; font-size: 1.4em; white-space: nowrap; max-width: calc(100vw - 32px); overflow: hidden; text-overflow: ellipsis;
}
.arrival-say.on { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { .arrival { display: none !important; } }
html[data-effects="off"] .arrival, html[data-reading="1"] .arrival { display: none !important; }

/* Looks for older students, grades 6 to 12 (owner's go 2026-10-25). Calmer than the younger looks: no cartoon
   animals, small motion only, nothing that copies a team's name, logo or marks. The page keeps one step darker
   than the cards (2026-10-25); --bg2 is the second stripe of a striped page and is held to the same contrast.
   Gaming PC and Calm dark are dark pages: their cards are a step lighter than the page, and html[data-dark]
   below repaints the few places that had white written into them. */
html[data-theme="court"], .look-card[data-theme="court"] {
  --bg: #ecd5ab; --bg2: #e5cb9b; --line: #b48a52; --chip: #f7ead2; --text: #24190d; --muted: #4a3420;
  --primary: #1b4d8f; --primary-dark: #11335f; --primary-text: #ffffff; --accent: #8c3a06; --chip-on: #1b4d8f; --chip-on-text: #ffffff;
  --good: #14612f; --bad: #9e2a1c; --warn: #7a3f00; --select: #1652b8; --dot: #f28c28;
  --tint: rgba(27, 77, 143, 0.18); --bar: linear-gradient(90deg, #1b4d8f, #f28c28); --rider: "🏀";
  --page-art: repeating-linear-gradient(90deg, var(--bg) 0 44px, var(--bg2) 44px 46px, var(--bg) 46px 88px, var(--bg2) 88px 132px);
}
html[data-theme="pitch"], .look-card[data-theme="pitch"] {
  --bg: #d3e8c4; --bg2: #c4ddb2; --line: #7fae72; --chip: #e6f2de; --text: #13241a; --muted: #2c3d2f;
  --primary: #1c6431; --primary-dark: #124221; --primary-text: #ffffff; --accent: #1b4a78; --chip-on: #14532d; --chip-on-text: #ffffff;
  --good: #125c2c; --bad: #9e2a1c; --warn: #713d00; --select: #1652b8; --dot: #ffffff;
  --tint: rgba(28, 100, 49, 0.18); --bar: linear-gradient(90deg, #1c6431, #8bc34a); --rider: "⚽";
  --page-art: repeating-linear-gradient(180deg, var(--bg) 0 80px, var(--bg2) 80px 160px);
}
/* Football field (2026-10-29): an American football field; the page round the field is a paler grass. */
html[data-theme="football"], .look-card[data-theme="football"] {
  --bg: #dce9d1; --line: #86ad78; --chip: #eaf3e3; --text: #13241a; --muted: #2c3d2f;
  --primary: #1e5e33; --primary-dark: #123d21; --primary-text: #ffffff; --accent: #7a3a12; --chip-on: #14532d; --chip-on-text: #ffffff;
  --good: #125c2c; --bad: #9e2a1c; --warn: #6b3a00; --select: #1652b8; --dot: #f0d470;
  --tint: rgba(30, 94, 51, 0.18); --bar: linear-gradient(90deg, #1e5e33, #c98a4b); --rider: "🏈";
  --page-art: none;
}
html[data-theme="race"], .look-card[data-theme="race"] {
  --bg: #dde0e5; --line: #9aa1ab; --chip: #eef0f3; --text: #15181c; --muted: #33373e;
  --primary: #b0141c; --primary-dark: #7a0d13; --primary-text: #ffffff; --accent: #2f343b; --chip-on: #15181c; --chip-on-text: #ffffff;
  --good: #146c3a; --bad: #a52a1f; --warn: #7a4200; --select: #1652b8; --dot: #f6c445;
  --tint: rgba(176, 20, 28, 0.16); --bar: linear-gradient(90deg, #15181c, #b0141c); --rider: "🏎️";
  --page-art: none;
}
html[data-theme="gaming"], .look-card[data-theme="gaming"] {
  --bg: #0e0b1a; --surface: #241e40; --line: #5b4ca6; --chip: #2f2854; --text: #eef0ff; --muted: #b9b4dc;
  --primary: #39e1f0; --primary-dark: #1d8f99; --primary-text: #0e0b1a; --accent: #ff7ad9; --chip-on: #39e1f0; --chip-on-text: #0e0b1a;
  --good: #5ee08f; --good-bg: #12301f; --bad: #ff8f8f; --bad-bg: #3a1522; --warn: #ffc66b;
  --select: #8fb0ff; --select-bg: #1e2a57; --focus: #ffe066; --q-ink: #f3f1ff; --q-bg: #2c2550; --q-edge: #39e1f0; --dot: #ff7ad9;
  --shadow: 0 0 0 1px rgba(57, 225, 240, 0.08); --lift: 0 2px 10px rgba(0, 0, 0, 0.45);
  --tint: rgba(57, 225, 240, 0.25); --bar: linear-gradient(90deg, #39e1f0, #7a6cff, #ff7ad9); --rider: "👾";
  --page-art: none;
}
html[data-theme="dark"], .look-card[data-theme="dark"] {
  --bg: #121417; --surface: #24282e; --line: #4f5660; --chip: #30353d; --text: #e8eaed; --muted: #a9b0ba;
  --primary: #8ab4f8; --primary-dark: #5a7fb8; --primary-text: #10161f; --accent: #c9b27c; --chip-on: #8ab4f8; --chip-on-text: #10161f;
  --good: #73d494; --good-bg: #15301f; --bad: #f4a097; --bad-bg: #3a1e1b; --warn: #eec27a;
  --select: #9cc0fa; --select-bg: #1e2b40; --focus: #ffd166; --q-ink: #eef1f5; --q-bg: #2d3239; --q-edge: #8ab4f8; --dot: #8ab4f8;
  --shadow: none; --lift: 0 2px 8px rgba(0, 0, 0, 0.4);
  --tint: transparent; --bar: var(--primary); --rider: "";
  --page-art: none;
}
/* The Classic card for grades 7 to 12: the plain navy look they always had. */
.look-card[data-theme="classic"][data-band="g712"] { --bg: #e7ebf1; --line: #b7c0cd; --chip: #eef1f6; --primary: #1f3a68; --accent: #5b6b82; }
/* The sports looks drawn as the real thing (owner's son, 2026-10-29): a basketball court, a soccer pitch, an
   American football field and a race circuit, made to their true measurements by tools/build_look_art.mjs. The
   drawing is fixed behind the page under the top bar, whole (contain), turned upright on a phone held upright.
   It is pale on purpose: tests/themes.test.js holds every colour in it to 4.5:1 against the text and muted colours,
   and the cards stay solid white over it. */
html[data-theme="court"], .look-card[data-theme="court"] { --art-wide: url("looks/court-wide.svg"); --art-tall: url("looks/court-tall.svg"); }
html[data-theme="pitch"], .look-card[data-theme="pitch"] { --art-wide: url("looks/pitch-wide.svg"); --art-tall: url("looks/pitch-tall.svg"); }
html[data-theme="football"], .look-card[data-theme="football"] { --art-wide: url("looks/football-wide.svg"); --art-tall: url("looks/football-tall.svg"); }
html[data-theme="race"], .look-card[data-theme="race"] { --art-wide: url("looks/race-wide.svg"); --art-tall: url("looks/race-tall.svg"); }
/* Gaming PC (2026-10-30): a drawn desk set-up (tower with a glass side, graphics card, curved monitor, keyboard,
   mouse, headset, controller) by the same generator; dim on the dark page, with its own upright layout for phones. */
html[data-theme="gaming"], .look-card[data-theme="gaming"] { --art-wide: url("looks/gaming-wide.svg"); --art-tall: url("looks/gaming-tall.svg"); }
html:is([data-theme="court"], [data-theme="pitch"], [data-theme="football"], [data-theme="race"], [data-theme="gaming"]) body::before {
  content: ""; position: fixed; left: 0; right: 0; bottom: 0; top: var(--topbar-h, 56px); z-index: -1; pointer-events: none;
  background: var(--art-wide) no-repeat center / contain;
}
@media (max-aspect-ratio: 1/1) {
  html:is([data-theme="court"], [data-theme="pitch"], [data-theme="football"], [data-theme="race"], [data-theme="gaming"]) body::before { background-image: var(--art-tall); }
}
/* The picker card shows the drawing small, behind its icons and name. */
.look-card:is([data-theme="court"], [data-theme="pitch"], [data-theme="football"], [data-theme="race"], [data-theme="gaming"]) {
  /* Longhands: WebKit dropped the image when it came through var() inside the shorthand (walk 2026-10-29). */
  background-color: var(--bg); background-image: var(--art-wide); background-repeat: no-repeat; background-position: center; background-size: 100% auto;
}
@media print { html[data-theme] body::before { display: none !important; } }

/* The page: a chequered strip under the bar, a neon keyboard glow. */
/* Court and pitch lines under the top bar: a blue and orange court line, a white touchline. */
html[data-theme="court"] .topbar { border-bottom: 4px solid #1b4d8f; box-shadow: 0 4px 0 #f28c28; }
html:is([data-theme="pitch"], [data-theme="football"]) .topbar { border-bottom: 4px solid #ffffff; box-shadow: 0 2px 0 rgba(28, 100, 49, 0.45); }
html[data-theme="race"] .topbar { border-bottom: 0; }
html[data-theme="race"] .topbar::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -12px; height: 12px; pointer-events: none;
  background: repeating-conic-gradient(#15181c 0 25%, #ffffff 0 50%) 0 0 / 12px 12px;
}
html[data-theme="gaming"] body::after {
  content: ""; position: fixed; left: 0; right: 0; bottom: 0; height: 5px; z-index: 0; pointer-events: none;
  background: linear-gradient(90deg, #39e1f0, #7a6cff, #ff7ad9, #39e1f0); background-size: 200% 100%;
  box-shadow: 0 0 18px 4px rgba(122, 108, 255, 0.45);
  animation: rgb-glow 9s linear infinite;
}
@keyframes rgb-glow { from { background-position: 0 0; } to { background-position: 200% 0; } }
html[data-theme="gaming"] .topbar { box-shadow: 0 1px 12px rgba(57, 225, 240, 0.18); }
/* Pixel-style score, still plain to read: a monospace face, wide spacing and a soft glow. */
html[data-theme="gaming"] .score, html[data-theme="gaming"] .progress-text {
  font-family: ui-monospace, "Cascadia Mono", Consolas, "Courier New", monospace; letter-spacing: 0.06em;
}
html[data-theme="gaming"] .score { color: var(--primary); text-shadow: 0 0 10px rgba(57, 225, 240, 0.55); }

/* Small motion: the ball or the car comes in once beside the greeting instead of waving. */
html[data-older="1"] .hello-pet { animation: none; transform-origin: 50% 50%; }
html[data-theme="court"][data-effects="on"] .hello-pet { animation: ball-bounce-in 1.1s ease-out 1 both; }
html[data-theme="pitch"][data-effects="on"] .hello-pet { animation: ball-roll-in 1.3s cubic-bezier(.2,.7,.3,1) 1 both; }
html[data-theme="race"][data-effects="on"] .hello-pet { animation: car-in 1s cubic-bezier(.2,.7,.3,1) 1 both; }
html[data-theme="football"][data-effects="on"] .hello-pet { animation: ball-throw-in 1.1s cubic-bezier(.2,.7,.3,1) 1 both; }
@keyframes ball-bounce-in {
  0% { transform: translate(-40vw, -40px); } 35% { transform: translate(-22vw, 0); } 55% { transform: translate(-10vw, -18px); }
  75% { transform: translate(-3vw, 0); } 88% { transform: translate(0, -5px); } 100% { transform: translate(0, 0); }
}
@keyframes ball-throw-in { 0% { transform: translate(-40vw, 30px) rotate(-30deg); } 50% { transform: translate(-18vw, -36px) rotate(-10deg); } 100% { transform: translate(0, 0) rotate(0); } }
@keyframes ball-roll-in { from { transform: translateX(-45vw) rotate(-720deg); } to { transform: translateX(0) rotate(0); } }
@keyframes car-in { from { transform: translateX(-45vw) scaleX(-1); } to { transform: translateX(0) scaleX(-1); } }
html[data-theme="race"] .hello-pet { transform: scaleX(-1); }

/* The arrival at grades 6 to 12: smaller, on a clear page, no tinted stage. */
.arrival.older { background: transparent; }
.arrival.older .arrival-ground { display: none; }
.arrival.older .arrival-face { font-size: clamp(80px, 22vw, 130px); }
.arrival.older .arrival-say { font-size: 1.15em; font-weight: 700; border-width: 2px; background: var(--surface); }

@media (prefers-reduced-motion: reduce) {
  html[data-theme] .hello-pet, html[data-theme="gaming"] body::after { animation: none !important; }
}
html[data-effects="off"][data-theme="gaming"] body::after { animation: none; }

/* Dark pages: the places that had white or a light tint written into them. */
html[data-dark="1"] { color-scheme: dark; }
html[data-dark="1"] :is(input[type="text"], input[type="email"], input[type="number"], select, textarea) { background: var(--surface); color: var(--text); }
html[data-dark="1"] .choice:is([aria-checked="true"], .is-right, .is-wrong) .letter { color: var(--primary-text); }
html[data-dark="1"] .btn.warn.armed, html[data-dark="1"] .req-mark, html[data-dark="1"] .reel-play { color: var(--primary-text); }
html[data-dark="1"] .grade-switch.other { background: var(--surface); }
html[data-dark="1"] .review-right { border-color: var(--good); background: var(--good-bg); }
html[data-dark="1"] .card { border-color: var(--line); }
html[data-dark="1"] .arrival-say { background: var(--surface); }
/* On a dark page the light looks' cards keep their own light colours (they set only some colours themselves). */
html[data-dark="1"] .look-card:not([data-theme="gaming"]):not([data-theme="dark"]) { --text: #17202e; --muted: #5b6575; --primary-text: #ffffff; --surface: #ffffff; }

/* Grade a paper test from a photo (plan 2026-10-24, Phase 2) */
.scan-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; margin: 12px 0; }
.scan-photo { border: 1px solid var(--line); border-radius: 10px; padding: 6px; }
.scan-photo img { width: 100%; height: auto; display: block; border-radius: 6px; }
.scan-photo p { margin: 6px 0; font-size: 0.9em; }
.wr-list { display: flex; flex-direction: column; gap: 10px; margin: 12px 0; }
.wr-row { display: flex; gap: 10px; align-items: flex-start; border-top: 1px solid var(--line); padding-top: 10px; }
.wr-row.done { color: var(--muted, #666); }
.wr-n { font-weight: 800; font-size: 1.2em; min-width: 2em; }
.wr-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.wr-crop canvas { max-width: 100%; height: auto; border: 1px solid var(--line); border-radius: 6px; }
.wr-input { font-size: 1.1em; padding: 8px 10px; width: 100%; box-sizing: border-box; }
.wr-note { margin: 0; font-size: 0.95em; }
.wr-note.ask { font-weight: 600; }
.wr-body .chip.mini { align-self: flex-start; }

/* Book chapter numbers (owner 2026-10-25): one square button per chapter, the chosen chapters named underneath */
.book-nums { margin: 8px 0; }
.chip.book-num { min-width: 48px; justify-content: center; font-weight: 700; }
.book-chosen ul { margin: 4px 0 8px; padding-left: 1.2em; }
.book-chosen li { margin: 2px 0; }
.book-chosen-lesson { margin-left: 0.6em; }
.book-lessons { margin: 8px 0; }
.chip.book-lesson { text-align: left; white-space: normal; }
.chip.book-lesson:disabled { opacity: 0.55; cursor: default; }
.book-lessons-fold { margin: 8px 0; }
.book-lessons-fold > summary { cursor: pointer; font-weight: 600; }

/* Reading passages (2026-10-26, docs/PLAN-2026-10-26-reading-passages.md): the passage card stands before its
   questions. From 900 px the page widens and the passage takes the left column, sticky with its own scroll, so it
   stays in view while the questions on the right scroll; under 900 px it sits above them. */
.passage { border-left: 6px solid var(--q-edge); }
.passage-kind { margin: 0 0 0.2em; font-size: 0.85em; font-weight: 700; color: var(--muted); letter-spacing: 0.02em; }
.passage-title { margin: 0 0 0.5em; font-family: var(--q-font); font-size: 1.35em; line-height: 1.3; color: var(--q-ink); overflow-wrap: anywhere; }
.passage-title:focus { outline: 3px solid var(--focus); outline-offset: 3px; }
.passage .read-btn { margin: 0 0 10px; }
.passage-text { font-family: var(--q-font); font-size: 1.12em; line-height: 1.65; color: var(--text); overflow-wrap: anywhere; }
.passage-text p { margin: 0 0 0.9em; }
.passage-poem .passage-text p.stanza { margin: 0 0 1.1em; padding-left: 0.6em; }
.passage-note { margin: 4px 0 0; font-size: 0.9em; font-weight: 600; color: var(--muted); }
.passage-back { margin-top: 10px; }
.show-passage { margin: 0 0 10px; }
.passage-group { min-width: 0; }
.passage-qs { min-width: 0; }
.passage-again { margin: 0 0 16px; }
.passage-again > summary { cursor: pointer; font-weight: 700; padding: 8px 0; }
.passage-again > .passage { margin-top: 6px; }
@media (min-width: 900px) {
  body[data-reading="1"] .view { max-width: 1240px; }
  .passage-group {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 20px; align-items: start; margin: 0 0 8px;
  }
  .passage-group > .passage {
    position: sticky; top: 12px; max-height: calc(100vh - 24px); overflow-y: auto; overscroll-behavior: contain; margin: 0;
  }
  .passage-group .show-passage { display: none; }
}
@media print { .passage-group > .passage { position: static; max-height: none; overflow: visible; } }

/* Word help (2026-10-28, docs/PLAN-2026-10-28-word-help.md): dotted words in the stem, a peek on hover or on a
   400 ms hold, pinned cards in a strip between the stem and the choices. Colours come from the look's tokens, so the
   dark looks (Gaming PC, Calm dark) need nothing of their own. Never printed. */
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
.stem .word {
  display: inline; font: inherit; color: inherit; letter-spacing: inherit; line-height: inherit; text-align: inherit;
  background: none; border: 0; margin: 0; padding: 0 1px; border-radius: 3px; cursor: pointer;
  text-decoration: underline dotted; text-decoration-color: var(--q-edge); text-decoration-thickness: 2px; text-underline-offset: 0.2em;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.stem .word:hover { background: color-mix(in srgb, var(--q-edge) 12%, transparent); }
.stem .word[aria-expanded="true"] { background: color-mix(in srgb, var(--q-edge) 18%, transparent); text-decoration-style: solid; }
.stem .word:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.word-strip-wrap { position: relative; margin: 0 0 14px; }
.word-strip-wrap[hidden] { display: none; }
.word-strip {
  display: flex; flex-direction: column; gap: 10px; margin: 0; padding: 2px;
  max-height: 35vh; overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
}
/* More cards above or below the part of the strip in view (owner: a second card showed only as a bare blue edge on a
   phone): a fade over the hidden edge and a small label. Taps pass through to the card under it. */
.word-more {
  position: absolute; left: 0; right: 0; height: 44px; display: flex; justify-content: center; pointer-events: none; z-index: 1;
}
.word-more[hidden] { display: none; }
.word-more-up { top: 0; align-items: flex-start; background: linear-gradient(to bottom, var(--surface) 25%, transparent); }
.word-more-down { bottom: 0; align-items: flex-end; background: linear-gradient(to top, var(--surface) 25%, transparent); }
.word-more span {
  font-size: 0.8em; font-weight: 700; line-height: 1; padding: 4px 10px; margin: 2px 0;
  color: var(--chip-on-text); background: var(--chip-on); border-radius: 999px;
}
@media (min-width: 700px) { .word-strip { max-height: 50vh; } }
.word-card {
  flex: none; background: var(--surface); color: var(--text); border: 2px solid var(--q-edge); border-radius: var(--radius);
  padding: 6px 6px 12px 14px; box-shadow: var(--lift); cursor: pointer;
}
.word-card-head { display: flex; align-items: center; gap: 8px; }
.word-card-title { flex: 1; margin: 0; font-family: var(--q-font); font-size: 1.15em; font-weight: 700; color: var(--q-ink); overflow-wrap: anywhere; }
.word-card-title:focus { outline: none; }
.word-card-title:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.word-close {
  flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; margin: 0;
  font: inherit; font-size: 1.6em; line-height: 1; color: var(--text); background: transparent;
  border: 2px solid transparent; border-radius: var(--radius); cursor: pointer;
}
.word-close:hover { background: var(--chip); }
.word-close:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; }
.word-tabs { display: flex; flex-wrap: wrap; gap: 6px; margin: 2px 8px 10px 0; }
.word-tab {
  min-height: 44px; padding: 4px 16px; font: inherit; font-weight: 600; cursor: pointer;
  color: var(--text); background: var(--chip); border: 2px solid var(--line); border-radius: 999px;
}
.word-tab[aria-selected="true"] { color: var(--chip-on-text); background: var(--chip-on); border-color: var(--chip-on); }
.word-tab:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.word-panel { padding-right: 8px; }
.word-panel p { margin: 0; line-height: 1.5; }
.word-peek {
  position: fixed; z-index: 900; top: 0; left: 0; box-sizing: border-box;
  width: max-content; max-width: min(340px, calc(100vw - 16px)); overflow-y: auto;
  padding: 10px 14px; background: var(--surface); color: var(--text);
  border: 2px solid var(--q-edge); border-radius: var(--radius); box-shadow: 0 6px 22px rgba(0, 0, 0, 0.28);
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none; cursor: pointer;
}
.word-peek p { margin: 0; line-height: 1.45; }
.word-peek-word { font-family: var(--q-font); font-weight: 700; color: var(--q-ink); margin-bottom: 2px !important; }
@media print {
  .word-strip-wrap, .word-strip, .word-peek, #word-live { display: none !important; }
  .stem .word { text-decoration: none; background: none; padding: 0; }
}

/* Send to my parents (2026-11-01): large, at the top of the score and review pages. */
.send-parents { margin: 0 0 14px; text-align: center; }
.send-parents:empty { display: none; }
.send-parents-btn { width: 100%; }
.send-parents .row { justify-content: center; }
@media (max-width: 559px) { .send-parents .row .btn { flex: 1 1 100%; } }

/* The three boxes (owner's rulings B1-B4, docs/PLAN-2026-11-02-three-boxes.md; drawings FMTA..FMTC). */
.type-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 8px; margin: 8px 0 10px; }
.type-row[hidden] { display: none; }
.type-box {
  min-height: 64px; padding: 8px 6px; font: inherit; font-weight: 650; font-size: 1em; line-height: 1.2;
  color: var(--text); background: var(--surface); border: 3px solid var(--line); border-radius: calc(var(--radius) + 6px);
  cursor: pointer; text-align: center; overflow-wrap: normal; word-break: normal; hyphens: manual;
}
/* A phone: "Synonyms" must not break inside the word (walk 2026-11-02, iPhone 15 at grade 4 type size). */
@media (max-width: 480px) { .type-box { font-size: 0.82em; padding: 8px 3px; } }
.type-box[aria-pressed="true"] { background: var(--chip-on); color: var(--chip-on-text); border-color: var(--chip-on); }
.type-box:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.type-note { margin: 4px 0 8px; font-size: 1.05em; }
/* Fill the gap (owner, 2 Nov): "The ________ (boy) ran home." The line is plain; the word in brackets is in the
   sentence's own style, no border and no fill; a fully transparent native select lies over both. */
.gap-stem { white-space: normal; }
.gap-pick { position: relative; display: inline-block; white-space: nowrap; border-radius: 4px; }
.gap-line { letter-spacing: -0.06em; }
.gap-shown { color: var(--muted); }
.gap-shown.picked { color: inherit; }
.gap-select {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0;
  opacity: 0; border: 0; background: transparent; cursor: pointer;
  font-size: 16px; /* 16 px: iOS does not zoom the page on focus */
}
.gap-pick:focus-within { outline: 3px solid var(--focus); outline-offset: 2px; }
.gap-pick.done.is-right .gap-shown { color: var(--good); }
.gap-pick.done.is-wrong .gap-shown { color: var(--bad); }
.gap-words {
  background: var(--q-bg); border: 3px solid var(--q-edge); border-radius: calc(var(--radius) + 6px);
  padding: 10px 14px; margin: 0 0 14px; font-family: var(--q-font); color: var(--q-ink);
}
.gap-words-title { margin: 0 0 6px; font-weight: 700; font-size: 1.15em; }
.gap-words-list { margin: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 1.2em; line-height: 1.5; }
.gap-word.used { text-decoration: line-through; text-decoration-thickness: 2px; color: var(--muted); }

/* Games earned by results (2026-11-02, rulings E1-E4): a shelf of tiles, four across, question marks on the games still
   to earn, one plain line under it (cuts/SHELF_2_eight.png). */
.shelf-head { margin: 14px 0 6px; font-size: 1.1em; }
.game-shelf { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin: 6px 0; }
.game-shelf .game-tile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 92px; padding: 8px 4px; border-radius: 14px; text-align: center; font-size: 0.9em; line-height: 1.15;
  border: 2px solid var(--line); background: var(--surface); color: var(--text); overflow-wrap: anywhere; }
.game-shelf .game-tile[aria-pressed="true"] { background: var(--chip-on); color: var(--chip-on-text); border-color: var(--chip-on); }
.game-shelf .game-tile[aria-pressed="true"]::before { content: none; }
.game-shelf .tile-icon { font-size: 1.9em; line-height: 1; }
.game-shelf .game-tile.locked { border-style: dashed; background: var(--chip); color: var(--muted, #5c6670); cursor: default; }
.game-shelf .game-tile.locked .tile-icon { font-size: 1.8em; font-weight: 400; }
.shelf-line { margin: 6px 0 4px; }
@media (max-width: 399px) { .game-shelf .game-tile { font-size: 0.8em; min-height: 84px; } }

/* Back inside a game (ruling 3 of 2026-11-02): a read-only look at the previous question under the head; the game
   waits hidden below, and the head with Leave stays on top. */
.test-head .back-btn { flex: none; }
.back-look { margin: 10px 0; }
.back-look h2 { margin-top: 0; }
.back-look .back-mark { font-weight: 700; }
.back-look .back-mark.good { color: var(--good, #2b8a3e); }
.back-look .back-mark.bad { color: var(--bad, #c92a2a); }
.play-game.looking-back > :not(.test-head):not(.back-look) { display: none; }
