/* Practice screens, built from the tokens in tokens.css.
 *
 * Every font-size here is a --text-* token, never a literal, so the
 * accessibility toggle scales the whole page rather than the parts someone
 * remembered to hook up. `test_type_sizes_derive_from_the_scale` enforces it.
 *
 * Sizing follows ks1-design's own rules: minimum 56px on anything tappable,
 * 64-72px preferred for question answers, 64px keypad keys.
 */

/* --- reset ---------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
}

button {
  font: inherit;
  cursor: pointer;
}

/* Touch-first: no hover recolouring, but keyboard focus must stay obvious. */
:focus-visible {
  outline: 3px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* --- app shell ------------------------------------------------------------ */

.app {
  min-height: 100vh;
  background-color: var(--color-paper);
  background-image: var(--bg-graph-lines-v), var(--bg-graph-lines-h);
  font-family: var(--font-ui);
  color: var(--color-ink);
}

.app-header {
  background: var(--color-navy);
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.app-wordmark {
  font-family: var(--font-question);
  font-size: var(--text-xl);
  font-weight: var(--weight-extrabold);
  color: #fff;
  letter-spacing: -0.02em;
  text-decoration: none;
}

.app-header-right {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.child-pill {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: rgba(255, 255, 255, 0.75);
  background: rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
}

.app-main {
  max-width: 480px;
  margin: 0 auto;
  padding: var(--space-4) var(--space-4) var(--space-12);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --- accessibility toggle (PRD §7.7) -------------------------------------- */

.a11y {
  position: relative;
}

.a11y-trigger {
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  border: 1.5px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-full);
  min-height: 40px;
  padding: 0 var(--space-3);
  font-family: var(--font-question);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  line-height: 1;
}

.a11y-panel {
  position: absolute;
  right: 0;
  top: calc(100% + var(--space-2));
  z-index: 20;
  width: 15rem;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--space-4);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.a11y-panel[hidden] {
  display: none;
}

.a11y-group-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-2);
}

.a11y-options {
  display: flex;
  gap: var(--space-2);
}

.a11y-option {
  flex: 1;
  min-height: 44px;
  background: var(--color-surface);
  color: var(--color-ink);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-md);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

.a11y-option[aria-pressed='true'] {
  background: var(--color-navy);
  border-color: var(--color-navy);
  color: #fff;
}

/* --- the swappable region ------------------------------------------------- */

/* Everything HTMX replaces lives in here, so the spacing between the meta row,
 * the passage, the card and the feedback belongs to it rather than to
 * .app-main — otherwise the whole region counts as one flex child and its
 * parts sit flush against each other. */
#practice-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --- question meta row ---------------------------------------------------- */

.practice-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.practice-meta-left {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.subject-tag {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--subject-light);
  color: var(--subject);
}

.strand-label {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
}

.focus-flag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-red);
  background: var(--color-red-light);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
}

.streak {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  background: var(--color-amber-light);
  border: 1.5px solid var(--color-amber);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-4);
}

.streak-flame {
  font-size: var(--text-2xl);
  line-height: 1;
}

.streak.is-hot .streak-flame {
  filter: drop-shadow(0 0 6px rgba(245, 159, 0, 0.5));
}

.streak-count {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-extrabold);
  color: var(--color-amber);
  line-height: 1;
  display: block;
}

.streak-best {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  line-height: 1;
}

/* --- reading passage ------------------------------------------------------ */

/* Stays visible in its own card while the child answers, rather than being
 * hidden after first read (docs/build-spec.md, UX requirements). */
.passage-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-reading);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-5);
}

.passage-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin: 0 0 var(--space-2);
}

.passage-text {
  font-family: var(--font-question);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-ink);
  margin: 0;
}

/* --- question card -------------------------------------------------------- */

.question-card {
  position: relative;
  background-color: var(--color-paper);
  background-image: var(--bg-graph-lines-v), var(--bg-graph-lines-h);
  border: 1px solid var(--color-border);
  border-top: 4px solid var(--subject);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-raised);
  padding: var(--space-6) var(--space-5) var(--space-5);
}

/* Subject accents. ks1-design's three subject colours, keyed off the strand's
 * subject so the card, tag and passage rule all agree. */
.subject-maths {
  --subject: var(--color-maths);
  --subject-light: var(--color-maths-light);
}

