/* ============================================================
   davidts.ai — STOIC
   One continuous photo world. In focus at the top; as you
   descend it pulls out of focus and the story takes the center,
   naked on the canvas. Inter Tight, hairline structure, one
   sunrise thread. No panes, no cards — just the image, the type,
   and the line.
   ============================================================ */

:root {
  --bg: #060607;
  --fg: #f5f5f7;
  --mut: rgba(245, 245, 247, .58);
  --fnt: rgba(245, 245, 247, .3);
  --line: rgba(245, 245, 247, .14);
  /* SUNRISE. Amber orange, pitched between the yellow of a sun core
     and the orange below it — the same light as the podcast hero.
     --acc is the single accent every page resolves through; --acc-hi
     and --acc-lo are its ends, for the few places that carry a
     gradient rather than a flat colour. */
  --acc: #ff9d4a;
  --acc-hi: #ffd07a;
  --acc-lo: #ff7833;
  --ease: cubic-bezier(.16, 1, .3, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }

body {
  background: var(--bg);
  color: var(--fg);
  font-family: 'Inter Tight', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
::selection { background: rgba(255, 157, 74, .3); }

/* ---------- the world (fixed photo, JS-driven defocus) ---------- */

.world {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: clip;
}
.world img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Which part of the photo survives the crop. cover throws away the
     overflow on the long axis, and the axis flips between desktop and
     mobile — a landscape frame loses its left and right thirds at 375,
     and a portrait frame loses its top and bottom at 1280. So a photo
     with something specific in it (a face, a sign) needs the anchor
     set per page and per breakpoint, not left at centre. Default is
     centre, which is what every current page wants. */
  object-position: var(--wpos, 50% 50%);
  transform: scale(var(--wscale, 1.06));
  /* --wbright is driven per-frame by the focus pull; --wbase is the
     page's own floor, set once, for worlds that are bright enough to
     fight white type on their own. They multiply, so a page can be
     held back without losing the defocus. */
  filter: blur(var(--wblur, 0px)) brightness(calc(var(--wbase, 1) * var(--wbright, 1))) saturate(var(--wsat, 1));
  will-change: filter, transform;
  transition: transform 2.4s var(--ease);
}
.world-tint {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 90% at 50% 110%, rgba(6, 6, 7, calc(.66 * var(--wp, 0))), transparent 60%),
    linear-gradient(to bottom, transparent 30%, rgba(6, 6, 7, calc(.5 * var(--wp, 0))));
  pointer-events: none;
}
/* entrance: gentle settle from a slightly wider crop */
body:not(.loaded) .world img { transform: scale(1.12); }

main { position: relative; z-index: 2; }

/* ---------- the reading line ---------- */

.progressline {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 2px;
  z-index: 95;
  background: linear-gradient(90deg, var(--acc-hi), var(--acc) 46%, rgba(255, 120, 51, .4));
  transform: scaleX(0);
  transform-origin: left;
  will-change: transform;
  pointer-events: none;
}

/* ---------- filmic grain ---------- */

.grain {
  position: fixed;
  inset: 0;
  z-index: 80;
  pointer-events: none;
  /* NOT soft-light. Measured 2026-08-26: a full-viewport fixed layer
     with a blend mode makes the compositor re-read the backdrop every
     frame, and on the home page that alone cost 12 points of frame
     rate — 44.7% of frames lost became 32.3%, worst frame 83ms -> 50ms.
     Nothing else in the grain was the problem; earlier rounds tested
     its brightness, its animation and its will-change and found little.
     Soft-light was also barely doing anything here: over a near-black
     palette it preserves darks almost exactly, so the flat-area
     difference between it and no grain at all measured 0.04/255.
     Normal blending at .020 sits closest to the old mean luminance
     (18.49 -> 19.20) while actually being visible. */
  opacity: .020;
  mix-blend-mode: normal;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grainShift 1.1s steps(3) infinite;
}
@keyframes grainShift {
  0% { background-position: 0 0; }
  33% { background-position: 42px -28px; }
  66% { background-position: -35px 20px; }
  100% { background-position: 0 0; }
}

/* ---------- THE STRIP: where you are in the thirty days ----------
   At the foot of every post. Five SQUARE days across with the current
   one lit, each carrying its own date and title, and the way out to the
   whole grid sitting quietly above the row rather than pretending to be
   a sixth day. Adjacent cells ARE previous and next, so a reader can
   see what is either side without leaving the page.
   Generated by scripts/build-minical.py from one table; never edit the
   markup by hand. */
.minical { display: flex; flex-direction: column; align-items: center; }
.mc-frame {
  width: 100%;
  border: 1px solid rgba(245, 245, 247, .09);
}
/* THE MONTH, once, across the top. It was repeated in all five cells,
   which cost the room the date wanted and said the same thing five
   times. The bar carries every month the window touches, so it stays
   right when the run crosses into September. */
.mc-month {
  padding: .5rem .75rem;
  border-bottom: 1px solid rgba(245, 245, 247, .09);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
}

/* THE WAY OUT, centred above the row. It used to be a bare label, which
   gave no sign it could be pressed — it is a real target now: a hairline
   that warms, a ground that lifts, and the nine squares filling in. */
.mc-all {
  display: inline-flex;
  align-items: center;
  gap: .75rem;
  margin-bottom: 1.1rem;
  padding: .55rem 1.1rem;
  color: rgba(245, 245, 247, .55);
  border: 1px solid rgba(245, 245, 247, .16);
  transition: color .35s ease, border-color .35s ease, background .35s ease, gap .4s var(--ease);
}
.mc-all:hover,
.mc-all:focus-visible {
  color: var(--acc);
  border-color: rgba(255, 157, 74, .5);
  background: rgba(255, 157, 74, .07);
  gap: 1.05rem;
}
.mc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; width: 15px; }
.mc-grid i { display: block; aspect-ratio: 1; background: currentColor; opacity: .55; }
.mc-all:hover .mc-grid i { opacity: 1; }
.mc-all b {
  font-size: 9px;
  font-weight: 550;
  letter-spacing: .22em;
  text-transform: uppercase;
}

.mc-row {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  background: rgba(245, 245, 247, .09);
}
.mc-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .15rem;
  text-align: center;
  aspect-ratio: 1;
  padding: .7rem .5rem;
  overflow: hidden;
  background: var(--bg);
  color: var(--fnt);
  transition: background .4s ease, color .4s ease;
}
/* the date, at the size a calendar actually gives it */
.mc-cell i {
  font-style: normal;
  font-size: clamp(1.5rem, 3.2vw, 2.3rem);
  font-weight: 300;
  letter-spacing: -.03em;
  line-height: 1;
}
/* the month, riding in front of the date. Small caps against the big
   numeral, baseline-aligned so the two sit on one line rather than the
   label floating. It earns its place from day 12, where the window
   crosses into September. */
