/* ghostavo.com
   Design system per BRIEF.md §8.
   Two deviations from the token table, both to hold WCAG AA (§11), both noted in NOTES.md:
   - body --muted darkened from #6B7B7A to #647473 (the brief value hits 3.94:1 on --surface)
   - --teal is 2.07:1 on --surface, so link text and chart strokes use --teal-deep and --slate.
     --teal keeps its job as the signature: handles, ticks, fills, underlines, active states. */

:root {
  --surface:     #F6F9F9;
  --ink:         #10201F;
  --teal:        #50C1B1;
  --teal-wash:   #E4F2EF;
  --teal-deep:   #1E5F58;
  --slate:       #3D5A80;
  --muted:       #647473;   /* text */
  --hairline:    #6B7B7A;   /* rules only, non-text */

  --sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --serif: Newsreader, ui-serif, Georgia, "Times New Roman", serif;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  --t-xs:  0.75rem;
  --t-sm:  0.8125rem;
  --t-base: 1.0625rem;
  --t-md:  1.25rem;
  --t-lg:  1.6rem;
  --t-xl:  2.1rem;

  --wrap: 1100px;
  --measure: 62ch;   /* prose stops where the eye starts losing the line */
  --wrap-wide: 1280px;
  --gap: clamp(1.25rem, 4vw, 2rem);
  --band: clamp(2.5rem, 5.5vw, 4.25rem);
  --r: 3px;
}

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 5rem; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font: 400 var(--t-base)/1.65 var(--sans);
  font-feature-settings: "kern", "liga";
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-weight: 400; line-height: 1.15; }
p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }
em { font-style: italic; }

a { color: var(--teal-deep); text-decoration: none; border-bottom: 1px solid var(--teal); padding-bottom: 1px; }
a:hover { color: var(--ink); border-bottom-color: var(--ink); }

:focus-visible { outline: 2px solid var(--teal-deep); outline-offset: 3px; border-radius: var(--r); }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gap); }
.section--wide .wrap { max-width: var(--wrap-wide); }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 20;
  background: var(--ink); color: var(--surface); padding: .7rem 1rem; border: 0;
}
.skip:focus { left: 0; }

/* ── eyebrow / mono ─────────────────────────────── */
.eyebrow {
  font: 500 var(--t-xs)/1 var(--mono);
  letter-spacing: .14em; text-transform: uppercase; color: var(--muted);
  margin: 0 0 1.4rem;
}

/* ── baseline and delta rule ────────────────────── */
.rule { position: relative; height: 1px; background: var(--hairline); opacity: .28; margin-bottom: var(--gap); }
.rule::before {
  content: ""; position: absolute; left: 0; bottom: 100%;
  width: 2px; height: 9px; background: var(--teal); opacity: 1;
}

/* ── top bar ────────────────────────────────────── */
.topbar {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid color-mix(in srgb, var(--hairline) 22%, transparent);
}
.topbar__inner { display: flex; align-items: center; justify-content: space-between; gap: 1rem; height: 3.5rem; }
.topbar__id { font: 500 var(--t-sm)/1 var(--mono); letter-spacing: .04em; border: 0; color: var(--ink); }
.topbar__nav { display: flex; gap: clamp(.85rem, 3vw, 1.75rem); }
.topbar__nav a {
  font: 400 var(--t-sm)/1 var(--sans); color: var(--muted);
  border: 0; padding-bottom: 3px; border-bottom: 1.5px solid transparent;
}
.topbar__nav a:hover { color: var(--ink); }
.topbar__nav a.is-current { color: var(--ink); border-bottom-color: var(--teal); }
@media (max-width: 30rem) { .topbar__id { display: none; } .topbar__inner { justify-content: center; } }

/* ── hero ───────────────────────────────────────── */
.hero { padding-top: clamp(3rem, 9vw, 6rem); padding-bottom: clamp(2rem, 5vw, 3.5rem); }
.hero__name {
  font-family: var(--serif);
  font-size: clamp(3.1rem, 12vw, 7.5rem);
  letter-spacing: -.028em; line-height: .95; margin-bottom: clamp(1.5rem, 4vw, 2.5rem);
}
.hero__line {
  font-family: var(--serif);
  font-size: clamp(1.55rem, 4.1vw, 2.7rem);
  line-height: 1.2; letter-spacing: -.012em; max-width: 20ch; margin-bottom: 1.5rem;
}
.hero__body { max-width: 58ch; color: var(--ink); }
.hero__links { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: 2rem; font-family: var(--sans); font-size: var(--t-sm); }

