/* front-6-journey. Owner: A.
   One dark room, one light. The document scrolls an empty track under a
   fixed canvas; copy cards fade in place by their band. Three ways the page
   runs: live (html.js.gl), stills (html.stills, html.nogl), static (html.no-js). */

/* the fonts every page shares, at one address (/fonts/, tools/front-journey/subset-fonts.sh);
   the proof's own copies (same bytes) and the full TTFs are the fallbacks */
@font-face {
  font-family: "Martian Mono";
  src: url("/fonts/martian-mono.woff2") format("woff2"),
       url("../fonts/martian-mono.woff2") format("woff2"),
       url("../../assets/MartianMono.ttf") format("truetype");
  font-weight: 100 800;
  font-stretch: 75% 112.5%;
  font-display: swap;
}
@font-face {
  font-family: "Hanken Grotesk";
  src: url("/fonts/hanken-grotesk.woff2") format("woff2"),
       url("../fonts/hanken-grotesk.woff2") format("woff2"),
       url("../../assets/HankenGrotesk.ttf") format("truetype");
  font-weight: 100 900;
  font-display: swap;
}

:root {
  --night: #0b0a09;
  --on-dark: #ece6dc;
  --light: #f2ae55;
  --light-2: #ffcf8a;
  --light-3: #ffe0a3;
  --light-4: #fffaf0;
  --signal: #c27c1a;
  --bright-ground: #e4dfd6;
  --text-2: rgba(236, 230, 220, .76);
  --text-3: rgba(236, 230, 220, .56);
  --hair: rgba(236, 230, 220, .16);
  --mono: "Martian Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --sans: "Hanken Grotesk", system-ui, -apple-system, "Segoe UI", sans-serif;
  --ease: cubic-bezier(.2, .8, .2, 1);
  --gut: clamp(16px, 6.4vw, 104px);
  --pt: 0;
  --pulse: .6;
  --breath: .6;
  color-scheme: dark;
}

* { box-sizing: border-box; }

