/* ═══════════════════════════════════════════════════════════════════════════
   MANYFOLD — the scrollytelling landing page.

   Written mobile-first: every base rule targets ~360px, and min-width queries
   layer the desktop on top. Motion is native — `animation-timeline: view()`
   and `scroll()` run the scrubs on the compositor, so no scroll handler ever
   touches the main thread. Everything degrades: @supports gates the
   scroll-driven layer, and main.js's IntersectionObserver draws the same
   states on browsers without it.

   COLOR IS INFORMATION, not decoration. The palette encodes branch state:
     --spark    the one thread, before it forks
     --lantern  the path the reader TOOK
     --cyan     the paths they didn't
     --coral    branches further out in the dark
   Use them that way or not at all.

   Signature: `.spine` — a single thread in the page gutter that forks as you
   scroll, its lit path pinned to your exact scroll offset. See §SPINE.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── §TOKENS ─────────────────────────────────────────────────────────────── */

:root {
  /* surfaces — the deep, lit from above */
  --abyss: #06050f;
  --ink: #0b0a1a;
  --tide: #121130;
  --tide-2: #1a1840;
  --glass: rgba(28, 26, 64, 0.55);
  --line: rgba(160, 150, 255, 0.14);
  --line-lit: rgba(160, 150, 255, 0.3);

  /* branch state */
  --spark: #7c5cff;
  --spark-bright: #9b82ff;
  --lantern: #ffb259;
  --lantern-deep: #e2923a;
  --cyan: #34e0e0;
  --coral: #ff8a5c;

  /* text */
  --foam: #f4f3ff;
  --mist: #c9c6ec;
  --mute: #948fc0;

  --ok: #6fd39a;
  --err: #ff7d7d;

  /* type */
  --display: 'Fraunces', Georgia, 'Iowan Old Style', serif;
  --body: 'Inter', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, monospace;

  /* the display face's wonk: forking, off-axis letterforms. Restraint —
     only h1/h2 and the story voice get it. */
  --wonk: 'SOFT' 40, 'WONK' 1;

  --maxw: 40rem;
  --pad: 1.25rem;
  --gutter: 20px;   /* the spine lives here — inside --pad, costs no width */
  --radius: 14px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  background: var(--abyss);
  color: var(--foam);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  /* `clip`, NOT `hidden`. overflow:hidden turns body into a scroll container,
     which silently re-parents every descendant's view() timeline onto body
     instead of the viewport — every scrub on the page stops firing. `clip`
     stops the horizontal bleed without creating a scroller. */
  overflow-x: clip;
}

::selection { background: var(--lantern); color: var(--abyss); }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--lantern);
  outline-offset: 3px;
  border-radius: 4px;
}

img, svg, canvas { max-width: 100%; }

/* ── §SHELL ──────────────────────────────────────────────────────────────── */

.wrap {
  width: min(100% - 2 * var(--pad), var(--maxw));
  margin-inline: auto;
}

.band { padding-block: 4.5rem; position: relative; }

.eyebrow {
  font: 600 0.72rem/1 var(--body);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--spark-bright);
}

h1, h2 {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  line-height: 1.06;
  letter-spacing: -0.015em;
  font-weight: 700;
}

h1 { font-size: clamp(2.4rem, 10vw, 4.4rem); margin: 0.9rem 0 1.1rem; }
h1 em { font-style: italic; color: var(--lantern); }

h2 {
  font-size: clamp(1.75rem, 6.4vw, 2.6rem);
  line-height: 1.15;
  margin-bottom: 0.6rem;
}
h2 em { font-style: italic; color: var(--lantern); }

.band-lede {
  color: var(--mute);
  margin-bottom: 2.2rem;
  max-width: 34rem;
}

.lede { color: var(--mist); font-size: 1.1rem; max-width: 34rem; }

/* the word "Spark" always carries the thread colour */
.spark-word { color: var(--spark-bright); font-weight: 600; }

/* ── §SPINE — the signature ──────────────────────────────────────────────────
   One thread down the page gutter. It forks at each band; the lit (amber)
   path is pinned to scroll offset via the --page timeline, so the reader's
   scroll position IS their position in the story graph. `pathLength="1"` on
   the SVG normalises every path to a 0→1 length, which is what lets one
   keyframe drive strokes of wildly different real lengths. */

.spine {
  position: fixed;
  left: 0;
  top: 0;
  width: var(--gutter);
  height: 100vh;
  height: 100svh;
  z-index: 5;
  pointer-events: none;
  overflow: visible;
}
.spine svg { width: 100%; height: 100%; display: block; overflow: visible; }

.spine .rail { fill: none; stroke: var(--line); stroke-width: 1.5; }
.spine .fork-cyan { fill: none; stroke: var(--cyan); stroke-width: 1.2; opacity: 0.35; }
.spine .fork-coral { fill: none; stroke: var(--coral); stroke-width: 1.2; opacity: 0.3; }

.spine .lit {
  fill: none;
  stroke: var(--lantern);
  stroke-width: 2;
  stroke-linecap: round;
  /* pathLength="1" on the element normalises the whole path to length 1, so
     dashoffset 1 → 0 is exactly "undrawn → drawn" regardless of real length.
     Rests at 0 (drawn) so a no-JS, no-@supports browser gets a static thread
     rather than a missing one. */
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  filter: drop-shadow(0 0 4px rgba(255, 178, 89, 0.5));
}

