/* MathTime: Blueprint theme and layout.
   See docs/superpowers/specs/2026-10-19-level1-design.md §3–§5. */

/* Registered, so a bad value falls back to a length: layout.js reads it. */
@property --gutter { syntax: '<length>'; inherits: true; initial-value: 24px; }

:root {
  color-scheme: dark;
  --bg: #12407e;
  --ink: #eef5ff;
  --muted: #b6cdee;
  --faint: #6f95cc;          /* upcoming roadmap segments, 3:1 on the background */
  --amber: #ffd66b;          /* caret and current roadmap segment */
  --good: #8ff0c0;
  --heart-lost: #8fb0dd;
  --key-ring: inset 0 0 0 1.5px rgba(238, 245, 255, 0.8);
  --key-press: rgba(255, 255, 255, 0.12);
  --go-press: #cfe0f7;       /* the check key while pressed */
  --font: "IBM Plex Mono", "IBM Plex Sans", ui-monospace, monospace;
  --gutter: 24px;            /* side gutters (spec §5.3); layout.js reads it too */
  --top-pad: 20px;           /* above the header */
  --top-safe: max(var(--top-pad), env(safe-area-inset-top));
  --crumb-line: 20px;        /* the breadcrumb's line */
  --road-gap: 8px;           /* between it and the roadmap strip */
  --road-h: 4px;             /* the roadmap strip */
  --top-h: calc(var(--top-safe) + var(--crumb-line) + var(--road-gap) + var(--road-h));   /* the header */
  --key-gap: 8px;
  --pad-bottom: max(16px, env(safe-area-inset-bottom));   /* below the keypad */
}

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
html.loading .top, html.loading .stage, html.loading .pad { visibility: hidden; }
body {
  background:
    linear-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px) -1px -1px / 100px 100px,
    linear-gradient(90deg, rgba(255, 255, 255, 0.14) 1px, transparent 1px) -1px -1px / 100px 100px,
    linear-gradient(rgba(255, 255, 255, 0.06) 1px, transparent 1px) -1px -1px / 20px 20px,
    linear-gradient(90deg, rgba(255, 255, 255, 0.06) 1px, transparent 1px) -1px -1px / 20px 20px,
    var(--bg);
  color: var(--ink);
  font-family: var(--font);
  overflow: hidden;
  height: 100dvh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: minmax(0, 1fr);
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}

