/* Palette: a lab notebook. Cool graph paper, blue-black ink, and marker colours, one per
   domain. In the lessons the same markers colour-code quantities (blue velocity, red
   force, green energy), the way a physics diagram is drawn by hand. */
:root {
  --bg: #f4f7f3;
  --bg-deep: #ffffff;
  --panel: #ffffff;
  --shade: #e9eff0;
  --line: #c3d2d9;
  --grid: #d9e6ea;
  --ink: #17233a;
  --dim: #5b6b82;
  --blue: #1f6fe0;
  --red: #e0362c;
  --indigo: #4338ca;
  --green: #2f8f17;
  --magenta: #d6247a;
  --brown: #9a5b22;
  --cyan: #0787a8;
  --orange: #e2620a;
  --teal: #0b8f71;
  --gold: #b38300;
  --violet: #8b3fd9;
  --slate: #4b5d73;
  --olive: #6f8200;
  --tone: var(--blue);
  --display: "Gabarito", "Lexend", system-ui, sans-serif;
  --body: "Lexend", system-ui, sans-serif;
  --ease: cubic-bezier(.2, .8, .2, 1);
  --spring: cubic-bezier(.3, 1.6, .5, 1);
  /* Graph paper: fine squares with a heavier line every fifth. */
  --paper:
    linear-gradient(var(--grid) 1.5px, transparent 1.5px) 0 0 / 120px 120px,
    linear-gradient(90deg, var(--grid) 1.5px, transparent 1.5px) 0 0 / 120px 120px,
    linear-gradient(color-mix(in srgb, var(--grid) 55%, transparent) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, color-mix(in srgb, var(--grid) 55%, transparent) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--bg);
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 400 16.5px/1.55 var(--body);
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
button { font: inherit; color: inherit; cursor: pointer; }
button:focus-visible, input:focus-visible {
  outline: 3px solid var(--ink);
  outline-offset: 3px;
}
#app { height: 100dvh; }
/* Room to leave at each edge of the screen: what the device reserves for a notch, a status
   bar or the home indicator (the page is laid out under them: viewport-fit=cover). */
:root {
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-r: env(safe-area-inset-right, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
}
/* An iPad's home-screen app: the system bar's fade reaches about this far below the safe
   area it reports (measured from a screenshot on iPadOS; see main.js). */
:root.ipad-app { --safe-t: calc(env(safe-area-inset-top, 0px) + 44px); }
/* On a touch screen the bottom edge also belongs to the system's swipes, so nothing to tap
   sits right against it even where the device reserves no room. */
@media (pointer: coarse) {
  :root { --safe-b: max(env(safe-area-inset-bottom, 0px), 10px); }
}

/* ───────────── Map ───────────── */
/* Nothing inside the map scrolls, and a touch on a tile or the card must never move the
   page. (None of this stops Safari zooming on a double tap: main.js does that.) */
.map, .map * { touch-action: none; }
.map {
  position: relative;
  height: 100%;
  overflow: hidden;
  touch-action: none;
  /* A drag moves the map; it must not also select topic names or raise the callout. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  contain: layout paint;
  cursor: grab;
  background: var(--paper);
}
.map.dragging { cursor: grabbing; }
.world { position: absolute; left: 0; top: 0; transform-origin: 0 0; will-change: transform; }
.world.glide { transition: transform .6s var(--ease); }
.links { position: absolute; left: 0; top: 0; overflow: visible; pointer-events: none; }
.link { stroke: #a9bcc6; stroke-width: 4; stroke-linecap: round; transition: stroke .5s; }
.link[data-state="open"] { stroke: var(--ink); stroke-dasharray: 2 11; animation: flow 1.2s linear infinite; }
.link[data-state="done"] { stroke: var(--ink); }
.link[data-state="ghost"] { stroke-width: 3; stroke-dasharray: 1 9; }
/* An arrow from a topic to one that is waiting for it (a prerequisite). */
.need { stroke: var(--tone); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 9 7; opacity: .85; }
/* Every frame of the flowing dashes repaints the map, so they rest while the map is being moved. */
.map.moving .link { animation-play-state: paused; }
@keyframes flow { to { stroke-dashoffset: -13; } }

/* A topic is a puck on the paper: a disc with its domain's glyph. */
.tile {
  --size: 84px;
  position: absolute;
  width: var(--size);
  height: var(--size);
  margin: calc(var(--size) / -2) 0 0 calc(var(--size) / -2);
  padding: 0;
  display: grid;
  place-items: center;
  border: 3px solid var(--tone);
  border-radius: 50%;
  background: var(--bg-deep);
  color: var(--tone);
  opacity: var(--fade, 1);
  transition: transform .25s var(--spring), background .4s, box-shadow .3s, opacity .3s;
}
.tile:hover, .tile.picked, .tile:focus-visible { transform: scale(1.08); opacity: 1; }
.tile .sym { display: grid; width: 44px; height: 44px; }
.tile .sym svg, .lsym svg, .big-tile svg, .mini svg { width: 100%; height: 100%; display: block; }
.tile .mark {
  position: absolute;
  top: -5px;
  right: -5px;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--ink);
  color: #fff;
  font-size: 14px;
  line-height: 1;
}
.tile .mark:empty { display: none; }
.tile .name {
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  width: 150px;
  translate: -50% 0;
  font: 600 14px/1.2 var(--body);
  color: var(--ink);
  text-wrap: balance;
  pointer-events: none;
  /* A paper-coloured edge keeps names readable where they cross grid and link lines. */
  text-shadow: 0 0 3px var(--bg), 0 0 3px var(--bg), 0 0 6px var(--bg), 0 0 6px var(--bg);
  transition: opacity .3s;
}
.tile[data-state="done"] { background: var(--tone); color: #fff; }
/* The pulsing ring is a layer of its own for the browser to composite, so only tiles on
   screen (.live) have one. It is ::after so that it is painted last: anything painted over
   a layer needs a layer too, and ::before put the name and the mark over it. (Rings as
   separate elements in one group after the tiles measured slower in Chrome.) */
.tile.live[data-state="open"]::after {
  content: "";
  position: absolute;
  inset: -9px;
  border-radius: 50%;
  border: 2.5px solid var(--tone);
  animation: ring 2.2s var(--ease) infinite;
}
@keyframes ring {
  from { opacity: .9; transform: scale(.94); }
  to { opacity: 0; transform: scale(1.2); }
}
.tile[data-state="open"] { box-shadow: 0 6px 18px color-mix(in srgb, var(--tone) 35%, transparent); }
.tile[data-state="locked"] { --faint: color-mix(in srgb, var(--tone) 40%, var(--line)); border-color: var(--faint); color: var(--faint); background: var(--bg-deep); }
.tile[data-state="locked"] .name, .tile[data-state="ghost"] .name { color: var(--dim); }
/* Held: in reach, but waiting for a topic it needs first. Full colour, no ring, no glow. */
.tile[data-state="held"] { border-style: dashed; background: color-mix(in srgb, var(--tone) 8%, var(--bg-deep)); }
.tile[data-state="ghost"] {
  --faint: color-mix(in srgb, var(--tone) 45%, var(--line));
  border: 2.5px dashed var(--faint);
  color: var(--faint);
  background: var(--bg);
}
.map.far .tile .name { opacity: 0; }
.tile.picked { box-shadow: 0 0 0 6px color-mix(in srgb, var(--tone) 25%, transparent); }

.masthead {
  position: absolute;
  left: calc(14px + var(--safe-l));
  top: calc(12px + var(--safe-t));
  max-width: 350px;
  padding: 12px 16px 14px;
  border: 1.5px solid var(--line);
  border-radius: 6px 18px 18px 6px;
  border-left: 5px solid var(--red);
  /* No backdrop blur: Safari would blur the map again on every frame of a drag. */
  background: color-mix(in srgb, var(--bg-deep) 94%, transparent);
  cursor: default;
}
.masthead h1 { margin: 0; font: 800 44px/.95 var(--display); letter-spacing: -.02em; }
.brand { display: flex; align-items: center; gap: 10px; }
.home {
  flex: none; display: grid; place-items: center; width: 42px; height: 42px;
  color: var(--ink); background: var(--bg-deep);
  border: 1.5px solid var(--line); border-radius: 12px;
  transition: border-color .2s var(--ease), transform .2s var(--spring);
}
.home:hover { border-color: var(--ink); }
.home:active { transform: scale(.92); }
.home:focus-visible { outline: 3px solid var(--ink); outline-offset: 3px; }
.masthead p { margin: 8px 0 0; color: var(--dim); font-size: 15.5px; line-height: 1.45; }
.tally {
  margin-top: 12px;
  display: inline-flex;
  gap: 10px;
  align-items: center;
  font-weight: 600;
  font-size: 15px;
}
.tally-bar { width: 120px; height: 8px; border-radius: 8px; background: var(--shade); box-shadow: inset 0 0 0 1px var(--line); overflow: hidden; }
.tally-bar i { display: block; height: 100%; background: var(--blue); border-radius: 8px; transition: width .8s var(--ease); }

.zoomer { position: absolute; right: calc(18px + var(--safe-r)); top: calc(18px + var(--safe-t)); display: flex; gap: 6px; }
.zoomer button, .legend {
  background: color-mix(in srgb, var(--bg-deep) 92%, transparent);
  border: 1.5px solid var(--line);
  border-radius: 12px;
}
.zoomer button { width: 42px; height: 42px; font: 700 20px/1 var(--display); }
.zoomer button svg { display: block; margin: auto; }
.zoomer button:hover { border-color: var(--ink); }
.zoomer button.wide { width: auto; padding: 0 14px; font-size: 15px; }
.legend {
  position: absolute;
  left: calc(14px + var(--safe-l));
  bottom: calc(16px + var(--safe-b));
  display: flex;
  flex-wrap: wrap;
  gap: 0 2px;
  padding: 5px 6px;
  font-size: 14px;
  color: var(--dim);
  max-width: min(700px, calc(100% - 28px));
}
.legend button {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 0 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: inherit;
}
.legend button:hover { color: var(--ink); background: var(--shade); }
.legend i { width: 11px; height: 11px; border-radius: 50%; background: var(--tone); }

.confetti { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.card {
  position: absolute;
  right: calc(18px + var(--safe-r));
  bottom: calc(18px + var(--safe-b));
  width: min(380px, calc(100% - 36px - var(--safe-l) - var(--safe-r)));
  padding: 20px;
  background: var(--panel);
  border: 1.5px solid var(--ink);
  border-radius: 20px;
  box-shadow: 5px 6px 0 color-mix(in srgb, var(--ink) 14%, transparent);
  cursor: default;
  -webkit-user-select: text;
  user-select: text;
  animation: rise .35s var(--spring);
}
@keyframes rise { from { opacity: 0; transform: translateY(18px) scale(.97); } }
.card h2 { margin: 0 0 6px; font: 700 26px/1.1 var(--display); letter-spacing: -.01em; }
.card p { margin: 0 0 14px; color: var(--dim); }
.card .where { color: var(--tone); font-weight: 600; font-size: 14.5px; margin-bottom: 4px; }
.card .note { color: var(--dim); font-size: 15px; margin: 0; }

.go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 0 24px;
  border: 0;
  border-radius: 14px;
  background: var(--tone);
  color: #fff;
  font: 700 18px/1 var(--display);
  transition: transform .2s var(--spring), opacity .3s, filter .2s;
}
.go:hover:not(:disabled) { transform: translateY(-2px) scale(1.02); filter: brightness(1.08); }
.go:active:not(:disabled) { transform: scale(.97); }
.go:disabled { opacity: .35; cursor: not-allowed; }
.quiet {
  min-height: 50px;
  padding: 0 16px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: transparent;
  color: var(--dim);
  font-weight: 600;
}
.quiet:hover { color: var(--ink); border-color: var(--ink); }

/* ───────────── Lesson ───────────── */
.lesson {
  height: 100%;
  display: grid;
  grid-template: "bar bar" auto "stage talk" minmax(0, 1fr) / minmax(0, 1.55fr) minmax(330px, 1fr);
  /* The top and bottom room is left inside the bar, the tray and the footer, so that the
     line between the model and the text runs to the bottom of the screen. */
  padding: 0 var(--safe-r) 0 var(--safe-l);
  background: var(--bg-deep);
}
.lbar {
  grid-area: bar;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: calc(10px + var(--safe-t)) 16px 10px;
  border-bottom: 1.5px solid var(--line);
}
.lbar .back { min-height: 40px; padding: 0 14px; }
.lsym {
  width: 40px;
  height: 40px;
  flex: none;
  padding: 7px;
  border-radius: 50%;
  background: var(--tone);
  color: #fff;
  view-transition-name: tile;
}
.lbar h1 { margin: 0; font: 700 20px/1.1 var(--display); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lprog { flex: 1; min-width: 60px; height: 8px; border-radius: 8px; background: var(--shade); box-shadow: inset 0 0 0 1px var(--line); overflow: hidden; }
.lprog i { display: block; height: 100%; width: 0; background: var(--tone); border-radius: 8px; transition: width .6s var(--ease); }

.stage {
  grid-area: stage;
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--paper);
  border-right: 1.5px solid var(--line);
}
.stage-view { position: relative; flex: 1; min-height: 0; overflow: hidden; }
.stage-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 10px 14px;
  padding: 12px 16px calc(12px + var(--safe-b));
  border-top: 1.5px solid var(--line);
  background: var(--bg-deep);
  min-height: 68px;
}
.stage-controls:empty { display: none; }
.kit-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; touch-action: none; }

.talk { grid-area: talk; display: flex; flex-direction: column; min-height: 0; }
.talk-body {
  flex: 1;
  overflow-y: auto;
  padding: 30px 28px 34px;
  /* Fades the last lines when the text overflows, as a cue that the pane scrolls. */
  -webkit-mask-image: linear-gradient(to bottom, #000 calc(100% - 30px), transparent);
  mask-image: linear-gradient(to bottom, #000 calc(100% - 30px), transparent);
}
.stage.resting .stage-view { pointer-events: none; }
.stage-finish { position: absolute; inset: 0; display: grid; place-content: center; justify-items: center; gap: 4px; text-align: center; }
.stage-finish p { margin: 0; font: 700 22px/1.2 var(--display); max-width: 16ch; text-wrap: balance; }
.stage-finish .big-tile {
  width: clamp(96px, 22vmin, 168px);
  height: clamp(96px, 22vmin, 168px);
  margin-bottom: 18px;
}
.talk-body > * { animation: beat-in .5s var(--ease) backwards; }
.talk-body > :nth-child(2) { animation-delay: .06s; }
.talk-body > :nth-child(3) { animation-delay: .12s; }
.talk-body > :nth-child(4) { animation-delay: .18s; }
@keyframes beat-in { from { opacity: 0; transform: translateY(14px); } }
.talk .count { color: var(--tone); font-weight: 600; font-size: 14.5px; margin: 0 0 8px; }
.talk h2 { margin: 0 0 14px; font: 700 31px/1.08 var(--display); letter-spacing: -.01em; text-wrap: balance; }
.talk p { margin: 0 0 14px; max-width: 46ch; }
.talk strong { color: var(--tone); font-weight: 600; }
.goal {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 12px 14px;
  border: 1.5px dashed var(--tone);
  border-radius: 14px;
  font-weight: 500;
  transition: background .4s, border-color .4s;
}
.goal .tick {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 2px solid var(--tone);
  display: grid;
  place-items: center;
  font-size: 14px;
  color: transparent;
  transition: background .3s, color .3s, transform .4s var(--spring);
}
.goal.met { background: color-mix(in srgb, var(--tone) 12%, transparent); border-style: solid; }
.goal.met .tick { background: var(--tone); color: #fff; transform: scale(1.15); }
.talk-foot { display: grid; gap: 12px; padding: 12px 28px calc(22px + var(--safe-b)); }
.foot-row { display: flex; gap: 10px; align-items: center; }
.foot-row .go { flex: 1; }
.goal-slot:empty { display: none; }
.stage.resting .stage-controls { display: none; }
.talk-foot .skip { border: 0; background: none; color: var(--dim); text-decoration: underline; font-size: 15px; padding: 8px; }

.options { display: grid; gap: 10px; margin-top: 18px; }
.option {
  text-align: left;
  padding: 14px 16px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  font-weight: 500;
  transition: transform .2s var(--spring), border-color .2s, background .3s;
}
.option:hover:not(:disabled) { border-color: var(--tone); transform: translateX(4px); }
.option.right { background: var(--tone); border-color: var(--tone); color: #fff; }
.option.wrong { border-color: var(--red); animation: shake .35s; opacity: .55; }
.option.wrong { text-decoration: line-through; text-decoration-thickness: 2px; }
.option.right::before { content: "✓ "; }
@keyframes shake { 25% { transform: translateX(-6px); } 75% { transform: translateX(6px); } }
.why { margin-top: 16px; color: var(--dim); }

.finish { text-align: left; }
.big-tile {
  width: 104px;
  height: 104px;
  padding: 18%;
  border-radius: 50%;
  background: var(--tone);
  color: #fff;
  margin-bottom: 20px;
  animation: pop .7s var(--spring) backwards;
  box-shadow: 0 0 0 0 var(--tone);
}
@keyframes pop {
  0% { transform: scale(.3) rotate(-18deg); opacity: 0; }
  60% { box-shadow: 0 0 0 22px color-mix(in srgb, var(--tone) 0%, transparent); }
}
.nexts { display: grid; gap: 10px; margin-top: 8px; }
.next {
  display: grid;
  grid-template-columns: 54px 1fr;
  gap: 14px;
  align-items: center;
  text-align: left;
  padding: 10px 14px 10px 10px;
  border: 1.5px solid var(--line);
  border-radius: 16px;
  background: var(--panel);
  transition: transform .2s var(--spring), border-color .2s;
}
.next:hover { transform: translateX(5px); border-color: var(--tone); }
.next .mini {
  width: 54px;
  height: 54px;
  padding: 11px;
  border-radius: 50%;
  border: 2.5px solid var(--tone);
  color: var(--tone);
}
.next b { display: block; font: 700 18px/1.15 var(--display); }
.finish .waits { margin: 4px 0 0; color: var(--dim); font-size: 14.5px; line-height: 1.4; }
.finish .waits b { color: var(--tone); }
.next small { color: var(--dim); font-size: 14px; line-height: 1.35; display: block; margin-top: 2px; }

/* ───────────── Practice ───────────── */
/* On the map a practice node is a small card (topics are discs) carrying ten pips, one per problem. */
.tile.practice { --size: 62px; border-radius: 16px; border-style: dotted; border-width: 3px; }
.tile.practice[data-state="open"], .tile.practice[data-state="done"] { border-style: solid; }
.tile.practice[data-state="open"]::after { border-radius: 22px; }
.tile.practice[data-state="done"] { background: color-mix(in srgb, var(--tone) 14%, var(--bg-deep)); color: var(--tone); }
.tile.practice .name { top: calc(100% + 7px); font-size: 13px; font-style: italic; width: 130px; }
.pips { display: grid; grid-template-columns: repeat(5, 7px); grid-auto-rows: 7px; gap: 5px 3px; }
.pips i { border-radius: 50%; border: 1.5px solid currentColor; opacity: .75; }
.pips i.on { background: var(--tone); border-color: var(--tone); opacity: 1; }
.tie { stroke: var(--tone); stroke-width: 3; stroke-linecap: round; stroke-dasharray: 1 9; opacity: .9; animation: tie-in .4s var(--ease) backwards; }
.tie.met { stroke-dasharray: none; }
@keyframes tie-in { from { opacity: 0; } }
.tile.needed { opacity: 1; box-shadow: 0 0 0 5px color-mix(in srgb, var(--ink) 30%, transparent); }
.card .best, .finish .best { color: var(--tone); font-weight: 600; }
.tally-more { margin-top: 4px; font-size: 14px; color: var(--dim); font-weight: 600; }

/* A problem with no model takes the whole page as one column. */
.practice.solo { grid-template: "bar" auto "talk" minmax(0, 1fr) / minmax(0, 1fr); }
.practice.solo .stage { display: none; }
.practice.solo .talk { width: min(100%, 720px); margin: 0 auto; }
.practice.solo .talk-body { padding-top: clamp(18px, 7vh, 64px); }
.practice .lbar h1 { flex: 1; min-width: 0; }
.ppips { display: flex; gap: 7px; flex: none; }
.ppips i, .big-pips i { width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--line); transition: background .4s, border-color .4s, transform .4s var(--spring); }
.ppips i.now { border-color: var(--tone); transform: scale(1.2); }
.ppips i.first, .big-pips i.first { background: var(--tone); border-color: var(--tone); }
.ppips i.helped, .big-pips i.helped { border-color: var(--tone); background: color-mix(in srgb, var(--tone) 22%, transparent); }
.big-pips { display: grid; grid-template-columns: repeat(5, max-content); gap: 14px; margin-bottom: 26px; }
.big-pips i { width: 44px; height: 44px; border-width: 3px; animation: pip-in .6s var(--spring) backwards; }
.big-pips i:nth-child(2) { animation-delay: .08s; }
.big-pips i:nth-child(3) { animation-delay: .16s; }
.big-pips i:nth-child(4) { animation-delay: .24s; }
.big-pips i:nth-child(5) { animation-delay: .32s; }
.big-pips i:nth-child(6) { animation-delay: .4s; }
.big-pips i:nth-child(7) { animation-delay: .48s; }
.big-pips i:nth-child(8) { animation-delay: .56s; }
.big-pips i:nth-child(9) { animation-delay: .64s; }
.big-pips i:nth-child(10) { animation-delay: .72s; }
@keyframes pip-in { from { transform: scale(.3); opacity: 0; } }

.prompt { font-size: 1.12em; line-height: 1.45; margin-bottom: 18px; max-width: 56ch; }
.prompt p { max-width: none; }
.prompt > :last-child { margin-bottom: 0; }
.prompt .eq { display: block; margin: 10px 0; font: 700 1.1em/1.3 var(--display); }
.prompt table { border-collapse: collapse; margin: 12px 0; font-size: .92em; font-variant-numeric: tabular-nums; }
.prompt th, .prompt td { padding: 5px 14px; border-bottom: 1.5px solid var(--line); text-align: left; }
.prompt th { color: var(--dim); font-weight: 600; }
.practice { --good: var(--teal); }
.practice .why { max-width: 56ch; min-height: 1.5em; margin-top: 16px; }
.practice .why:empty { min-height: 0; margin: 0; }
.practice .options { margin-top: 0; }
.practice .option.right { background: var(--good); border-color: var(--good); }

.blanks { display: flex; flex-wrap: wrap; gap: 12px 22px; align-items: flex-end; }
.blank { display: inline-flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; font-weight: 600; }
.blank .lab { flex-basis: 100%; color: var(--dim); font-size: .9em; }
.blank .unit { color: var(--dim); }
.blank input {
  min-height: 52px;
  max-width: 100%;
  padding: 0 14px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  color: var(--ink);
  font: 700 22px/1 var(--display);
  font-variant-numeric: tabular-nums;
  transition: border-color .2s, background .3s;
}
.blank input:focus { border-color: var(--tone); outline: none; }
.blank input.bad { border-color: var(--red); animation: shake .35s; }
.blank input.good { border-color: var(--good); background: color-mix(in srgb, var(--good) 12%, var(--panel)); }

.order-wrap { max-width: 460px; }
.order-wrap .end { color: var(--dim); font-size: .88em; font-weight: 600; margin: 4px 2px; }
.order { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.order li {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 8px;
  min-height: 50px;
  padding: 4px 6px 4px 12px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  font-weight: 600;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.order li.lifted { border-color: var(--tone); box-shadow: 0 10px 26px rgb(23 35 58 / .22); position: relative; z-index: 1; cursor: grabbing; }
.order .grip { color: var(--dim); letter-spacing: -3px; }
.order button { width: 40px; height: 40px; border: 0; border-radius: 10px; background: none; color: var(--dim); font-size: 18px; }
.order.locked li { cursor: default; border-color: var(--good); }
.order.locked button, .order.locked .grip { visibility: hidden; }

.sort { display: grid; gap: 8px; max-width: 560px; }
.sort-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 12px;
  padding: 6px 6px 6px 14px;
  border: 1.5px solid var(--line);
  border-radius: 14px;
  background: var(--panel);
  font-weight: 600;
}
.sort-row.bad { border-color: var(--red); }
.sort-row.good { border-color: var(--good); }
.sort-row .bins { display: inline-flex; gap: 4px; margin-left: auto; }
.sort-row .bins button { min-height: 38px; padding: 0 12px; border: 1.5px solid var(--line); border-radius: 10px; background: transparent; color: var(--dim); font-weight: 700; font-size: .92em; }
.sort-row .bins button[aria-pressed="true"] { background: var(--tone); border-color: var(--tone); color: #fff; }
.next.practice .mini { border-radius: 14px; display: grid; place-items: center; padding: 0; font: 700 20px/1 var(--display); }
@media (hover: hover) {
  .order button:hover { background: var(--tone); color: #fff; }
}

/* ───────────── Kit controls (used inside lessons) ───────────── */
.kit-slider { display: grid; gap: 4px; min-width: 190px; flex: 1 1 190px; max-width: 360px; font-size: 15px; }
.kit-slider .row { display: flex; justify-content: space-between; gap: 10px; color: var(--dim); font-weight: 500; }
.kit-slider output { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.kit-slider input {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 26px;
  margin: 0;
  background: transparent;
  cursor: pointer;
}
.kit-slider input::-webkit-slider-runnable-track { height: 8px; border-radius: 8px; background: var(--shade); box-shadow: inset 0 0 0 1px var(--line); }
.kit-slider input::-moz-range-track { height: 8px; border-radius: 8px; background: var(--shade); box-shadow: inset 0 0 0 1px var(--line); }
.kit-slider input::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -9px;
  border-radius: 50%;
  border: 2px solid var(--ink);
  background: var(--tone);
  transition: transform .15s var(--spring);
}
.kit-slider input::-moz-range-thumb { width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--ink); background: var(--tone); }
.kit-slider input:active::-webkit-slider-thumb { transform: scale(1.2); }
.kit-btn {
  min-height: 44px;
  padding: 0 18px;
  border: 1.5px solid var(--ink);
  border-radius: 12px;
  background: var(--bg-deep);
  color: var(--ink);
  font-weight: 600;
  transition: transform .2s var(--spring), background .2s, color .2s, border-color .2s;
}
/* Hover only where there is a pointer that hovers: on a touch screen it would stick to the last tap. */
@media (hover: hover) {
  .kit-btn:hover:not(:disabled) { background: var(--tone); border-color: var(--tone); color: #fff; transform: translateY(-1px); }
}
.kit-btn:active:not(:disabled) { transform: scale(.95); }
.kit-btn:disabled { opacity: .4; cursor: not-allowed; }
.kit-btn.solid { background: var(--tone); border-color: var(--tone); color: #fff; }
/* A question on the stage: the prompt, then answer buttons that all look alike. */
.kit-quiz { flex: 1 1 100%; min-width: 0; display: grid; align-content: center; justify-items: center; }
.kit-ask { display: grid; justify-items: center; gap: 8px; animation: ask-in .4s var(--ease) backwards; }
.kit-ask.leaving { opacity: 0; transform: translateY(-6px); transition: opacity .2s, transform .2s; }
.kit-ask-q { margin: 0; text-align: center; font-weight: 600; line-height: 1.25; text-wrap: balance; max-width: 60ch; }
.kit-ask-step { display: block; color: var(--tone); font-size: 13.5px; font-weight: 600; }
.kit-ask-step:empty { display: none; }
.kit-ask-opts { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px 10px; }
.kit-ask-opts .kit-btn { position: relative; animation: ask-in .4s var(--ease) backwards; }
.kit-ask-opts .kit-btn:nth-child(2) { animation-delay: .05s; }
.kit-ask-opts .kit-btn:nth-child(3) { animation-delay: .1s; }
.kit-ask-opts .kit-btn:nth-child(n+4) { animation-delay: .15s; }
.kit-ask-opts .kit-btn.right { background: var(--teal); border-color: var(--teal); color: #fff; opacity: 1; }
.kit-ask-opts .kit-btn.wrong, .kit-ask-opts .kit-btn.out, .option.out {
  color: var(--dim); text-decoration: line-through; text-decoration-thickness: 2px; opacity: .5;
}
.kit-ask-opts .kit-btn.out { border-color: var(--line); }
/* The learner's own wrong pick stays told apart from the choices that were merely crossed out. */
.kit-ask-opts .kit-btn.wrong { border-color: var(--red); opacity: .8; }
/* The tick and the cross are corner badges, so marking a choice never changes its width. */
.kit-ask-opts .kit-btn.right::after, .kit-ask-opts .kit-btn.wrong::after {
  content: "✓"; position: absolute; top: -8px; right: -8px; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; font: 700 12px/1 var(--body); text-decoration: none;
  background: var(--ink); color: #fff; box-shadow: 0 0 0 2px var(--bg-deep);
}
.kit-ask-opts .kit-btn.wrong::after { content: "✕"; background: var(--red); }
.kit-ask-note { margin: 0; min-height: 1.35em; line-height: 1.35; font-size: 14px; color: var(--dim); font-weight: 600; text-align: center; }
.kit-ask-note:empty:not(.kept) { display: none; }
.kit-ask-done { margin: 0; text-align: center; font-weight: 600; color: var(--teal); animation: ask-in .4s var(--ease) backwards; }
.kit-ask-done::before { content: "✓ "; }
@keyframes ask-in { from { opacity: 0; transform: translateY(8px); } }

/* An explanation. It rises over the tray, so the model above stays in view, and waits to be closed. */
.kit-pop {
  position: absolute; inset: 0; z-index: 3;
  display: grid; align-items: end; justify-items: center; padding: 12px;
  background: linear-gradient(to top, rgb(23 35 58 / .22) 0, rgb(23 35 58 / 0) min(45%, 260px));
  animation: pop-fade .2s backwards;
}
.kit-pop-card {
  --edge: var(--ink);
  position: relative; width: min(100%, 460px); max-height: 100%; overflow: auto;
  display: grid; gap: 8px; padding: 14px 16px;
  border: 1.5px solid var(--edge); border-radius: 16px; background: var(--panel);
  box-shadow: 5px 6px 0 color-mix(in srgb, var(--ink) 14%, transparent);
  animation: pop-in .32s var(--spring) backwards;
}
.kit-pop.good .kit-pop-card { --edge: var(--teal); }
.kit-pop.bad .kit-pop-card { --edge: var(--red); }
.kit-pop h3 { margin: 0 36px 0 0; display: flex; align-items: center; gap: 8px; font: 700 19px/1.15 var(--display); }
.kit-pop h3 i {
  flex: none; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center;
  background: var(--edge); color: #fff; font: 700 14px/1 var(--body);
}
.kit-pop p { margin: 0; line-height: 1.45; }
.kit-pop .kit-btn { justify-self: end; margin-top: 2px; }
.kit-pop-x {
  position: absolute; top: 6px; right: 6px; width: 36px; height: 36px;
  border: 0; border-radius: 10px; background: none; color: var(--dim); font-size: 24px; line-height: 1;
}
.kit-pop-x:hover { color: var(--ink); background: var(--shade); }
.kit-pop.leaving { opacity: 0; transition: opacity .18s; pointer-events: none; }
.stage.resting .kit-pop { display: none; }
@keyframes pop-fade { from { opacity: 0; } }
@keyframes pop-in { from { opacity: 0; transform: translateY(24px) scale(.96); } }

.kit-chips { display: inline-flex; padding: 4px; gap: 4px; border-radius: 14px; background: var(--shade); flex-wrap: wrap; justify-content: center; }
.kit-chips button {
  min-height: 38px;
  padding: 0 14px;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--dim);
  font-weight: 600;
  transition: background .25s, color .25s;
}
.kit-chips button[aria-pressed="true"] { background: var(--tone); color: #fff; }
.kit-readout { display: grid; font-size: 13.5px; color: var(--dim); font-weight: 500; line-height: 1.2; text-align: center; min-width: 84px; }
.kit-readout b { font: 700 22px/1.1 var(--display); color: var(--ink); font-variant-numeric: tabular-nums; }

/* ───────────── Small screens ───────────── */
@media (max-width: 820px) {
  .lesson { grid-template: "bar" auto "stage" minmax(0, 47fr) "talk" minmax(0, 53fr) / minmax(0, 1fr); }
  .stage { border-right: 0; border-bottom: 1.5px solid var(--line); }
  /* During the check questions the model only rests in view, so the questions get the room. */
  .lesson:has(.stage.resting) { grid-template-rows: auto minmax(0, 30fr) minmax(0, 70fr); }
  .stage.resting:not(.finished) .stage-view { opacity: .45; transition: opacity .4s; }
  .lesson { transition: grid-template-rows .4s var(--ease); }
  body { font-size: 15.5px; }
  .talk-body { padding: 14px 18px 30px; }
  .talk p { margin-bottom: 10px; }
  .next { padding: 7px 12px 7px 7px; }
  .next .mini { width: 46px; height: 46px; padding: 9px; }
  .next small { display: none; }
  .talk h2 { font-size: 24px; margin-bottom: 8px; }
  .talk-foot { padding: 8px 18px calc(12px + var(--safe-b)); gap: 8px; }
  .go, .quiet { min-height: 46px; }
  .goal { padding: 8px 12px; font-size: 15px; }
  .talk .count { margin-bottom: 4px; }
  .tally { font-size: 14px; white-space: nowrap; margin-top: 6px; }
  /* The bar takes what the count leaves, so the line never runs out of the panel. */
  .tally { display: flex; }
  .tally-bar { flex: 1 1 24px; width: auto; min-width: 24px; }
  /* The tray sits above the text here, not at the bottom of the screen. */
  .stage-controls { padding: 8px 10px; min-height: 0; gap: 6px 10px; }
  .kit-ask { gap: 6px; }
  /* Room for two lines always, so the model does not jump when a longer question arrives. */
  .kit-ask-q { font-size: 15px; min-height: 2.5em; display: grid; align-content: center; }
  .kit-ask-step { font-size: 12.5px; }
  .kit-ask-opts .kit-btn { padding: 0 14px; }
  .kit-pop { padding: 8px; }
  .kit-pop-card { padding: 12px 14px; gap: 6px; }
  .kit-pop h3 { font-size: 17px; }
  .kit-pop p { font-size: 15px; }
  .masthead { left: calc(8px + var(--safe-l)); top: calc(8px + var(--safe-t)); max-width: calc(100% - 188px); padding: 8px 12px 10px; }
  .masthead h1 { font-size: 26px; }
  .brand { gap: 7px; }
  .home { width: 32px; height: 32px; border-radius: 10px; }
  .home svg { width: 19px; height: 19px; }
  .masthead p { display: none; }
  .legend { display: none; }
  /* A long title takes two lines here instead of being cut short. */
  .lbar h1 { font-size: 16px; min-width: 0; white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; text-wrap: balance; }
  .lprog { max-width: 90px; }
  .tile { --size: 76px; }
  .tile.practice { --size: 56px; }
  .practice.solo .talk-body { padding-top: 16px; }
  .prompt { font-size: 1.05em; margin-bottom: 12px; }
  /* Ten pips in one row would crowd out the title: two rows of five. */
  .ppips { display: grid; grid-template-columns: repeat(5, 9px); gap: 4px; }
  .ppips i { width: 9px; height: 9px; border-width: 1.5px; }
  .blank input { font-size: 20px; min-height: 48px; }
  .big-pips { gap: 10px; }
  .big-pips i { width: 36px; height: 36px; }
  .zoomer { right: calc(8px + var(--safe-r)); top: calc(8px + var(--safe-t)); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
::view-transition-old(root), ::view-transition-new(root) { animation-duration: .35s; }
::view-transition-group(tile) { animation-duration: .5s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