/* No "you are here" marker: the leading edge of the amber line already is one.
   Adding a travelling dot on top of it was an accessory doing a job the line
   already did. */

/* ── §NAV ────────────────────────────────────────────────────────────────── */

.nav {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem var(--pad) 0.8rem calc(var(--pad) + 0.5rem);
  background: rgba(6, 5, 15, 0.82);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s ease, background 0.3s ease;
}
.nav.stuck { border-bottom-color: var(--line); }

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-size: 1.2rem;
  font-weight: 700;
  text-decoration: none;
}
.brand svg { display: block; flex: none; }

.nav-links { display: none; }

.nav .btn { padding: 0.5rem 1rem; font-size: 0.88rem; }

/* scroll progress hairline under the nav */
.nav-progress {
  position: absolute;
  left: 0;
  bottom: -1px;
  height: 2px;
  width: 100%;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: linear-gradient(90deg, var(--spark), var(--cyan) 60%, var(--lantern));
}

/* ── §BUTTONS ────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.5rem;
  border: 0;
  border-radius: 999px;
  font: 600 1rem var(--body);
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.btn-lantern { background: var(--lantern); color: #221302; }
.btn-lantern:hover { background: var(--lantern-deep); transform: translateY(-1px); }
.btn-ghost { background: transparent; color: var(--foam); border: 1px solid var(--line-lit); }
.btn-ghost:hover { border-color: var(--mute); }

/* ── §HERO ───────────────────────────────────────────────────────────────── */

.hero {
  position: relative;
  padding-block: 3.5rem 3rem;
  overflow: clip;   /* see the note on body — `hidden` would break view() here too */
}

/* the hero's right-hand column: desktop only, holds the scroll cue */
.hero-art { display: none; }

/* the constellation canvas sits behind the words, never over them */
.hero-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  /* atmosphere, not competition — it sits under the headline and the lede */
  opacity: 0.55;
}
.hero .wrap { position: relative; z-index: 1; }

.premise {
  margin-top: 1.6rem;
  padding-left: 1rem;
  border-left: 2px solid var(--spark);
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-style: italic;
  font-size: 1.05rem;
}
.premise small {
  display: block;
  margin-top: 0.3rem;
  font: 500 0.7rem var(--body);
  font-style: normal;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mute);
}

.play-note { margin-top: 1rem; font-size: 0.84rem; color: var(--mute); }

/* counters — these count the STORY, not users. See §STORY. */
.counts {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.8rem;
  margin-top: 2.2rem;
  padding-top: 1.6rem;
  border-top: 1px solid var(--line);
}
.count .num {
  font: 700 1.7rem/1 var(--display);
  font-variation-settings: var(--wonk);
  font-variant-numeric: tabular-nums;
  background: linear-gradient(120deg, var(--lantern), var(--coral) 70%, var(--spark-bright));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.count .label {
  margin-top: 0.3rem;
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mute);
  line-height: 1.3;
}

.scroll-hint {
  margin-top: 2rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mute);
}
.scroll-hint::after {
  content: '';
  width: 1px;
  height: 22px;
  background: linear-gradient(var(--mute), transparent);
  animation: drip 2s ease-in-out infinite;
}
@keyframes drip {
  0%, 100% { transform: scaleY(0.4); transform-origin: top; opacity: 0.4; }
  50% { transform: scaleY(1); transform-origin: top; opacity: 1; }
}

/* ── §MANIFESTO — one sentence, brightened word by word on scroll ─────────── */