.subject-gps {
  --subject: var(--color-gps);
  --subject-light: var(--color-gps-light);
}

.subject-reading {
  --subject: var(--color-reading);
  --subject-light: var(--color-reading-light);
}

.question-prompt {
  font-family: var(--font-question);
  font-size: var(--text-3xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: var(--leading-snug);
  margin: 0 0 var(--space-6);
  white-space: pre-line;
}

/* Word problems and the spelling cloze run long; the shorter arithmetic
 * prompts get the display size. Mirrors the prototype's length switch. */
.question-prompt.is-long {
  font-size: var(--text-2xl);
}

/* Keep the prompt clear of the mark drawn in the corner. Reserved rather than
 * hoped for: at the "Larger" text size a wrapped question ran straight under
 * the cross, which is exactly the reader the size control exists for. */
.question-card.is-marked .question-prompt {
  padding-right: var(--space-16);
}

/* --- marking overlay ------------------------------------------------------ */

/* The hand-drawn stroke, ported from the prototype's MarkOverlay + .mark-path
 * CSS (lines 412-441, 920-927): same stroke-dasharray/dashoffset technique,
 * same 0.4s draw and 0.15s delay on the cross's second stroke.
 *
 * COLOUR DIVERGES FROM THE PROTOTYPE, DELIBERATELY. The prototype draws both
 * marks in red; ks1-design assigns green to "correct" and red to "wrong", and
 * CLAUDE.md makes ks1-design ground truth for colour. The technique is the
 * prototype's, the palette is the skill's. */
.mark-overlay {
  position: absolute;
  top: calc(-1 * var(--space-4));
  right: calc(-1 * var(--space-3));
  pointer-events: none;
}

.mark-path {
  stroke-dasharray: 40;
  stroke-dashoffset: 40;
  animation: drawMark 0.4s ease forwards;
}

.mark-path--second {
  animation-delay: 0.15s;
}

@keyframes drawMark {
  to {
    stroke-dashoffset: 0;
  }
}

/* --- answer controls ------------------------------------------------------ */

.answer-area {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.choices {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.choice {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
  min-height: 72px;
  padding: var(--space-5) var(--space-6);
  text-align: left;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  color: var(--color-ink);
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-semibold);
  transition: transform var(--transition-bounce);
}

.choice:active {
  transform: scale(0.97);
}

.choice-prefix {
  font-weight: var(--weight-bold);
  opacity: 0.6;
  min-width: 1.25em;
}

.choice-mark {
  margin-left: auto;
  font-weight: var(--weight-extrabold);
  font-size: var(--text-2xl);
}

.choice.is-correct {
  background: var(--color-green-light);
  border: 3px solid var(--color-green);
  color: var(--color-green);
  box-shadow: none;
}

.choice.is-wrong {
  background: var(--color-red-light);
  border: 3px solid var(--color-red);
  color: var(--color-red);
  box-shadow: none;
}

.choice:disabled {
  cursor: default;
}

/* Numeric keypad ----------------------------------------------------------- */

.keypad-display {
  background: var(--color-navy);
  color: #fff;
  font-family: var(--font-question);
  font-size: var(--text-4xl);
  font-weight: var(--weight-extrabold);
  text-align: center;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-lg);
  min-height: 72px;
  display: flex;
  align-items: center;
  justify-content: center;
  letter-spacing: 0.12em;
}

.keypad-display:empty::before {
  content: '—';
  opacity: 0.3;
}

.keypad-keys {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-2);
}

.keypad-key {
  height: 64px;
  border: none;
  border-radius: var(--radius-md);
  background: var(--color-surface);
  color: var(--color-navy);
  box-shadow: var(--shadow-sm);
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  transition: transform var(--transition-bounce);
}

.keypad-key:active {
  transform: scale(0.97);
}

.keypad-key--delete {
  background: var(--color-red-light);
  color: var(--color-red);
  font-size: var(--text-xl);
}

.keypad-key--submit {
  background: var(--color-green);
  color: #fff;
  font-size: var(--text-xl);
}

.keypad-key:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Free-text answer --------------------------------------------------------- */

