/*
 * Headlift: a brain gym. Chalk, ink navy, one coral mascot.
 * Thick outlines, flat fills, hard shadows. Propshaft serves this file as-is.
 *
 * Coral and yellow are fills only: they fail contrast as text on --bg and --surface.
 * Text on a coral or yellow fill is --on-accent.
 */

/* ---------- Tokens ---------- */
:root {
  color-scheme: light;

  --bg: #F7F3E8;
  --surface: #FFFFFF;
  --text: #16213E;
  --muted: #4A5270;
  --outline: #16213E;
  --coral: #FF6B57;
  --yellow: #FFD60A;
  --on-accent: #16213E;
  --danger: #B3261E;
  --water: #A5DCF5;
  --copper: #E0A070;
  --silver: #D6DBE4;
  --bill: #BFE3C0;

  --font-body: "Atkinson Hyperlegible", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Anton", Impact, "Arial Narrow", sans-serif;

  --border: 3px solid var(--outline);
  --shadow: 4px 4px 0 var(--outline);
  --radius: 12px;
  --gutter: 16px;
  --column: 720px;
}

/* Dark: follow the OS unless a theme was picked explicitly. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --bg: #10182E;
    --surface: #1B2542;
    --text: #F7F3E8;
    --muted: #B8BFD4;
    --outline: #F7F3E8;
    --coral: #FF6B57;
    --yellow: #FFD60A;
    --on-accent: #16213E;
    --danger: #FFB4AB;
    --water: #2F7FB0;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #10182E;
  --surface: #1B2542;
  --text: #F7F3E8;
  --muted: #B8BFD4;
  --outline: #F7F3E8;
  --coral: #FF6B57;
  --yellow: #FFD60A;
  --on-accent: #16213E;
  --danger: #FFB4AB;
  --water: #2F7FB0;
}

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

html {
  font-size: 112.5%; /* 18px */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

h1,
h2 {
  margin: 0 0 0.5em;
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.15;
}

h1 {
  font-size: 2.25rem;
}

h2 {
  font-size: 1.5rem;
}

p {
  margin: 0 0 1em;
}

a {
  color: var(--text);
}

:focus-visible {
  outline: 3px solid var(--text);
  outline-offset: 3px;
}

/* ---------- Layout ---------- */
.app-header {
  background: var(--surface);
  border-bottom: var(--border);
}

.app-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  max-width: var(--column);
  margin: 0 auto;
  padding: 8px var(--gutter);
}

.app-header__actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
}

.app-header__actions form {
  margin: 0;
}

.app-header__label {
  padding: 0 8px;
  background: var(--yellow);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--on-accent);
  font-size: 0.8rem;
  font-weight: 700;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 1.75rem;
  line-height: 1;
  letter-spacing: 0.02em;
  text-decoration: none;
}

.app-main {
  max-width: var(--column);
  margin: 0 auto;
  padding: 24px var(--gutter) 48px;
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  text-align: center;
}