.mc-cell i { display: inline-flex; align-items: baseline; gap: .3em; }
.mc-cell i em {
  font-style: normal;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(190, 198, 214, .62);
}
.mc-cell b {
  font-size: 9px;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: rgba(190, 198, 214, .62);
}
.mc-t {
  margin-top: .5rem;
  font-size: clamp(.8rem, 1.15vw, .95rem);
  font-weight: 300;
  line-height: 1.32;
  color: rgba(245, 245, 247, .8);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.mc-void { background: rgba(6, 6, 7, .55); }
.mc-wait { color: rgba(245, 245, 247, .22); }
.mc-wait b { color: rgba(245, 245, 247, .16); }
a.mc-cell:hover { background: rgba(245, 245, 247, .05); color: rgba(245, 245, 247, .85); }
.mc-now { color: var(--acc); background: rgba(255, 157, 74, .07); }
.mc-now b { color: rgba(255, 157, 74, .6); }
.mc-now .mc-t { color: #fff; }
.mc-now::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 2px;
  background: var(--acc);
}
@media (max-width: 720px) {
  .mc-row { grid-template-columns: repeat(3, 1fr); }
  .mc-cell:nth-child(1), .mc-cell:nth-child(5) { display: none; }
  .mc-cell { padding: .5rem .4rem; }
  .mc-t { font-size: .78rem; -webkit-line-clamp: 3; margin-top: .35rem; }
}

/* ---------- fixed chrome ---------- */

.brand {
  position: fixed;
  top: 24px;
  z-index: 90;
  font-size: 12px;
  font-weight: 550;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #fff;
  mix-blend-mode: difference;
  transition: opacity .25s ease;
}
.brand { left: 30px; }
.brand:hover, .menu-btn:hover { opacity: .65; }
/* TAP TARGETS. Both of these are 12px type, which gave a hit area 14px
   tall — a third of the 44px a finger needs. The padding is negative-
   margined back out so nothing moves on screen; only the target grows.
   Measured on a phone before this: brand 85x14, MENU 45x14. */
.brand, .menu-btn {
  padding: 15px 10px;
  margin: -15px -10px;
}
/* the wordmark: one word, the family name in bold */
.brand b { font-weight: 800; }

/* THE CHROME SCRIM. The chrome is fixed and the page scrolls under
   it, which was survivable when the band held a wordmark on the left
   and a button on the right — both outside the 880px reading column.
   The topnav sits in the middle of that column, so a post's meta line
   ran straight through it. This is the same treatment the podcast page
   already used at the top of its bright hero, generalised: a short fade
   that sits above the content and below the chrome, so whatever passes
   underneath goes quiet instead of colliding. */
body::after {
  content: "";
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 118px;
  z-index: 60;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(6, 6, 7, .90) 0%, rgba(6, 6, 7, .62) 46%, rgba(6, 6, 7, 0) 100%);
}
/* the menu overlay covers the whole screen and owns its own ground.
   It sits at z-index 380, well above the scrim, so nothing is needed
   here — noted so the next person does not go looking. */

/* the strip cells stay positioned; the read-marker that needed it
   was removed 2026-08-31 at David's request. */
.mc-cell { position: relative; }

/* ---------- topnav: the sections, always reachable ----------
   Added 2026-08-25. Every cross-page move used to cost two clicks —
   open Menu, pick a page — and the footer index sits 9,975px down a
   page that is 11.4 screens tall, so in practice the Menu was the only
   way through. This is the same five destinations the Menu overlay
   carries, in the same words, sitting in the chrome band where they
   can be reached from any scroll position.

   It takes the Menu button's place on a wide screen rather than
   joining it: two indexes in one band is clutter. Below 820px the
   labels do not fit, so the button comes back and this hides. */
.topnav {
  position: fixed;
  top: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 90;
  display: flex;
  gap: 1.9rem;
  mix-blend-mode: difference;
}
.topnav a {
  font-size: 11px;
  font-weight: 550;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #fff;
  opacity: .58;
  transition: opacity .25s ease;
}
.topnav a:hover, .topnav a:focus-visible { opacity: 1; }
/* where you are: full strength plus a hairline, so it reads without
   relying on the opacity difference alone */
.topnav a[aria-current="page"] { opacity: 1; }
.topnav a[aria-current="page"]::after {
  content: "";
  display: block;
  height: 1px;
  margin-top: .45rem;
  background: currentColor;
  opacity: .45;
}
@media (min-width: 821px) { .menu-btn { display: none; } }
@media (max-width: 820px) { .topnav { display: none; } }

/* ---------- menu: the index overlay ---------- */

.menu-btn {
  position: fixed;
  top: 24px;
  right: 30px;
  z-index: 90;
  font-size: 12px;
  font-weight: 550;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: #fff;
  mix-blend-mode: difference;
  transition: opacity .25s ease;
}
.menu-btn:hover { opacity: .65; }
.menu {
  position: fixed;
  inset: 0;
  z-index: 380;
  display: grid;
  place-items: center;
  visibility: hidden;
  opacity: 0;
  transition: opacity .45s var(--ease), visibility 0s linear .45s;
}
.menu.on { visibility: visible; opacity: 1; transition: opacity .45s var(--ease); }
.menu-skin { position: absolute; inset: 0; background: rgba(7, 7, 8, .97); }
.menu-x {
  position: absolute;
  top: 26px; right: 30px;
  width: 40px; height: 40px;
  z-index: 2;
  transition: transform .45s var(--ease);
}
.menu-x span { position: absolute; left: 8px; right: 8px; top: 50%; height: 1.5px; background: var(--fg); }
.menu-x span:first-child { transform: rotate(45deg); }
.menu-x span:last-child { transform: rotate(-45deg); }
.menu-x:hover { transform: rotate(90deg); }
.menu-list { position: relative; display: grid; gap: clamp(1rem, 3vh, 1.8rem); }
.menu-list a {
  display: flex;
  align-items: baseline;
  gap: 1.4rem;
  font-size: clamp(2rem, 5.4vw, 3.6rem);
  font-weight: 300;
  letter-spacing: -.02em;
  color: var(--mut);   /* greyed until chosen */
  opacity: 0;
  transform: translateY(26px);
  filter: blur(10px);   /* everything arrives by coming into focus */
  transition: opacity .7s var(--ease), transform .7s var(--ease), filter .7s var(--ease), color .3s ease;
}
.menu.on .menu-list a { opacity: 1; transform: translateY(0); filter: blur(0); }
.menu.on .menu-list a:nth-child(1) { transition-delay: .1s; }
.menu.on .menu-list a:nth-child(2) { transition-delay: .18s; }
.menu.on .menu-list a:nth-child(3) { transition-delay: .26s; }
.menu.on .menu-list a:nth-child(4) { transition-delay: .34s; }
.menu.on .menu-list a:nth-child(5) { transition-delay: .42s; }
.menu-list a i {
  font-style: normal;
  font-size: 11px;
  letter-spacing: .3em;
  color: var(--acc);
}
.menu-list a:hover { color: #fff; }
/* the selected page: white, with a subtle breathing ice line */
.menu-list a[aria-current="page"] { color: #fff; }
.menu-list a[aria-current="page"] span { position: relative; }
.menu-list a[aria-current="page"] span::after {
  content: "";
  position: absolute;
  left: 0; right: .1em; bottom: -8px;
  height: 1px;
  background: var(--acc);
  animation: selBreathe 2.8s ease-in-out infinite;
}
@keyframes selBreathe {
  0%, 100% { opacity: .25; }
  50% { opacity: 1; }
}

/* ---------- page heads (subpages) ---------- */
/* THE RULE (all pages, present and future): the head IS a full
   hero — 100svh, title landing bottom-left exactly like home;
   no section, label, or divider starts until below the fold */

.page-head {
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
/* the head runs on the hero's machinery: .hero-inner carries the
   padding, the word masks, the scroll rise + dissolve */
.page-head h1 {
  font-size: clamp(2rem, 7svw, 6.4rem);
  font-weight: 640;
  font-variation-settings: "wght" 640;
  letter-spacing: -.045em;
  line-height: .96;
  /* no text-shadow: the word-mask clips would box it */
}
/* the page subtitle: the hero-sub's twin, non-interactive */
.page-sub { cursor: default; }
/* head veil (opt-in per page): ink pooling bottom-left, clearing
   diagonally to the top right — the title's ground */
.ph-veil { position: relative; }
.ph-veil::before {
  content: "";
  position: absolute;
  inset: 0 0 -90svh 0;   /* room for the radial to die out — no seam */
  z-index: -1;
  pointer-events: none;
  /* ink pooled at the title's corner, fading radially in every
     direction — strongest exactly where the words land */
  background: radial-gradient(120vw 90svh at 0% 100svh,
    rgba(6, 6, 7, .92) 0%, rgba(6, 6, 7, .5) 42%, rgba(6, 6, 7, .12) 72%, rgba(6, 6, 7, 0) 92%);
}

/* ---------- ethos: the spine returns, over stitched video ---------- */

/* 260vh, down from 380. Four beats over 280vh of scroll gave each one
   ~70vh: 14 fading in, 42 held, 14 fading out. Forty-two vh of hold
   on a single short line is half a screen of wheel work to read two
   seconds of text. At 160vh of scroll each beat gets ~40vh — 8 in,
   24 held, 8 out — which is still an unhurried read and a third of
   the section's cost. */
.ethos2 { position: relative; height: 260vh; }
/* THE SEAM. The wall's stage ends in black; ethos opens on a lighter
   ground, so the boundary drew a hard line across the full width —
   read as a gap. This lays the page's own black over ethos's first
   fold and lets it clear as the section takes over. It is anchored to
   the section (not the sticky stage), so it masks the join and then
   scrolls away with it. */
.ethos2::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 30vh;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(180deg,
    var(--bg) 0%, rgba(6, 6, 7, .82) 30%, rgba(6, 6, 7, .38) 62%, rgba(6, 6, 7, 0) 100%);
}
.e2-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
  background:
    radial-gradient(120% 90% at 30% 20%, rgba(35, 38, 46, .9), transparent 60%),
    radial-gradient(110% 80% at 75% 85%, rgba(32, 24, 17, .85), rgba(6, 6, 7, .95));
}
.e2-video { position: absolute; inset: 0; }
/* the films stack; the active beat's loop breathes in over the rest */
.e2-video video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 1.4s ease;
}
.e2-video video.on { opacity: 1; }
.e2-veil {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom,
    rgba(6, 6, 7, .58), rgba(6, 6, 7, .34) 45%, rgba(6, 6, 7, .64));
}