html {
  background: var(--night);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
/* the cord replaces the native scrollbar, on fine pointers only */
@media (pointer: fine) {
  html.js { scrollbar-width: none; }
  html.js::-webkit-scrollbar { display: none; }
}

body {
  margin: 0;
  background: var(--night);
  color: var(--on-dark);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; }
.mono {
  font-family: var(--mono);
  font-stretch: 100%;
  letter-spacing: .02em;
  font-weight: 400;
}
.price { font-family: var(--mono); font-stretch: 100%; letter-spacing: .01em; }
.vh {
  position: absolute !important;
  width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus { outline: none; }
:focus-visible { outline: 1.5px solid var(--light-2); outline-offset: 4px; border-radius: 4px; }

/* alternates: shown by a class on html, never written by script */
.v-rm, .v-sale, .div16 { display: none; }
html.rm .v-live { display: none; }
html.rm .v-rm { display: inline; }
html.carve-on-sale .v-workshop { display: none; }
html.carve-on-sale .v-sale { display: inline; }
/* the kicker follows gate's division as the clock plays it (html[data-div], main.js), so it
   says 1/16 only once gate has switched; without the 3D runtime (no WebGL) it follows the beat */
html[data-div="16"] #floor .div8 { display: none; }
html[data-div="16"] #floor .div16 { display: inline; }
html:not([data-div]) #floor[data-beat="reveal"] .div8, html:not([data-div]) #floor[data-beat="rise"] .div8 { display: none; }
html:not([data-div]) #floor[data-beat="reveal"] .div16, html:not([data-div]) #floor[data-beat="rise"] .div16 { display: inline; }

.skip {
  position: fixed; left: var(--gut); top: 12px; z-index: 80;
  padding: 12px 16px; border-radius: 999px;
  background: var(--on-dark); color: #1f1d1a; font-size: 14px; font-weight: 500;
  transform: translateY(-180%); transition: transform .2s var(--ease);
}
.skip:focus, .skip:focus-visible { transform: none; }

/* ── the LED: the only colour on the page ──────────────────────────── */
.led {
  display: inline-block; flex: none;
  width: 7px; height: 7px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, rgba(236,230,220,.34), rgba(236,230,220,.16));
}
.led.on, .led.breath {
  background: radial-gradient(circle at 40% 35%, var(--light-3), var(--light) 62%);
  box-shadow: 0 0 0 1px rgba(194,124,26,.25), 0 0 calc(5px + 6px * var(--pulse)) 1px rgba(242,174,85,calc(.3 + .4 * var(--pulse)));
}
.led.breath {
  opacity: calc(.32 + .68 * var(--breath));
  box-shadow: 0 0 0 1px rgba(194,124,26,.2), 0 0 calc(3px + 6px * var(--breath)) 1px rgba(242,174,85,calc(.15 + .45 * var(--breath)));
}

/* ── nav: the shared bar (css/bar.css, linked first); here only what the journey adds ── */
/* the bar stays put over the room */
.nav { position: fixed; }
/* the lights breathe on the journey's clock (ui.js --breath), not bar.css's animation */
.nav a[data-led-state="breath"] .led { animation: none; opacity: calc(.3 + .7 * var(--breath)); box-shadow: 0 0 calc(2px + 5px * var(--breath)) 1px rgba(242,174,85,calc(.2 + .4 * var(--breath))); }

/* ── the stage ─────────────────────────────────────────────────────── */
.stage {
  position: fixed; z-index: 0; left: 0; top: 0; width: 100%;
  height: 100vh; height: 100lvh;
  overflow: hidden; background: var(--night);
}
#gl {
  position: absolute; inset: 0; width: 100%; height: 100%; display: block;
  opacity: 0; transition: opacity .7s ease-out;
}
html.gl #gl { opacity: 1; }
.preglow {
  position: absolute; left: 50%; top: 70%;
  width: 70vmin; height: 70vmin; transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(255,196,120,.75) 0, rgba(242,150,60,.55) 3.4%, rgba(194,110,30,.16) 5%, rgba(194,124,26,.06) 14%, rgba(194,124,26,.02) 28%, rgba(11,10,9,0) 50%);
  opacity: 0; animation: strike 1.6s .15s var(--ease) forwards;
  pointer-events: none;
}
html.tall .preglow { top: 75%; }
@media (max-aspect-ratio: 17/20) { .preglow { top: 75%; } }
html.gl .preglow { opacity: 0 !important; animation: none; transition: opacity .7s ease-out; }
@keyframes strike { 0% { opacity: 0; filter: saturate(2.2) brightness(.4); } 100% { opacity: 1; filter: none; } }
.stage img.still {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  display: none;
}
html.nogl .stage img.still, html.lost .stage img.still, html.waiting .stage img.still, html.boot-stills .stage img.still { display: block; }
html.nogl #gl, html.lost #gl, html.waiting #gl, html.boot-stills #gl { opacity: 0; }
html.nogl .preglow, html.waiting .preglow, html.boot-stills .preglow { display: none; }
.veil { position: absolute; inset: 0; background: var(--night); opacity: 0; pointer-events: none; transition: opacity .3s ease; }
html.stills .veil { transition-duration: .45s; }
html.cut .veil { opacity: 1; }
.paper {
  position: absolute; inset: 0; background: var(--bright-ground);
  opacity: 0; transform: translateY(5%); pointer-events: none;
  transition: opacity .8s var(--ease), transform 1s var(--ease);
}
/* the doors (ui.js door(), S2): the tone comes from where the link goes.
   night (gate, carve, mangler): the room falls to night under the bar, which stays.
   bone (support, account, legal): the paper sheet rises over everything, as before.
   With the browser's view transition (html.door-vt) there is no sheet: the room
   falls to night, the instrument clicked stays lit (.vt-stand, flight.js) and the
   browser carries it into the next page. */
html.door[data-door="bone"]:not(.door-vt) .paper { opacity: 1; transform: none; }
html.door[data-door="bone"]:not(.door-vt) .stage { z-index: 70; transition: z-index 0s linear .35s; }
html.door #chapters, html.door .cord, html.door .sound,
html.door[data-door="bone"]:not(.door-vt) .nav { opacity: 0 !important; transition: opacity .35s var(--ease); }
html.door[data-door="night"] .veil, html.door-vt .veil { opacity: 1; transition: opacity .42s var(--ease); }
.vt-stand { position: fixed; z-index: 5; pointer-events: none; display: block; }
/* back to a lit room without the back/forward cache (main.js, S8): the chapter's
   still at once, the 3D fading in over it; no strike from black */
html.returning .stage img.still { display: block; }
html.returning #gl { transition: none; }
html.returning.gl .stage img.still { opacity: 0; transition: opacity .6s ease-out .05s; }
html.returning .preglow { display: none; }
html.returning #chapters #room.card { opacity: 0; }
/* the flight between pages (S4): the bar stays, the instrument moves, the rest
   crossfades; off with reduced motion (no transition, an instant navigation) */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-group(*) { animation-duration: .55s; animation-timing-function: cubic-bezier(.2, .8, .2, 1); }
  ::view-transition-group(root) { animation-duration: .45s; }
}

