/* ── Story page: scroll-driven narrative ──
   Layers on styles.css (header/footer/tokens). Everything scoped under
   body.story-page so nothing leaks into other pages that share styles.css.

   Progressive enhancement model:
   - <html class="story-static"> ships in the markup. This file styles BOTH
     modes; the static mode (gradient backgrounds, fallback images, no canvas)
     is the complete designed experience for no-JS / no-WebGL / old Safari /
     prefers-reduced-motion visitors.
   - story.js removes .story-static ONLY after the WebGL renderer constructs
     successfully (M3+). */

body.story-page {
  background: #0e0f14;
  color: #f4f3ef;
  /* Counteract styles.css's uppercase 10px base — the story reads as
     editorial prose, not nav chrome. */
  text-transform: none;
  letter-spacing: normal;
  font-size: 16px;
  /* All non-title text. Monaspace Neon (GitHub Next) — terminal-flavored
     to match the 90s-tech scene. Swap Neon for Argon/Xenon/Krypton here
     to try the other Monaspace voices. */
  --story-mono: "Monaspace Neon", "SF Mono", "Menlo", "Consolas", monospace;
}

/* ── Fixed canvas (M3+) ── */
#storyCanvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
html.story-static #storyCanvas {
  display: none;
}

/* ── Header overrides ──
   styles.css gives us the floating pill; keep it but make it legible on the
   dark story background. Always visible (narrative page — no hide-on-scroll). */
body.story-page .site-header {
  background: rgba(14, 15, 20, 0.55);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
body.story-page .site-header .brand__name,
body.story-page .site-header .site-nav a {
  color: #f4f3ef;
  font-family: var(--story-mono);
}
body.story-page .site-header .brand__role {
  color: rgba(244, 243, 239, 0.55);
  font-family: var(--story-mono);
}
body.story-page .site-nav a:hover {
  color: #ffffff;
}

/* ── CRT overlay (enhanced mode only) ──
   Soft-90s finishing pass over the WebGL canvas: faint scanlines + a
   gentle vignette. Sits between the canvas (z0) and the DOM text (z2).
   pointer-events: none — purely cosmetic. */
.story-crt {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  display: none;
  background:
    repeating-linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.14) 0px,
      rgba(0, 0, 0, 0.14) 1px,
      transparent 1px,
      transparent 3px
    ),
    radial-gradient(
      130% 100% at 50% 50%,
      transparent 55%,
      rgba(0, 0, 0, 0.32) 100%
    );
}
html.story-enhanced:not(.story-static) .story-crt {
  display: block;
}
/* Mobile: full-viewport repeating gradients are compositor-expensive on
   phone GPUs and the scanlines are barely visible at small sizes anyway. */
@media (pointer: coarse), (max-width: 700px) {
  html.story-enhanced:not(.story-static) .story-crt {
    display: none;
  }
}

/* ── Chapter sections ── */
.story {
  position: relative;
  z-index: 2; /* above canvas (0) and CRT overlay (1) */
}

.story-chapter {
  /* 150svh of scroll runway per chapter (svh not vh: iOS URL-bar jump).
     The extra 50svh slows the pacing — the 3D transition gets breathing
     room while the sticky wrapper below keeps the text center-stage. */
  min-height: 150svh;
  position: relative;
}

.story-chapter__sticky {
  position: sticky;
  top: 0;
  min-height: 100svh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 96px 6vw;
  box-sizing: border-box;
}

.story-chapter__inner {
  max-width: 720px;
  width: 100%;
}

/* Mobile: native CSS scroll-snap instead of ScrollTrigger's tween-based
   snap — iOS momentum scrolling integrates with native snap natively,
   while the JS snap waits for scroll-end and feels like it "doesn't
   work". story.js skips ScrollTrigger snap in lite mode; this media
   query matches story.js's isLite condition (coarse pointer OR <760px)
   so every mode has exactly one snap mechanism. */
@media (pointer: coarse), (max-width: 760px) {
  html {
    scroll-snap-type: y proximity;
  }
  .story-chapter {
    scroll-snap-align: start;
  }
}

/* ── Static-mode chapter backgrounds ──
   One accent hue per chapter; these gradients ARE the fallback experience
   and double as the color script the 3D palette follows in M3+. */