/* ---------- now links ---------- */

/* the beats are pointer-transparent; the CTA must not be */
.now-links { margin-top: 1.6rem; display: flex; gap: 2rem; pointer-events: auto; }
.now-links a {
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--mut);
  background: linear-gradient(var(--acc), var(--acc)) no-repeat 0 100% / 0 1px;
  padding-bottom: 4px;
  transition: color .3s ease, background-size .4s var(--ease);
}
.now-links a:hover { color: var(--fg); background-size: 100% 1px; }

.notes { padding: 4vh 5vw 16vh; }
.n-list { margin-top: 1rem; }
.n-row {
  display: flex;
  align-items: baseline;
  gap: clamp(1.4rem, 3.4vw, 3rem);
  border-top: 1px solid var(--line);
  padding: clamp(1.2rem, 3vh, 1.9rem) 0;
}
.n-row:last-child { border-bottom: 1px solid var(--line); }
.n-row i {
  font-style: normal;
  font-size: 10px;
  letter-spacing: .3em;
  color: var(--acc);
  flex: 0 0 3em;
}
.n-row p {
  font-size: clamp(1.05rem, 1.9vw, 1.4rem);
  font-weight: 300;
  line-height: 1.5;
  color: var(--mut);
}

/* ---------- hairline rules: they draw across on reveal ---------- */

.rule {
  flex: 1;
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.6s var(--ease) .15s;
}
.in .rule { transform: scaleX(1); }

/* ---------- hero ---------- */

.hero {
  position: relative;
  height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}
.hero-inner {
  /* the bottom padding clears iOS Safari's floating toolbar:
     safe-area inset (with viewport-fit=cover) keeps the words
     inside the frame on iPhones */
  padding: 0 clamp(1.4rem, 4vw, 3.4rem)
    calc(clamp(2.8rem, 7vh, 5rem) + env(safe-area-inset-bottom, 0px));
  color: #fff;
  will-change: transform, opacity;
  /* no text-shadow here: shadows inside the word-mask clips render
     as visible rectangles over flat backdrops */
}
/* THE 3px. .wmask carries padding-right: .07em so its own clip does not
   shave the right edge of a glyph, and a matching negative margin pulls
   the next word back so spacing is untouched. The box still PAINTS that
   .07em wider though, and at the hero's size that is 3px — enough, on
   the longest line at 320px, to push the document sideways. The padding
   is doing a real job so it stays; the hero clips horizontally instead.
   It is empty padding being clipped, so nothing is lost, and clip (not
   hidden) leaves the vertical alone for the word-mask animation. */
.hero, .hero-inner { overflow-x: clip; }
.hero h1 {
  font-size: clamp(2.7rem, 10.4svw, 9.4rem);
  line-height: .96;
  letter-spacing: -.045em;
  font-weight: 640;
  font-variation-settings: "wght" 640;
}
/* fixed headline lines that never re-wrap (hero + outro mirror) */
.hline { display: block; white-space: nowrap; }
/* the mask boxes are line-height tall (.96em) — shorter than the
   glyphs — so each carries descender room below (padding, cancelled
   by margin so line spacing is untouched); the hidden rest sits
   deeper to stay fully out of the taller window */
/* The clip box carries room on THREE sides now. Vertically it always
   did, for descenders. Horizontally it was losing ink: letter-spacing
   is negative here (-.045em) and CSS subtracts that after the LAST
   character too, so the box ends ~.045em short of where the glyph
   actually paints. Round and flag terminals — a, e, r, s — were being
   shaved by up to 7px at the hero's largest size. The padding opens
   the box, the negative margin gives the space straight back, so
   nothing moves and nothing is cut. */
.wmask { display: inline-block; overflow: clip; vertical-align: bottom; padding-bottom: .22em; margin-bottom: -.22em; padding-right: .07em; margin-right: -.07em; }
.wmask > span { display: inline-block; transform: translateY(135%); transition: transform 1.1s var(--ease); }
body.loaded .wmask > span { transform: translateY(0); }

/* the subtitle: present, unhurried — breathes in once and remains */
.hero-sub {
  display: block;
  margin-top: 1.7rem;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: #fff;
  white-space: nowrap;
  width: fit-content;
  cursor: pointer;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 2.2s var(--ease) .75s, transform 2.2s var(--ease) .75s;
}
body.loaded .hero-sub { opacity: 1; transform: translateY(0); }

/* the cue: a bare chevron, bottom center, breathing slowly */
.scroll-cue {
  position: absolute;
  bottom: calc(1.9rem + env(safe-area-inset-bottom, 0px));
  left: 50%;
  translate: -50% 0;
  color: rgba(255, 255, 255, .62);
  opacity: 0;
  transition: opacity 1.2s var(--ease) 1.5s;
}
body.loaded .scroll-cue { opacity: 1; }
.scroll-cue svg { display: block; animation: cueNod 5.6s ease-in-out 1.2s infinite; }
/* two soft nods, then a long rest */
@keyframes cueNod {
  0%, 24%, 100% { transform: translateY(0); }
  7% { transform: translateY(7px); }
  14% { transform: translateY(1px); }
  19% { transform: translateY(5px); }
}

/* ---------- experience: the spine ---------- */

.eth-head {
  max-width: 880px;
  margin: 0 auto;
  padding: 16vh 0 7vh;
  display: flex;
  align-items: center;
  gap: 1.6rem;
  font-size: 10px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
}

.exp2 { position: relative; height: 480vh; }
.x-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
}
.x-head {
  position: absolute;
  top: clamp(68px, 10vh, 110px);
  left: clamp(1.4rem, 4vw, 3.4rem);
  right: clamp(1.4rem, 4vw, 3.4rem);
  display: flex;
  align-items: center;
  gap: 1.6rem;
  font-size: 10px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
  opacity: var(--xhead, 1);
  transition: opacity .6s ease;
}