.manifesto {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-size: clamp(1.5rem, 5.6vw, 2.3rem);
  line-height: 1.35;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.manifesto .w { color: #2b2853; transition: color 0.3s ease; }
.manifesto .w.lit { color: var(--foam); }
.manifesto .w.accent.lit { color: var(--lantern); }

/* ── §UNFOLD — scenes stack and hold, the way a story reveals itself ──────── */

.scenes { display: grid; gap: 1rem; }

.scene {
  position: sticky;
  top: 5rem;
  background: linear-gradient(160deg, var(--tide) 0%, #101736 60%, #16112e 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem 1.3rem;
  box-shadow: 0 18px 40px -20px rgba(0, 0, 0, 0.9);
}
.scene .scene-no {
  font: 600 0.68rem var(--mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--spark-bright);
}
.scene h3 {
  font: 700 1.25rem/1.2 var(--display);
  font-variation-settings: var(--wonk);
  margin: 0.5rem 0 0.4rem;
}
.scene p { color: var(--mist); font-size: 0.96rem; }

/* each scene sinks + dims as the next slides over it */
.scene-inner { transform-origin: 50% 0; }

/* ── §HOW — a true sequence, so the steps carry numbers ───────────────────── */

.steps { display: grid; gap: 1rem; position: relative; }

.step {
  position: relative;
  background: var(--tide);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.3rem 1.3rem 1.3rem 3.5rem;
  transition: border-color 0.4s ease;
}
.step.in { border-color: var(--line-lit); }
.step-no {
  position: absolute;
  left: 1.1rem;
  top: 1.35rem;
  font: 700 0.95rem var(--display);
  color: var(--lantern);
}
.step h3 { font: 700 1.05rem var(--body); margin-bottom: 0.35rem; }
.step p { color: var(--mute); font-size: 0.94rem; }

/* ── §SPARK — the console types its generation, then shows what it made ───── */

.console {
  background: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem;
  font: 0.8rem/1.75 var(--mono);
  overflow: hidden;
}
.console .prompt-line {
  color: var(--lantern);
  padding-bottom: 0.7rem;
  margin-bottom: 0.7rem;
  border-bottom: 1px solid var(--line);
  font-style: italic;
}
.console .out { color: var(--mute); min-height: 7.5rem; }
.console .out span { display: block; }
.console .out .done { color: var(--cyan); }
.console .caret {
  display: inline-block;
  width: 7px;
  height: 1em;
  background: var(--spark-bright);
  vertical-align: -2px;
  animation: blink 1.1s steps(2) infinite;
}
@keyframes blink { 50% { opacity: 0; } }

.beats {
  margin-top: 1.2rem;
  display: grid;
  gap: 0.4rem;
  list-style: none;
}
.beats li {
  display: flex;
  gap: 0.7rem;
  align-items: baseline;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--glass);
  font-size: 0.9rem;
}
.beats .n { font: 600 0.72rem var(--mono); color: var(--spark-bright); }

.art-card {
  margin-top: 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--tide);
}
.art-frame {
  aspect-ratio: 16 / 10;
  background:
    radial-gradient(120% 90% at 50% 105%, rgba(255, 178, 89, 0.5), transparent 60%),
    radial-gradient(90% 70% at 20% 10%, rgba(52, 224, 224, 0.22), transparent 60%),
    linear-gradient(180deg, #0d1030, #1b1440);
  display: grid;
  place-items: end center;
  padding: 1rem;
  position: relative;
}
/* the lighthouse beam, drawn in CSS — no image payload */
.art-frame::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 22%;
  width: 2px;
  height: 46%;
  background: linear-gradient(var(--mist), transparent);
  transform: translateX(-50%);
}
.art-frame::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 60%;
  width: 150%;
  height: 22%;
  background: conic-gradient(from 200deg at 50% 100%, transparent 0deg, rgba(255, 178, 89, 0.28) 18deg, transparent 36deg);
  transform: translateX(-50%);
  animation: sweep 9s linear infinite;
  transform-origin: 50% 100%;
}
@keyframes sweep {
  to { transform: translateX(-50%) rotate(360deg); }
}
.art-card .cap {
  padding: 0.8rem 1rem;
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mute);
  border-top: 1px solid var(--line);
}

/* ── §FEATURES ───────────────────────────────────────────────────────────── */

.features { display: grid; gap: 0.9rem; }

.feature {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.9rem;
  align-items: start;
  padding: 1.1rem;
  background: var(--tide);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color 0.25s ease, transform 0.25s ease;
}
.feature:hover { border-color: var(--line-lit); }
.feature .glyph {
  width: 2.2rem;
  height: 2.2rem;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: var(--tide-2);
  color: var(--lantern);
  font-size: 1.05rem;
  flex: none;
}
.feature h3 { font: 600 1rem var(--body); }
.feature p { color: var(--mute); font-size: 0.89rem; margin-top: 0.2rem; }

/* ── §TIMELINE — the branch map draws itself as you scroll past ───────────── */

/* The branch map is drawn as a CONSTELLATION, not a flowchart — it's the same
   night sky as the hero, so the page reads as one world. Two rules keep it
   there: no card chrome (a border would make it a diagram widget sitting on
   the page instead of a place inside it), and the svg is width-capped so a
   wide column can't inflate its strokes into org-chart tubes. */
.map {
  position: relative;
  padding-block: 1.5rem;
}
/* Bleeds vertically only. A horizontal bleed (inset: 0 -25%) pushed 88px past
   each edge and scrolled the page sideways on a phone — and `overflow-x: clip`
   on body does NOT catch it, because body's overflow propagates up to the
   viewport, leaving body itself computed as visible. Nothing may extend past
   the inline edges here. */
.map::before {
  content: '';
  position: absolute;
  inset: -4% 0;
  background: radial-gradient(85% 55% at 50% 42%, rgba(124, 92, 255, 0.14), transparent 72%);
  pointer-events: none;
}
.map svg {
  position: relative;
  width: min(100%, 26rem);
  height: auto;
  margin-inline: auto;
  display: block;
}

.map .star { fill: var(--foam); opacity: 0.22; }

/* Drawn by default (see §MOTION PRIMITIVES) — @supports re-hides and scrubs it.
   The map is a diagram: if it can't animate, it must still be a map. */
.map .branch {
  fill: none;
  stroke-width: 1.3;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  stroke-linecap: round;
}
.map .b-trunk { stroke: var(--spark); opacity: 0.9; }
.map .b-cyan { stroke: var(--cyan); opacity: 0.42; }
.map .b-coral { stroke: var(--coral); opacity: 0.38; }
.map .b-lit {
  stroke: var(--lantern);
  stroke-width: 1.9;
  filter: drop-shadow(0 0 4px rgba(255, 178, 89, 0.75));
}