/* ---------- Components ---------- */
.card {
  width: 100%;
  margin: 0 0 24px;
  padding: 20px;
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.card > :last-child {
  margin-bottom: 0;
}

.muted {
  color: var(--muted);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 44px;
  max-width: 100%;
  min-height: 44px;
  padding: 6px 16px;
  border: var(--border);
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
  cursor: pointer;
}

.btn-primary {
  background: var(--coral);
  box-shadow: var(--shadow);
  color: var(--on-accent);
}

.btn-primary:active {
  box-shadow: none;
  transform: translate(4px, 4px);
}

.btn-secondary {
  background: var(--surface);
  color: var(--text);
}

.btn-icon {
  padding: 6px;
}

/* The hidden attribute does nothing on SVG elements by default. */
.btn-icon svg[hidden] {
  display: none;
}

.field {
  margin: 0 0 16px;
}

.field label {
  display: block;
  margin-bottom: 4px;
  font-weight: 700;
}

.field input[type="text"],
.field input[type="password"],
.field input[type="email"],
.field input[type="number"],
.field input[type="date"],
.field input[type="file"],
.field textarea,
.field select {
  display: block;
  width: 100%;
  min-height: 44px;
  padding: 6px 12px;
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1rem;
}

.field-check {
  display: flex;
  align-items: center;
  gap: 8px;
}

.field-check input {
  flex: none;
  width: 24px;
  height: 24px;
  margin: 0;
  accent-color: var(--coral);
}

.field-check label {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin: 0;
  font-weight: 400;
}

.problem-check {
  margin-bottom: 16px;
}

/* A reading runs longer than a screen, so its box stays by its title. */
.problem-check[data-role="reading"],
.problem-check[data-role="reading"] label {
  align-items: flex-start;
}

.material-topic {
  margin: 0 0 16px;
  padding: 0;
  border: 0;
}

.material-topic legend {
  padding: 0;
  font-weight: 700;
}

.flash {
  margin: 0 0 20px;
  padding: 12px 16px;
  border: var(--border);
  border-radius: var(--radius);
  font-weight: 700;
}

.flash-notice {
  background: var(--yellow);
  color: var(--on-accent);
}

.flash-alert {
  background: var(--surface);
  border-color: var(--danger);
  color: var(--danger);
}

ul.flash {
  padding-left: 36px;
}

.link-list {
  margin: 0 0 24px;
  padding: 0;
  list-style: none;
}

.link-list li + li {
  border-top: var(--border);
}

.link-list a {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 4px 0;
  font-weight: 700;
}

.admin-table-scroll {
  overflow-x: auto;
}

.admin-table {
  width: 100%;
  margin: 0 0 12px;
  border-collapse: collapse;
}

.admin-table th,
.admin-table td {
  padding: 8px 12px 8px 0;
  text-align: left;
  border-bottom: var(--border);
  overflow-wrap: normal;
}

.admin-table tbody th {
  font-weight: 400;
}

.admin-table .admin-num {
  text-align: right;
  white-space: nowrap;
}

.admin-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 24px;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* Buttons stacked, in the order they matter. */
.btn-column {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

/* Extra practice: every skill is a full-width button, and a long label wraps inside it. */
.practice-section h3 {
  margin: 20px 0 8px;
  font-size: 1.125rem;
}

.practice-section summary {
  min-height: 44px;
  font-size: 1.25rem;
  font-weight: 700;
  cursor: pointer;
}

.skill-form {
  margin: 0 0 8px;
}

.skill-form .btn {
  width: 100%;
  justify-content: flex-start;
  text-align: left;
}

.skill-score {
  margin: 0 0 8px;
  font-size: 1.25rem;
}

/* The parent's lesson preview: the prompt, then its answer on its own line in a filled chip. */
.item-list {
  margin: 0;
  padding-left: 32px;
}

.item-list li {
  padding: 12px 0;
}

.item-list li:first-child {
  padding-top: 0;
}

.item-list li:last-child {
  padding-bottom: 0;
}

.item-list li + li {
  border-top: var(--border);
}

.item-prompt,
.item-detail {
  display: block;
}

.item-prompt {
  font-weight: 700;
}

.item-answer {
  display: inline-block;
  max-width: 100%;
  margin: 4px 0;
  padding: 0 8px;
  background: var(--yellow);
  border: var(--border);
  border-radius: var(--radius);
  color: var(--on-accent);
  font-weight: 700;
}

.item-detail {
  font-size: 0.9rem;
}

/* ---------- Workout ---------- */
.workout-progress {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-size: 1.5rem;
  line-height: 1.15;
}

.workout-prompt {
  margin: 0 0 16px;
  font-size: 2.25rem;
  font-weight: 700;
  line-height: 1.2;
  overflow-wrap: anywhere;
}

.workout-prompt.workout-prompt-long { font-size: 1.375rem; line-height: 1.3; }

.workout-read {
  font-size: 1.25rem;
  white-space: pre-line;
}

.workout-score {
  margin: 0 0 16px;
  font-size: 3rem;
  font-weight: 700;
  line-height: 1.1;
}

/* The button on the redo screen sits between two cards. */
.more-reps-start {
  margin-bottom: 24px;
}

.missed-list {
  margin: 0;
  padding-left: 24px;
  font-size: 1.25rem;
}

.missed-list li + li {
  margin-top: 8px;
}

/* The paper is white in both themes: it's what the ink is read against. Ink is drawn black, whatever the theme. */
.canvas-box {
  position: relative;
  width: 100%;
  height: clamp(240px, 45vh, 530px);
  overflow: hidden;
  background: #FFFFFF;
  border: var(--border);
  border-radius: var(--radius);
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.canvas-paper {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  touch-action: none;
}

/* Writing lines for a kid, on the white paper in both themes. Pale, so ink always stands out. */
.canvas-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.canvas-line { stroke: #B9C6DA; stroke-width: 1.5; }
.canvas-line-middle { stroke-dasharray: 8 8; }
.canvas-line-base { stroke: #8FA3C0; stroke-width: 2; }
/* Graph paper for math. The paper is white in both themes, so one color serves both. */
.canvas-grid-line { stroke: #C4D2E6; stroke-width: 2; }

.canvas-status {
  margin: 12px 0 0;
  font-weight: 700;
}

/* Read by screen readers, with no box of its own, so saving moves nothing on the page. */
.canvas-status-quiet {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.canvas-actions {
  margin-top: 16px;
}

/* Erase is a mode, so the button stays pressed while it's on: the colors swap, in either theme. */
.canvas-erase-on {
  background: var(--text);
  color: var(--surface);
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* Saving is busy, not unavailable: full strength, pressed in and striped, unlike a disabled button. */
.btn-saving:disabled {
  background-image: linear-gradient(-45deg, var(--yellow) 25%, var(--coral) 25% 50%, var(--yellow) 50% 75%, var(--coral) 75%);
  background-size: 32px 32px;
  box-shadow: none;
  opacity: 1;
  transform: translate(4px, 4px);
  cursor: progress;
}

.ink-image {
  display: block;
  max-width: 100%;
  max-height: 40vh;
  margin: 0 0 12px;
  background: #FFFFFF;
  border: var(--border);
  border-radius: var(--radius);
}

/* A correction round's prompt and last try share a row, so the canvas and Next stay on screen either way up. */
.workout-prompt-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 16px;
}

.workout-prompt-row .workout-prompt {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
}

.workout-prompt-col {
  flex: 1 1 0;
  min-width: 0;
}

.workout-prompt-col .workout-prompt {
  margin: 0 0 8px;
}

.workout-last-try {
  flex: 0 1 50%;
  min-width: 0;
}

.workout-last-try-label {
  margin: 0 0 4px;
  font-weight: 700;
}

.ink-image-small {
  max-height: 120px;
  margin: 0;
}

@media (max-width: 599px) {
  .workout-prompt-row {
    flex-direction: column;
  }
}

/* The link shares the progress line and sets no height of its own, so the canvas and Next stay on screen with it there. */
.workout-progress-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}

.workout-steps-link {
  font-weight: 700;
}

.coach-steps,
.coach-example-steps {
  margin: 0 0 16px;
  font-size: 1.25rem;
}

.coach-steps {
  padding-left: 32px;
}

.coach-example-steps {
  padding: 0;
  list-style: none;
}

.coach-steps li + li,
.coach-example-steps li + li {
  margin-top: 8px;
}

.coach-example-answer {
  font-size: 1.25rem;
  font-weight: 700;
}

/* ---------- Max Cortex ---------- */
/* Always chalk and ink, in both themes, so Max stays readable in dark mode. */
.max {
  display: inline-grid;
  flex: none;
  place-items: center;
  overflow: hidden;
  background: #F7F3E8;
  border: 3px solid #16213E;
  border-radius: 50%;
}

.max img {
  display: block;
  width: 92%;
  height: 92%;
}

.max-small {
  width: 96px;
  height: 96px;
}

.max-medium {
  width: 160px;
  height: 160px;
}

.max-large {
  width: 240px;
  height: 240px;
}

/* ---------- Motion ---------- */
/* Every animation and transition lives inside this rule, so reduced motion turns them all off. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes celebrate {
    0%, 100% {
      transform: scale(1);
    }

    40% {
      transform: scale(1.12) rotate(-3deg);
    }
  }

  .celebrate {
    animation: celebrate 500ms ease-out;
  }

  /* While the fill is yellow the text is --on-accent, because --text in dark mode can't be read on it. */
  @keyframes question-arrives {
    0% {
      opacity: 0;
      transform: translateY(16px);
      background-color: var(--yellow);
      box-shadow: -8px 0 0 var(--yellow), 8px 0 0 var(--yellow);
      color: var(--on-accent);
    }

    50% {
      opacity: 1;
      transform: none;
      background-color: var(--yellow);
      box-shadow: -8px 0 0 var(--yellow), 8px 0 0 var(--yellow);
      color: var(--on-accent);
    }
  }

  .workout-prompt-new {
    animation: question-arrives 400ms ease-out;
  }

  @keyframes saving-stripes {
    to {
      background-position: 32px 0;
    }
  }

  .btn-saving:disabled {
    animation: saving-stripes 800ms linear infinite;
  }
}

/* "Read to me" beside a prompt or a heading. The button keeps its own 44px height and adds none to the row. */
.read-aloud-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.read-aloud-row > h1,
.read-aloud-row > .workout-prompt {
  flex: 1 1 0;
  min-width: 0;
}

.read-aloud {
  flex: 0 0 auto;
}

/* .btn sets display, which would otherwise win over the hidden attribute. */
.read-aloud[hidden] {
  display: none;
}

/* Streak and the parent's calendar. State is always in words; color only backs it up. */
.streak-line {
  font-weight: 700;
  font-size: 1.5rem;
  margin: 0 0 16px;
}

.calendar-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

.calendar-nav h2 {
  margin: 0;
  text-align: center;
}

.calendar-nav a {
  white-space: nowrap;
}

.calendar {
  width: 100%;
  table-layout: fixed;
  border-collapse: separate;
  border-spacing: 2px;
}

.calendar th {
  font-size: 0.8rem;
  color: var(--muted);
}

.calendar-day {
  padding: 0;
  border: 2px solid var(--outline);
  border-radius: 6px;
}

.calendar-day a,
.calendar-day .calendar-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 64px;
  padding: 4px 2px;
  text-decoration: none;
  color: inherit;
}

.calendar-number {
  font-weight: 700;
}

.calendar-label,
.calendar-score,
.calendar-reading {
  font-size: 0.72rem;
  line-height: 1.1;
  white-space: nowrap;
}

.calendar-day-done {
  background: var(--yellow);
  color: var(--on-accent);
}

.calendar-day-needs-help {
  background: var(--coral);
  color: var(--on-accent);
}

.calendar-day-excused {
  border-style: dashed;
}

.calendar-day-missed .calendar-label,
.calendar-day-unfinished .calendar-label {
  color: var(--danger);
  font-weight: 700;
}

/* A kid's own calendar states a missed day plainly, with no alarm: Max never mocks. */
.calendar-day-missed .calendar-cell .calendar-label,
.calendar-day-unfinished .calendar-cell .calendar-label {
  color: var(--muted);
  font-weight: 400;
}

.calendar-day a[aria-current="date"],
.calendar-day .calendar-cell[aria-current="date"] {
  outline: 3px solid currentColor;
  outline-offset: -3px;
}

.calendar-blank {
  border: 0;
}

.spotted-list {
  margin: 0;
  padding-left: 24px;
}

.spotted-list li + li {
  margin-top: 8px;
}

.tag {
  display: inline;
  font-weight: 700;
}

.tag-struggle {
  color: var(--danger);
}

.day-item summary {
  cursor: pointer;
}

.day-item-result {
  display: block;
  color: var(--muted);
}

.attempt {
  margin-top: 12px;
}

.attempt h3 {
  font-size: 1rem;
}

@media (max-width: 480px) {
  .calendar-card {
    padding: 12px 8px;
  }

  .calendar {
    border-spacing: 1px;
  }

  .calendar-day a,
  .calendar-day .calendar-cell {
    padding: 4px 0;
  }

  .calendar-day-missed .calendar-label,
  .calendar-day-unfinished .calendar-label {
    font-weight: 400;
  }

  .calendar-nav {
    font-size: 0.9rem;
  }

  .calendar-nav h2 {
    font-size: 1.1rem;
  }

  .calendar-label,
  .calendar-score,
  .calendar-reading {
    font-size: 0.65rem;
  }
}

/* ---------- Kid home ---------- */
/* One column on a phone. Everything here is under .home, so the parent's calendar, which shares the .calendar classes, stays as it is. */
/* Signing in lands here with a flash above the tiles, so it takes less room on this page. */
.app-main:has(.home) .flash {
  margin-bottom: 12px;
  padding: 4px 16px;
}

.home-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-bottom: 16px;
}

.home-hero .max {
  width: 72px;
  height: 72px;
}

.home-hero h1 {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
}

.home-streaks {
  flex: 1 1 100%;
  padding: 6px 16px;
  background: var(--yellow);
  border: var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--on-accent);
  font-size: 1.125rem;
  font-weight: 700;
  line-height: 1.3;
}

.home-streaks p {
  margin: 0;
}

.home-tiles {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
}

.home-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  margin: 0;
  padding: 12px 16px;
  box-shadow: none;
}

.home-tile h2 {
  margin-bottom: 4px;
}

.home-tile p {
  margin-bottom: 8px;
  font-size: 0.9rem;
  line-height: 1.35;
}

.home-tile .btn-row {
  gap: 8px;
}

/* What's left to do has the hard shadow and the coral button. What's finished has neither, a dashed line, and says Done. */
.home-tile-todo {
  box-shadow: var(--shadow);
}

.home-tile-done {
  background: transparent;
  border-style: dashed;
}

.home-done {
  display: inline-block;
  padding: 0 8px;
  border: var(--border);
  border-radius: var(--radius);
}

.home-tile-workout h2 {
  font-size: 2.5rem;
}

.home-tile-workout > p {
  font-size: 1.25rem;
}

.home-tile-workout .btn {
  width: 100%;
  min-height: 64px;
  margin-top: auto;
  font-size: 1.5rem;
}

/* The tile's button sits at the bottom, whatever the words above it take. */
.home-tile-reading .btn,
.home-tile-extra .btn-row {
  margin-top: auto;
}

.home-note {
  margin: 0;
  padding: 8px 16px;
  border: var(--border);
  border-radius: var(--radius);
  font-size: 0.9rem;
}

.home-calendar {
  margin: 16px 0 0;
}

.home-calendar .calendar-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

@media (min-width: 700px) {
  /* The same break out of the column as the workout's figure and canvas. */
  .home {
    width: min(1100px, calc(100vw - 32px));
    margin-left: calc(50% - min(550px, calc(50vw - 16px)));
  }

  .home-hero {
    flex-wrap: nowrap;
  }

  .home-streaks {
    flex: 0 0 auto;
  }

  /* Today's workout runs down the left. Without a Reading tile, Extra practice takes the whole right side. */
  .home-tiles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .home-tile-workout {
    grid-column: 1;
    grid-row: 1 / span 2;
  }

  .home-tile-workout:only-child {
    grid-column: 1 / -1;
    align-self: start;
  }

  .home-tile-reading {
    grid-column: 2;
    grid-row: 1;
  }

  .home-tile-extra {
    grid-column: 2;
    grid-row: 2;
  }

  .home-tile-workout + .home-tile-extra {
    grid-row: 1 / span 2;
  }

  /* Short cells, so a six-week month fits. Each is still 44px or more, and says its state in words. */
  .home-calendar {
    padding: 8px 12px;
  }

  .home-calendar .calendar-nav {
    font-size: 0.9rem;
  }

  .home-calendar .calendar-nav h2 {
    font-size: 1.25rem;
  }

  .home-calendar .calendar-cell {
    justify-content: center;
    min-height: 44px;
    padding: 2px;
  }

  .home-calendar .calendar-number {
    line-height: 1.2;
  }
}

@media (orientation: landscape) and (min-width: 900px) {
  .home-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 372px;
    gap: 16px;
    align-items: stretch;
  }

  .home-calendar {
    margin: 0;
  }
}

