/* Instrument readout, not a landing page. The mark is two identical halves
   with a 4/64 seam — the hero pair and the table carry the same seam. */
:root {
  --bg: #0A0A0A;
  --fg: #FAFAFA;
  --muted: #8A8A8A;
  --line: #1E1E1E;
  --panel: #0F0F0F;
  --ok: #4ADE80;
  --bad: #F87171;
  --limit: #FACC15;
  --seam: 4px;
  /* Measured, not chosen: `parity motion` found 150ms and 300ms ease dominant
     across bruno-simon.com and oryzo.ai, with 500ms for the largest moves and
     one anticipation curve. This page speaks the same language as its subjects. */
  --t-fast: 150ms;
  --t-base: 300ms;
  --t-slow: 500ms;
  --ease: ease;
  --ease-accent: cubic-bezier(0.3, 0, 0.66, -0.3);
  --mono: ui-monospace, "Cascadia Mono", Consolas, "SF Mono", Menlo, monospace;
}
@media (prefers-color-scheme: light) {
  :root {
    --bg: #F4F0E6;      /* cream */
    --fg: #17150F;
    --muted: #6B6455;
    --line: #E0D9C9;
    --panel: #FBF8F1;
    --ok: #15803D;
    --bad: #B4211B;
    --limit: #8A5D06;
  }
}

* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 400 15px/1.55 var(--mono);
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}

/* ── scrollbars ───────────────────────────────────────────────────────────
   The browser's default bar is painted from the OS theme, not the page, so on
   the dark register it arrives as a white strip down the right edge. `color-
   scheme` tells the browser which register it is in — that alone fixes the
   native bar, form controls and the overscroll gutter — and the rules under it
   give the page its own: a 10px rail, square, no arrows, built from the same
   two tokens as every other line on the page. Both registers follow, because
   the tokens do. */
:root { color-scheme: dark; }
@media (prefers-color-scheme: light) { :root { color-scheme: light; } }