/* ── signature ──────────────────────────────────── */
.signature { padding-bottom: var(--band); }
.sig__h { font-family: var(--serif); font-size: var(--t-lg); max-width: 24ch; margin-bottom: .9rem; }
.sig__intro { max-width: 60ch; color: var(--muted); margin-bottom: 2rem; }

/* ── career strip ───────────────────────────────── */
.strip { border-block: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); padding-block: 1.1rem; }
.strip__list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: .4rem 1.5rem;
  font: 400 var(--t-sm)/1.6 var(--mono); color: var(--muted); letter-spacing: .01em;
}
.strip__list span { color: var(--ink); margin-right: .45em; }
.strip__list li:last-child { color: var(--ink); }

/* ── sections ───────────────────────────────────── */
.section { padding-block: var(--band); }
.section__h { font-family: var(--serif); font-size: var(--t-xl); letter-spacing: -.018em; max-width: 22ch; margin-bottom: 1rem; }
.section__sub { max-width: 62ch; color: var(--muted); margin-bottom: 3rem; }

/* ── introduction ───────────────────────────────── */
.intro { display: grid; grid-template-columns: 200px 1fr; gap: clamp(1.75rem, 5vw, 4rem); align-items: start; }
.intro__portrait { display: block; }
.intro__portrait img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: var(--r); background: var(--teal-wash);
}
.intro__text { max-width: 62ch; }
.intro__meta { font: 400 var(--t-sm)/1.6 var(--mono); color: var(--muted); margin-top: 1.6rem; }
@media (max-width: 46rem) {
  .intro { grid-template-columns: 1fr; }
  .intro__portrait { max-width: 160px; }
}

/* ── point of view ──────────────────────────────── */
.piece { border-top: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); }
.piece:last-of-type { border-bottom: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); }
.piece h3 { font-size: inherit; }

.piece__toggle, .card__toggle {
  display: grid; align-items: baseline; width: 100%;
  background: none; border: 0; padding: 1.5rem 0; margin: 0;
  font: inherit; color: var(--ink); text-align: left; cursor: pointer;
}
.piece__toggle {
  grid-template-columns: 3.25rem minmax(0, 1fr) 1.5rem;
  grid-template-areas: "n t i" ".  d i";
  gap: .45rem .5rem;
}
.piece__n { grid-area: n; }
.piece__t { grid-area: t; }
.piece__toggle .piece__i { grid-area: i; }
.piece__d {
  grid-area: d; max-width: 62ch;
  font: 400 var(--t-sm)/1.55 var(--sans); color: var(--muted);
}
[aria-expanded="true"] .piece__d { color: var(--teal-deep); }
.piece__n { font: 400 var(--t-xs)/1.9 var(--mono); color: var(--muted); letter-spacing: .1em; }

.piece__t { font-family: var(--serif); font-size: clamp(1.25rem, 2.6vw, 1.7rem); line-height: 1.25; }
.piece__toggle:hover .piece__t, .card__toggle:hover .card__t { color: var(--teal-deep); }

.piece__i { position: relative; width: 14px; height: 14px; justify-self: end; align-self: center; }
.piece__i::before, .piece__i::after {
  content: ""; position: absolute; inset: 0; margin: auto; background: var(--teal-deep);
}
.piece__i::before { width: 14px; height: 1.5px; }
.piece__i::after  { width: 1.5px; height: 14px; transition: transform .25s ease-out; }
[aria-expanded="true"] .piece__i::after { transform: scaleY(0); }

.piece__panel, .card__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .25s ease-out; }
.piece__panel.is-open, .card__panel.is-open { grid-template-rows: 1fr; }
.piece__inner, .card__inner { overflow: hidden; }
.piece__inner { padding-left: 3.75rem; }
@media (max-width: 40rem) { .piece__inner { padding-left: 0; } .piece__toggle { grid-template-columns: 2.5rem minmax(0, 1fr) 1rem; } }