/* drifting frames in the margins — ambient, uncaptioned */
.x-frames { position: absolute; inset: 0; pointer-events: none; }
.x-f {
  position: absolute;
  top: 50%;
  left: var(--fl, 5%);
  width: var(--fw, 15vw);
  min-width: 96px;
  aspect-ratio: 3 / 4;
  border-radius: 2px;
  overflow: clip;
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(0, 0, 0, .3);
  transform: scale(0);
  transform-origin: right bottom;
  will-change: transform, opacity;
}
.x-f.xr { transform-origin: left bottom; }
.x-f img { width: 100%; height: 100%; object-fit: cover; display: block; filter: saturate(.85) brightness(.92); }

/* the beats: refined caps, each finding its own place off center */
.x-spine { position: absolute; inset: 0; }
.x-beat {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  padding: 0 clamp(2rem, 10vw, 10rem);
  opacity: 0;
  will-change: transform, opacity, filter;
  pointer-events: none;
}
/* frames alternate margins; the words take the opposite side,
   and wander the vertical thirds */
.x-beat:nth-child(1) { align-items: flex-end; text-align: right; justify-content: flex-start; padding-top: 26vh; }
.x-beat:nth-child(2) { justify-content: flex-end; padding-bottom: 28vh; }
.x-beat:nth-child(3) { align-items: flex-end; text-align: right; }
.x-beat:nth-child(4) { justify-content: flex-end; padding-bottom: 26vh; }
/* the closing statement lands at dead center, its lines ragged left */
.x-beat:nth-child(5) { align-items: center; text-align: left; justify-content: center; }
.x-beat em {
  display: block;
  font-style: normal;
  font-size: 10px;
  letter-spacing: .34em;
  color: var(--acc);
  margin-bottom: 1.1rem;
  font-variant-numeric: tabular-nums;
}
.x-beat h3 {
  font-size: clamp(1rem, 2.2vw, 1.6rem);
  line-height: 1.55;
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 470;
  max-width: 34ch;
  text-wrap: balance;
  text-shadow: 0 1px 24px rgba(0, 0, 0, .55);
}
.x-sub {
  margin-top: .9rem;
  font-size: 10.5px;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--mut);
}

/* ---------- "Next": the full Bourdain, near the end ---------- */
/* the arc breathes through dead space, not ornament */

.dossier { padding: 20vh 5vw 10vh; }
.dos-in { max-width: 880px; margin: 0 auto; }
.dos-head {
  display: flex;
  align-items: center;
  gap: 1.6rem;
  font-size: 10px;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
  margin-bottom: 2.2rem;
}
.dos-copy {
  font-weight: 300;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  line-height: 1.55;
  color: rgba(245, 245, 247, .62);
}
.dos-copy + .dos-copy { margin-top: 1.3em; }
/* the last lines land brighter and heavier */
.dos-copy .q-em {
  color: var(--fg);
  font-weight: 430;
}
.dos-meta {
  margin-top: 1.7rem;
  font-size: 10px;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--fnt);
}

/* ---------- the wall: nine marks arrive one by one ---------- */
/* a full-viewport 3×3 over the blurring world; each mark rises
   out of its clip exactly like the hero's words */

/* 240vh, down from 300: the marks used to be scrubbed up one at a
   time across two thirds of the section. They now roll as a single
   wave (delays below), which frees the back half of the section to
   be what it should have been — a held beat on the citations. */
.wall { position: relative; height: 240vh; }
.wall-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
}
/* the film: David on stage, present but recessed — the marks stay
   the subject. Desaturated and dimmed at the source, then veiled:
   a center-softening vignette (he remains visible mid-frame), a
   vertical press at top and bottom where the outer rows sit, and
   one faint cold breath in the corner */
.wall-film { position: absolute; inset: 0; }
.wall-film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the crop holds just left of center — the stage where David
     moves stays in frame as narrow screens trim the sides */
  object-position: 30% center;
  display: block;
  filter: saturate(.65) brightness(.58) contrast(1.05);
  opacity: 0;
  transition: opacity 1.4s ease;
}
.wall-film video.on { opacity: 1; }
.wall-veil {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(60% 40% at 88% 6%, rgba(255, 157, 74, .07), transparent 60%),
    radial-gradient(120% 80% at 50% 50%, rgba(6, 6, 7, .3), rgba(6, 6, 7, .68) 80%),
    linear-gradient(to bottom, rgba(6, 6, 7, .74), rgba(6, 6, 7, .36) 44%, rgba(6, 6, 7, .78));
}
.wall-grid {
  position: absolute;
  inset: 0 0 9vh 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  place-items: center;
  padding: 16vh 6vw 10vh;
}
.wl { overflow: clip; }   /* the clip box is the mask */
.wl img {
  display: block;
  height: clamp(20px, 2.8vw, 42px);
  max-width: 27vw;
  object-fit: contain;
  opacity: .85;
  transform: translateY(112%);
  transition: transform 1.15s var(--ease), opacity .45s ease;
}
.wl.on img { transform: translateY(0); }
.wl img:hover { opacity: 1; }
/* THE WAVE — all nine are tripped by the same threshold and the
   stagger lives here instead: rows a tenth of a second apart, marks
   within a row barely so. It reads as one gesture rolling top to
   bottom, not as nine separate arrivals. Safe as delays because
   nothing drives these per-frame — the class is the whole drive. */
.wl:nth-child(1) img { transition-delay: 0s; }
.wl:nth-child(2) img { transition-delay: .035s; }
.wl:nth-child(3) img { transition-delay: .07s; }
.wl:nth-child(4) img { transition-delay: .10s; }
.wl:nth-child(5) img { transition-delay: .135s; }
.wl:nth-child(6) img { transition-delay: .17s; }
.wl:nth-child(7) img { transition-delay: .20s; }
.wl:nth-child(8) img { transition-delay: .235s; }
.wl:nth-child(9) img { transition-delay: .27s; }

/* the citations beneath the wall: a label and two marks, held
   deliberately smaller than the career logos above */
/* Full section width, with the same gutters the section header uses,
   so the dividing rule below spans exactly what the header's rule
   spans — one measure for both lines in the section. */
.press {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(1.6rem, 3.2vh, 3rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.3rem;
  padding: 0 clamp(1.4rem, 4vw, 3.4rem) 1.6rem;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 1.2s var(--ease), transform 1.2s var(--ease);
  pointer-events: none;
}
/* THE DIVIDING LINE. One hairline, no plane. The lit alcove separated
   the citations from the wall but did it by putting a wash of light on
   the film, which read as a smudge rather than as structure. A rule
   does the same job with nothing to notice.
   It stretches the full width of the section, matching the header's
   rule at the top of the same stage — the two lines bracket the wall
   on the same measure rather than each finding its own. */
.press-rule {
  align-self: stretch;
  height: 1px;
  margin-bottom: 2.4rem;
  background: rgba(255, 255, 255, .17);
}
.press.on { opacity: 1; transform: translateY(0); pointer-events: auto; }
.press-label {
  font-size: 10px;
  letter-spacing: .34em;
  text-indent: .34em;
  text-transform: uppercase;
  color: var(--fnt);
}
.press-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(1.8rem, 4vw, 3.2rem);
}
.pr-mark { display: block; }
.pr-mark img {
  display: block;
  width: auto;
  max-width: 38vw;
  object-fit: contain;
  opacity: .72;
  transition: opacity .4s ease;
}
a.pr-mark:hover img { opacity: .95; }
/* optical balance: the Times wordmark is fine-lined, the NPR bug
   is a solid block — the block runs smaller to weigh the same */
.pr-mark img[alt="The New York Times"] { height: clamp(17px, 2.45vw, 37px); }
.pr-mark img[alt="NPR"] { height: clamp(12px, 1.65vw, 25px); }
@media (max-width: 1023px) {
  .wl img { height: 20px; }
}
@media (max-width: 560px) {
  .wall-grid { padding: 18vh 4vw 14vh; }
  .wl img { height: 14px; max-width: 28vw; }
}

/* Background page — THE REEL: one held frame per chapter.
   The mark stands alone at center; the words float up through it. */