/* Firefox: one colour, no hover rule — `*:hover` would recalculate style on
   every mousemove for a bar Firefox does not repaint on hover anyway. */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line);
  border: 3px solid var(--bg);   /* inset the bar without needing a second colour */
  border-radius: 0;
}
::-webkit-scrollbar-thumb:hover { background: var(--muted); }
.sr-only {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
:focus-visible { outline: 2px solid var(--fg); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { * { animation: none !important; } }

/* ── hero: exactly one viewport ───────────────────────────────────────── */
.hero {
  min-height: 100svh;
  max-width: 68rem; margin: 0 auto; padding: 1.75rem 1.5rem 1.25rem;
  display: grid; grid-template-rows: auto auto auto 1fr auto auto; gap: clamp(0.9rem, 2.2vh, 1.75rem);
}

.logo { display: inline-flex; align-items: center; gap: 0.6rem; color: inherit; text-decoration: none; justify-self: start; }
.logo svg rect { fill: currentColor; }
.logo span { font-size: 1.05rem; letter-spacing: -0.02em; }
.logo:hover { color: var(--muted); }

h1 {
  margin: 0; font-size: clamp(1.75rem, 4.6vw + 0.4rem, 3.4rem); font-weight: 400;
  line-height: 1.06; letter-spacing: -0.045em;
}
h1 em { font-style: normal; color: var(--muted); }
.lede { max-width: 44rem; margin: 1rem 0 0; color: var(--muted); font-size: 0.9rem; }
.lede em { font-style: normal; color: var(--fg); }

/* the pair — two identical halves, seam between, same proportion as the mark */
.stage { display: grid; grid-template-columns: 1fr 1fr; gap: var(--seam); min-height: 0; }
.pane { margin: 0; display: flex; flex-direction: column; min-width: 0;
        background: var(--panel); border: 1px solid var(--line); border-radius: 2px; }
.pane figcaption {
  padding: 0.6rem 0.9rem; border-bottom: 1px solid var(--line);
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
  display: flex; justify-content: space-between; gap: 0.75rem;
}
.pane figcaption span { text-transform: none; letter-spacing: 0; opacity: 0.75; overflow: hidden; text-overflow: ellipsis; }
/* media slot: a <video> or <img> dropped into .pane fills the frame */
.pane video, .pane img { display: block; width: 100%; height: 100%; object-fit: contain; min-height: 0; }

.mini {
  margin: 0; padding: clamp(0.75rem, 2.4vh, 1.5rem) 0.9rem;
  flex: 1; display: grid; align-content: center; gap: clamp(0.4rem, 1.4vh, 0.9rem);
}
.mini div { display: flex; align-items: baseline; gap: 0.75rem; min-width: 0; }
.mini dt { color: var(--muted); font-size: 0.72rem; flex: 1; overflow: hidden;
           text-overflow: ellipsis; white-space: nowrap; }
.mini dd { margin: 0; font-size: clamp(0.95rem, 2.4vw, 1.5rem); letter-spacing: -0.03em; }

.strip { margin: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.4rem 1rem;
         font-size: 0.78rem; color: var(--muted); }
.strip b { font-weight: 400; color: var(--ok); }

.cue { color: var(--muted); text-decoration: none; font-size: 0.75rem;
       letter-spacing: 0.1em; text-transform: uppercase; }
.cue::after { content: "↓"; }
.cue:hover { color: var(--fg); }

/* ── section ─────────────────────────────────────────────────────────── */
.section { max-width: 68rem; margin: 0 auto; padding: clamp(4rem, 12vh, 8rem) 1.5rem 6rem; }
h2 { margin: 0; font-size: clamp(1.25rem, 3vw, 1.9rem); font-weight: 400; letter-spacing: -0.035em; }
.sub { max-width: 42rem; margin: 0.85rem 0 2.25rem; color: var(--muted); font-size: 0.85rem; }
.sub code, .foot code { color: var(--fg); }

.readout { background: var(--panel); border: 1px solid var(--line); border-radius: 2px; }

.tabs { display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--line); }
.tabs button {
  flex: 1 1 auto; padding: 0.85rem 1rem; min-height: 44px;
  background: none; border: 0; border-right: 1px solid var(--line);
  color: var(--muted); font: inherit; font-size: 0.85rem; cursor: pointer;
  text-align: left; white-space: nowrap;
}
.tabs button:last-child { border-right: 0; }
.tabs button[aria-selected="true"] { color: var(--fg); background: var(--bg); }
.tabs button:hover { color: var(--fg); }
.tabs b { display: block; font-weight: 400; color: var(--muted); font-size: 0.75rem; }

.subject { margin: 1.25rem 1.25rem 0; color: var(--muted); font-size: 0.8rem; }

.scroller { overflow-x: auto; padding: 1rem 1.25rem 0; }
table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
th { text-align: left; font-weight: 400; color: var(--muted); font-size: 0.72rem;
     letter-spacing: 0.08em; text-transform: uppercase; padding-bottom: 0.6rem; }
td { padding: 0.28rem 0; vertical-align: top; }
th.mark, td.mark { width: 1.4rem; }
td.mark { color: var(--ok); }
tr.bad td.mark { color: var(--bad); }
td.metric { color: var(--muted); padding-right: 2rem; white-space: nowrap; }
td.val { padding-right: 1.5rem; white-space: nowrap; }   /* one row = one line, .scroller pans */
th.clone, td.clone { border-left: var(--seam) solid var(--panel); padding-left: 1.5rem; }
tr.bad td.clone { color: var(--bad); }

tbody tr { animation: in 220ms ease-out both; }
@keyframes in { from { opacity: 0; transform: translateY(-2px); } }

.notes { margin: 1.5rem 1.25rem 0; padding: 0; list-style: none; font-size: 0.78rem; color: var(--muted); }
.notes li { padding: 0.15rem 0 0.15rem 1rem; text-indent: -1rem; overflow-wrap: anywhere;
            animation: in 220ms ease-out both; }
.notes li::before { content: "· "; }
.notes li.limit { color: var(--limit); }

.verdict { margin: 1.5rem 1.25rem 0; color: var(--ok); font-size: 0.9rem; animation: in 220ms ease-out both; }
.verdict span { color: var(--muted); }

.bar { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; justify-content: space-between;
       margin-top: 1.75rem; padding: 0.75rem 1.25rem; border-top: 1px solid var(--line); }
.bar code { color: var(--muted); font-size: 0.78rem; overflow-wrap: anywhere; }
.bar button { min-height: 34px; padding: 0 0.9rem; background: none; color: var(--muted);
              border: 1px solid var(--line); border-radius: 2px; font: inherit; font-size: 0.78rem; cursor: pointer; }
.bar button:hover { color: var(--fg); border-color: var(--muted); }

.foot { max-width: 42rem; margin: 2rem 0 0; color: var(--muted); font-size: 0.78rem; }

/* ── narrow ───────────────────────────────────────────────────────────── */
@media (max-width: 34rem) {
  .stage { grid-template-columns: 1fr; grid-template-rows: 1fr 1fr; }
  .mini dd { font-size: 1.1rem; }
}

/* the hero pair carries images; the frame crops, it never letterboxes */
/* contain, not cover: a comparison pair has to show the whole page, or the
   crop decides what the reader is allowed to compare. */
.pane img, .pane video { flex: 1; min-height: 0; background: var(--bg); }
.strip small { flex-basis: 100%; font-size: 0.72rem; opacity: 0.7; }
/* a subject without a shot pair keeps the frame, admits it has no picture */
.stage.empty .pane::after {
  content: "no screenshot pair yet";
  flex: 1; display: grid; place-content: center;
  color: var(--muted); font-size: 0.75rem;
}

/* ── scroll axis ──────────────────────────────────────────────────────── */
/* The rule is 2px wide but its labels are not — the column has to hold both,
   or they run straight into the text beside them. */
.axis { display: grid; grid-template-columns: minmax(8rem, 11rem) 1fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: stretch; }
.rule {
  position: relative; width: 2px; height: 46vh; min-height: 15rem;
  background: linear-gradient(var(--line), var(--muted));
}
.rule i {
  position: absolute; left: 0; width: 1.5rem; height: 1px; background: var(--muted);
  font-style: normal;
}
.rule i::after {
  content: attr(data-label); position: absolute; left: 1.9rem; top: -0.6em;
  white-space: nowrap; color: var(--muted); font-size: 0.72rem;
}
.rule i:first-child::after, .rule i:last-child::after { color: var(--fg); }
.axis-note { margin: 0; max-width: 32rem; color: var(--muted); font-size: 0.82rem; }


/* ── limits ───────────────────────────────────────────────────────────── */
.limits { display: grid; grid-template-columns: repeat(auto-fit, minmax(19rem, 1fr)); gap: var(--seam); }
.limits article {
  background: var(--panel); border: 1px solid var(--line); border-radius: 2px;
  padding: 1.25rem;
}
.limits h3 { margin: 0 0 0.75rem; font-size: 0.95rem; font-weight: 400; letter-spacing: -0.02em; }
.limits p { margin: 0 0 0.75rem; color: var(--muted); font-size: 0.82rem; overflow-wrap: anywhere; }
.limits code { color: var(--fg); }
.limits em { font-style: normal; color: var(--fg); }
.limits .why { margin: 0; padding-top: 0.75rem; border-top: 1px solid var(--line); color: var(--limit); }

/* ── film ─────────────────────────────────────────────────────────────── */
/* Same frame as .pane and .readout — a recording is shown in the same box as
   the evidence, not dressed up as something more. The film is graded dark and
   cannot follow the light theme; the frame is what carries it there. */
.film {
  position: relative; margin: 0 0 1rem; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-radius: 2px;
}
.film video { display: block; width: 100%; height: auto; background: #0A0A0A; }

.film-cue {
  position: absolute; inset: 0; display: grid; place-content: center;
  padding: 0; border: 0; background: transparent; cursor: pointer;
  font: inherit; -webkit-tap-highlight-color: transparent;
}
.film-cue span {
  padding: 0.65rem 1.15rem; border: 1px solid rgba(250, 250, 250, 0.28);
  border-radius: 2px; background: rgba(10, 10, 10, 0.66);
  color: rgba(250, 250, 250, 0.86);
  font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase;
  transition: color var(--t-base) var(--ease), border-color var(--t-base) var(--ease);
}
.film-cue:hover span, .film-cue:focus-visible span { color: #FAFAFA; border-color: #FAFAFA; }
.film-cue[hidden] { display: none; }
.film.is-playing .film-cue { display: none; }

/* ── incident ─────────────────────────────────────────────────────────── */
.section.warn { border-top: 1px solid var(--line); }
.section.warn h2 { color: var(--limit); }
.section.warn .sub { margin-bottom: 1rem; }
.section.warn code { color: var(--fg); }
.section.warn em { font-style: normal; color: var(--fg); }

/* ── commands ─────────────────────────────────────────────────────────── */
.cmd {
  margin: 0 0 1.5rem; padding: 1.25rem; overflow-x: auto;
  background: var(--panel); border: 1px solid var(--line); border-radius: 2px;
}
.cmd code { color: var(--fg); font-size: 0.8rem; line-height: 1.7; white-space: pre; }
.links { display: flex; gap: 1rem; align-items: baseline; margin: 2rem 0 0; font-size: 0.85rem; }
.links a { color: var(--fg); }
.links span { color: var(--muted); font-size: 0.75rem; }

@media (max-width: 34rem) {
  .axis { grid-template-columns: 1fr; }
  .rule { width: 100%; height: 2px; background: linear-gradient(90deg, var(--line), var(--muted)); }
  .rule i { display: none; }

}

/* ── motion ───────────────────────────────────────────────────────────────
   Every animation here is a measurement happening: something settles into
   place, nothing decorates. Timings come from the tokens above, which came
   from `parity motion` run against the subjects on this page. */

html { scroll-behavior: smooth; }

/* reveal on entry — the unit is a row of the instrument, not a slide */
.reveal { opacity: 0; transform: translateY(8px); }
.reveal.in {
  opacity: 1; transform: none;
  transition: opacity var(--t-base) var(--ease), transform var(--t-base) var(--ease);
  transition-delay: var(--d, 0ms);
}

/* hero pair: the image changes, the frame does not */
.pane img { transition: opacity var(--t-fast) var(--ease); }
.stage.swapping .pane img { opacity: 0; }

/* switcher */
.tabs button { transition: color var(--t-fast) var(--ease), background-color var(--t-fast) var(--ease); }
.tabs button[aria-selected="true"] { position: relative; }
.tabs button[aria-selected="true"]::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--fg);
  animation: draw var(--t-base) var(--ease) both;
}
@keyframes draw { from { transform: scaleX(0); } }

.logo, .links a, .cue, .bar button { transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease); }
.cue::after { display: inline-block; margin-left: 0.5em; transition: transform var(--t-base) var(--ease); }
.cue:hover::after { transform: translateY(3px); }