/* ── the track: an empty, tall document (10.12 viewports, config TRACK_VIEWPORTS; js sets px) ── */
#journey { position: relative; z-index: 1; height: 1116vh; display: none; pointer-events: none; }
html.js #journey { display: block; }

/* ── copy cards ────────────────────────────────────────────────────── */
html.js #chapters .card {
  position: fixed; inset: 0; z-index: 10;
  opacity: 0; pointer-events: none;
}
html.js #chapters #room.card { opacity: 1; }              /* first paint, before the script */
html.js #chapters .card.live a,
html.js #chapters .card.live button { pointer-events: auto; }
.card .copy, .card .film-cap, .card .way, .card .end {
  text-shadow: 0 0 28px rgba(11,10,9,.7), 0 0 2px rgba(11,10,9,.45);
}
.card-still { display: none; }

h1, h2 { font-weight: 360; margin: 0; text-wrap: balance; }
h1 { font-size: clamp(42px, 5.6vw, 88px); line-height: 1.02; letter-spacing: -.045em; }
h2 { font-size: clamp(28px, 3vw, 46px); line-height: 1.08; letter-spacing: -.025em; }
.kicker {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 20px; font-size: 11px; color: var(--text-3);
}
.body { margin: 18px 0 0; max-width: 30em; font-size: 16px; line-height: 1.55; color: var(--text-2); }
.readout {
  display: block; margin: 22px 0 0; font-size: 11px; color: var(--on-dark);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.readout.words { color: var(--text-3); letter-spacing: .04em; }
.readout.words span { transition: color .12s linear, text-shadow .12s linear; }
.readout.words span.on { color: var(--light-2); text-shadow: 0 0 10px rgba(242,174,85,.55); }
.words + .readout { margin-top: 10px; }

.button {
  display: inline-flex; align-items: center; gap: 12px;
  min-height: 48px; margin-top: 28px; padding: 12px 20px 12px 17px; border-radius: 999px;
  font-size: 15px; font-weight: 500; color: var(--on-dark);
  background: rgba(236,230,220,.07);
  box-shadow: inset 0 0 0 1px rgba(236,230,220,.2);
  text-shadow: none;
  transition: background .3s var(--ease), box-shadow .3s var(--ease);
}
.button b { font-weight: 400; transition: transform .3s var(--ease); }
.button:hover { background: rgba(236,230,220,.11); box-shadow: inset 0 0 0 1px rgba(236,230,220,.34); }
.button:hover b { transform: translateX(3px); }

/* chapter 1: the room */
#room .copy { position: absolute; left: var(--gut); top: 25%; max-width: min(36em, 46vw); }
#room h1 { max-width: 9em; }
.lede { margin: 20px 0 0; max-width: 24em; font-size: clamp(17px, 1.45vw, 21px); line-height: 1.4; color: var(--text-2); }
.first-doors { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 0; font-size: 12px; }
.first-doors a {
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px;
  color: var(--on-dark); transition: color .3s var(--ease);
}
/* the workshop's door is quieter; the doors you can open today are equal */
.first-doors li.workshop a { color: var(--text-2); }
.first-doors a:hover { color: var(--light-3); }
.hint { display: inline-flex; align-items: center; gap: 12px; margin: 14px 0 0; font-size: 11px; color: var(--text-3); }
.hint i { font-style: normal; display: inline-block; animation: bob 2.82s var(--ease) infinite; }
@keyframes bob { 0%, 100% { transform: translateY(-1px); } 50% { transform: translateY(3px); } }

/* chapter 2: gate in the beam (gate sits right, the copy left) */
#gate .copy { position: absolute; left: var(--gut); top: 50%; transform: translateY(-50%); width: min(31vw, 440px); }

/* chapter 3: every step (over the macro close-ups the copy sits on its own patch of night:
   the blurred bone of gate's top edge crosses its lower lines; phones use their own scrim) */
#steps .copy { position: absolute; left: var(--gut); top: 20%; width: min(30vw, 420px); }
@media (min-aspect-ratio: 17/20) { #steps .copy::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: -18vw; right: -9vw; top: -14vh; bottom: -10vh;
  background: radial-gradient(closest-side, rgba(11,10,9,.84), rgba(11,10,9,.62) 55%, rgba(11,10,9,0));
} }

/* chapter 4: the floor */
#floor .copy { position: absolute; left: var(--gut); bottom: 11%; width: min(40vw, 560px); }