.map .node {
  fill: var(--abyss);
  stroke: var(--spark-bright);
  stroke-width: 1.1;
  filter: drop-shadow(0 0 4px rgba(124, 92, 255, 0.7));
}
/* two edges in, not one — the branch that came back */
.map .node-rejoin { stroke: var(--cyan); filter: drop-shadow(0 0 5px rgba(52, 224, 224, 0.85)); }
.map .node-end { fill: var(--coral); stroke: none; filter: drop-shadow(0 0 5px rgba(255, 138, 92, 0.8)); }
.map .node-lit { fill: var(--lantern); stroke: none; filter: drop-shadow(0 0 7px rgba(255, 178, 89, 0.95)); }
.map .node-secret { fill: var(--cyan); stroke: none; filter: drop-shadow(0 0 7px rgba(52, 224, 224, 0.95)); }

.map text {
  font: 500 8px var(--mono);
  fill: var(--mute);
  letter-spacing: 0.14em;
}

/* reads as a caption under the sky, not a chart legend bolted to a widget */
.map-key {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem 1.2rem;
  margin-top: 1.4rem;
  font: 500 0.72rem var(--mono);
  letter-spacing: 0.03em;
  color: var(--mute);
}
.map-key span { display: inline-flex; align-items: center; gap: 0.45rem; }
.map-key i {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 6px currentColor;
}
.k-lit { color: var(--lantern); }
.k-cyan { color: var(--cyan); }
.k-coral { color: var(--coral); }

.map-notes { display: grid; gap: 0.9rem; margin-top: 1.6rem; }
.map-note h4 { font: 600 0.98rem var(--body); margin-bottom: 0.2rem; }
.map-note p { color: var(--mute); font-size: 0.9rem; }
.canvas-intro .band-lede { margin-bottom: 0; }

/* ── §READER — the phone, tilted by your scroll ───────────────────────────── */

.reader-grid { display: grid; gap: 2rem; }

.phone-stage { perspective: 1200px; display: grid; place-items: center; }
.phone {
  width: min(100%, 17rem);
  aspect-ratio: 9 / 18;
  border-radius: 30px;
  border: 1px solid var(--line-lit);
  background: linear-gradient(170deg, #14123a, var(--abyss));
  padding: 1.1rem 1rem;
  display: flex;
  flex-direction: column;
  box-shadow: 0 40px 70px -30px rgba(0, 0, 0, 1), inset 0 1px 0 rgba(255, 255, 255, 0.06);
  transform-style: preserve-3d;
}
.phone .bar {
  width: 34%;
  height: 4px;
  border-radius: 999px;
  background: var(--line-lit);
  margin: 0 auto 1rem;
  flex: none;
}
.phone .page {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-size: 0.86rem;
  line-height: 1.6;
  color: var(--mist);
  flex: 1;
}
.phone .choices { display: grid; gap: 0.5rem; margin-top: auto; }

.choice {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.8rem;
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(6, 5, 15, 0.6);
  font-size: 0.8rem;
  position: relative;
  overflow: hidden;
}
/* the live weight of each choice, drawn as a fill behind the label. Starts
   empty and fills to --pct once the card is actually on screen — the number
   landing at the same moment you read it is the whole effect. */
.choice .fill {
  position: absolute;
  inset: 0;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: rgba(255, 178, 89, 0.14);
  transition: transform 1.2s cubic-bezier(0.22, 1, 0.36, 1);
}
.choice.filled .fill { transform: scaleX(var(--pct, 0)); }
.choice span { position: relative; }
.choice .pct { color: var(--mute); font-variant-numeric: tabular-nums; font-family: var(--mono); font-size: 0.72rem; }
.choice.hot { border-color: var(--lantern); }
.choice.hot .pct { color: var(--lantern); }

.ticks { list-style: none; display: grid; gap: 0.6rem; margin-top: 1.4rem; }
.ticks li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.7rem;
  color: var(--mist);
  font-size: 0.94rem;
}
.ticks li::before { content: '◆'; color: var(--spark-bright); font-size: 0.7rem; line-height: 1.9; }

/* ── §IMMERSIVE — a pinned stage; backdrops cross-fade as you scroll ──────── */

.cinema { position: relative; }
.cinema-stage {
  position: sticky;
  top: 4.5rem;
  height: 78svh;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  display: grid;
}
.backdrop {
  grid-area: 1 / 1;
  position: relative;   /* the ::before/::after scenery anchors to this */
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.8s ease, transform 0.8s ease;
  transform: scale(1.06);
}
.backdrop.on { opacity: 1; transform: none; }

/* Three painted scenes, all CSS — no image payload on a phone. Each one is
   built from a horizon, a light source, and a texture, so the stage reads as
   a place instead of a dark rectangle. */

/* 1 — the lamp answers: night sea, a lighthouse throwing its beam.
   All the scenery lives in the top ~56% — below that is the sea, and below
   THAT is where .cinema-copy lays its scrim over the words. Anything drawn
   under 60% is just decorating the back of a text panel. */