/* the sweep draws itself: source first, clone over it */

/* the rule is drawn downward, its marks land one after the other */
.rule { transform-origin: top; }
.axis.in .rule { animation: grow var(--t-base) var(--ease) both; }
.axis.in .rule i { animation: mark var(--t-base) var(--ease) both; animation-delay: calc(var(--t-base) + var(--i, 0) * 55ms); }
@keyframes grow { from { transform: scaleY(0); } }
@keyframes mark { from { opacity: 0; transform: translateX(-6px); } }

/* the limits admit themselves at the accent curve — the one deliberate move */
.limits article { transition: border-color var(--t-base) var(--ease-accent); }
.limits article:hover { border-color: var(--limit); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
}

/* height comparison beside the rule — the number means nothing without one */
/* The rule sets the height of the row. Without this the text stops a third of
   the way down and the section reads as a mistake rather than a measurement. */
.axis-body { display: grid; gap: 1.5rem; align-content: space-between; }
.axis-note.dim { opacity: 0.75; font-size: 0.75rem; }
.heights { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; max-width: 34rem; }
.heights li { display: grid; grid-template-columns: 9.5rem 1fr 8.5rem; gap: 0.75rem; align-items: center; font-size: 0.75rem; }
.heights span { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.heights b { font-weight: 400; color: var(--fg); font-size: 0.72rem; text-align: right; }
.heights u {
  height: 6px; text-decoration: none; display: block; background: var(--line);
  position: relative; overflow: hidden;
}
.heights u::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: var(--pct);
  min-width: 2px; background: var(--muted);
  transform: scaleX(0); transform-origin: left;
}
.axis.in .heights u::after {
  animation: grow-x var(--t-slow) var(--ease) both;
  animation-delay: calc(var(--t-base) + var(--i, 0) * 80ms);
}
@media (prefers-reduced-motion: reduce) {
  .heights u::after { transform: scaleX(1); }
}
.heights li:first-child u::after { background: var(--ok); }
@keyframes grow-x { to { transform: scaleX(1); } }