/* chapter 5: the films, one caption at a time in the lower third */
#films .film-cap { position: absolute; left: var(--gut); bottom: 12%; width: min(30vw, 400px); opacity: 0; }
#films .film-cap[data-side="right"] { left: auto; right: calc(var(--gut) + 40px); }
#films .film-cap h2 { font-size: clamp(26px, 2.6vw, 40px); }
.film-tap {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  display: inline-flex; align-items: center; gap: 10px; min-height: 44px; padding: 10px 16px;
  border: 0; border-radius: 999px; background: rgba(11,10,9,.6); font-size: 11px; cursor: pointer; white-space: nowrap;
}
.film-tap[hidden] { display: none; }

/* chapter 6: a recording */
#recording .copy { position: absolute; left: var(--gut); top: 19%; width: min(36vw, 520px); }
#ro-time { position: absolute; left: var(--gut); bottom: 18%; margin: 0; }
#ro-time.pinned { position: fixed; left: 0; top: 0; bottom: auto; opacity: var(--pin-o, 1); transition: opacity .2s linear; will-change: transform; }
/* a readout pinned beside the light sits on its own patch of night, so it reads over lit grains */
#ro-time {
  padding: 3px 9px; margin-left: -9px; border-radius: 999px;
  background: rgba(11,10,9,.78); box-shadow: 0 0 14px 6px rgba(11,10,9,.6);
  text-shadow: none;
}

/* chapter 7: the pads */
#pads .copy { position: absolute; left: var(--gut); top: 50%; transform: translateY(-50%); width: min(30vw, 420px); }

/* chapter 8: carve (carve sits left, the copy on the free side) */
#carve .copy { position: absolute; right: calc(var(--gut) + 40px); top: 50%; transform: translateY(-50%); width: min(30vw, 430px); }

/* chapter 9: two ways in */
#ways .column { position: absolute; left: var(--gut); top: 28%; display: grid; gap: 18px; }
#ways .way {
  display: grid; grid-template-columns: auto 1fr; align-items: center;
  column-gap: 12px; row-gap: 4px; min-height: 56px;
  padding: 10px 14px 10px 12px; border-radius: 14px;
  transition: background .3s var(--ease), opacity .2s linear;
}
#ways .way.pinned { position: fixed; left: 0; top: 0; opacity: var(--pin-o, 1); will-change: transform; white-space: nowrap; }
#ways .way:hover { background: rgba(236,230,220,.06); }
.way .led { grid-row: 1; }
.way-name { grid-row: 1; grid-column: 2; font-size: clamp(26px, 2.3vw, 34px); line-height: 1; letter-spacing: -.03em; font-weight: 380; }
.way-meta { grid-row: 2; grid-column: 2; font-size: 11px; color: var(--text-3); }
#ways .end {
  position: absolute; left: var(--gut); right: var(--gut); bottom: max(18px, env(safe-area-inset-bottom));
  display: grid; justify-items: center; gap: 6px;
}
/* the last lines sit on night whatever hangs above them */
#ways .end::before {
  content: ""; position: absolute; z-index: -1; left: 50%; bottom: -18px; width: min(1100px, 100vw); height: calc(100% + 90px);
  transform: translateX(-50%); pointer-events: none;
  background: radial-gradient(60% 75% at 50% 100%, rgba(11,10,9,.86), rgba(11,10,9,.55) 60%, rgba(11,10,9,0));
}
.doors { display: flex; gap: clamp(16px, 4vw, 56px); font-size: 12px; }
.doors a {
  display: inline-flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 18px;
  border-radius: 999px; box-shadow: inset 0 0 0 1px rgba(236,230,220,.16);
  transition: box-shadow .3s var(--ease), background .3s var(--ease);
}
.doors a:hover { background: rgba(236,230,220,.07); box-shadow: inset 0 0 0 1px rgba(236,230,220,.32); }
/* one line on wide screens (name, dot, state); name over state on tall ones */
.doors .door-text { white-space: nowrap; }
.doors a.workshop .door-state { color: var(--text-2); }
/* the doors come with the word (brief chapter 9: two equal doors under the word); in the
   column the labels beside the panels are the doors. Opacity only, so they stay focusable
   (a focused one shows); hidden doors take no pointer. */