.bd-1 {
  background:
    radial-gradient(1.5px 1.5px at 22% 14%, rgba(255, 255, 255, 0.85), transparent),
    radial-gradient(1.5px 1.5px at 68% 9%, rgba(255, 255, 255, 0.6), transparent),
    radial-gradient(1.5px 1.5px at 84% 22%, rgba(255, 255, 255, 0.5), transparent),
    radial-gradient(1.5px 1.5px at 40% 6%, rgba(255, 255, 255, 0.7), transparent),
    radial-gradient(1.5px 1.5px at 12% 32%, rgba(255, 255, 255, 0.45), transparent),
    radial-gradient(1.5px 1.5px at 91% 40%, rgba(255, 255, 255, 0.4), transparent),
    radial-gradient(2px 2px at 57% 18%, rgba(255, 255, 255, 0.75), transparent),
    /* the lamp's halo, sitting exactly on top of the tower */
    radial-gradient(70px 70px at 50% 30%, rgba(255, 205, 140, 0.5), transparent 70%),
    /* the sea catching it */
    radial-gradient(80% 30% at 50% 62%, rgba(255, 178, 89, 0.28), transparent 70%),
    linear-gradient(180deg, #05081c 0%, #0a1030 50%, #1b2450 56%, #0a1130 58%, #05091d 100%);
}
/* the beam — sweeps back and forth rather than a full rotation, so it's
   actually on screen most of the time */
.bd-1::before {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 70%;
  width: 260%;
  height: 46%;
  transform: translateX(-50%) rotate(-40deg);
  transform-origin: 50% 100%;
  background: conic-gradient(
    from -9deg at 50% 100%,
    rgba(255, 210, 150, 0.34) 0deg,
    rgba(255, 180, 90, 0.1) 11deg,
    transparent 19deg
  );
  filter: blur(5px);
  animation: beam-sweep 9s ease-in-out infinite alternate;
}
/* the tower, standing on the horizon */
.bd-1::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 44%;
  width: 16px;
  height: 26%;
  transform: translateX(-50%);
  background: linear-gradient(180deg, rgba(255, 205, 140, 0.95) 0 12%, #10152e 12%);
  clip-path: polygon(30% 0, 70% 0, 86% 100%, 14% 100%);
}
@keyframes beam-sweep {
  to { transform: translateX(-50%) rotate(40deg); }
}

/* 2 — the door beneath: underwater, cold light through a warm doorway */
.bd-2 {
  background:
    radial-gradient(60% 42% at 50% 50%, rgba(255, 200, 130, 0.5), transparent 70%),
    radial-gradient(120% 70% at 50% 0%, rgba(52, 224, 224, 0.3), transparent 62%),
    linear-gradient(180deg, #04121f 0%, #062033 60%, #02090f 100%);
}
/* caustics drifting over the water */
.bd-2::before {
  content: '';
  position: absolute;
  inset: -20%;
  background:
    repeating-linear-gradient(72deg, transparent 0 22px, rgba(52, 224, 224, 0.07) 22px 26px),
    repeating-linear-gradient(-58deg, transparent 0 30px, rgba(52, 224, 224, 0.05) 30px 34px);
  animation: drift 14s ease-in-out infinite alternate;
}
/* the door itself */
.bd-2::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 22%;
  height: 30%;
  transform: translate(-50%, -50%);
  border-radius: 40% 40% 3px 3px;
  background: linear-gradient(180deg, rgba(255, 210, 150, 0.85), rgba(255, 160, 70, 0.25));
  box-shadow: 0 0 50px 14px rgba(255, 190, 110, 0.35);
}

/* 3 — a sky that has never heard of her stars */
.bd-3 {
  background:
    radial-gradient(2px 2px at 30% 22%, rgba(255, 255, 255, 0.9), transparent),
    radial-gradient(2px 2px at 74% 14%, rgba(200, 255, 255, 0.8), transparent),
    radial-gradient(1.5px 1.5px at 56% 30%, rgba(255, 220, 255, 0.7), transparent),
    radial-gradient(70% 45% at 26% 24%, rgba(255, 138, 92, 0.5), transparent 66%),
    radial-gradient(60% 40% at 82% 30%, rgba(124, 92, 255, 0.55), transparent 64%),
    linear-gradient(180deg, #180b28 0%, #2a1240 46%, #3a1a4a 58%, #120820 100%);
}
/* the shore, and someone waiting on it */
.bd-3::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 34%;
  background:
    radial-gradient(3px 8px at 62% 12%, rgba(10, 4, 18, 0.95), transparent 70%),
    linear-gradient(180deg, rgba(255, 178, 89, 0.18), rgba(6, 5, 15, 0.9) 60%);
}

@keyframes drift {
  to { transform: translate3d(6%, -4%, 0) rotate(2deg); }
}
.cinema-copy {
  grid-area: 1 / 1;
  align-self: end;
  padding: 1.4rem;
  background: linear-gradient(transparent, rgba(6, 5, 15, 0.9) 55%);
  z-index: 2;
}
.cinema-line {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-style: italic;
  font-size: clamp(1rem, 4.4vw, 1.35rem);
  line-height: 1.5;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.6s ease, transform 0.6s ease;
  grid-area: 1 / 1;
}
.cinema-line.on { opacity: 1; transform: none; }
.cinema-lines { display: grid; margin-bottom: 1rem; }
.cinema-badge {
  display: inline-flex;
  gap: 0.5rem;
  align-items: center;
  font: 600 0.66rem var(--mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--lantern);
  margin-bottom: 0.7rem;
}
.cinema-badge::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--lantern);
  box-shadow: 0 0 0 0 rgba(255, 178, 89, 0.6);
  animation: pulse 2.4s ease-out infinite;
}
@keyframes pulse {
  70% { box-shadow: 0 0 0 9px rgba(255, 178, 89, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 178, 89, 0); }
}
.cinema-choices { display: grid; gap: 0.5rem; }
/* the tall scroll track that drives the pinned stage */
.cinema-track { height: 240svh; }