/* ---------- A kid's stats ---------- */
/* Filled stars are the yellow accent, and the outline is what makes them read on a white card. */
.stars {
  white-space: nowrap;
}

.stars-on {
  color: var(--yellow);
  -webkit-text-stroke: 1px var(--outline);
}

.stars-off {
  color: var(--muted);
}

.new-star {
  margin: 0 0 8px;
  font-size: 1.25rem;
  font-weight: 700;
}

.new-star-stars {
  display: inline-block;
}

.stats-section h2 {
  margin: 0;
}

.stats-list,
.stats-next-list,
.stats-rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.stats-list {
  display: flex;
  flex-wrap: wrap;
  gap: 0 16px;
}

.stats-next-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-width: 0;
}

.stats-next-item > span {
  min-width: 0;
  overflow-wrap: break-word;
  line-height: 1.2;
}

.stats-next-item .btn {
  white-space: nowrap;
}

.stats-next-item form {
  flex: none;
}

/* On the My stats page. */
.stats-highlights {
  display: grid;
  gap: 12px;
}

.stats-highlights .stats-section h2 {
  margin-bottom: 4px;
  font-size: 1.25rem;
}

.stats-highlights .stats-list {
  flex-direction: column;
}

.stats-highlights .stats-next-list {
  display: grid;
  gap: 8px;
}