/* Narrow: the three-column row (9.5rem name · bar · 8.5rem value) leaves about
   14px for the bar at 375px — fourteen pixels to carry the one thing this list
   measures. Stack instead: name and value share the first line, the bar takes
   the full width beneath. Same linear scale, roughly twenty-five times the
   pixels to read it in. Placement is by grid-area, so it does not depend on the
   order replay.js appends the three elements in. This block has to sit AFTER
   the base rules above — same specificity, so source order decides. */
@media (max-width: 34rem) {
  .heights li { grid-template-columns: 1fr auto; gap: 0.35rem 0.75rem; }
  .heights span { grid-area: 1 / 1; }
  .heights b { grid-area: 1 / 2; }
  .heights u { grid-area: 2 / 1 / 3 / -1; height: 8px; }
}

/* dots have to survive the line drawn over them */

/* ── the prompt, verbatim ─────────────────────────────────────────────── */
.prompt { margin: 0 0 1.5rem; background: var(--panel); border: 1px solid var(--line); border-radius: 2px; }
.prompt figcaption {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.7rem 1.25rem; border-bottom: 1px solid var(--line);
  font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.prompt figcaption span { text-transform: none; letter-spacing: 0; }
.prompt button {
  min-height: 32px; padding: 0 0.8rem; background: none; color: var(--muted);
  border: 1px solid var(--line); border-radius: 2px; font: inherit; font-size: 0.72rem;
  cursor: pointer; white-space: nowrap;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.prompt button:hover { color: var(--fg); border-color: var(--muted); }
.prompt button[data-done] { color: var(--ok); border-color: var(--ok); }
/* Capped, not collapsed: the length is part of what it is, but it must not
   own the page. */
.prompt-body { max-height: 26rem; overflow: auto; padding: 1.25rem; }
.prompt-body pre { margin: 0; }
.prompt-body code { font-size: 0.76rem; line-height: 1.65; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--fg); }

/* ── the skill ────────────────────────────────────────────────────────────
   Same panel as the prompt, different job: the description an agent weighs
   before reaching for the tool, and the shape of the file under it. Not capped
   in height — the point of the outline is that you can take it in at once. */
.skill-body { padding: 1.25rem; }
.skill-body p { margin: 0 0 1.35rem; max-width: 46rem;
                color: var(--muted); font-size: 0.8rem; line-height: 1.7; }
.prompt figcaption a { color: var(--muted); font-size: 0.72rem; white-space: nowrap; text-decoration: none; }
.prompt figcaption a:hover { color: var(--fg); }
.outline {
  list-style: none; margin: 0; padding: 0; counter-reset: s;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 0.4rem 1.5rem; font-size: 0.78rem;
}
.outline li { counter-increment: s; color: var(--fg); overflow-wrap: anywhere; }
.outline li::before { content: counter(s, decimal-leading-zero); margin-right: 0.6rem; color: var(--muted); }

/* ── command reference ────────────────────────────────────────────────── */
.cmds { width: 100%; border-collapse: collapse; font-size: 0.8rem; margin-bottom: 1rem; }
.cmds th { text-align: left; font-weight: 400; color: var(--muted); font-size: 0.7rem;
           letter-spacing: 0.08em; text-transform: uppercase; padding-bottom: 0.6rem; }
.cmds td { padding: 0.3rem 1.5rem 0.3rem 0; vertical-align: top; white-space: nowrap; }
.cmds td:first-child { color: var(--fg); }
.cmds td:nth-child(2), .cmds td:last-child { color: var(--muted); }
.cmds td:last-child { white-space: normal; }

/* ── responsive ladder ────────────────────────────────────────────────────
   Fifteen rows, both numbers on each, verdict at the mark. The bar behind the
   row is the page height to scale — shape and proof in the same object. */
.sweep { list-style: none; margin: 0 0 1.25rem; padding: 0; display: grid; gap: 1px; }
.srow {
  position: relative; display: grid; align-items: center; gap: 0.75rem;
  grid-template-columns: 1.2rem 4.5rem 1fr 1fr 11rem;
  padding: 0.5rem 0.9rem; font-size: 0.8rem;
  background: var(--panel); border: 1px solid transparent; border-radius: 2px;
}
/* the bar sits behind the text, never over it */
.srow::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: var(--w);
  background: var(--line); border-radius: 2px;
  transform: scaleX(0); transform-origin: left; z-index: 0;
}
.sweep.in .srow::before {
  animation: grow-x var(--t-slow) var(--ease) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}