.reel { position: relative; height: 440vh; }
.reel-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
}
.reel-item img {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  height: clamp(30px, 5.6vw, 72px);
  width: auto;
  max-width: 82vw;
  object-fit: contain;
  opacity: 0;
  will-change: transform, opacity;
  z-index: 1;
}
.reel-item p {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  width: min(36ch, 82vw);
  text-align: center;
  font-size: clamp(1.02rem, 1.8vw, 1.35rem);
  font-weight: 300;
  line-height: 1.6;
  color: rgba(245, 245, 247, .85);
  text-shadow: 0 1px 20px rgba(0, 0, 0, .6);
  opacity: 0;
  will-change: transform, opacity;
  z-index: 2;
}
/* ---------- THE CARD ----------
   Rebuilt 2026-08-26. What was here: 350vh of scroll for 62 words, on
   nineteen separately-timed reveals, in five type treatments — three
   beat sizes driven by a decorative data-w, plus an accent word class,
   plus a word-mask on the closing line. Read as jumbled because it was
   nineteen arrivals, and read as chaotic because amber appeared inside
   the words as well as the frame.

   This is CNN's construction, which is the reference David chose (they
   broadcast Bourdain's show): a short bar, one flush-left axis, and
   the heavy uppercase treatment reserved for the line that earns it.
   Their cards work at eleven words; at 62 the same treatment is a wall,
   so the body keeps a reading size and only the landing goes to
   headline. Two sizes. Two reveals. Amber in the bar and nowhere else.

   Both films are kept and unchanged — .ser-film, .ser-slot and
   .ser-veil below still run the pair, and the ending still swaps to
   the closing frame. */
.ser-card {
  position: absolute;
  left: clamp(1.6rem, 6vw, 6rem);
  right: clamp(1.6rem, 6vw, 6rem);
  bottom: clamp(2.4rem, 11vh, 7rem);
  /* THE BLOCK WANTS TO BE A RECTANGLE. A CNN card reads as a solid
     shape because its lines all run nearly to the same edge. That is a
     function of the measure: too wide and the last line of each
     sentence leaves a gap, too narrow and the rag opens up.

     Tuned by measuring how far short of the column edge every rendered
     line stops, across candidate measures. At 43rem the four lines at
     1280 fall 13, 29, 51 and 3px short of a 688px column — the block
     is square. 44rem gave 8/66/67/19, 46rem gave 40/4/16/228, and
     48rem broke it completely at 1/21/135/260. */
  max-width: 43rem;
}
.ser-bar {
  display: block;
  width: 74px;
  height: 5px;
  background: var(--acc);
  margin-bottom: clamp(.95rem, 2.2vh, 1.6rem);
}
/* the body: ONE size, the whole quote, flush left. The opening
   quotation mark hangs into the margin so the first LETTER lands on
   the same axis as every line under it. */
.ser-quote {
  margin: 0;
  font-size: clamp(.78rem, 1.38vw, 1.1rem);
  font-weight: 500;
  line-height: 1.38;
  /* caps need tracking OPENED, not closed — the negative value that
     suits lowercase jams capitals together */
  letter-spacing: .012em;
  text-transform: uppercase;
  color: rgba(245, 245, 247, .74);
  text-wrap: pretty;
  text-indent: -.36em;
}
/* the landing: the only line that gets the headline treatment */
.ser-land {
  margin: clamp(1.1rem, 2.6vh, 1.9rem) 0 0;
  font-size: clamp(1.3rem, 3.3vw, 2.85rem);
  font-weight: 700;
  line-height: 1.06;
  letter-spacing: -.022em;
  text-transform: uppercase;
  color: #fff;
  text-wrap: balance;
  text-indent: 0;
}
/* THE PIVOT. "You take something with you." is the turn in the quote,
   so it leaves the body block and arrives on its own — a quick blurred
   fade a beat behind the passage above it, then a pause before the
   landing follows. Same size as the body on purpose: the section holds
   two type sizes and a third would put the wall back. Full white and
   its own airspace do the work instead. */
.ser-mid {
  margin: clamp(.6rem, 1.5vh, 1rem) 0 0;
  font-size: clamp(.78rem, 1.38vw, 1.1rem);
  font-weight: 600;
  line-height: 1.38;
  letter-spacing: .012em;
  text-transform: uppercase;
  color: #fff;
  text-indent: 0;
}
/* it blurs into focus rather than rising, and it is quick */
.ser-mid.rv {
  transform: none;
  filter: blur(9px);
  transition: opacity .45s ease .70s, filter .45s ease .70s;
}
.ser-mid.rv.in { filter: blur(0); }

.ser-sign {
  margin: clamp(1.3rem, 3.2vh, 2.2rem) 0 0;
  font-size: 10px;
  font-weight: 520;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
}
.ser-sign .sa-y { display: block; margin-top: .5rem; letter-spacing: .28em; color: var(--fnt); }
/* and the landing waits out the pause after the pivot */
.ser-close.rv { transition-delay: 1.85s; }

/* ---------- the sermon: Bourdain, sentence by sentence ---------- */
/* each line floats up alone, a step larger and brighter; the last
   two land near-headline, word by word, and stay */

.sermon { position: relative; height: 140vh; }
.ser-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
  background:
    radial-gradient(120% 90% at 50% -10%, rgba(30, 33, 41, .88), transparent 55%),
    radial-gradient(130% 100% at 50% 115%, rgba(34, 25, 16, .85), rgba(6, 6, 7, .97));
}
.ser-film {
  position: absolute;
  inset: 0;
  overflow: clip;
}
.ser-film video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 1.4s ease;
}
.ser-film video.on { opacity: 1; }
/* the film lives in its own slot, sized to cover. There is one
   now: David removed the closing frame on 2026-08-27, so the same
   film runs behind the whole section. */
.ser-film.on .ser-slot-film { opacity: 1; }
.ser-slot {
  position: absolute;
  inset: 0;
  overflow: clip;
  opacity: 0;
  transition: opacity 1.2s ease;
  pointer-events: none;
}
/* centered and oversized enough to cover any viewport — an
   off-center anchor would expose the stage as a black bar */
.ser-slot iframe, .ser-slot > div {
  position: absolute;
  top: 50%;
  left: 50%;
  width: max(100vw, 177.78svh);
  height: max(100svh, 56.25vw);
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;
  filter: saturate(.65) brightness(.5);
}
/* heavy veil: the film is atmosphere, never subject. A deep
   vignette pockets the edges; the bottom tenth runs nearly
   black — it buries YouTube's caption strip */
.ser-veil {
  position: absolute;
  inset: 0;
  background:
    /* top band: buries the video's own title overlay */
    linear-gradient(to bottom, rgba(6, 6, 7, .99) 0%, rgba(6, 6, 7, .97) 8%, rgba(6, 6, 7, 0) 16%),
    linear-gradient(to top, rgba(6, 6, 7, .99) 0%, rgba(6, 6, 7, .97) 10%, rgba(6, 6, 7, 0) 22%),
    radial-gradient(85% 78% at 6% 102%, rgba(6, 6, 7, .88), rgba(6, 6, 7, .5) 46%, transparent 74%),
    radial-gradient(115% 82% at 50% 46%, transparent 34%, rgba(6, 6, 7, .55) 72%, rgba(6, 6, 7, .88) 100%),
    linear-gradient(to bottom, rgba(6, 6, 7, .66), rgba(6, 6, 7, .44) 45%, rgba(6, 6, 7, .72));
}
.ser-flow { position: absolute; inset: 0; }
.ser-beat {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 clamp(1.6rem, 6vw, 6rem);
  opacity: 0;
  will-change: transform, opacity, filter;
  pointer-events: none;
}
/* the ethos lines carry their own locked breaks — give them a
   wider measure and margin than the story spine's beats (narrow
   viewports still wrap naturally before the locked break).
   Longhand padding only: the nth-child vertical offsets that
   place each beat in its own third must survive. */
