/* Sticky-canvas chapters: one held full-viewport media layer per chapter,
   copy beats passing over it (the researched Apple/Pudding grammar).
   Pure position:sticky — no JS pinning; scenes.js only fires beat/layer
   toggles via IntersectionObserver. Loaded by every chapter layout,
   including variant I, the live design. */

/* ══════════════════════════════════════════════════════════════════════
   THE CHAPTER — every knob for the scrolling story, in one place.

   This is the whole tuning surface for the live layout (site/i/). Nothing
   here is set anywhere else: the page's code reads these same values, so
   changing one number here changes it everywhere, including the pauses.

   ── What happens when you scroll a section into view ──────────────
     1. it reaches --start-when of the screen and the section begins
     2. the headline and first photo hold ALONE for --wait-headline-alone
     3. the content arrives over --fade-content, rising --rise-content
     4. the photo darkens behind it by --darken-under-text
     5. if the section has more photos, it changes every --wait-per-photo,
        each dissolving over --fade-photo, and rests on the last one

   ── Reading the values ────────────────────────────────────────────
     2400ms = 2.4 seconds. Bigger is slower.
     0.38   = how dark, from 0 (untouched) to 1 (black).
     26px   = how far something slides while it fades in.

   To try something: edit a number here and reload. Or, to see it without
   rebuilding, open the browser inspector, find :root, and change it live.
   ══════════════════════════════════════════════════════════════════════ */
:root {
  /* ── PAUSES: how long the page waits ─────────────────────────────── */
  --wait-headline-alone: 1050ms;  /* the headline sits on the photo by itself
                                     before anything else arrives. This is the
                                     held breath you feel in every section. */
  --wait-per-photo: 4200ms;       /* sections with several photos: how long
                                     each is held before changing to the next */
  --start-when: 0.6;              /* how much of a section must be on screen
                                     before any of it begins, 0 to 1.
                                     Lower = starts earlier as you scroll. */

  /* ── FADES: how long each change takes ───────────────────────────── */
  --fade-photo: 2400ms;           /* one photo dissolving into the next. Slow on
                                     purpose: it should read as the light
                                     changing, not as a slideshow. */
  --fade-headline: 700ms;         /* the headline arriving */
  --fade-content: 900ms;          /* the text and lists that follow it */
  --fade-document: 800ms;         /* the timings document, which arrives line
                                     by line rather than all at once */
  --fade-darkening: 1100ms;       /* the photo darkening behind arriving text */
  --fade-wash: 700ms;             /* the gentle wash that is always present */

  /* ── DARKNESS: how far each photo dims so text stays readable ────── */
  --darken-under-text: 0.38;      /* under a headline and a line or two */
  --darken-under-list: 0.58;      /* under a list — there is more to read */
  --darken-under-document: 0.74;  /* under the full timings document, the most
                                     text the page ever shows at once */

  /* ── MOVEMENT: how far things slide while they fade in ───────────── */
  --rise-content: 26px;
  --rise-document: 22px;

  /* ── THE DOCUMENT: section 04, which arrives line by line ────────── */
  --stagger-document-line: 110ms; /* gap between one line and the next in the
                                     timings document - each element waits one
                                     gap longer than the one above it. (The
                                     document beat overrides this below with a
                                     slower, more deliberate step.) */
  --wait-caption: 950ms;          /* the small caption underneath waits for the
                                     lines to land before appearing */

  --chapter-ease: cubic-bezier(0.2, 0, 0, 1);  /* slow start, gentle stop */
}

/* ══ WHERE ONE SECTION DIFFERS ═════════════════════════════════════════
   Everything above applies to every section. A section only appears below
   when it should behave differently — and it inherits the rest.
   ══════════════════════════════════════════════════════════════════════ */

/* 05 The Moment — the only section carrying three photographs. It holds
   longer before the content lands, and walks its photos more slowly:
   the thin-sun seascape, then the deck crescents, then the shadow wall
   crossing the sea, where it rests. */