html.js #ways .end { opacity: 0; transition: opacity .45s var(--ease); }
html.js[data-beat="word"] #ways .end, html.js[data-beat="doors"] #ways .end, html.js #ways .end:focus-within { opacity: 1; }
html.js:not([data-beat="word"]):not([data-beat="doors"]) #ways .end:not(:focus-within) a { pointer-events: none; }
/* the card's own column (the plain list) never shows over the word: until the finale is
   ready (a boot at the end card, a Back without the back/forward cache) the labels are not
   pinned yet and would sit over the word and the instruments; the end card has its four doors.
   Pinned labels keep their own --pin-o (09-ways.js). No fade: the first frame after Back is
   what the view transition shows. Review 2026-10-09. */
html.js[data-beat="word"] #ways .way:not(.pinned):not(:focus-visible),
html.js[data-beat="doors"] #ways .way:not(.pinned):not(:focus-visible) { opacity: 0; pointer-events: none; transition: none; }
.made { margin: 8px 0 0; font-size: 11px; color: var(--text-3); }
.foot { display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 22px; font-size: 11px; color: var(--text-3); }
.foot a, .foot .linkish { display: inline-flex; align-items: center; gap: 6px; min-height: 44px; transition: color .3s var(--ease); }
.foot a:hover, .foot .linkish:hover { color: var(--on-dark); }
/* the front page's "cookies" button (quiver.fm only) reads as one more footer link */
.foot .linkish { padding: 0; border: 0; background: none; font: inherit; letter-spacing: inherit; color: inherit; cursor: pointer; }
.foot i { font-style: normal; }

/* ── the cord: the scrollbar ───────────────────────────────────────── */
.cord {
  position: fixed; z-index: 25; right: 22px; width: 30px;
  top: 96px; bottom: 76px;
  display: none;
  transition: opacity .35s var(--ease), visibility 0s linear;
}
html.js .cord { display: block; }
.cord-rail { position: absolute; inset: 0; cursor: grab; touch-action: none; }
html.dragging .cord-rail { cursor: grabbing; }
.cord-line, .cord-lit { position: absolute; left: 50%; width: 1px; transform: translateX(-.5px); top: 0; }
.cord-line { bottom: 0; background: linear-gradient(to bottom, rgba(236,230,220,0), var(--hair) 8%, var(--hair) 94%, rgba(236,230,220,.06)); }
.cord-lit {
  height: calc(var(--pt) * 100%);
  background: linear-gradient(to bottom, rgba(242,174,85,0), rgba(242,174,85,.18) 40%, rgba(255,207,138,.62));
}
.cord-bead {
  position: absolute; left: 50%; top: calc(var(--pt) * 100%);
  width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px; border-radius: 50%;
  background: radial-gradient(circle at 40% 35%, var(--light-4), var(--light-3) 35%, var(--light) 72%);
  box-shadow: 0 0 0 1px rgba(194,124,26,.3), 0 0 calc(8px + 10px * var(--pulse)) calc(1px + 2px * var(--pulse)) rgba(242,174,85,calc(.3 + .4 * var(--pulse)));
  pointer-events: none;
}
.cord-ticks { list-style: none; margin: 0; padding: 0; position: absolute; inset: 0; pointer-events: none; }
.cord-ticks li { position: absolute; left: 0; right: 0; height: 0; }
/* each tick at its chapter's hold in page p (config.js CHAPTERS[].hold; ui.js layoutCord sets
   the same values), here too so the ticks are in place at first paint (no layout shift, acceptance 1) */