.stats-row {
  padding: 8px 0;
  border-top: 2px solid var(--muted);
}

.stats-row:first-child {
  border-top: 0;
}

.stats-row-label {
  display: block;
  font-weight: 700;
  overflow-wrap: anywhere;
}

.stats-row-facts {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 16px;
}

/* On home, between the hero and the tiles. In landscape it has 77px with its margin, so there it's a single row. */
.stats-strip {
  display: grid;
  gap: 8px;
  margin-bottom: 16px;
  padding: 4px 12px;
  border: var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: 0.9rem;
  line-height: 1.25;
}

.stats-strip h2 {
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
}

.stats-strip .stats-next-list {
  display: grid;
  gap: 4px 12px;
}

.stats-strip .btn {
  min-height: 44px;
  padding: 2px 10px;
  border-width: 2px;
  box-shadow: none;
  font-size: 0.85rem;
}

.stats-link {
  justify-self: start;
}

@media (min-width: 700px) {
  .stats-strip {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .stats-strip .stats-section {
    grid-column: 1;
    display: flex;
    align-items: baseline;
    gap: 12px;
  }

  .stats-strip .stats-section h2 {
    flex: none;
  }

  .stats-strip .stats-next {
    display: block;
    grid-column: 1 / -1;
  }

  .stats-strip .stats-next-list {
    flex: 1;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .stats-link {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
  }
}

/* Short enough for landscape: What I've done and Next to level up. The rest waits on My stats. */
@media (orientation: landscape) and (min-width: 900px) {
  .stats-strip {
    grid-template-columns: 224px minmax(0, 1fr) auto;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
    padding: 3px 12px;
    font-size: 0.8rem;
    line-height: 1.15;
  }

  .stats-strip h2 {
    font-size: 0.8rem;
  }

  .stats-strip .stats-next-item .btn {
    width: 72px;
    padding: 0 4px;
    font-size: 0.8rem;
    white-space: normal;
  }

  .stats-strip .stats-great,
  .stats-strip .stats-stronger {
    display: none;
  }

  .stats-strip .stats-section {
    grid-row: 1;
  }

  .stats-strip .stats-done {
    display: block;
    grid-column: 1;
  }

  .stats-strip .stats-next {
    display: flex;
    align-items: center;
    grid-column: 2;
  }

  .stats-strip .stats-next h2 {
    width: 64px;
    overflow-wrap: normal;
  }

  .stats-link {
    grid-column: 3;
  }
}

/* ---------- Figures ---------- */
/* Figures. Inline SVG, sized by its container, with color from the theme tokens. */
.figure {
  display: block;
  width: 100%;
  max-width: 460px;
  max-height: min(38vh, 360px);
  margin: 0 0 16px;
}
.figure-small .figure { max-width: 180px; max-height: 140px; margin: 4px 0 8px; }
/* Coins and graphs are mostly words and numbers, which are too small to read at the size of a clock. A dashed line or a hidden edge shrinks to a speck, and so do eighths and a bar's label. */
.figure-small .figure:has(.fig-money-word, .fig-graph-title, .fig-fold, .fig-flat, .fig-solid-face, .fig-fraction) { max-width: 340px; max-height: 280px; }
.fig-grid { stroke: var(--muted); stroke-width: 1; opacity: 0.35; }
.fig-axis { stroke: var(--text); stroke-width: 2.5; }
.fig-axis-head, .fig-ray-head { fill: var(--text); }
.fig-tick { fill: var(--text); font: 700 19px var(--font-body); paint-order: stroke; stroke: var(--surface); stroke-width: 4px; }
.fig-label { fill: var(--text); font: 700 16px var(--font-body); }
.fig-name { fill: var(--text); font: 700 24px var(--font-body); paint-order: stroke; stroke: var(--surface); stroke-width: 4px; }
.fig-measure { fill: var(--text); font: 400 19px var(--font-body); paint-order: stroke; stroke: var(--surface); stroke-width: 4px; }
.fig-point { fill: var(--coral); stroke: var(--text); stroke-width: 2; }
.fig-shape { fill: var(--coral); fill-opacity: 0.18; stroke: var(--text); stroke-width: 3; stroke-linejoin: round; }
.fig-ray { stroke: var(--text); stroke-width: 4; }
.fig-ray-closed { fill: var(--text); stroke: var(--text); stroke-width: 3; }
.fig-ray-open { fill: var(--surface); stroke: var(--text); stroke-width: 3; }
.fig-cell { fill: var(--surface); stroke: var(--text); stroke-width: 2; }
.fig-cell-on { fill: var(--coral); stroke: var(--text); stroke-width: 2; }
.fig-mark { stroke: var(--text); stroke-width: 2.5; }
.fig-mark-open { fill: none; stroke: var(--text); stroke-width: 2; }
/* The kid's own points. A fixed point is coral, and yellow can't be mistaken for it. The stroke is what makes it read on a white surface. */
.fig-attempt { fill: var(--yellow); stroke: var(--text); stroke-width: 3; }
.fig-attempt-shape { fill: var(--yellow); fill-opacity: 0.25; stroke: var(--text); stroke-width: 3; stroke-linejoin: round; }
.figure-small .fig-attempt { stroke-width: 7; }
.fig-clock-face { fill: var(--surface); stroke: var(--text); stroke-width: 4; }
.fig-clock-tick { stroke: var(--text); stroke-width: 2; }
.fig-clock-number { fill: var(--text); font: 700 22px var(--font-body); }
.fig-clock-hour { stroke: var(--text); stroke-width: 8; stroke-linecap: round; }
.fig-clock-minute { stroke: var(--coral); stroke-width: 5; stroke-linecap: round; }
.fig-clock-pin { fill: var(--text); }
.fig-ruler-bar { fill: var(--coral); stroke: var(--text); stroke-width: 3; }
.fig-ruler-body { fill: var(--surface); stroke: var(--text); stroke-width: 3; }
.fig-ruler-tick { stroke: var(--text); stroke-width: 3; }
.fig-ruler-number { fill: var(--text); font: 700 22px var(--font-body); }
.fig-scale-face { fill: var(--surface); stroke: var(--text); stroke-width: 4; }
.fig-scale-tick { stroke: var(--text); stroke-width: 2; }
.fig-scale-tick-five { stroke: var(--text); stroke-width: 4; }
.fig-scale-number { fill: var(--text); font: 700 22px var(--font-body); }
.fig-scale-needle { stroke: var(--coral); stroke-width: 5; stroke-linecap: round; }
.fig-scale-pin { fill: var(--text); }
.fig-cup { fill: var(--surface); }
.fig-cup-water { fill: var(--water); }
.fig-cup-surface { stroke: var(--text); stroke-width: 3; }
.fig-cup-line { stroke: var(--text); stroke-width: 3; }
.fig-cup-number { fill: var(--text); font: 700 26px var(--font-body); }
.fig-cup-glass { fill: none; stroke: var(--text); stroke-width: 4; }
.fig-cup-handle { fill: none; stroke: var(--text); stroke-width: 8; }
.fig-fold { stroke: var(--coral); stroke-width: 4; stroke-dasharray: 12 8; }
.fig-flat { fill: var(--water); stroke: var(--text); stroke-width: 4; }
.fig-solid-face { fill: var(--water); stroke: var(--text); stroke-width: 4; stroke-linejoin: round; }
.fig-solid-edge { fill: none; stroke: var(--text); stroke-width: 3; }
.fig-solid-hidden { fill: none; stroke: var(--text); stroke-width: 3; stroke-dasharray: 8 7; }
.fig-coin-copper { fill: var(--copper); stroke: var(--text); stroke-width: 3; }
.fig-coin-silver { fill: var(--silver); stroke: var(--text); stroke-width: 3; }
.fig-bill { fill: var(--bill); stroke: var(--text); stroke-width: 3; }
.fig-money-word { fill: var(--on-accent); font: 700 18px var(--font-body); }
.fig-graph-title { fill: var(--text); font: 700 22px var(--font-body); }
.fig-graph-note { fill: var(--text); font: 700 16px var(--font-body); }
.fig-graph-label { fill: var(--text); font: 700 20px var(--font-body); }
.fig-picto-symbol { fill: var(--coral); stroke: var(--text); stroke-width: 3; }
.fig-bar { fill: var(--coral); stroke: var(--text); stroke-width: 3; }
.fig-bar-line { stroke: var(--muted); stroke-width: 1.5; }
.fig-bar-number { fill: var(--text); font: 700 18px var(--font-body); }
.fig-bar-name { fill: var(--text); font: 700 17px var(--font-body); }

/* The figure is the writing surface here, so it's as large as fits with Next on screen. The room is everything else on the page. */
.plot-figure { --plot-room: 400px; }
.workout-prompt-row ~ .plot-figure { --plot-room: 520px; }
.hero ~ .plot-figure { --plot-room: 490px; }
.plot-figure .figure {
  max-width: min(100%, calc(100vh - var(--plot-room)));
  max-height: none;
  margin: 0;
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}
.plot-hint { margin: 8px 0 0; font-weight: 700; }

/* Everything on a reading page but the passage keeps its size, and the passage takes what's left and scrolls in its own box, so Submit stays on screen whatever else is on the page. A short passage takes only what it needs. 100svh leaves out Safari's bars where a browser counts them, and the room is for the ones it doesn't. */
.reading-write {
  --reading-above: 90px; /* The app's header and the page's top padding. */
  --reading-room: 130px;
  display: flex;
  flex-direction: column;
  max-height: calc(100svh - var(--reading-above) - var(--reading-room));
}
.reading-write-older {
  --passage-size: 1.25rem;
  --passage-title-size: 1.5rem;
  --question-size: 1.125rem;
}
.reading-write-young {
  --passage-size: 1.625rem;
  --passage-title-size: 1.875rem;
  --question-size: 1.25rem;
}
.reading-text { display: contents; }
.reading-text > * { flex: none; }
.reading-text > .reading-passage {
  flex: 0 1 auto;
  min-height: 120px;
  margin: 0 0 16px;
  padding: 12px 16px;
  overflow-y: auto;
  overscroll-behavior: contain;
  font-size: var(--passage-size);
  background: var(--surface);
  border: var(--border);
  border-radius: var(--radius);
}
.reading-passage h2 { margin: 0 0 8px; font-size: var(--passage-title-size); }
.reading-passage p:last-child { margin-bottom: 0; }
.reading-answer { flex: none; }
.reading-answer .workout-prompt { font-size: var(--question-size); }
/* Three rows of the lines, which repeat every 116px, inside the box's border. It's the same either way up, so ink never falls off the bottom on rotation. */
.reading-answer .canvas-box { height: 354px; }
/* Older kids get six rows of the smaller, 78px lines, inside the box's border. A try-again also has hints and the last try to fit, so it gets five. */
.reading-write-older .reading-answer .canvas-box { height: 474px; }
.reading-write-older .reading-answer:has(.workout-last-try) .canvas-box { height: 396px; }
.reading-hints { margin: 0 0 12px; padding-left: 24px; font-size: 1.25rem; font-weight: 700; }
/* Max's score and what to do, with the notes to check closed, on a rewrite after Max's results page. */
.reading-rewrite-line { margin-bottom: 8px; padding-left: 0; line-height: 1.35; }
.reading-rewrite-notes { margin: 0 0 8px; line-height: 1.35; }
.reading-rewrite-notes summary { font-weight: 700; cursor: pointer; }
.reading-rewrite-notes ul { margin: 4px 0 0; padding-left: 24px; }
.reading-mark { margin-top: 16px; }

/* Max's notes on a kid's answer, and the score beside what Max wrote on a parent's card. */
.reading-feedback { margin: 0 0 16px; font-size: 1.25rem; }
.reading-feedback h2 { margin: 0 0 4px; font-size: 1.25rem; }
.reading-feedback p { margin: 0 0 4px; }
.reading-feedback ul { margin: 0 0 4px; padding-left: 24px; }
.reading-right-notes .workout-prompt { font-size: 1.5rem; }
.reading-right-notes .ink-image-small { margin-bottom: 12px; }
.reading-right-notes .workout-read { margin: 0 0 12px; }
.reading-score-card { margin: 12px 0; }
.reading-score { margin: 0; font-size: 3rem; font-weight: 700; line-height: 1.1; }
.reading-feedback .reading-kid-score { margin: 0; font-size: 2rem; font-weight: 700; line-height: 1.1; }

/* A word in a problem the kid can tap for its meaning, and the one card that shows it. */
.vocab-word { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; text-decoration: underline dotted; text-decoration-thickness: 2px; text-underline-offset: 0.2em; touch-action: manipulation; }
.vocab-card { padding: 0; max-width: min(90vw, 480px); color: var(--text); background: var(--surface); border: 3px solid var(--text); border-radius: 16px; }
.vocab-card::backdrop { background: rgb(0 0 0 / 0.45); }
.vocab-card-body { padding: 24px; }
.vocab-card-term { margin: 0 0 8px; }
.vocab-card-actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 16px; }

/* Three rows of reps, always on screen with Next, so nothing scrolls either way up. The zone's height leaves room for all that's around the three zones. */
.sheet-row {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) auto;
  gap: 12px;
  align-items: center;
  margin-top: 10px;
}
.sheet-row .canvas-box {
  height: min(calc((100dvh - 260px) / 3), 220px);
  min-height: 110px;
}
.sheet-prompt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
}
.sheet-prompt .workout-prompt { margin: 0; font-size: 2rem; }
.sheet-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 12px;
}
.sheet-status {
  flex: 1 1 0;
  min-width: 0;
  margin: 0;
  font-weight: 700;
}