.beat-moment {
  --wait-headline-alone: 2400ms;
  --wait-per-photo: 5200ms;
}

/* 04 The Timings — the document beat. The vessel at anchor gets a LONG
   wordless hold before anything lands on it, and then the document arrives
   line by line with a slower, more deliberate step between lines:
   kicker, then the chart, then the schedule, then the caption. */
.beat.doc {
  --wait-headline-alone: 3200ms;  /* how long the vessel holds ALONE, undimmed,
                                     before the document starts arriving */
  --stagger-document-line: 420ms; /* the pause between document lines: kicker,
                                     then chart, then schedule, then caption */
}

/* PAGING: native mandatory snap with scroll-snap-stop — one gesture moves
   one screen, inertia halts at every page DURING the gesture (no delayed
   JS snapback), and no rest position can fall between pages. The scrub
   regions stay free via the covering-area rule: a snap area taller than
   the viewport makes every interior position a valid rest — so the hero
   pin, the Shadow Clock pin, and the ending runway are snap areas whose
   whole range scrolls freely. */
html { scroll-snap-type: y mandatory; }
.beat { scroll-snap-align: center; scroll-snap-stop: always; }
/* a chapter's first page rests with its media edge flush to the viewport —
   never with a sliver of the previous page showing */
.chapter .beat:first-child { scroll-snap-align: start; }
.screen, .interstitial { scroll-snap-align: start; scroll-snap-stop: always; }
/* free-scroll ranges (taller than the viewport, so their interior is
   always a valid rest) */
.pin-spacer, .ending { scroll-snap-align: start; }
/* the hero must be a valid rest BEFORE GSAP wraps it in its pin-spacer —
   otherwise the load-time snap jumps the page into the middle of the
   transit before the scrub even exists */
.hero { scroll-snap-align: start; }
.invite { scroll-snap-align: none; }

.chapter { position: relative; }
.chapter-media {
  position: sticky; top: 0; height: 100svh; overflow: hidden;
  background: #121212;
}
.media-layer {
  position: absolute; inset: 0; opacity: 0;
  transition: opacity var(--fade-photo) var(--chapter-ease);
}
.media-layer.active { opacity: 1; }
.media-layer img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* type protection: gradient scrim, never capsules (imagery grammar) */
/* type protection plus EDGE VEILS: the topmost and bottommost bands melt
   into the page surface so a chapter never hard-cuts against its
   neighbors — every seam is a dissolve, not an edge */
.chapter-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(18,18,18,0.88) 0%, rgba(18,18,18,0.30) 9%, rgba(18,18,18,0.14) 30%, rgba(18,18,18,0.10) 55%, rgba(18,18,18,0.12) 86%, rgba(18,18,18,0.35) 95%, rgba(18,18,18,0.92) 100%);
  transition: opacity var(--fade-wash) var(--chapter-ease);
}
/* quiet (caption-only) beats: the image is the content — no veil at all */
.chapter.bare .chapter-scrim { opacity: 0; }
/* the media itself dims while copy is on stage (Apple pattern): the dim is
   attached to the STICKY layer, so nothing travels with the scroll — the
   image breathes back to full between beats */
.chapter-dim {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  background: #0A0910;
  transition: opacity var(--fade-darkening) var(--chapter-ease);
}
/* the image leads; the dim arrives only once content has rendered, and
   stays gentle */
.chapter.veiled .chapter-dim { opacity: var(--darken-under-text); }
.chapter.deep .chapter-dim { opacity: var(--darken-under-list); }

.chapter-beats { position: relative; z-index: 2; margin-top: -100svh; }
.beat {
  min-height: 100svh; display: flex; align-items: center; justify-content: center;
  padding: 0 28px; text-align: center;
}
.beat:has(.beat-rows) { min-height: 80svh; }
/* staged beats: the statement arrives alone over the early canvas; when
   the beat settles the canvas dissolves and the content column stages in */