.piece__inner > .prose { max-width: 66ch; padding-bottom: 2.5rem; }
.piece__inner > .chart { margin-bottom: 3rem; }
@media (min-width: 62rem) {
  .piece__inner { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 3rem; align-items: start; }
  .piece__inner > .prose { padding-bottom: 3rem; }
  .piece__inner > .chart { position: sticky; top: 5rem; }
}

/* ── pulled figures ─────────────────────────────── */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 1px; margin: 1.9rem 0 1.6rem;
  background: color-mix(in srgb, var(--hairline) 26%, transparent);
  border-block: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent);
}
.stat { background: var(--surface); padding: 1.05rem 1rem 1.15rem; }
.stat b {
  display: block; font: 400 clamp(1.65rem, 3.4vw, 2.15rem)/1 var(--mono);
  color: var(--teal-deep); letter-spacing: -.02em; margin-bottom: .5rem;
}
.stat span { display: block; font: 400 var(--t-xs)/1.45 var(--sans); color: var(--muted); }

/* ── charts ─────────────────────────────────────── */
.chart { margin: 0; }
.chart__h { font: 500 var(--t-sm)/1.4 var(--sans); color: var(--muted); margin-bottom: .9rem; }
.chart__h--second { margin-top: 2.25rem; }
.chart__svg { width: 100%; }
.chart__svg svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart--sig .chart__svg { max-width: 780px; }
.chart figcaption { font: 400 var(--t-sm)/1.6 var(--sans); color: var(--muted); margin-top: 1.1rem; max-width: 56ch; }

.axis line, .axis path { stroke: var(--hairline); stroke-opacity: .45; shape-rendering: crispEdges; }
.axis text { fill: var(--muted); font: 400 11px var(--mono); }
.grid line { stroke: var(--hairline); stroke-opacity: .18; shape-rendering: crispEdges; }
.serie-label { font: 500 11px var(--mono); letter-spacing: .04em; }

/* ── controls ───────────────────────────────────── */
.control { margin-top: 1.5rem; display: grid; gap: .55rem; max-width: 32rem; }
.control label { font: 400 var(--t-sm)/1.4 var(--sans); color: var(--muted); }
.control output { font: 400 var(--t-sm)/1.5 var(--mono); color: var(--ink); }
.control output b { font-weight: 500; color: var(--teal-deep); }

input[type="range"] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 22px;
  background: none; cursor: pointer;
  touch-action: none;                    /* the page must not pan while the thumb is being dragged */
}
/* The travelled part of the track is filled, so the control reads as a value rather than a knob. */
input[type="range"]::-webkit-slider-runnable-track {
  height: 3px; border-radius: 2px;
  background: linear-gradient(to right,
    var(--teal-deep) var(--pct, 0%),
    color-mix(in srgb, var(--hairline) 35%, transparent) var(--pct, 0%));
}
input[type="range"]::-moz-range-track {
  height: 3px; border-radius: 2px;
  background: linear-gradient(to right,
    var(--teal-deep) var(--pct, 0%),
    color-mix(in srgb, var(--hairline) 35%, transparent) var(--pct, 0%));
}
input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -7.5px;
  background: var(--teal); border: 2px solid var(--teal-deep); border-radius: 50%;
  transition: transform .12s cubic-bezier(.22,.61,.36,1), box-shadow .12s ease;
}
input[type="range"]::-moz-range-thumb {
  width: 16px; height: 16px; background: var(--teal); border: 2px solid var(--teal-deep);
  border-radius: 50%;
  transition: transform .12s cubic-bezier(.22,.61,.36,1), box-shadow .12s ease;
}
input[type="range"]:hover::-webkit-slider-thumb { transform: scale(1.12); }
input[type="range"]:hover::-moz-range-thumb     { transform: scale(1.12); }
input[type="range"]:active::-webkit-slider-thumb {
  transform: scale(1.2); box-shadow: 0 0 0 7px color-mix(in srgb, var(--teal) 16%, transparent);
}
input[type="range"]:active::-moz-range-thumb {
  transform: scale(1.2); box-shadow: 0 0 0 7px color-mix(in srgb, var(--teal) 16%, transparent);
}
input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px color-mix(in srgb, var(--teal) 30%, transparent); }
input[type="range"]:focus-visible::-moz-range-thumb     { box-shadow: 0 0 0 4px color-mix(in srgb, var(--teal) 30%, transparent); }