/* ── §SOCIAL — the feed card turns as it enters ───────────────────────────── */

.feed-stage { perspective: 1000px; }
.feed-card {
  background: var(--tide);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.2rem;
  transform-style: preserve-3d;
}
.feed-head { display: flex; align-items: center; gap: 0.7rem; }
.avatar {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--spark), var(--cyan));
  display: grid;
  place-items: center;
  font: 700 0.85rem var(--body);
  color: var(--abyss);
  flex: none;
}
.feed-head .who { font-weight: 600; font-size: 0.92rem; }
.feed-head .meta { color: var(--mute); font-size: 0.76rem; }
.feed-head .btn { margin-left: auto; }
.feed-body {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.feed-title {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-size: 1.15rem;
  font-weight: 700;
}
.feed-quote {
  margin-top: 0.5rem;
  color: var(--mist);
  font-family: var(--display);
  font-style: italic;
  font-size: 0.98rem;
}
.feed-foot {
  margin-top: 1rem;
  display: flex;
  gap: 1.1rem;
  font-size: 0.78rem;
  color: var(--mute);
  font-family: var(--mono);
}

/* ── §STORY — what we built to test it. Real structure, no invented users ─── */

.story-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: linear-gradient(165deg, var(--tide), var(--ink));
  padding: 1.5rem 1.3rem;
}
.story-panel .title {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-style: italic;
  font-size: 1.35rem;
  color: var(--lantern);
}
.story-panel .by {
  font: 500 0.72rem var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mute);
  margin-top: 0.3rem;
}
.story-panel .excerpt {
  margin-top: 1.1rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
  font-family: var(--display);
  font-style: italic;
  color: var(--mist);
  font-size: 0.98rem;
}
.story-stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.7rem;
  margin-top: 1.3rem;
}
.story-stat {
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.8rem;
  background: var(--glass);
}
.story-stat .v {
  font: 700 1.25rem/1 var(--display);
  font-variation-settings: var(--wonk);
  font-variant-numeric: tabular-nums;
  color: var(--lantern);
}
.story-stat .k {
  font-size: 0.7rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mute);
  margin-top: 0.3rem;
}

/* ── §PRICING ────────────────────────────────────────────────────────────── */

.tiers { display: grid; gap: 1rem; }

.tier {
  position: relative;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--tide);
  padding: 1.5rem 1.3rem;
  display: flex;
  flex-direction: column;
}
.tier.featured { border-color: var(--lantern); }
.tier-flag {
  position: absolute;
  top: -0.65rem;
  left: 1.3rem;
  background: var(--lantern);
  color: #221302;
  font: 700 0.64rem var(--mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
}
.tier .name {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-size: 1.2rem;
  font-weight: 700;
}
.tier .price {
  font: 700 2.2rem/1 var(--display);
  font-variation-settings: var(--wonk);
  margin: 0.6rem 0 0.2rem;
}
.tier .price small { font: 500 0.8rem var(--body); color: var(--mute); }
.tier .who { color: var(--mute); font-size: 0.88rem; margin-bottom: 1.1rem; }
.tier ul { list-style: none; display: grid; gap: 0.5rem; margin-bottom: 1.4rem; }
.tier li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.6rem;
  font-size: 0.9rem;
  color: var(--mist);
}
.tier li::before { content: '✓'; color: var(--cyan); font-size: 0.8rem; line-height: 1.8; }
.tier .btn { margin-top: auto; width: 100%; }

.pricing-note {
  margin-top: 1.2rem;
  font-size: 0.8rem;
  color: var(--mute);
  text-align: center;
}

/* ── §BETA FORM ──────────────────────────────────────────────────────────── */

.beta-form { display: grid; gap: 0.7rem; margin-top: 1.6rem; }
.beta-form input[type='email'] {
  width: 100%;
  padding: 0.85rem 1.1rem;
  border-radius: 999px;
  border: 1px solid var(--line-lit);
  background: var(--tide);
  color: var(--foam);
  font: 1rem var(--body);
}
.beta-form input[type='email']::placeholder { color: var(--mute); }
.beta-form input[type='email']:focus {
  outline: 2px solid var(--lantern);
  border-color: transparent;
}
.msg { font-size: 0.9rem; color: var(--mute); min-height: 1.4em; }
.msg.ok { color: var(--ok); }
.msg.err { color: var(--err); }