/* Visually hidden, still read by screen readers (live region for answers). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- Header: roadmap position and lives ---------- */
.top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  /* Clear of any notch or rounded corner (viewport-fit=cover). */
  padding: var(--top-safe) max(var(--gutter), env(safe-area-inset-right)) 0 max(var(--gutter), env(safe-area-inset-left));
}
.where { min-width: 0; }
.crumbs {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  line-height: var(--crumb-line);
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
}
.crumbs .here { color: var(--ink); font-weight: 600; }
.crumbs .sep { width: 12px; height: 12px; flex: none; }
.crumbs .sep path { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
/* When the header gets tight, crumbs drop from the left (set by layout.js). */
.top.tight .stage-name, .top.tight .stage-sep,
.top.tighter .sub-name, .top.tighter .sub-sep { display: none; }
.road { display: flex; gap: 4px; margin-top: var(--road-gap); }
.road span { width: 20px; height: var(--road-h); background: var(--faint); }
.road span.now { background: var(--amber); }

/* Each heart's viewBox is cropped to its ink, stroke included (index.html),
   so the right ink edge is the padding edge, like the crumbs' left ink edge.
   The hearts are centred on the crumbs' text line, whose ink sits centred in
   its 20px line box, and keep their 12px ink gap. */
.lives { display: flex; align-items: center; height: var(--crumb-line); gap: 12px; color: var(--ink); flex: none; }
.lives svg { width: 20px; height: 18px; display: block; overflow: visible; }
.lives svg path { fill: currentColor; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; transition: fill .2s, stroke .2s; }
.lives svg.lost path { fill: none; stroke: var(--heart-lost); stroke-dasharray: 2.5 2; }

/* ---------- Problem area ---------- */
.stage {
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* Ink metrics measured from the real font by layout.js:
   --ink-top / --ink-h: where digit ink sits in each 1em line box
   --wide: widest digit (a problem digit's cell)
   --box-w: ink width of the widest possible answer
   --slot-gap: extra space before the box, which has no side bearing
   --pad: the box padding (--box-pad em) in whole device pixels
   --bw: the box border width in px (kept outside the padding)
   --outline-offset: the dashed outline's offset, in whole device pixels as drawn
   --fs: the equation font size in px
   --label-x: where "Question N" goes, so its ink is centred over what you see
   --label-scale: shrinks the label's px minimums with the font on short screens
   --line-scale: shrinks the box's px minimums too, when the problem area is very short */
.eq {
  --ink-top: 0.2;
  --ink-h: 0.72;
  --wide: 0.6;
  --box-w: 1.2;
  --slot-gap: 0;
  --box-pad: 0.17;
  --bw-em: 0.025;            /* the box border: the larger of these two */
  --bw-min: 2px;
  --outline-em: 0.06;        /* the outline's offset from it: likewise */
  --outline-min: 5px;
  --pad: calc(var(--box-pad) * 1em);
  --bw: 3px;
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.3em;
  font-weight: 500;
  font-size: clamp(40px, min(17vw, 15vh), 128px);
  font-size: clamp(40px, min(17vw, 15dvh), 128px);
}
.eq > * { display: block; height: 1em; line-height: 1; }
.op { color: var(--muted); position: relative; }

/* Every digit sits in a fixed cell, nudged so its ink is centred. */
#a, #b, .shown, #shown { display: flex; }
.cell {
  display: block;
  flex: none;
  width: calc(var(--wide) * 1em);
  height: 1em;
  white-space: pre;
}

.qnum {
  position: absolute;
  left: var(--label-x, 50%);   /* its ink centred over what you see */
  top: calc(var(--ink-top) * var(--fs, 100px) - var(--pad) - var(--bw) - max(0.2 * var(--fs, 100px), 18px * var(--label-scale, 1)));
  transform: translate(-50%, -100%);
  height: auto !important;
  font-size: max(15px * var(--label-scale, 1), calc(var(--fs, 100px) * 0.16));
  line-height: 1.25;
  letter-spacing: 0.04em;
  color: var(--muted);
  white-space: nowrap;
}

/* The answer box: one fixed size for the level, equal padding inside the
   border on all four sides, never resizes (spec §4). */
.slot {
  position: relative;
  width: calc(var(--box-w) * 1em + 2 * var(--pad) + 2 * var(--bw));
  margin-left: calc(var(--slot-gap) * 1em);
}
.slot::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--ink-top) * 1em - var(--pad) - var(--bw));
  height: calc(var(--ink-h) * 1em + 2 * var(--pad) + 2 * var(--bw));
  border: max(calc(var(--bw-em) * 1em), calc(var(--bw-min) * var(--line-scale, 1))) solid var(--ink);
  outline: 1px dashed rgba(238, 245, 255, 0.55);
  outline-offset: var(--outline-offset, max(calc(var(--outline-em) * 1em), calc(var(--outline-min) * var(--line-scale, 1))));
}
.shown {
  position: absolute;
  z-index: 1;
  top: 0;
  left: calc(var(--pad) + var(--bw));
  height: 1em;
}
.caret {
  position: absolute;
  left: 100%;
  top: calc(var(--ink-top) * 1em);      /* layout.js replaces with a snapped px value */
  width: 0.05em;
  min-width: 2px;
  height: calc(var(--ink-h) * 1em);
  background: var(--amber);
  animation: blink 1.06s steps(1) infinite;
}
.slot:not(.focused) .caret,
.slot.full .caret { visibility: hidden; }
@keyframes blink { 50% { opacity: 0; } }
.slot input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  font: inherit;
  caret-color: transparent;
}

.eq.correct .shown { color: var(--good); }
/* The fade is on the way in only: the next problem's box is white at once. */
.eq.correct .slot::after { border-color: var(--good); transition: border-color .15s; }
.eq.correct .caret { visibility: hidden; }