/* The signature control lines up with the plot area rather than the figure box. The chart
   publishes --track-l and --track-r; the input overhangs by half a thumb at each end so the
   thumb centre, not its edge, lands on 0% and on the slider's maximum. */
.chart--sig .control { max-width: none; padding-left: var(--track-l, 0); padding-right: var(--track-r, 0); }
.chart--sig .control input[type="range"] { width: calc(100% + 18px); margin-inline: -9px; }

@media (prefers-reduced-motion: reduce) {
  input[type="range"]::-webkit-slider-thumb,
  input[type="range"]::-moz-range-thumb { transition: none; }
  input[type="range"]:hover::-webkit-slider-thumb,
  input[type="range"]:hover::-moz-range-thumb,
  input[type="range"]:active::-webkit-slider-thumb,
  input[type="range"]:active::-moz-range-thumb { transform: none; }
}

.toggles { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.4rem; }
.readout { font: 400 var(--t-sm)/1.5 var(--sans); color: var(--muted); margin-top: 1rem; }
.readout b { font-weight: 500; color: var(--ink); }

.chip {
  font: 400 var(--t-xs)/1 var(--mono); letter-spacing: .05em;
  color: var(--muted); background: none; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--hairline) 38%, transparent);
  border-radius: 999px; padding: .5rem .85rem;
  transition: background-color .15s, color .15s, border-color .15s;
}
.chip:hover { color: var(--ink); border-color: var(--teal-deep); }
.chip.is-on, .chip[aria-pressed="true"] { background: var(--teal-wash); color: var(--teal-deep); border-color: var(--teal); }
@media (prefers-reduced-motion: reduce) { .chip { transition: none; } }

/* ── selected work ──────────────────────────────── */
.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 2.5rem; }
.grid { display: grid; gap: 0; }
.card { border-top: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); }
.card:last-child { border-bottom: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); }
.card[hidden] { display: none; }
.card h3 { font-size: inherit; }
.card__toggle { grid-template-columns: 1fr 1.5rem; grid-template-areas: "t i" "k i"; gap: .3rem .5rem; padding-bottom: .9rem; }
.card__t { grid-area: t; font-family: var(--serif); font-size: clamp(1.15rem, 2.2vw, 1.45rem); }
.card__k { grid-area: k; font: 400 var(--t-sm)/1.5 var(--sans); color: var(--muted); }
.card__toggle .piece__i { grid-area: i; }
.card__inner > * { max-width: 66ch; }
/* padding lives on the open state only: on a collapsed grid row, padding on the
   overflow-hidden element still renders as height and leaks the first lines through */
.card__inner { padding-bottom: 0; transition: padding-bottom .25s ease-out; }
.card__panel.is-open .card__inner { padding-bottom: 2.25rem; }
.card__lede { color: var(--muted); }
.privacy {
  border-left: 2px solid var(--teal); background: var(--teal-wash);
  padding: .9rem 1.1rem; border-radius: 0 var(--r) var(--r) 0; color: var(--teal-deep);
}
.card__stack { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0 0 1.5rem; padding-left: 0; }
.card__inner .card__stack { margin-top: 1.4rem; }
.card__stack span {
  font: 400 var(--t-xs)/1 var(--mono); color: var(--muted);
  border: 1px solid color-mix(in srgb, var(--hairline) 30%, transparent);
  border-radius: var(--r); padding: .35rem .6rem;
}

.earlier { margin: 1.6rem 0 0; }
.earlier dt {
  font: 500 var(--t-sm)/1.5 var(--sans); color: var(--ink);
  margin-top: 1.4rem; display: flex; flex-wrap: wrap; gap: .75rem; align-items: baseline;
}
.earlier dt span { font-weight: 400; color: var(--muted); font-size: var(--t-xs); }
.earlier dd { margin: .35rem 0 0; color: var(--muted); }

/* ── ask ────────────────────────────────────────── */
.ask__line { max-width: 52ch; color: var(--muted); margin-bottom: 1.75rem; }