html.story-static .story-chapter--intro                  { background: radial-gradient(120% 100% at 50% 0%, #1b2030 0%, #0e0f14 70%); }
html.story-static .story-chapter[data-chapter-index="1"] { background: radial-gradient(120% 100% at 50% 20%, #14233c 0%, #0e0f14 75%); }
html.story-static .story-chapter[data-chapter-index="2"] { background: radial-gradient(120% 100% at 50% 20%, #15301f 0%, #0e0f14 75%); }
html.story-static .story-chapter[data-chapter-index="3"] { background: radial-gradient(120% 100% at 50% 20%, #2b1a30 0%, #0e0f14 75%); }
html.story-static .story-chapter[data-chapter-index="4"] { background: radial-gradient(120% 100% at 50% 20%, #33201a 0%, #0e0f14 75%); }
html.story-static .story-chapter[data-chapter-index="5"] { background: radial-gradient(120% 100% at 50% 20%, #102e31 0%, #0e0f14 75%); }
html.story-static .story-chapter--outro                  { background: radial-gradient(120% 100% at 50% 80%, #1b2030 0%, #0e0f14 70%); }

/* ── Typography ── */
.story-chapter__kicker {
  margin: 0 0 18px;
  font-family: var(--story-mono);
  font-size: 10px;
  font-weight: 500;
  /* Mono is naturally airy — heavy tracking on top reads gappy */
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(244, 243, 239, 0.55);
}

.story-chapter__title {
  margin: 0 0 20px;
  font-family: "Geologica", "Helvetica Neue", Arial, sans-serif;
  font-weight: 900;
  font-size: clamp(40px, 7vw, 48px);
  line-height: 1.02;
  letter-spacing: 0.01em;
  color: #ffffff;
}

.story-chapter__lede {
  margin: 0 0 28px;
  font-family: var(--story-mono);
  /* Mono runs wide — a step smaller than the Inter sizing it replaces */
  font-size: clamp(14px, 1.45vw, 16px);
  font-weight: 400;
  line-height: 1.65;
  color: rgba(244, 243, 239, 0.78);
  max-width: 58ch;
}

.story-chapter__meta {
  margin: 0 0 14px;
  display: flex;
  gap: 14px;
  align-items: baseline;
  font-family: var(--story-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(244, 243, 239, 0.5);
}
.story-chapter__meta strong {
  color: rgba(244, 243, 239, 0.85);
  font-weight: 500;
}

/* ── CTAs ── */
.story-chapter__actions {
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
}

/* Scoped under body.story-page (specificity 0,2,1) so the dark-on-light
   text beats styles.css's `a[href^="mailto"] { color: inherit;
   -webkit-text-fill-color: currentColor }` (0,1,1) — without this, the
   "Email Me" mailto button inherited near-white text onto its near-white
   fill and vanished. -webkit-text-fill-color must be set explicitly
   because that property, once set by the mailto rule, wins over `color`. */
body.story-page .story-chapter__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 13px 24px;
  border-radius: 999px;
  background: #f4f3ef;
  color: #0e0f14;
  -webkit-text-fill-color: #0e0f14;
  font-family: var(--story-mono);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.01em;
  transition: transform 0.25s cubic-bezier(0.22, 1, 0.36, 1), background 0.25s ease;
}
body.story-page .story-chapter__cta:hover {
  transform: translateY(-2px);
  background: #ffffff;
  color: #0e0f14;
  -webkit-text-fill-color: #0e0f14;
}
body.story-page .story-chapter__cta--ghost {
  background: transparent;
  color: #f4f3ef;
  -webkit-text-fill-color: #f4f3ef;
  border: 1px solid rgba(244, 243, 239, 0.5);
}
body.story-page .story-chapter__cta--ghost:hover {
  background: rgba(244, 243, 239, 0.08);
  color: #ffffff;
  -webkit-text-fill-color: #ffffff;
}

/* ── Static-mode fallback image ──
   Hidden in enhanced mode (the 3D planes replace it). */
.story-chapter__fallback {
  display: none;
  margin-top: 36px;
  width: 100%;
  max-width: 560px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
}
html.story-static .story-chapter__fallback {
  display: block;
}

/* ── Chapter number ── */
.story-chapter__index {
  font-family: var(--story-mono);
  font-weight: 500;
  font-size: 10px;
  letter-spacing: 0.3em;
  color: rgba(244, 243, 239, 0.35);
}

/* ── Intro cues: mouse + keyboard ── */
.story-chapter__cues {
  margin-top: 56px;
  display: flex;
  align-items: center;
  gap: 16px;
}

.story-chapter__cue-or {
  font-family: var(--story-mono);
  font-size: 9px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(244, 243, 239, 0.35);
}

.story-chapter__scroll-cue {
  width: 26px;
  height: 42px;
  border: 2px solid rgba(244, 243, 239, 0.35);
  border-radius: 14px;
  position: relative;
}
.story-chapter__scroll-cue span {
  position: absolute;
  top: 8px;
  left: 50%;
  width: 4px;
  height: 8px;
  margin-left: -2px;
  border-radius: 2px;
  background: rgba(244, 243, 239, 0.7);
  animation: storyScrollCue 1.8s ease-in-out infinite;
}
@keyframes storyScrollCue {
  0%, 100% { transform: translateY(0); opacity: 1; }
  60%      { transform: translateY(12px); opacity: 0.2; }
  80%      { transform: translateY(12px); opacity: 0; }
}

/* Keycap that presses itself — advertises the arrow-key navigation.
   3D press: the cap drops onto its shadow ledge, then springs back.
   Same 1.8s period as the mouse cue so the two breathe together. */
.story-key-cue__cap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border: 2px solid rgba(244, 243, 239, 0.35);
  border-radius: 7px;
  font-family: var(--story-mono);
  font-size: 13px;
  color: rgba(244, 243, 239, 0.7);
  box-shadow: 0 3px 0 rgba(244, 243, 239, 0.25);
  animation: storyKeyPress 1.8s ease-in-out infinite;
}
@keyframes storyKeyPress {
  0%, 38%, 100% {
    transform: translateY(0);
    box-shadow: 0 3px 0 rgba(244, 243, 239, 0.25);
  }
  12%, 24% {
    transform: translateY(3px);
    box-shadow: 0 0 0 rgba(244, 243, 239, 0.25);
  }
}

/* No physical keyboard on touch devices — hide the keycap + "or",
   keep the mouse/scroll cue as the universal affordance. */
@media (pointer: coarse), (max-width: 760px) {
  .story-key-cue,
  .story-chapter__cue-or {
    display: none;
  }
}

/* ── Outro ── */
.story-chapter__copyright {
  margin-top: 48px;
  font-family: var(--story-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* 0.55 keeps this real text content above WCAG AA 4.5:1 on #0e0f14 */
  color: rgba(244, 243, 239, 0.55);
}

/* Visible keyboard focus on the dark story page. styles.css's default
   focus ring is near-black (1px #111) — invisible here. Light, offset
   ring for keyboard users; mouse clicks stay clean via :focus-visible. */
body.story-page a:focus-visible,
body.story-page button:focus-visible {
  outline: 2px solid #f4f3ef;
  outline-offset: 3px;
  border-radius: 2px;
}

/* ── Chapter dot rail ──
   Hidden by default; story.js adds html.story-enhanced once GSAP loads
   (M2). Note this is a separate gate from .story-static, which controls
   the VISUAL fallbacks (gradients, images, canvas) and is only removed
   when the WebGL renderer constructs (M3). */
.story-rail {
  position: fixed;
  right: 22px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  display: none;
  flex-direction: column;
  gap: 12px;
}
html.story-enhanced .story-rail {
  display: flex;
}
.story-rail__dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border: 1px solid rgba(244, 243, 239, 0.4);
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  transition: background 0.25s ease, transform 0.25s ease;
}
.story-rail__dot:hover {
  transform: scale(1.3);
}
.story-rail__dot.is-active {
  background: #f4f3ef;
  border-color: #f4f3ef;
}

/* ── Terminal HUD readout (enhanced desktop only) ──
   Fixed wayfinding chip: chapter + raw scroll percent in tracked mono,
   mirroring the kicker treatment. Hidden on lite/mobile — the rail and
   native snap carry orientation there. */
.story-hud {
  position: fixed;
  left: 22px;
  bottom: 18px;
  z-index: 5;
  display: none;
  gap: 16px;
  font-family: var(--story-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: rgba(244, 243, 239, 0.45);
  pointer-events: none;
}
html.story-enhanced .story-hud {
  display: flex;
}
@media (pointer: coarse), (max-width: 760px) {
  html.story-enhanced .story-hud {
    display: none;
  }
}

/* ── Text reveal ──
   .is-active is toggled by IntersectionObserver (static mode) or
   ScrollTrigger (enhanced mode, M2+). Same class, same CSS. */
.story-chapter__inner > * {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.7s cubic-bezier(0.22, 1, 0.36, 1),
              transform 0.7s cubic-bezier(0.22, 1, 0.36, 1);
}
.story-chapter.is-active .story-chapter__inner > * {
  opacity: 1;
  transform: translateY(0);
}
/* Stagger the children */
.story-chapter.is-active .story-chapter__inner > *:nth-child(2) { transition-delay: 0.08s; }
.story-chapter.is-active .story-chapter__inner > *:nth-child(3) { transition-delay: 0.16s; }
.story-chapter.is-active .story-chapter__inner > *:nth-child(4) { transition-delay: 0.24s; }
.story-chapter.is-active .story-chapter__inner > *:nth-child(5) { transition-delay: 0.32s; }
.story-chapter.is-active .story-chapter__inner > *:nth-child(6) { transition-delay: 0.4s; }

@media (prefers-reduced-motion: reduce) {
  .story-chapter__inner > * {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .story-chapter__scroll-cue span,
  .story-key-cue__cap {
    animation: none;
  }
}

/* ── Mobile ── */
@media (max-width: 700px) {
  .story-chapter {
    /* Slightly shorter runway on phones — 150svh reads as dead air there */
    min-height: 130svh;
  }
  .story-chapter__sticky {
    padding: 80px 24px;
  }
  .story-chapter__title {
    font-size: clamp(34px, 11vw, 52px);
  }
  .story-rail {
    right: 12px;
    gap: 10px;
  }
  .story-chapter__fallback {
    max-width: 100%;
  }
  body.story-page .site-header {
    width: calc(100vw - 32px);
    min-width: 0;
  }
}