.ethos2 .x-beat {
  padding-left: clamp(2rem, 7vw, 7rem);
  padding-right: clamp(2rem, 7vw, 7rem);
}
.ethos2 .x-beat h3 { max-width: 56ch; }
/* the two iterations under comparison */
/* Nearly all of this height is dwell. The six lines cascade in on
   their own clock (below) rather than being scrubbed in one at a
   time, and the last breath's solo hold is now ~65vh — half what it
   was — leaving ~90vh on the closing statement, which is the beat
   that still needs the room. 600vh at its longest; 425vh now. */
/* B — the accumulation: lines stack in a centered column, each
   arriving bright and dimming as the next lands */
/* THE CASCADE — one scroll trips `cast` and all six float up, top to
   bottom, on their own clock rather than on the reader's wheel. */
/* The stagger lives on transition-delay, so it MUST NOT survive into
   the scrubbed phase: a .69s delay against a per-frame drive doesn't
   slow it down, it stops it dead (the same way the attribution's
   delay once cancelled its own fade). `live` drops these rules out of
   matching entirely rather than trying to out-specify them. */

/* ---- THE PASSAGE HAS A SHAPE ----
   Six lines all one size read as a wall. data-w is how much weight a
   line carries: 2 is a short declarative that turns the passage, 1
   supports it, 0 is the longer descriptive run. Size and brightness
   follow, so the eye is told where to slow down. Bourdain's words are
   untouched; only their scale changes. */

/* ---- CLAUSES ARRIVE IN SEQUENCE ----
   Inside a beat, each clause comes on its own beat rather than the
   whole line appearing at once, so a line BUILDS. Delay-based, and
   dropped out of matching the moment the engine takes over — the same
   guard the cascade uses, for the same reason. */

/* ---- ONE WORD PER BEAT CARRIES THE THREAD ----
   The accent walks down the passage — hurts, okay, changes, marks —
   pulling the eye through it. Held well under full strength on
   purpose: the ending's one amber word is the destination, and four
   shouting rivals would halve its force. This is a thread, not a
   highlight. */

/* ONE LEFT EDGE. Centred, the six lines gave six different ragged
   left starts — the eye had to re-find the beginning of every line,
   which is what made the block tiring to read rather than the length
   of it. Every line now shares a single measure and a single flush
   left edge, and the ending inherits the same edge so the passage
   never switches alignment under the reader. The column itself stays
   centred in the stage. */
/* SENTENCES THAT WON'T SPLIT. A beat carrying two sentences must break
   between them or not at all — never mid-sentence, which is the one
   break that looks like an accident. Each sentence is its own nowrap
   run, so the line simply falls at the join when there isn't room.
   No breakpoint to guess at: it holds at every width. */

/* HANGING THE QUOTE. With the block flush left, the opening quotation
   mark sat ON the edge, which pushed "Life" inboard of every line
   beneath it — the letters no longer lined up even though the boxes
   did. The mark now hangs into the margin so the first LETTER lands
   on the same edge as all the others. Same for the ending, which
   opens on a quote too. */
/* ...but the ending's words each live in their own clip box, and an
   inline-block is a block container, so it inherits the indent and
   shifts its word left inside a box that does not move — which
   guillotines the first letter off every word. The mask boxes opt
   out; only the line itself hangs. */

/* one voice throughout: every breath the exact size, face, and
   weight of the first — only the light climbs */
.ser-beat p {
  max-width: 30ch;
  text-wrap: balance;
  font-size: clamp(1.12rem, 2.6vw, 1.85rem);
  font-weight: 300;
  line-height: 1.5;
  letter-spacing: -.01em;
  /* no text-shadow: it smudges a halo box on the veiled backdrop */
}
.ser-beat:nth-child(1) p { color: rgba(245,245,247,.60); }
.ser-beat:nth-child(2) p { color: rgba(245,245,247,.67); }
.ser-beat:nth-child(3) p { color: rgba(245,245,247,.74); }
.ser-beat:nth-child(4) p { color: rgba(245,245,247,.80); }
.ser-beat:nth-child(5) p { color: rgba(245,245,247,.86); }
.ser-beat:nth-child(6) p { color: rgba(245,245,247,.92); }
/* the finale: near-headline, full white, the hero's word-rise */
.ser-final {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 clamp(1.4rem, 5vw, 4rem);
  pointer-events: none;
}
/* the memorial ground: plain black, complete before the last
   words rise — nothing lives behind them */
.ser-skin {
  position: absolute;
  inset: 0;
  background: var(--bg);
  opacity: 0;
  transition: opacity .9s ease;
  pointer-events: none;
}
.ser-skin.in { opacity: 1; }
/* after the dark dip, the ink settles to a legible ground over
   the still — dark enough to read, open enough to see */
.ser-skin.in.lift { opacity: .35; }
/* the landing: a thin, luminous line over the reminder,
   the one glacial word carrying the charge */
.sf-line {
  position: relative;
  font-size: clamp(1.35rem, 4.6svw, 4rem);
  font-weight: 300;
  letter-spacing: -.02em;
  line-height: 1.08;
  color: #fff;
  max-width: 24ch;
  text-wrap: balance;
  /* no text-shadow: the wmask3 clips would box it */
}
.sf-line .w-acc { color: var(--acc); }
.wmask3 { display: inline-block; overflow: clip; vertical-align: bottom; padding-right: .06em; margin-right: -.06em; padding-bottom: .22em; margin-bottom: -.22em; }
.wmask3 > span {
  display: inline-block;
  transform: translateY(135%);
  transition: transform 1.1s var(--ease);
}
.sf-line.in .wmask3 > span { transform: translateY(0); }
/* the attribution whispers in last */
.ser-attr {
  position: relative;   /* above the settled ink */
  margin-top: 2.4rem;
  font-size: 10px;
  font-weight: 520;
  letter-spacing: .34em;
  text-transform: uppercase;
  color: var(--mut);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 1.6s var(--ease) .3s, transform 1.6s var(--ease) .3s;
}
.ser-attr.in { opacity: 1; transform: translateY(0); }
/* the final lift is driven per-frame: no transition may fight it */
/* the last breath: a shade heavier than the lines before it */
/* name and years on their own lines */
.ser-attr .sa-n, .ser-attr .sa-y { display: block; }
.ser-attr .sa-y { margin-top: .55rem; color: var(--fnt); }
/* the accessible copy: whole passage for readers; visible only
   when motion is off */