.ask__form { display: flex; gap: .6rem; flex-wrap: wrap; max-width: 46rem; }
.ask__form input {
  flex: 1 1 18rem; min-width: 0;
  font: 400 var(--t-sm)/1.5 var(--sans); color: var(--ink);
  background: #FFF; border: 1px solid var(--hairline); border-radius: var(--r);
  padding: .85rem 1rem;
}
.ask__form input::placeholder { color: var(--muted); }
.ask__form input:focus-visible { border-color: var(--teal-deep); }

.ask__go {
  font: 500 var(--t-sm)/1.5 var(--mono); letter-spacing: .04em;
  background: var(--ink); color: var(--surface);
  border: 1px solid var(--ink); border-radius: var(--r);
  padding: .85rem 1.5rem; cursor: pointer;
}
.ask__go:hover { background: var(--teal-deep); border-color: var(--teal-deep); }
.ask__go[disabled] { opacity: .5; cursor: default; }

.ask__seeds { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .9rem; }
.ask__seed {
  font: 400 var(--t-xs)/1.4 var(--mono); color: var(--muted);
  background: none; border: 1px solid color-mix(in srgb, var(--hairline) 55%, transparent);
  border-radius: 999px; padding: .4rem .8rem; cursor: pointer; text-align: left;
}
.ask__seed:hover { color: var(--ink); border-color: var(--teal); }

/* Collapsed until there is something to say, so the section is not a hole in the page */
.ask__out { display: none; margin-top: 1.75rem; max-width: 52ch; }
.ask__out.is-on { display: block; }
.ask__out p { color: var(--ink); }
.ask__out p + p { margin-top: .8rem; }
.ask__out .ask__note {
  font: 400 var(--t-xs)/1.6 var(--mono); color: var(--muted); margin-top: 1rem;
}
.ask__out.is-waiting p { color: var(--muted); }
/* An answer takes about five seconds, which is the model, not the plumbing. A static word
   for five seconds reads as broken, so the caret says the page is still working. */
.ask__out.is-waiting p::after {
  content: '\258C';
  margin-left: .1em;
  color: var(--teal-deep);
  animation: caret 1.05s step-end infinite;
}
@keyframes caret { 0%, 50% { opacity: 1; } 50.01%, 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .ask__out.is-waiting p::after { animation: none; opacity: .5; }
}

/* ── contact ────────────────────────────────────── */
.contact__links { display: flex; flex-wrap: wrap; gap: 1.5rem; margin-top: 1.5rem; font: 400 var(--t-sm) var(--mono); }

/* ── footer ─────────────────────────────────────── */
.foot { border-top: 1px solid color-mix(in srgb, var(--hairline) 26%, transparent); padding-block: 2rem; }
/* One line, one source. The film states the figure plainly and the credit lives here, so the
   copy reads like a sentence rather than a citation. */
.foot__src { margin: 1rem 0 0; max-width: 52ch; font: 400 var(--t-xs) var(--mono); color: var(--muted); line-height: 1.7; }
.foot__inner { display: flex; flex-wrap: wrap; gap: .5rem 2rem; font: 400 var(--t-xs) var(--mono); color: var(--muted); letter-spacing: .06em; }
/* The one place the charts are qualified. It used to be said three times, above the argument. */
.foot__note { max-width: 52ch; margin-bottom: 1.5rem; font: 400 var(--t-xs) var(--mono); color: var(--muted); line-height: 1.7; }

/* ── entrance ───────────────────────────────────── */
.reveal > * { opacity: 0; transform: translateY(14px); }
.reveal.is-in > * {
  opacity: 1; transform: none;
  transition: opacity .5s cubic-bezier(.22,.61,.36,1), transform .5s cubic-bezier(.22,.61,.36,1);
  transition-delay: calc(var(--i, 0) * 26ms);
}
@media (prefers-reduced-motion: reduce) {
  .reveal > *, .reveal.is-in > * { opacity: 1; transform: none; transition: none; }
  .piece__panel, .card__panel, .card__inner { transition: none; }
  .piece__i::after { transition: none; }
}

/* ── scroll-world film ──────────────────────────────
   Theme tokens for the camera-flight engine (vendor/scrub-engine.js). Unlayered, so they
   beat the engine's own defaults, which sit inside `@layer sw` in scroll-world.css.
   --sw-bg is the exact background the dioramas were rendered on, so the poster, the video
   and the page are one continuous surface with no visible edge. */