/* eleven since 2026-10-09: roll's beat sits between a recording and mangler's */
.cord-ticks li:nth-child(1) { top: 0%; }
.cord-ticks li:nth-child(2) { top: 8.268%; }
.cord-ticks li:nth-child(3) { top: 18.504%; }
.cord-ticks li:nth-child(4) { top: 23.307%; }
.cord-ticks li:nth-child(5) { top: 36.220%; }
.cord-ticks li:nth-child(6) { top: 47.087%; }
.cord-ticks li:nth-child(7) { top: 56.756%; }
.cord-ticks li:nth-child(8) { top: 65.748%; }
.cord-ticks li:nth-child(9) { top: 78.740%; }
.cord-ticks li:nth-child(10) { top: 88.976%; }
.cord-ticks li:nth-child(11) { top: 100%; }
.cord-ticks a {
  position: absolute; left: 50%; top: 0; width: 30px; height: 26px; margin: -13px 0 0 -15px;
  pointer-events: auto; display: block; cursor: pointer;
}
.cord-ticks a::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 7px; height: 1px; margin-left: -3.5px;
  background: rgba(236,230,220,.34);
}
.cord-ticks a.here::before { background: var(--light-2); }
.cord-ticks a span {
  position: absolute; right: 30px; top: 50%; transform: translate(6px, -50%);
  font-family: var(--mono); font-stretch: 100%; font-size: 10.5px; letter-spacing: .02em; white-space: nowrap;
  color: var(--text-3); opacity: 0; transition: opacity .35s var(--ease), transform .35s var(--ease);
  pointer-events: none;
}
.cord:hover .cord-ticks a span, .cord-ticks a:focus-visible span { opacity: 1; transform: translate(0, -50%); }
.cord-ticks a.here span { color: var(--on-dark); }
html.touch .cord { right: env(safe-area-inset-right, 0px); width: 44px; }
html.touch .cord-ticks a { width: 44px; height: 44px; margin: -22px 0 0 -22px; }
/* Keep the drawn ticks fixed while separating the two closest touch targets. */
@media (max-aspect-ratio: 17/20) {
  html.touch .cord-ticks li:nth-child(3) a { margin-top: -32px; }
  html.touch .cord-ticks li:nth-child(3) a::before, html.touch .cord-ticks li:nth-child(3) a span { top: calc(50% + 10px); }
  html.touch .cord-ticks li:nth-child(4) a { margin-top: -12px; }
  html.touch .cord-ticks li:nth-child(4) a::before, html.touch .cord-ticks li:nth-child(4) a span { top: calc(50% - 10px); }
}
html.touch .foot a, html.touch .foot .linkish { min-width: 44px; justify-content: center; }

/* ── sound ─────────────────────────────────────────────────────────── */
.sound {
  position: fixed; z-index: 25; left: var(--gut); bottom: max(14px, env(safe-area-inset-bottom));
  display: none; align-items: center; gap: 10px; min-height: 44px;
  padding: 0 4px 0 0; border: 0; background: none; cursor: pointer;
  font-size: 11px; color: var(--text-3);
  transition: color .3s var(--ease), opacity .4s var(--ease), visibility 0s linear;
}
html.js .sound { display: inline-flex; }
.sound:hover, .sound[aria-pressed="true"] { color: var(--on-dark); }
.sound .s-on { display: none; }
.sound[aria-pressed="true"] .s-on { display: inline; }
.sound[aria-pressed="true"] .s-off { display: none; }
.sound[aria-pressed="true"] .led {
  background: radial-gradient(circle at 40% 35%, var(--light-3), var(--light) 62%);
  box-shadow: 0 0 0 1px rgba(194,124,26,.25), 0 0 calc(5px + 6px * var(--pulse)) 1px rgba(242,174,85,calc(.3 + .4 * var(--pulse)));
}
.sound.busy { opacity: .6; }
.sound::before {
  content: ""; position: absolute; z-index: -1; inset: 0 -20px 0 -16px;
  border-radius: 999px; pointer-events: none;
  background: radial-gradient(closest-side, rgba(11,10,9,.86), rgba(11,10,9,.7) 60%, rgba(11,10,9,0));
}
/* the nav wordmark steps aside while the big word is on screen (chapter 9) */
.logo { transition: opacity .6s var(--ease); }
html[data-ch="ways"][data-beat="word"] .logo, html[data-ch="ways"][data-beat="doors"] .logo { opacity: 0; }

.hud {
  position: fixed; z-index: 90; left: 8px; top: 70px; margin: 0;
  font: 10px/1.5 var(--mono); color: var(--light-2); white-space: pre; pointer-events: none;
  text-shadow: 0 0 4px #000;
}