.srow > * { position: relative; z-index: 1; }
.srow b { color: var(--ok); font-weight: 400; }
.srow.bad b { color: var(--bad); }
.srow.bad { border-color: var(--bad); }
.srow .wq { color: var(--muted); }
.srow .v { color: var(--fg); font-variant-numeric: tabular-nums; }
.srow .v.c { color: var(--fg); }
.srow.bad .v.c { color: var(--bad); }
.srow .ok { color: var(--limit); font-size: 0.72rem; white-space: nowrap; text-align: right; }
.srow.jump { border-color: var(--limit); }

.sweep.in .srow {
  animation: in var(--t-base) var(--ease) both;
  animation-delay: calc(var(--i, 0) * 45ms);
}
.sweep-verdict { margin: 0 0 1.5rem; color: var(--ok); font-size: 0.82rem; }

@media (max-width: 40rem) {
  .srow, .sweep-head { grid-template-columns: 1.2rem 4rem 1fr 1fr; row-gap: 0.2rem; }
  .srow .ok { grid-column: 2 / -1; }
}
@media (prefers-reduced-motion: reduce) {
  .srow::before { transform: scaleX(1); }
}
/* column labels, so nobody has to infer which side is which */
.sweep-head {
  display: grid; align-items: center; gap: 0.75rem;
  grid-template-columns: 1.2rem 4.5rem 1fr 1fr 11rem;
  padding: 0 0.9rem 0.55rem;
  font-size: 0.68rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--muted);
}