/* A figure shares the screen with the canvas, so Next stays on screen either way up. */
.figure-and-canvas .canvas-box { height: clamp(240px, 36vh, 430px); }
/* Show me how makes the progress line taller, so the canvas gives that back. */
.workout-progress-row:has(form) ~ .figure-and-canvas .canvas-box { height: clamp(240px, 35vh, 430px); }

/* A correction round has a heading and the half-width prompt above, so it has less room. */
.workout-prompt-row ~ .figure-and-canvas .figure { max-height: 300px; }
.workout-prompt-row ~ .figure-and-canvas .canvas-box { height: clamp(240px, 33vh, 390px); }

/* A stored problem's prompt runs to a few lines, so with the correction round's heading above it, the writing box gives up some height in landscape. Ruby generators' prompts never carry the long class. */
@media (orientation: landscape) {
  .workout-prompt-row:has(.workout-prompt-long) ~ [data-controller="canvas"] .canvas-box { height: max(240px, calc(45vh - 119px)); }
}

/* A question on a figure is often long, and the drawing needs the room more than big type does. */
.read-aloud-row:has(~ .figure-and-canvas) .workout-prompt,
.workout-prompt-row:has(~ .figure-and-canvas) .workout-prompt,
.read-aloud-row:has(~ .plot-figure) .workout-prompt,
.workout-prompt-row:has(~ .plot-figure) .workout-prompt,
.workout-prompt:has(~ .figure-and-canvas),
.workout-prompt:has(+ .figure-frame) { font-size: 1.625rem; }
.read-aloud-row:has(~ .figure-and-canvas) h1 { font-size: 2rem; }