.ser-static {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- tenets: the engraved plaque ---------- */

.tenets { padding: 0 5vw 12vh; }
.eth-head { padding-bottom: 7vh; }
/* the intro line: the About band's voice, a breath before the list */
.ten-intro {
  max-width: 880px;
  margin: -3vh auto 3.4rem;
  font-weight: 300;
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  line-height: 1.55;
  color: rgba(245, 245, 247, .62);
}
.ten-list {
  max-width: 880px;
  margin: 0 auto;
}
.ten {
  display: flex;
  align-items: baseline;
  gap: clamp(1.4rem, 3.4vw, 3rem);
  border-top: 1px solid var(--line);
  padding: clamp(1.3rem, 3.2vh, 2.1rem) 0;
  opacity: .3;
  will-change: opacity;
  cursor: pointer;
}
.ten:last-child { border-bottom: 1px solid var(--line); }
.ten i {
  font-style: normal;
  font-size: 11px;
  letter-spacing: .3em;
  color: var(--acc);
  flex: 0 0 2.4em;
  transition: transform .5s var(--ease), opacity .3s ease;
  transform-origin: left top;
}
/* version C: the row crossing center lights — numeral swells,
   an ice hairline draws beneath the tenet, the story unfolds */
.ten.lit i { transform: scale(1.6); }
.ten-body > p:first-child {
  width: fit-content;
  padding-bottom: .3em;
  background: linear-gradient(var(--acc), var(--acc)) no-repeat 0 100% / 0 1px;
  transition: background-size .7s var(--ease);
}
.ten.lit .ten-body > p:first-child { background-size: 100% 1px; }
.ten-body { flex: 1; min-width: 0; }
.ten p {
  font-size: clamp(1.3rem, 2.6vw, 2.1rem);
  font-weight: 330;
  line-height: 1.35;
  letter-spacing: .002em;
}
/* the story breathes open on demand — placeholder until David's words */
.ten .ten-story {
  font-size: clamp(.95rem, 1.5vw, 1.1rem);
  font-weight: 300;
  line-height: 1.6;
  color: var(--mut);
  max-width: 58ch;
  max-height: 0;
  opacity: 0;
  overflow: clip;
  margin-top: 0;
  transition: max-height .7s var(--ease), opacity .55s ease, margin-top .55s var(--ease);
}
.ten.open .ten-story { max-height: 24em; opacity: 1; margin-top: .8rem; }
/* quiet plus that folds to a close */
.ten-x {
  position: relative;
  flex: 0 0 30px;
  height: 30px;
  align-self: center;
  opacity: .45;
  transition: opacity .3s ease, transform .5s var(--ease);
}
.ten:hover .ten-x { opacity: .9; }
.ten-x span {
  position: absolute;
  left: 8px; right: 8px; top: 50%;
  height: 1px;
  background: var(--fg);
}
.ten-x span:last-child { transform: rotate(90deg); }
.ten.open .ten-x { transform: rotate(45deg); opacity: .9; }

/* ---------- outro: the world returns ---------- */

/* 150vh, down from 220: the question was pinned for well over a
   screen after it had finished arriving. It now lands, holds just
   long enough to be read, and releases straight into the footer. */
.outro2 { position: relative; height: 150vh; }
.o-stage {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: clip;
}
/* dusk veil: fades in as the world refocuses, keeping the
   ending distinct from the hero's clean sharpness */
.o-veil {
  position: absolute;
  inset: 0;
  opacity: 0;
  will-change: opacity;
  background:
    radial-gradient(80% 60% at 92% 104%, rgba(255, 157, 74, .1), transparent 60%),
    linear-gradient(135deg, rgba(6, 6, 7, 0) 0%, rgba(6, 6, 7, .16) 34%, rgba(6, 6, 7, .62) 64%, rgba(6, 6, 7, .96) 100%);
}
/* flipped variant: the ink pools bottom-LEFT under the statement,
   clearing to the top right (the cold breath moves with it) */
.o-veil-left {
  background:
    radial-gradient(80% 60% at 8% 104%, rgba(255, 157, 74, .1), transparent 60%),
    linear-gradient(45deg, rgba(6, 6, 7, .98) 0%, rgba(6, 6, 7, .72) 34%, rgba(6, 6, 7, .22) 64%, rgba(6, 6, 7, 0) 96%);
}
/* the ending mirrors the hero: statement bottom-left, the
   invitation as a quiet line beneath it */
.o-core {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  text-align: left;
  padding: 0 clamp(1.4rem, 4vw, 3.4rem) clamp(2.8rem, 7vh, 5rem);
  pointer-events: none;
}
.o-core h2 {
  font-size: clamp(1.7rem, 7.2svw, 6.8rem);
  font-weight: 640;
  letter-spacing: -.045em;
  line-height: .96;
  /* no text-shadow: the wmask2 clips would box it */
}
/* the words float in one by one, just like the hero's arrival —
   but triggered when you reach the ending */
.wmask2 { display: inline-block; overflow: clip; vertical-align: bottom; padding-right: .07em; margin-right: -.07em; padding-bottom: .22em; margin-bottom: -.22em; }
.wmask2 > span {
  display: inline-block;
  transform: translateY(135%);
  transition: transform 1.1s var(--ease);
}
.o-core h2.in .wmask2 > span { transform: translateY(0); }
/* the invitation: an exact twin of the hero subtitle */
.o-sub {
  display: block;
  margin-top: 1.5rem;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  height: 1.5em;
  overflow: clip;
  white-space: nowrap;
  width: fit-content;
  cursor: pointer;
  opacity: 0;
  will-change: transform, opacity;
  pointer-events: auto;
}
.o-sub .osr { display: block; transition: transform .5s var(--ease); }
.o-sub .osr span { display: block; height: 1.5em; }
.o-sub:hover .osr { transform: translateY(-1.5em); }

/* ---------- footer band ---------- */

.foot2 {
  position: relative;
  z-index: 2;
  background: var(--bg);
  padding: 4.6rem 6vw 1.6rem;
  border-top: 1px solid var(--line);
  overflow: clip;
}
.f-grid {
  max-width: 1180px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 2.4rem;
}
.fmark {
  font-size: 13px;
  font-weight: 400;
  letter-spacing: .3em;
  text-transform: uppercase;
}
.fmark b { font-weight: 800; }
.f-line { margin-top: 1rem; font-size: .95rem; font-weight: 300; color: var(--mut); }
.f-col h4 {
  font-size: 10px;
  font-weight: 500;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: var(--fnt);
  margin-bottom: 1.1rem;
}
.f-col a, .f-soon {
  display: block;
  width: fit-content;
  font-size: 13px;
  color: var(--mut);
  padding: .28em 0;
}
.f-col a {
  background: linear-gradient(var(--acc), var(--acc)) no-repeat 0 100% / 0 1px;
  transition: color .3s ease, background-size .4s var(--ease);
}
.f-col a:hover { color: var(--fg); background-size: 100% 1px; }
.f-soon { color: var(--fnt); }
.f-soon::after {
  content: "soon";
  font-size: 8.5px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--acc);
  opacity: .6;
  margin-left: .7em;
  vertical-align: middle;
}
.f-base {
  max-width: 1180px;
  margin: 3.4rem auto 0;
  padding: 1.2rem 0;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: .8rem 2rem;
}
.colophon { font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--fnt); }
/* THE TWO CLOCKS. David's time, then the reader's, with the gap
   between them — so a visitor can see at a glance how far off he is
   without doing the arithmetic. The second half hides itself for anyone
   already on Pacific time. */
.f-time {
  display: flex;
  align-items: center;
  gap: .9rem;
  flex-wrap: wrap;
  font-size: 10.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--fnt);
  font-variant-numeric: tabular-nums;
}
.ft-b { display: inline-flex; align-items: center; gap: .55rem; }
.ft-b[hidden] { display: none; }
/* the tick between the two, so they read as one instrument */
.ft-b i { width: 1.4rem; height: 1px; background: rgba(245, 245, 247, .2); }
.ft-b b { font-weight: 500; color: rgba(245, 245, 247, .62); }
/* the difference, in the accent — the one number a visitor actually
   wants from a clock that is not theirs */
.ft-b em {
  font-style: normal;
  font-weight: 550;
  letter-spacing: .12em;
  color: var(--acc);
}
@media (max-width: 560px) { .f-time { gap: .5rem 0; } .ft-b i { display: none; } }

.rv { opacity: 0; transform: translateY(24px); transition: opacity 1s var(--ease), transform 1s var(--ease); }
.rv.in { opacity: 1; transform: translateY(0); }

/* ---------- contact sheet ---------- */

.sheet {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  justify-content: center;
  visibility: hidden;
  opacity: 0;
  transition: opacity .45s var(--ease), visibility 0s linear .45s;
}
.sheet.on { visibility: visible; opacity: 1; transition: opacity .45s var(--ease); }
.sheet-skin {
  position: absolute;
  inset: 0;
  background: rgba(7, 7, 8, .96);
}
.sheet-x {
  position: absolute;
  top: 26px; right: 30px;
  width: 40px; height: 40px;
  z-index: 2;
  transition: transform .45s var(--ease);
}
.sheet-x span { position: absolute; left: 8px; right: 8px; top: 50%; height: 1.5px; background: var(--fg); }
.sheet-x span:first-child { transform: rotate(45deg); }
.sheet-x span:last-child { transform: rotate(-45deg); }
.sheet-x:hover { transform: rotate(90deg); }