/* A 900px page is 1.6% of 56,691 — its bar is 2px wide, and growing 2px from
   zero is invisible. The row carries the entrance so every subject visibly
   arrives; the bar still carries the comparison. */
.axis.in .heights li {
  animation: in var(--t-base) var(--ease) both;
  animation-delay: calc(var(--t-base) + var(--i, 0) * 80ms);
}
.heights u::after { transition: background-color var(--t-fast) var(--ease); }
.heights li:hover u::after { background: var(--fg); }
/* a scroll-locked subject states it, instead of posing as a short page */
.heights li.locked b { color: var(--limit); }
.heights li.locked u::after { background: var(--limit); }
/* a subject that rendered nothing is not a small measurement, it is no
   measurement — it must not sit on the scale as if it were one */
.heights li.void b { color: var(--bad); }
.heights li.void u { opacity: 0.35; }
.heights li.void u::after { background: var(--bad); }

/* ── first load ───────────────────────────────────────────────────────────
   The overlay is in the markup, not built by script: it has to be on screen
   before any JavaScript runs, or there is nothing to look at while the page
   is deciding what it is. */
#boot {
  position: fixed; inset: 0; z-index: 50;
  background: var(--bg); color: var(--fg);
  display: grid; place-content: center; justify-items: center; gap: 1.5rem;
  transition: opacity var(--t-slow) var(--ease);
}
#boot[hidden] { display: none; }
#boot.done { opacity: 0; pointer-events: none; }
#boot rect { fill: currentColor; transition: transform var(--t-base) var(--ease); }
/* the two halves start apart and close as the work completes */
#boot-l { transform: translateX(calc(var(--gap, 10) * -1px)); }
#boot-r { transform: translateX(calc(var(--gap, 10) * 1px)); }

.boot-bar { width: 13rem; height: 2px; background: var(--line); overflow: hidden; }
.boot-bar i { display: block; height: 100%; width: var(--p, 0%); background: var(--fg); transition: width var(--t-base) var(--ease); }
.boot-label { margin: 0; font-size: 0.72rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* while booting nothing behind should move or be reachable */
body.booting { overflow: hidden; }

/* ── sound ────────────────────────────────────────────────────────────────
   Off by default and it says so. A page cannot start audio without a gesture
   anyway, so pretending otherwise would only produce a silent lie. */
#sound {
  position: fixed; left: 1.25rem; bottom: 1.25rem; z-index: 40;
  display: inline-flex; align-items: center; gap: 0.6rem;
  min-height: 34px; padding: 0 0.85rem;
  background: var(--panel); color: var(--muted);
  border: 1px solid var(--line); border-radius: 2px;
  font: inherit; font-size: 0.72rem; letter-spacing: 0.04em; cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
#sound:hover { color: var(--fg); border-color: var(--muted); }
#sound[aria-pressed="true"] { color: var(--fg); }
.wave { display: inline-flex; align-items: flex-end; gap: 2px; height: 11px; }
.wave i { width: 2px; height: 3px; background: currentColor; }
#sound[aria-pressed="true"] .wave i { animation: bob 1.1s var(--ease) infinite; }
#sound[aria-pressed="true"] .wave i:nth-child(2) { animation-delay: 0.16s; }
#sound[aria-pressed="true"] .wave i:nth-child(3) { animation-delay: 0.32s; }
#sound[aria-pressed="true"] .wave i:nth-child(4) { animation-delay: 0.48s; }
@keyframes bob { 0%, 100% { height: 3px; } 50% { height: 11px; } }

@media (prefers-reduced-motion: reduce) {
  #boot rect { transition: none; }
  #sound[aria-pressed="true"] .wave i { animation: none; height: 7px; }
}
.strip b.bad { color: var(--bad); }