@media (orientation: landscape) and (min-width: 900px) {
  .figure-and-canvas {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 16px;
    align-items: start;
    width: min(1100px, calc(100vw - 32px));
    margin-left: calc(50% - min(550px, calc(50vw - 16px)));
  }
  .figure-and-canvas .figure { max-height: calc(100vh - 260px); margin: 0; }
  .figure-and-canvas .canvas-box { height: clamp(240px, calc(100vh - 320px), 530px); }
  /* A heading and a two-line question sit above, and a tall figure like the measuring cup takes all the height it's given. */
  .read-aloud-row ~ .figure-and-canvas .figure { max-height: calc(100vh - 340px); }
  .read-aloud-row ~ .figure-and-canvas .canvas-box { height: clamp(240px, calc(100vh - 340px), 530px); }
  .workout-prompt-row ~ .figure-and-canvas .figure { max-height: calc(100vh - 430px); }
  .workout-prompt-row ~ .figure-and-canvas .canvas-box { height: clamp(240px, calc(100vh - 480px), 530px); }

  /* The hint and buttons go beside the figure, so only what's above it takes room. */
  .plot-figure {
    --plot-room: 225px;
    display: grid;
    grid-template-columns: minmax(0, calc(100vh - var(--plot-room))) minmax(0, 1fr);
    gap: 24px;
    align-items: start;
    width: min(1100px, calc(100vw - 32px));
    margin-left: calc(50% - min(550px, calc(50vw - 16px)));
  }
  .workout-prompt-row ~ .plot-figure { --plot-room: 400px; }
  .hero ~ .plot-figure { --plot-room: 330px; }
  .plot-figure .figure { max-width: 100%; }
  .plot-hint { margin-top: 0; }

  /* The passage and all that's above it on the left, the question and the writing on the right. */
  .reading-write {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 16px;
    align-items: start;
    width: min(1100px, calc(100vw - 32px));
    max-height: none;
    margin-left: calc(50% - min(550px, calc(50vw - 16px)));
  }
  .reading-text {
    display: flex;
    flex-direction: column;
    max-height: calc(100svh - var(--reading-above) - var(--reading-room));
  }
  .reading-text > .reading-passage { margin: 0; }

  /* Max and the question on the left, and the card with its notes and Next on the right. */
  .reading-right-notes {
    display: grid;
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    gap: 16px;
    align-items: start;
    width: min(1100px, calc(100vw - 32px));
    margin-left: calc(50% - min(550px, calc(50vw - 16px)));
  }
}