.sheet-body {
  position: relative;
  z-index: 1;
  width: min(760px, 90vw);
  max-height: 88vh;
  overflow-y: auto;
}
.sh-kick { font-size: 11px; letter-spacing: .3em; text-transform: uppercase; color: var(--acc); margin-bottom: 3rem; }
.sh-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 1rem 1.4rem;
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--line);
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--ease), transform .7s var(--ease);
}
.sheet.on .sh-line { opacity: 1; transform: translateY(0); }
.sheet.on .sh-line:nth-of-type(1) { transition-delay: .12s; }
.sheet.on .sh-line:nth-of-type(2) { transition-delay: .2s; }
.sheet.on .sh-line:nth-of-type(3) { transition-delay: .28s; }
.sh-line label {
  font-weight: 300;
  font-size: clamp(1rem, 1.8vw, 1.3rem);
  color: var(--mut);
  flex: none;
}
.sh-line input, .sh-line textarea {
  flex: 1;
  min-width: 220px;
  background: none;
  border: 0;
  outline: none;
  color: var(--fg);
  font-family: inherit;
  font-weight: 650;
  font-size: clamp(1.5rem, 3.2vw, 2.4rem);
  letter-spacing: -.01em;
  caret-color: var(--acc);
}
.sh-line textarea { resize: none; line-height: 1.25; font-size: clamp(1.2rem, 2.4vw, 1.8rem); }
.sh-line ::placeholder { color: var(--fnt); font-weight: 400; }
.sh-msg { flex-direction: column; align-items: flex-start; }
.sh-msg textarea { width: 100%; }
.sh-send {
  margin-top: 2.4rem;
  display: inline-flex;
  align-items: center;
  gap: .8rem;
  padding: 1rem 1.5rem 1rem 2rem;
  border-radius: 16px;
  background: var(--fg);
  color: #0a0a0c;
  font-size: 13px;
  letter-spacing: .14em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s var(--ease) .36s, transform .7s var(--ease) .36s, scale .3s var(--ease);
}
.sheet.on .sh-send { opacity: 1; transform: translateY(0); }
.sh-send:hover { scale: 1.04; }
.sh-send b { font-weight: 400; }
.hp { position: absolute; left: -9999px; }
.sh-done p.d1 { font-size: clamp(1.6rem, 3.4vw, 2.6rem); font-weight: 650; letter-spacing: -.01em; }
.sh-done p.d2 { margin-top: 1rem; font-weight: 300; color: var(--mut); }

/* ---------- privacy ---------- */

.pmodal {
  position: fixed; inset: 0; z-index: 420;
  display: none; align-items: center; justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, .45);
}
.pmodal.on { display: flex; }
.ppanel {
  width: min(620px, 94vw);
  max-height: 82vh;
  overflow: auto;
  border-radius: 4px;
  padding: 38px;
  background: #0b0b0d;
  border: 1px solid var(--line);
}
.ppanel h3 { font-size: 1.4rem; margin-bottom: 1rem; }
.ppanel p { font-size: .93rem; line-height: 1.6; color: var(--mut); margin-bottom: .9rem; }
.ppanel b { color: var(--fg); }
.pclose { position: absolute; top: 12px; right: 16px; font-size: 24px; }

/* ---------- responsive ---------- */

/* THE HERO SUB ON A NARROW PHONE. It is nowrap and fit-content, which
   was fine for the four-word line it used to carry. The line David
   chose on 2026-08-26 is 41 characters and measured 345px against a
   375px viewport — 8px of clearance — and at 320px it pushed the
   document wide enough to scroll sideways. It steps down a size below
   400px and is allowed to break if it still has to. */
@media (max-width: 400px) {
  .hero-sub {
    font-size: 13px;
    letter-spacing: .14em;
    white-space: normal;
    max-width: 86vw;
  }
}
@media (max-width: 820px) {
  .brand { left: 18px; }
  .menu-btn { right: 18px; }
  .x-f { width: calc(var(--fw, 15vw) * 1.6); opacity: .85; }
}
@media (max-width: 560px) {
  .x-f { width: 24vw; min-width: 76px; opacity: .55; left: 3%; }
  .x-f.xr { left: auto; right: 3%; }
}
@media (max-width: 560px) {
  .hero-sub, .o-sub { font-size: 11px; }
}
@media (max-width: 360px) {
  .hero-sub, .o-sub { font-size: 9.5px; }
  .page-head h1 { font-size: 1.7rem; }
}
@media (max-width: 720px) {
  .f-grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
  .f-lead { grid-column: 1 / -1; }
}

/* ---------- reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .grain { animation: none; }
  .world img { --wblur: 14px; --wbright: .55; transform: none; transition: none; filter: blur(14px) brightness(.55); }
  .world-tint { --wp: 1; }
  .wmask > span { transform: none; transition: none; }
  .hero-sub, .scroll-cue { opacity: 1; transform: none; transition: none; }
  .hero-sub::after { transform: scaleX(1); transition: none; }
  .scroll-cue svg { animation: none; }
  .menu-list a { opacity: 1; transform: none; filter: none; transition: none; }
  .menu-list a[aria-current="page"] span::after { animation: none; opacity: 1; }
  .wall { height: auto; }
  .wall-stage { position: relative; height: auto; padding: 10vh 0; }
  .wall-film { display: none; }
  .wall-stage .x-head { position: static; padding: 0 clamp(1.4rem, 4vw, 3.4rem) 6vh; }
  .wall-grid { position: static; padding: 0 6vw; row-gap: 3rem; }
  .press { position: static; width: auto; margin: 0 auto; opacity: 1; transform: none; pointer-events: auto; padding-top: 4vh; }
  .wl img { transform: none; transition: none; }
  .sermon, .sermon[data-mode] { height: auto; }
  .ser-stage { position: relative; height: auto; padding: 16vh 5vw; background: none; }
  .ser-stage .x-head { position: static; max-width: 880px; margin: 0 auto; padding-bottom: 2.2rem; }
  .ser-film, .ser-flow { display: none; }
  .ser-static {
    position: static; width: auto; height: auto;
    overflow: visible; clip-path: none; white-space: normal;
    max-width: 880px; margin: 0 auto;
  }
  .exp2 { height: auto; }
  .x-stage { position: relative; height: auto; padding: 10vh 0 4vh; }
  .x-head { position: static; padding-bottom: 6vh; }
  .x-frames { display: none; }
  .x-spine { position: static; }
  .x-beat { position: static; opacity: 1 !important; transform: none !important; filter: none !important; padding: 7vh 7vw; }
  .outro2 { height: auto; }
  .o-stage { position: relative; }
  .o-veil { opacity: 1; }
  .o-core { position: relative; padding: 26vh 6vw 22vh; }
  .o-core h2 { opacity: 1 !important; transform: none !important; }
  .wmask2 > span { transform: none; transition: none; }
  .ten .ten-story { transition: none; }
  .ethos2 { height: auto; }
  .e2-stage { position: relative; height: auto; padding: 8vh 0; }
  .e2-video { display: none; }
  .reel { height: auto; }
  .reel-stage { position: relative; height: auto; padding: 10vh 7vw; }
  .reel-item { display: block; padding: 5vh 0; }
  .reel-item img, .reel-item p {
    position: static; translate: none; opacity: 1 !important;
    transform: none !important; margin: 0 auto;
  }
  .reel-item p { margin-top: 1.2rem; }
  .o-sub { opacity: 1 !important; transform: none !important; }
  .ten { opacity: 1 !important; }
  .rv { opacity: 1; transform: none; transition: none; }
  .rule { transform: none; transition: none; }
  .sh-line, .sh-send { opacity: 1 !important; transform: none !important; transition: none; }
}