.text-answer {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.text-answer-input {
  width: 100%;
  min-height: 64px;
  padding: 0 var(--space-4);
  text-align: center;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  color: var(--color-ink);
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
}

.text-answer-input::placeholder {
  color: var(--color-ink-muted);
  font-weight: var(--weight-normal);
}

/* --- buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 56px;
  padding: var(--space-4) var(--space-8);
  border-radius: var(--radius-lg);
  border: 2px solid var(--color-navy);
  background: var(--color-navy);
  color: #fff;
  font-family: var(--font-question);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: 0.01em;
  box-shadow: var(--shadow-md);
  transition: transform var(--transition-bounce);
}

.btn:active {
  transform: scale(0.97);
}

.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  box-shadow: none;
}

.btn--full {
  width: 100%;
}

.btn--success {
  background: var(--color-green);
  border-color: var(--color-green);
}

/* --- feedback ------------------------------------------------------------- */

.feedback-card {
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* Teacher's pen: Caveat, slightly rotated. The rotation is dropped in the
 * hyperlegible mode below along with the font. */
.feedback-caption {
  font-family: var(--font-hand);
  font-size: var(--text-2xl);
  line-height: var(--leading-snug);
  margin: 0;
  transform: rotate(-1.2deg);
  transform-origin: left center;
}

.feedback-caption.is-correct {
  color: var(--color-green);
}

.feedback-caption.is-wrong {
  color: var(--color-red);
}

/* The worked explanation. Set in the UI face rather than the handwriting one:
 * this is the part a struggling child most needs to be able to read. */
.feedback-explanation {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-ink);
  margin: 0;
}

html[data-font='hyperlegible'] .feedback-caption {
  transform: none;
}

/* --- empty state ---------------------------------------------------------- */

.empty-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  padding: var(--space-8) var(--space-6);
  text-align: center;
}

.empty-title {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0 0 var(--space-3);
}

.empty-body {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-2);
}

.empty-body code {
  background: var(--color-surface-raised);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
}

/* --- child switcher ------------------------------------------------------- */

/* The real one, replacing Plan 02's DEBUG-gated `.dev-switcher`. Each option is
 * a submit button in its own POST form, so it is styled to read as a link
 * rather than inheriting `.btn`. */
.child-switcher {
  text-align: center;
  margin-top: var(--space-4);
}

.child-switcher-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-2);
}

.child-switcher-options {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
}

.child-switcher-option {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  min-height: 40px;
  padding: 0 var(--space-4);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-navy);
}

/* --- account screens ------------------------------------------------------ */

.app-nav-link {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: rgba(255, 255, 255, 0.9);
  background: rgba(255, 255, 255, 0.12);
  border: 1.5px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-full);
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--space-3);
  text-decoration: none;
}

.account-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  padding: var(--space-6) var(--space-5);
}

.account-title {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0 0 var(--space-3);
}

.account-subtitle {
  font-family: var(--font-question);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0 0 var(--space-3);
}

.account-lede {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-ink);
  margin: 0 0 var(--space-5);
}

.account-note {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
  margin: var(--space-5) 0 0;
}

.account-note code {
  background: var(--color-surface-raised);
  border-radius: var(--radius-sm);
  padding: 0 var(--space-1);
}

.account-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.account-form + .account-form {
  margin-top: var(--space-3);
}

.field-label {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

/* Inputs are styled by element rather than class: they are rendered by Django's
 * widgets, and threading a class through every one of them buys nothing here. */
.account-form input[type='email'],
.account-form input[type='text'],
.account-form input[type='password'],
.account-form select {
  width: 100%;
  min-height: 56px;
  padding: 0 var(--space-4);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-lg);
  background: var(--color-surface);
  font-family: var(--font-ui);
  font-size: var(--text-lg);
  color: var(--color-ink);
}

.field-error {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-red);
  background: var(--color-red-light);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  margin: 0;
}

.flash {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-green);
  background: var(--color-green-light);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0;
}

.account-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  margin: var(--space-5) 0 0;
}

.account-links a {
  color: var(--color-navy);
}

.danger-link {
  color: var(--color-red);
}

.btn--quiet {
  background: var(--color-surface);
  border-color: var(--color-border);
  color: var(--color-navy);
  box-shadow: none;
  text-decoration: none;
}

.btn--danger {
  background: var(--color-red);
  border-color: var(--color-red);
}

/* --- child list ----------------------------------------------------------- */

.child-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.child-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3) var(--space-4);
}

.child-row-name {
  font-family: var(--font-question);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0;
}