/* ── tall screens (phones, portrait tablets): aspect below 0.85 ────── */
@media (max-aspect-ratio: 17/20) {
  :root { --gut: 20px; }
  h1 { font-size: clamp(40px, 11.5vw, 64px); }
  h2 { font-size: clamp(26px, 7.4vw, 40px); }
  .body { font-size: 15px; margin-top: 12px; }
  .kicker { margin-bottom: 12px; font-size: 10.5px; }
  .readout { margin-top: 14px; }

  #room .copy { top: 21%; right: 56px; max-width: none; }
  .first-doors { gap: 0; }
  .first-doors a { min-height: 44px; }

  /* a solid night band under the copy where a lit panel sits above it */
  #gate .copy, #carve .copy, #pads .copy, #floor .copy {
    position: absolute; left: 0; right: 0; bottom: 0; top: auto; width: auto; transform: none;
    padding: 46px 56px calc(78px + env(safe-area-inset-bottom)) var(--gut);
    background: linear-gradient(to bottom, rgba(11,10,9,0), rgba(11,10,9,.94) 34px, var(--night) 60px);
    text-shadow: none;
  }
  #steps .copy, #recording .copy {
    left: var(--gut); right: 56px; top: 13%; width: auto;
    padding: 14px 16px 18px; margin-left: -16px; border-radius: 18px;
    background: radial-gradient(120% 140% at 30% 40%, rgba(11,10,9,.82), rgba(11,10,9,.55) 60%, rgba(11,10,9,0));
  }
  #steps .copy { background: radial-gradient(120% 140% at 30% 40%, rgba(11,10,9,.88), rgba(11,10,9,.66) 60%, rgba(11,10,9,0)); }
  #steps .kicker, .sound { color: rgba(236,230,220,.66); }
  #films .film-cap {
    left: 0; right: 0; bottom: 0; width: auto;
    padding: 40px 56px calc(78px + env(safe-area-inset-bottom)) var(--gut);
    background: linear-gradient(to bottom, rgba(11,10,9,0), rgba(11,10,9,.9) 32px, var(--night) 58px);
    text-shadow: none;
  }
  #films .film-cap[data-side="right"] { left: 0; right: 0; }
  #ro-time { left: var(--gut); bottom: 22%; }
  #ways .column { top: 18%; }
  #ways .end {
    left: 0; right: 0; bottom: 0; gap: 2px;
    padding: 40px var(--gut) max(10px, env(safe-area-inset-bottom));
    background: linear-gradient(to bottom, rgba(11,10,9,0), rgba(11,10,9,.94) 32px, var(--night) 58px);
    text-shadow: none;
  }
  #ways .end::before { display: none; }
  /* four doors two by two, name over state, so the stack never covers the instruments
     (2026-10-09: roll made four; four across overflows "in the workshop" at 390 px) */
  .doors { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; gap: 8px; }
  .doors a {
    display: grid; grid-template-columns: auto auto; justify-content: center; align-items: center;
    column-gap: 7px; row-gap: 3px; min-height: 56px; padding: 7px 6px; border-radius: 16px; text-align: center;
  }
  .doors .door-text { display: contents; }
  .doors .door-sep { display: none; }
  .doors a .led { grid-row: 1; grid-column: 1; }
  .doors .door-name { grid-row: 1; grid-column: 2; font-size: 12px; }
  .doors .door-state, .doors a.workshop .door-state { grid-row: 2; grid-column: 1 / span 2; font-size: 10px; color: var(--text-3); white-space: nowrap; }
  .foot { gap: 0 16px; }
  .cord { top: 84px; bottom: 96px; }
  .cord-ticks a span { display: none; }
  html[data-ch="ways"] .cord { opacity: 0; pointer-events: none; visibility: hidden; transition-delay: 0s, .35s; }
  /* the doors fill the bottom of a phone in the last chapter: the pill steps aside */
  html[data-ch="ways"] .sound:not([aria-pressed="true"]) { opacity: 0; pointer-events: none; visibility: hidden; transition-delay: 0s, 0s, .4s; }
  html[data-ch="ways"] .cord * { pointer-events: none !important; }
  .way-name { font-size: 26px; }
}
@media (max-aspect-ratio: 17/20) and (max-width: 380px) {
  .readout.words { letter-spacing: 0; font-size: 10.5px; }
}
/* Short tall screens (a phone with its browser bars showing: 390 x 664, 375 x 667, 360 x 640,
   390 x 750): with four doors the first frame's copy reached down to the bulb's socket, which
   sits higher on the screen there. The copy rides up as the screen gets shorter (never under
   the bar) and its gaps close a little, so the hint keeps 8 to 15 px over the socket (8 on a
   390 x 844 screen), in Chromium and WebKit. Screens 830 px tall and more are unchanged (2026-10-09, integration;
   tools/front-journey/test/first-frame-fit.mjs). */