/* ── §FOOTER ─────────────────────────────────────────────────────────────── */

.footer {
  border-top: 1px solid var(--line);
  padding: 2.5rem var(--pad) 3rem;
  color: var(--mute);
  font-size: 0.85rem;
}
.footer .wrap { display: grid; gap: 1.6rem; }
.footer .brand { color: var(--foam); }
.footer .blurb { margin-top: 0.6rem; max-width: 22rem; }
.foot-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1.4rem; }
.foot-cols h5 {
  font: 600 0.7rem var(--mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--foam);
  margin-bottom: 0.6rem;
}
.foot-cols ul { list-style: none; display: grid; gap: 0.4rem; }
.foot-cols a { text-decoration: none; }
.foot-cols a:hover { color: var(--foam); }
.foot-base {
  border-top: 1px solid var(--line);
  padding-top: 1.4rem;
  display: grid;
  gap: 0.4rem;
  font-size: 0.78rem;
}

/* ── §SHARE PAGE ─────────────────────────────────────────────────────────── */

.share-main {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 2rem var(--pad);
}
.share-card {
  width: min(100%, 26rem);
  text-align: center;
  background: var(--tide);
  border: 1px solid var(--line);
  border-radius: calc(var(--radius) + 6px);
  padding: 2.2rem 1.6rem;
}
.share-card .brand { justify-content: center; font-size: 1.35rem; }
.share-card h1 { font-size: clamp(1.5rem, 7vw, 2rem); margin: 1.2rem 0 0.4rem; }
.share-card .story-title {
  font-family: var(--display);
  font-variation-settings: var(--wonk);
  font-style: italic;
  color: var(--lantern);
  font-size: 1.15rem;
  margin-bottom: 0.6rem;
}
.share-card p { color: var(--mute); font-size: 0.95rem; }
.share-card .btn { width: 100%; margin-top: 1.4rem; }
.share-card .beta-form { text-align: left; }

/* ── §MOTION PRIMITIVES ──────────────────────────────────────────────────────
   BASE STATE IS VISIBLE, and that is deliberate. Reveals are a progressive
   enhancement layered on in @supports below — a browser that can't scrub them
   simply gets the finished page. Nothing about *reading* this site may depend
   on a script running: if main.js 404s or is blocked, every word is still
   there. (An earlier cut started these at opacity:0 and waited for JS to add
   a class — one failed request from a blank page.) */

.reveal { opacity: 1; transform: none; }

/* ── §SCROLL-DRIVEN LAYER ────────────────────────────────────────────────────
   The real thing. Every animation here runs off a view() or scroll() timeline,
   which the compositor evaluates — no scroll listener, no jank, and it stays
   perfectly locked to the finger on a touch screen (where JS scroll handlers
   famously lag behind during momentum scrolling). */

@supports (animation-timeline: view()) {
  /* reveals become scrubbed entrances */
  .reveal {
    animation: enter linear both;
    animation-timeline: view();
    animation-range: entry 5% cover 32%;
  }
  @keyframes enter {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: none; }
  }

  /* The spine: lit path pinned to page scroll. `scroll(root block)` is the
     anonymous root-scroller timeline — a named timeline would have to resolve
     through .spine's ancestors, and .spine is position:fixed. This just works. */
  .spine .lit {
    animation: draw linear both;
    animation-timeline: scroll(root block);
  }
  /* explicit `from` — the resting state is now 0 (drawn), so a bare `to: 0`
     would animate nothing */
  @keyframes draw {
    from { stroke-dashoffset: 1; }
    to { stroke-dashoffset: 0; }
  }

  /* nav progress hairline — same timeline, so it and the spine always agree */
  .nav-progress {
    animation: grow linear both;
    animation-timeline: scroll(root block);
  }
  @keyframes grow { to { transform: scaleX(1); } }

  /* hero exits with parallax — words drift up and dim as you leave */
  .hero .wrap {
    animation: hero-exit linear both;
    animation-timeline: view(block);
    animation-range: exit 0% exit 100%;
  }
  @keyframes hero-exit {
    to { opacity: 0; transform: translateY(-40px); }
  }

  /* unfold: each scene sinks + dims under the next */
  .scene-inner {
    animation: sink linear both;
    animation-timeline: view(block);
    animation-range: exit 0% exit 100%;
  }
  @keyframes sink {
    to { transform: scale(0.9) translateY(-14px); opacity: 0.25; }
  }

  /* timeline map: branches draw across the section's pass */
  .map .branch {
    animation: draw linear both;
    animation-timeline: view(block);
    animation-range: entry 30% cover 60%;
  }
  .map .b-lit { animation-range: entry 55% cover 85%; }

  /* the phone tilts through your scroll — a real 3D turn, not a hover trick */
  .phone {
    animation: tilt linear both;
    animation-timeline: view(block);
    animation-range: entry 10% exit 90%;
  }
  @keyframes tilt {
    from { transform: rotateY(16deg) rotateX(9deg) translateY(24px); }
    50% { transform: rotateY(0deg) rotateX(0deg) translateY(0); }
    to { transform: rotateY(-16deg) rotateX(-7deg) translateY(-24px); }
  }

  /* social feed card turns in on scrub */
  .feed-card {
    animation: turn linear both;
    animation-timeline: view(block);
    animation-range: entry 5% cover 45%;
  }
  @keyframes turn {
    from { transform: rotateX(26deg) translateY(30px); opacity: 0; }
    to { transform: none; opacity: 1; }
  }

  /* feature cards rise in sequence off their own view timelines */
  .feature {
    animation: rise linear both;
    animation-timeline: view(block);
    animation-range: entry 0% cover 30%;
  }
  @keyframes rise {
    from { opacity: 0; transform: translateY(22px) scale(0.98); }
    to { opacity: 1; transform: none; }
  }
}