.child-row-active {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  color: var(--color-green);
  background: var(--color-green-light);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-2);
  margin-left: var(--space-2);
}

.child-row-meta {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  margin: var(--space-1) 0 0;
}

.child-row-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.child-row-actions a {
  color: var(--color-navy);
}

/* A submit button that has to read as a link, because switching child is a
 * POST and an <a> would be the wrong verb. */
.link-button {
  background: none;
  border: none;
  padding: 0;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-navy);
  text-decoration: underline;
}

/* --- past papers (Plan 05) ------------------------------------------------- */

/* The swappable region, same job as #practice-card's rule: the gaps between
 * the meta row, the card and the skip control belong to it rather than to
 * .app-main, which would otherwise treat the whole thing as one flex child. */
#paper-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.paper-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  flex-wrap: wrap;
}

.paper-eyebrow {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-1);
}

.paper-title {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-extrabold);
  color: var(--color-ink);
  margin: 0;
  line-height: var(--leading-tight);
}

.paper-lede {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  margin: 0;
}

/* --- the timer ------------------------------------------------------------- */

/* Amber, never red. Red is this app's "wrong" colour throughout, and running
 * over on a paper the real guidance calls "not strictly timed" is not a wrong
 * answer — it is not even a problem. */
.paper-timer {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--space-1);
  background: var(--color-surface);
  border: 1.5px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-2) var(--space-4);
  margin: 0;
}

.paper-timer.is-over {
  background: var(--color-amber-light);
  border-color: var(--color-amber);
}

.paper-timer-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
}

.paper-timer-value {
  font-family: var(--font-question);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  line-height: 1;
  /* Tabular figures, so a ticking clock doesn't shuffle its own width. */
  font-variant-numeric: tabular-nums;
}

/* --- the sitting ----------------------------------------------------------- */

.paper-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  flex-wrap: wrap;
}

.paper-progress {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  margin: 0;
}

.paper-marks {
  display: inline-block;
  margin-left: var(--space-2);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-amber);
  background: var(--color-amber-light);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
}

.question-image {
  display: block;
  max-width: 100%;
  height: auto;
  margin: var(--space-4) auto 0;
  border-radius: var(--radius-md);
}

.paper-skip,
.paper-finish {
  align-self: center;
  margin-top: var(--space-2);
}

.paper-finish {
  text-align: center;
  margin-top: var(--space-6);
}

/* --- the picker ------------------------------------------------------------ */

.paper-section {
  margin-top: var(--space-6);
}

.paper-section-title {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-3);
}

.paper-section-note {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  background: var(--color-surface-raised);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin: 0;
}

.paper-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.paper-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--subject);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-5);
}

.paper-row-title {
  font-family: var(--font-question);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0;
}

.paper-row-meta {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  margin: var(--space-1) 0 0;
}

/* --- coverage note --------------------------------------------------------- */

/* Amber, on the same reasoning as the timer: this is a caveat, not an error.
 * An incompletely transcribed paper is still a perfectly good sitting — red
 * would say something has gone wrong, and nothing has. */
.coverage-note {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  background: var(--color-amber-light);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  margin: var(--space-2) 0 0;
  /* The picker puts this inside a flex row whose other child is the Start
   * button; without a left-aligned block the note would inherit the row's
   * centring on the review screen. */
  text-align: left;
}

.coverage-note-label {
  display: block;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-amber);
  margin-bottom: var(--space-1);
}

/* On the review screen the note sits between two full-width blocks rather than
 * inside a paper row, so it gets the same breathing room as the score card. */
.score-card + .coverage-note {
  margin: var(--space-4) 0 0;
}

/* --- the review screen ----------------------------------------------------- */

.score-card {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-top: 4px solid var(--subject);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-raised);
  padding: var(--space-5);
  text-align: center;
}

.score-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  margin: 0;
}

.score-value {
  margin: var(--space-2) 0 var(--space-3);
}

.score-number {
  font-family: var(--font-question);
  font-size: var(--text-5xl);
  font-weight: var(--weight-extrabold);
  color: var(--subject);
  line-height: 1;
}

.score-total {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  margin-top: var(--space-1);
}

/* Deliberately not styled down to a footnote. This is what stops the number
 * above being read as an official SATs mark (decision D1), so it has to be
 * legible rather than tucked away. */