@media (max-aspect-ratio: 17/20) and (max-height: 830px) {
  #room .copy { top: max(60px, min(21%, calc(62.6% - 336px))); }   /* the socket's top sits at 62.6 % */
  #room .lede { margin-top: 14px; }
  .first-doors { margin-top: 14px; }
  .hint { margin-top: 8px; }
}
@media (max-aspect-ratio: 17/20) and (min-aspect-ratio: 1/2) and (max-width: 480px) {
  html[data-ch="carve"] .nav li a { color: var(--on-dark); }
  html[data-ch="carve"] .stage img.still { object-fit: contain; }
}
/* Wide phones keep the wide scene, with copy in the clear band below the nav. */
@media (orientation: landscape) and (max-height: 500px) {
  h1 { font-size: clamp(30px, 8.4vh, 42px); }
  h2, #films .film-cap h2 { font-size: clamp(22px, 5.4vh, 30px); }
  .body { margin-top: 10px; font-size: 14px; line-height: 1.4; }
  .kicker { margin-bottom: 10px; font-size: 10px; }
  .readout { margin-top: 12px; font-size: 10px; }
  .button { margin-top: 14px; min-height: 44px; padding: 10px 16px; font-size: 13px; }
  #room .copy { top: 64px; }
  #room .lede { margin-top: 10px; font-size: 15px; }
  .first-doors { margin-top: 8px; }
  .hint { margin-top: 6px; }
  #gate .copy, #pads .copy, #carve .copy { top: 64px; transform: none; }
  #steps .copy, #recording .copy { top: 64px; }
  #steps .readout { display: inline-block; position: relative; padding: 3px 9px; margin-left: -9px; border-radius: 12px; background: rgba(11,10,9,.84); box-shadow: 0 0 10px 6px rgba(11,10,9,.7); }
  #floor .copy, #films .film-cap { bottom: 68px; }
  #floor .copy {
    padding: 10px 14px; margin-left: -14px; border-radius: 18px;
    background: radial-gradient(120% 140% at 30% 40%, rgba(11,10,9,.94), rgba(11,10,9,.82) 75%, rgba(11,10,9,0));
  }
  #ways .way-meta { display: none; }
  html[data-ch="ways"] .sound:not([aria-pressed="true"]) { opacity: 0; pointer-events: none; visibility: hidden; transition-delay: 0s, 0s, .4s; }
  /* four doors in one row from about 780 px; narrower, mangler's goes to a second row,
     kept low enough to clear the word's descender (2026-10-09: four across overflowed
     844 x 390 by 6 px, and three already overflowed 667 x 375) */
  .doors { flex-wrap: wrap; justify-content: center; gap: 4px 10px; }
  .doors a { padding: 0 13px; gap: 8px; min-height: 40px; }
  .made { margin-top: 2px; }
}

/* ── static: no JavaScript ─────────────────────────────────────────── */
html.no-js .stage { position: fixed; }
html.no-js #gl, html.no-js .veil, html.no-js .paper { display: none; }
html.no-js .preglow { opacity: .7; animation: none; top: 18%; }
html.no-js #chapters { position: relative; z-index: 2; padding: 112px var(--gut) 64px; }
html.no-js .card {
  position: relative; display: block; max-width: 1040px; margin: 0 auto;
  padding: 56px 0; border-top: 1px solid rgba(236,230,220,.08);
}
html.no-js #room.card { border-top: 0; padding-top: 18vh; }
html.no-js .card .copy, html.no-js .card .film-cap {
  position: static; transform: none; width: auto; max-width: 40em; opacity: 1;
  background: none; padding: 0;
}
html.no-js #films .film-cap + .film-cap { margin-top: 36px; }
html.no-js .card-still { display: block; margin-top: 30px; }
html.no-js .card-still img { display: block; width: 100%; height: auto; border-radius: 14px; background: #141210; }
html.no-js #ro-time { position: static; display: block; margin-top: 16px; }
html.no-js #ways .column { position: static; display: grid; gap: 10px; margin-bottom: 26px; }
html.no-js #ways .end { position: static; justify-items: start; background: none; padding: 0; }
html.no-js #ways .end::before { display: none; }
html.no-js #ro-time { background: none; box-shadow: none; padding: 0; margin-left: 0; }
html.no-js .hint, html.no-js .up, html.no-js .sound, html.no-js .cord, html.no-js .film-tap { display: none !important; }

/* ── stills: reduced motion, no WebGL, the last rung ───────────────── */
html.rm .hint i { animation: none; }
html.rm .preglow { animation: none; opacity: 1; }
html.rm #chapters .card { transition: opacity .45s ease; }
@media (prefers-reduced-motion: reduce) {
  .preglow, .hint i { animation: none !important; }
  .preglow { opacity: 1; }
  html { scroll-behavior: auto; }
}

/* ── posters.mjs: the canvas alone ─────────────────────────────────── */
html.poster .nav, html.poster #chapters, html.poster .cord, html.poster .sound,
html.poster .skip, html.poster .preglow, html.poster .veil, html.poster .hud { display: none !important; }
/* the canvas is at full strength in a poster, not part way through its 0.7 s fade-in */
html.poster #gl { transition: none !important; }