/* ── §REDUCED MOTION — everything resolves to its finished state ──────────── */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
  }
  .reveal { opacity: 1; transform: none; }
  .spine .lit, .map .branch { stroke-dashoffset: 0; }
  .choice .fill { transform: scaleX(var(--pct, 0)); }
  .backdrop.on, .cinema-line.on { opacity: 1; transform: none; }
  .backdrop { transform: none; }
  .scene { position: static; }
  .cinema-stage { position: static; height: auto; min-height: 60svh; }
  .cinema-track { height: auto; }
  .nav-progress { display: none; }
  .phone { transform: none; }
}

/* ── §≥ 700px — two-column rhythm ────────────────────────────────────────── */

@media (min-width: 700px) {
  :root { --maxw: 62rem; --pad: 2.5rem; --gutter: 34px; }

  .nav { padding-inline: 2.5rem; }
  .nav-links { display: flex; gap: 1.6rem; font-size: 0.9rem; }
  .nav-links a { text-decoration: none; color: var(--mute); }
  .nav-links a:hover { color: var(--foam); }

  .band { padding-block: 7rem; }
  .hero { padding-block: 5rem 4rem; }

  .beta-form { grid-template-columns: 1fr auto; align-items: center; max-width: 30rem; }
  .beta-form .msg { grid-column: 1 / -1; }

  .counts { gap: 1.5rem; }
  .count .num { font-size: 2.3rem; }

  .steps { grid-template-columns: 1fr 1fr; }
  .features { grid-template-columns: repeat(2, 1fr); }
  .tiers { grid-template-columns: repeat(3, 1fr); }
  .map-notes { grid-template-columns: repeat(3, 1fr); }
  .story-stats { grid-template-columns: repeat(4, 1fr); }

  .reader-grid { grid-template-columns: 0.9fr 1.1fr; align-items: center; gap: 3rem; }
  .scene { top: 6rem; padding: 2rem 1.8rem; }
  .console { padding: 1.5rem; font-size: 0.85rem; }
  .cinema-stage { top: 5.5rem; height: 74svh; }
  .cinema-copy { padding: 2rem; }

  .foot-cols { grid-template-columns: repeat(4, 1fr); }
  .footer .wrap { grid-template-columns: 1.2fr 2fr; gap: 3rem; }
  .foot-base { grid-column: 1 / -1; display: flex; justify-content: space-between; }
}

/* ── §≥ 1100px — the hero splits, the spine gets room to fork ─────────────── */

@media (min-width: 1100px) {
  :root { --maxw: 68rem; --gutter: 46px; }

  /* #timeline: copy + notes stack down the left, the constellation takes the
     right. Source order stays mobile-correct (copy → map → notes); the grid
     just re-seats them. */
  .canvas-grid {
    display: grid;
    grid-template-columns: 1fr 26rem;
    /* `auto 1fr`, not `auto auto`: the map spans both rows and is taller than
       the copy, so any slack must land in row 2 — otherwise row 1 inflates and
       tears a gap between the lede and the notes. */
    grid-template-rows: auto 1fr;
    column-gap: 4rem;
    align-items: start;
  }
  .canvas-intro { grid-column: 1; grid-row: 1; }
  .canvas-grid .map { grid-column: 2; grid-row: 1 / span 2; margin-top: 0; }
  .canvas-grid .map-notes { grid-column: 1; grid-row: 2; grid-template-columns: 1fr; margin-top: 2rem; }

  .hero { padding-block: 6.5rem 5rem; }
  .hero .wrap { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 3.5rem; align-items: center; }
  /* the second column is mostly negative space on purpose — it's the window
     the constellation is seen through. The cue just anchors the eye. */
  .hero-art { display: grid; place-items: center; align-self: stretch; }
  .features { grid-template-columns: repeat(3, 1fr); }
  .spark-grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 2rem; align-items: start; }
  .spark-grid .beats { margin-top: 0; }
}

/* ── §HOVER-CAPABLE ONLY — pointer sheen, never on touch ──────────────────── */

@media (hover: hover) and (pointer: fine) {
  .feature::after {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(
      18rem circle at var(--mx, 50%) var(--my, 50%),
      rgba(124, 92, 255, 0.16),
      transparent 45%
    );
    opacity: 0;
    transition: opacity 0.3s ease;
    pointer-events: none;
  }
  .feature:hover::after { opacity: 1; }
  .feature:hover { transform: translateY(-3px); }
}