:root, .sw-root {
  --sw-bg:       var(--surface);
  --sw-ink:      var(--ink);
  --sw-ink-soft: var(--muted);
  --sw-accent:   var(--teal-deep);
  --sw-font-display: var(--serif);
  --sw-font-body:    var(--sans);
}

/* The engine's stage is position:fixed at z-index 10, the same layer the topbar was on,
   so the film would paint over the nav. The topbar wins instead: it reads cleanly against
   the film because the scenes were rendered on --surface, the same cream it is tinted with. */
.topbar { z-index: 60; }

/* The <h1> exists for search engines, screen readers and the no-JS case. Once the engine
   mounts, the film's own copy carries the message, so the heading is taken out of the
   visual flow without being hidden from assistive tech. */
.film { position: relative; }
.film__h {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* Multi-beat scene copy. A scene that carries two or three points stacks them in one grid
   cell so they cross-fade in place instead of pushing each other down the page; the row
   sizes to the tallest beat, so nothing reflows as they swap. Single-beat scenes are left
   in normal flow and behave exactly as the engine shipped them. */
.sw-copy:not([data-beats="1"]) {
  display: grid;
  grid-template-areas: "num" "beat" "cta";
  grid-template-rows: auto 1fr auto;
  /* Centring a block whose height is set by its tallest beat put the chips under the fold, and
     nudging the centre up was a guess that only moved the problem. Anchor the bottom instead:
     the last thing in the block now sits a fixed distance above the viewport floor, whichever
     beat is showing and however tall it is. This is what the engine already does on phones. */
  top: auto;
  bottom: clamp(72px, 11vh, 132px);
  transform: none;
}
.sw-copy:not([data-beats="1"]) .sw-copy__tags { margin-top: 18px; }
.sw-copy:not([data-beats="1"]) > .sw-copy__num  { grid-area: num; }
.sw-copy:not([data-beats="1"]) > .sw-copy__beat { grid-area: beat; opacity: 0; will-change: opacity; }
.sw-copy:not([data-beats="1"]) > .sw-copy__cta  { grid-area: cta; }

/* The engine mounts seven fixed, full-viewport layers and never unmounts them: an opaque
   sky, a copy scrim, the stage, the route rail, the progress bar, the hint and its topbar.
   That is fine while the film owns the screen and wrong the moment anything follows it —
   a positioned z-index:0 element paints above non-positioned block content, so the whole
   page below the film sat under a cream sheet. `atmosphere:false` does not help: it only
   skips the sky's children, not the sky.
   Hiding by visibility rather than display keeps .sw-track's height, which is the scroll
   spacer the whole film is measured against. */
#world.is-past > * { visibility: hidden; }

/* Everything except the video has finished its job the moment the track ends; only the stage
   still has a frame worth dissolving. Anything else left painted over the page is just a veil. */
#world.is-exiting .sw-copylayer,
#world.is-exiting .sw-sky,
#world.is-exiting .sw-route,
#world.is-exiting .sw-scrollbar,
#world.is-exiting .sw-hint { visibility: hidden; }

/* ── the route rail ─────────────────────────────────
   Shipped with every label at opacity 0, revealed only on hover or when active, so a
   visitor could not tell there were seven stops or how far the film ran. The rail is the
   only thing on screen that can say "this is long on purpose" before someone decides
   whether to keep going, so all seven names stay legible and the current one steps forward. */
.sw-route__label {
  opacity: .5;
  transform: translateY(-50%) translateX(0);
  font-size: .74rem;
  font-weight: 500;
  letter-spacing: .01em;
}
.sw-route__dot:hover .sw-route__label,
.sw-route__dot.is-active .sw-route__label {
  opacity: 1;
  font-weight: 650;
}
.sw-route__dot.is-active .sw-route__label {
  box-shadow: 0 1px 10px color-mix(in srgb, var(--ink) 10%, transparent);
}

/* The rail's own line is a flat 28% tint end to end, which says nothing about position.
   Overlay a fill driven by --sw-progress (published from world.js) so the distance still
   to travel is visible, and the next stop is visibly being approached. */
.sw-route::after {
  content: "";
  position: absolute;
  left: 50%; top: 22px; bottom: 22px;
  width: 2px;
  /* Scale rather than a percentage height: the rail is an auto-height flex column, and a
     percentage height against an indefinite containing block resolves to nothing, so the
     calc() version measured 0px at every progress value. Top and bottom insets give the
     pseudo-element a definite height without a percentage; scaleY then fills it. */
  transform: translateX(-50%) scaleY(var(--sw-progress, 0));
  transform-origin: 50% 0;
  background: var(--sw-accent);
}
@media (prefers-reduced-motion: no-preference) {
  .sw-route::after { transition: transform .18s linear; }
}

/* ── incrementality chart ───────────────────────────
   The channel chips filter the cloud; each carries its channel's colour so the legend and
   the marks are the same object. Pressed means isolated, not selected-among-many. */
.chart--inc { margin: 0; }
.inc__keys { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1rem; }
.inc__keys button[data-ch="offsite"] { --k: var(--slate); }
.inc__keys button[data-ch="instore"] { --k: var(--teal-deep); }
.inc__keys button[data-ch="onsite"]  { --k: var(--teal-deep); }
.inc__keys button::before {
  content: ""; display: inline-block; width: .55rem; height: .55rem; border-radius: 50%;
  background: var(--k); margin-right: .45rem; vertical-align: -1px;
}
.inc__keys button[data-ch="instore"]::before { background: var(--teal); }

/* ── film to page handover ──────────────────────────
   --sw-exit runs 0 to 1 across the engine's run-out viewport, published from world.js.
   The film dims across that band while the first section below rises into it. Both the
   film's background and the page are --surface, so what crosses over is only the diorama,
   not a colour change, and the seam reads as the camera pulling out of the world. */
#world .sw-stage,
#world .sw-copylayer,
#world .sw-route,
#world .sw-scrollbar,
#world .sw-hint { opacity: calc(1 - var(--sw-exit, 0)); }

/* The film used to hand over to the incrementality chart. The chart is gone — the film makes
   the argument now — so the run-out band delivers the reader straight to his face and bio. */
#intro {
  opacity: calc(0.9 + 0.1 * var(--sw-enter, 1));
  transform: translateY(calc((1 - var(--sw-enter, 1)) * 1vh));
}
@media (prefers-reduced-motion: reduce) {
  #world .sw-stage, #world .sw-copylayer, #world .sw-route,
  #world .sw-scrollbar, #world .sw-hint { opacity: 1; }
  #intro { opacity: 1; transform: none; }
}