.score-caveat {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  max-width: 46ch;
  margin: 0 auto;
}

.score-caveat + .score-caveat {
  margin-top: var(--space-3);
}

.review-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.review-row {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-4) var(--space-5);
}

.review-row.is-correct {
  border-left-color: var(--color-green);
}

.review-row.is-wrong {
  border-left-color: var(--color-red);
}

/* A question the paper was submitted before reaching. Its own state, not a
 * wrong answer wearing the same colour: the child didn't get it wrong, they
 * didn't get to it. A deliberate *skip* is different again — that one they saw
 * and passed, which is a miss, so it stays red above. */
.review-row.is-unreached {
  border-left-color: var(--color-ink-muted);
  border-left-style: dashed;
}

.review-row-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.review-number {
  font-family: var(--font-question);
  font-size: var(--text-base);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
}

.review-marks {
  margin-left: auto;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
  font-variant-numeric: tabular-nums;
}

.review-prompt {
  font-family: var(--font-question);
  font-size: var(--text-base);
  color: var(--color-ink);
  margin: var(--space-2) 0 0;
}

.review-answers {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-1) var(--space-3);
  margin: var(--space-3) 0 0;
}

.review-answers dt {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  align-self: center;
}

.review-answers dd {
  font-family: var(--font-question);
  font-size: var(--text-base);
  color: var(--color-ink);
  margin: 0;
}

.review-blank {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  color: var(--color-ink-muted);
  font-style: italic;
}

.review-explanation {
  font-family: var(--font-hand);
  font-size: var(--text-lg);
  color: var(--color-navy-light);
  line-height: var(--leading-snug);
  margin: var(--space-3) 0 0;
}

html[data-font='hyperlegible'] .review-explanation {
  font-size: var(--text-base);
}

.review-actions {
  margin-top: var(--space-6);
}

/* The Open Government Licence attribution the ingested papers carry. Small and
 * quiet — it is a legal obligation, not something a family came here to read —
 * but real text at a real size, not 9px grey-on-grey. */
.paper-attribution {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  line-height: var(--leading-normal);
  text-align: center;
  margin: var(--space-6) auto 0;
  max-width: 52ch;
}

/* --- parent dashboard (Plan 07) -------------------------------------------- */

/* Built against `ks1-design`'s AccuracyBar and BadgeItem reference components
 * and its tokens, which CLAUDE.md makes ground truth for all visual design.
 * The prototype's ProgressView is the precedent for *layout and logic* — what
 * is on the page and in what order — not for colour, type or spacing. */

.dash-title {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  text-align: center;
  margin: 0 0 var(--space-5);
}

.dash-summary {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}

.dash-stat {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: var(--space-3) var(--space-2);
  text-align: center;
}

.dash-stat-label {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-1);
}

.dash-stat-value {
  font-family: var(--font-question);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  color: var(--color-ink);
  margin: 0;
}

.dash-legend {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-4);
}

.dash-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
}

.dash-section {
  margin-bottom: var(--space-6);
}

.dash-section-title {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--color-ink-muted);
  margin: 0 0 var(--space-3);
}

.dash-empty {
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  line-height: var(--leading-normal);
  color: var(--color-ink-muted);
  margin: 0;
}

/* --- per-strand rows ------------------------------------------------------- */

.strand-list,
.untried-list,
.badge-shelf {
  list-style: none;
  margin: 0;
  padding: 0;
}

.strand-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.strand-row {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--space-3) var(--space-4);
}

.strand-row-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.strand-row-name {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-ink);
}

/* The subject dot. `--subject` comes from the `.subject-*` classes Plan 02
 * defined for the question card, so a strand is the same colour on both
 * screens without a second mapping to keep in step. */
.strand-row-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background: var(--subject, var(--color-navy));
  flex: none;
}

.strand-row-score {
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
  white-space: nowrap;
}

.strand-bar {
  height: 10px;
  background: var(--color-border);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.strand-bar-fill {
  height: 100%;
  border-radius: var(--radius-full);
  transition: width var(--transition-bounce);
}

/* The prototype's display thresholds, and only those — see
 * apps/dashboard/services.py BAR_TIERS for why these are deliberately not
 * pick_strand's weighting tiers. */
.bar--red {
  background: var(--color-red);
}

.bar--amber {
  background: var(--color-amber);
}

.bar--green {
  background: var(--color-green);
}

/* Plan 11's Less/Normal/More control lands here. Empty until then, and
 * collapsed to nothing so the row is not padded for something absent. */
.strand-row-controls:empty {
  display: none;
}

/* --- untried strands ------------------------------------------------------- */

.untried-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.untried-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-surface-raised);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-ink-muted);
}