.beat.staged { min-height: 100svh; }
.beat.staged .beat-inner > div:last-of-type,
.beat.staged .foot-cap {
  opacity: 0; transform: translateY(var(--rise-content));
  transition: opacity var(--fade-content) var(--chapter-ease), transform var(--fade-content) var(--chapter-ease);
}
.beat.staged.full .beat-inner > div:last-of-type,
.beat.staged.full .foot-cap { opacity: 1; transform: none; }
.beat-inner {
  max-width: 720px; position: relative; padding: 10px;
  opacity: 0; transform: translateY(var(--rise-content));
  transition: opacity var(--fade-headline) var(--chapter-ease), transform var(--fade-headline) var(--chapter-ease);
}
.beat.in .beat-inner { opacity: 1; transform: none; }
.beat .statement { max-width: 16ch; margin-left: auto; margin-right: auto; text-shadow: 0 2px 18px rgba(0,0,0,0.65); }
.beat .support { margin-left: auto; margin-right: auto; text-shadow: 0 1px 12px rgba(0,0,0,0.7); }
.beat .kicker { text-shadow: 0 1px 10px rgba(0,0,0,0.8); }
.beat .dataline { text-shadow: 0 1px 10px rgba(0,0,0,0.8); }

/* compact utility stacks inside beats (lists, timelines, sensory lines) */
.beat-rows { margin: 0 auto; max-width: 560px; text-align: left; }
.beat-rows .br { display: grid; grid-template-columns: 130px 1fr; gap: 18px; align-items: baseline; padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.14); }
.beat-rows .br:first-child { border-top: 1px solid rgba(255,255,255,0.14); }
.beat-rows .bt { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 16px; letter-spacing: 0.06em; color: rgba(255,253,245,0.64); font-variant-numeric: tabular-nums; white-space: nowrap; }
.beat-rows .br.key .bt { color: #E2B383; font-weight: 500; }
.beat-rows .bh { font-family: "Moderno", Georgia, serif; font-size: 20px; }
.beat-rows .bp { font-size: 14.5px; font-weight: 300; color: rgba(255,253,245,0.7); margin-top: 2px; }
.beat-rows .br > div:last-child { text-shadow: 0 1px 10px rgba(0,0,0,0.7); }

/* quiet caption beats read as CAPTIONS: small type resting at the bottom
   of the image, never a centered title */
.beat.quiet { align-items: flex-end; }
/* captions are captions: always painted at full strength — they never
   fade in from below like statements do */
.beat.quiet .beat-inner { padding-bottom: clamp(28px, 5vh, 56px); opacity: 1; transform: none; transition: none; }
/* ...except on a STAGED quiet beat, where the caption belongs to the full
   image (totality), not the entry image (the shadow wall) */
.beat.quiet.staged .beat-inner { opacity: 0; transition: opacity var(--fade-content) var(--chapter-ease); }
.beat.quiet.staged.full .beat-inner { opacity: 1; }
.beat.quiet .beat-cap { text-shadow: 0 1px 14px rgba(0,0,0,0.9), 0 0 30px rgba(0,0,0,0.6); }

/* gold solo caption beat (the Glasses Off moment) */
.beat .beat-cap { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 13px; letter-spacing: 0.26em; text-transform: uppercase; color: #E2B383; text-shadow: 0 1px 12px rgba(0,0,0,0.8); }

@media (max-width: 760px) {
  .beat-inner { max-width: 92vw; }
  .beat-rows .br { grid-template-columns: 96px 1fr; gap: 12px; }
  .beat-rows .bh { font-size: 18px; }
}

@media (prefers-reduced-motion: reduce) {
  .beat-inner { opacity: 1; transform: none; transition: none; }
  .media-layer { transition: none; }
  .beat.staged .beat-inner > div:last-of-type,
  .beat.staged .foot-cap { opacity: 1; transform: none; transition: none; }
}