/* ── prose measure ──────────────────────────────
   The wrap is 1100px because the cards, the rules and the film want that width. Prose does not:
   at 17px Inter that runs past 80 characters and the eye starts losing its place on the return.
   The column narrows, the container does not. */
.intro__text p, #ask .wrap > p, .card__lede { max-width: var(--measure); }


/* ── the film reads in the site's voice ─────────
   The families were already mapped, but the engine asks for weights this site does not load:
   700 on the serif titles and the eyebrow, 600 on the tags and the route labels. Newsreader and
   Inter are here at 400 only, so the browser was synthesising all of it, and a faked bold serif
   next to a real 400 serif is exactly the mismatch that made the film look like a different
   document. Everything below asks only for weights that exist: 400 for the text faces, 500 for
   IBM Plex Mono, which is the one face that ships two. */
#world .sw-copy__title {
  font-weight: 400;
  letter-spacing: -.018em;      /* the value .section__h uses, so a headline reads the same */
  line-height: 1.1;
}
#world .sw-copy__eyebrow {
  font: 500 var(--t-xs)/1 var(--mono);
  letter-spacing: .04em;
  text-transform: none;         /* uppercase letterspaced labels are the tell we just removed */
  color: var(--teal-deep);
}
#world .sw-copy__num { font-family: var(--mono); }
#world .sw-copy__body {
  font-family: var(--sans);
  font-weight: 400;
  line-height: 1.65;            /* the body rhythm the page below uses */
}
#world .sw-copy__tags li { font: 400 var(--t-sm)/1 var(--sans); }
#world .sw-route__label  { font: 500 var(--t-xs)/1 var(--mono); letter-spacing: .02em; }
#world .sw-copy__cta a   { font: 400 var(--t-sm)/1 var(--sans); }