/* --- badge shelf ----------------------------------------------------------- */

.badge-shelf {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.badge-item {
  width: 88px;
  text-align: center;
}

.badge-medal {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  margin: 0 auto var(--space-2);
  border-radius: var(--radius-full);
  background: var(--color-amber-light);
  border: 2px solid rgba(30, 58, 95, 0.07);
  box-shadow: var(--shadow-md);
  font-size: var(--text-2xl);
}

.badge-label {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  line-height: var(--leading-snug);
  color: var(--color-ink);
}

.badge-date {
  display: block;
  font-family: var(--font-ui);
  font-size: var(--text-xs);
  color: var(--color-ink-muted);
}

/* --- reset ----------------------------------------------------------------- */

/* Below the fold of everything else and visually quiet, like the prototype's.
 * It is the one irreversible action in the app; it should be findable, not
 * inviting. */
.dash-danger {
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-4);
  margin-top: var(--space-8);
  text-align: center;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
}

/* --- motion --------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }

  /* The mark must still end up drawn, not stuck at full dashoffset. */
  .mark-path {
    stroke-dashoffset: 0;
  }
}

/* --- badge icons (Plan 08) -------------------------------------------------- */

/* Per-type tint behind the shelf's emoji. Appended as its own section rather
 * than folded into the `.badge-shelf` block above so that Plan 07's rules and
 * this plan's mapping stay separately legible; source order is what makes these
 * win over `.badge-medal`'s base background.
 *
 * The tints come from `ks1-design`'s `BadgeItem.jsx`, which is ground truth for
 * anything visual — but only where it names a token. It hard-codes two literals
 * the design system has no token for (`#ffe4a0` for the 10 tier, `#ffd700` for
 * the 20), and `tokens/colors.css` ships exactly one amber tint. Inventing two
 * more colours to match a reference component's inline styles is the drift
 * `test_every_colour_token_matches_the_skill_verbatim` exists to catch, so the
 * escalation is kept with real tokens instead: amber-light for the two lower
 * streak tiers, full amber for the 20. The 5 and the 10 therefore share a tint
 * and an icon and are told apart by their label, which is the one thing on the
 * chip that is real text. */

.badge-medal--streak-5,
.badge-medal--streak-10 {
  background: var(--color-amber-light);
}

.badge-medal--streak-20 {
  background: var(--color-amber);
}

.badge-medal--paper-completion {
  background: var(--color-maths-light);
}

.badge-medal--topic-mastery {
  background: var(--color-gps-light);
}

/* ---- Footer + long-form prose (privacy notice) ---- */

/* The app had no footer until the privacy notice needed somewhere to live.
 * Deliberately understated: this is a child-facing app, and a footer competing
 * with the practice card would be worse than no footer. It still appears on
 * every page, including sign-in, because that is the page a parent reads
 * before they have an account. */
.app-footer {
  padding: var(--space-8) var(--space-5) var(--space-6);
  text-align: center;
  font-family: var(--font-ui);
  font-size: var(--text-sm);
}

.app-footer a {
  color: var(--color-ink-muted);
}

/* Widens the 480px child-facing measure for parent-facing prose. 640px keeps
 * lines near the 60-75 character range that is comfortable to read; the default
 * measure exists for a single practice question on a phone, which is a
 * different job. Narrow viewports are unaffected — this is a max, not a width. */
.app-main--reading {
  max-width: 640px;
}

/* Long-form reading, as opposed to the short labelled fields the other
 * .account-card screens hold. Only the privacy notice uses it so far. */
.prose h2 {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  color: var(--color-navy);
  margin: var(--space-6) 0 var(--space-2);
}

.prose p,
.prose li {
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: var(--leading-relaxed);
  color: var(--color-ink);
}

.prose p {
  margin: 0 0 var(--space-3);
}

.prose ul {
  margin: 0 0 var(--space-3);
  padding-left: var(--space-5);
}

.prose li {
  margin-bottom: var(--space-2);
}