.eq.shake { animation: shake .32s ease; }
@keyframes shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-0.12em); }
  40% { transform: translateX(0.1em); }
  60% { transform: translateX(-0.06em); }
  80% { transform: translateX(0.04em); }
}
.eq.out { animation: out .22s ease-in forwards; }
.eq.in { animation: in .22s ease-out; }
@keyframes out { to { transform: translateX(-40vw); opacity: 0; } }
@keyframes in { from { transform: translateX(40vw); opacity: 0; } }

/* ---------- Keypad ---------- */
.pad {
  width: 100%;
  max-width: 420px;
  justify-self: center;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--key-gap);
  padding: 0 16px var(--pad-bottom);
}
.pad button {
  height: clamp(48px, 7.5vh, 64px);
  height: clamp(48px, 7.5dvh, 64px);
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: var(--key-ring);
  color: var(--ink);
  font: 500 26px/1 var(--font);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
  transition: background .08s, transform .08s;
}
/* Digit labels sit in their own box so layout.js can centre their ink. */
.pad .kl { display: block; height: 1em; line-height: 1; }
.pad button svg { width: 28px; height: 28px; display: block; }
.pad button svg path { fill: none; stroke: currentColor; stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; }
.pad button.go { background: var(--ink); color: var(--bg); box-shadow: none; }
.pad button:active, .pad button.pressed { background: var(--key-press); transform: scale(0.97); }
.pad button.go:active, .pad button.go.pressed { background: var(--go-press); }
.pad button:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---------- Level selector (bare minimum) ---------- */
.select { display: none; align-items: center; justify-content: center; }
.select button {
  font: 500 20px/1 var(--font);
  color: var(--ink);
  background: transparent;
  border: 1.5px solid var(--ink);
  border-radius: 0;
  padding: 16px 40px;
  cursor: pointer;
}
.select button:hover { background: var(--key-press); }
/* Amber, so it reads as focus rather than a second white border. */
.select button:focus-visible { outline: 2px solid var(--amber); outline-offset: 4px; }
body.at-select .stage, body.at-select .pad, body.at-select .lives { display: none; }
body.at-select .select { display: flex; }

/* Narrow screens and phones held sideways (§3.4): 16px gutters and a tighter
   header. Sideways, the header's right padding is the keypad's, so the
   hearts end where the keys do. */
@media (max-width: 480px), (orientation: landscape) and (max-height: 560px) and (min-aspect-ratio: 3/2) {
  :root { --gutter: 16px; --top-pad: 16px; }
}

/* ---------- Landscape phones (spec §3.4) ---------- */
/* At least 3:2 (a nearly square window would leave the equation a sliver
   beside the keypad, so it keeps the keypad below). The problem area on the
   left at the full height below the header, the keypad on the right. Its
   four rows share that height, less the gutters above and below and three
   gaps. The gutters are equal (16px, or the home bar's inset if larger), so
   the band's centre is the problem area's. Keys are up to 64px tall, and at
   least 40px from 264px tall up; on shorter screens they shrink rather than
   run into the header. They are 1.5 times as wide as they are tall. Capped
   at 64px, the keypad is centred in that band. */
@media (orientation: landscape) and (max-height: 560px) and (min-aspect-ratio: 3/2) {
  body {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr);
    grid-template-areas: "top top" "stage pad";
  }
  .top { grid-area: top; }
  .stage, .select { grid-area: stage; }
  .stage { margin-left: env(safe-area-inset-left); }   /* its rect is the safe part, which layout.js centres in */
  .pad {
    --key-h: min(64px, (100dvh - var(--top-h) - 2 * var(--pad-bottom) - 3 * var(--key-gap)) / 4);
    grid-area: pad;
    width: auto;
    max-width: none;
    grid-template-columns: repeat(3, calc(var(--key-h) * 1.5));
    grid-auto-rows: var(--key-h);
    align-content: center;
    padding: var(--pad-bottom) max(var(--gutter), env(safe-area-inset-right)) var(--pad-bottom) 0;
  }
  .pad button { height: auto; }
  @supports not (height: 1dvh) {
    .pad { --key-h: min(64px, (100vh - var(--top-h) - 2 * var(--pad-bottom) - 3 * var(--key-gap)) / 4); }
  }
}
