/* Lynx FP — cinematic scrollytelling engine styles.

   Every new rule here is namespaced `sc-` so it can never collide with the
   scene-specific CSS (scene-<id>.css) or the presenter stage (theme.css's
   `.scene` / `.stage`, used only by presentation.html / control.html).
   Loaded after theme.css + every scene-<id>.css, so it wins ties on equal
   specificity without needing `!important`.

   Reuses theme.css tokens (--ink, --gold, --speed, --t) and the existing
   `--fit` contract on `.scene-inner` (see theme.css:180-191) — story.html's
   own shrink-only autofit (frontend/js/scroll.js:recomputeFits) just writes
   into that same custom property instead of reinventing scaling. */

/* theme.css sets body{overflow:hidden} for the fixed presenter stage — this
   page scrolls natively. */
html, body {
  height: auto;
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior-y: none;
}

.sc-root {
  position: relative;
  background: var(--grad-stage);
}

/* ---------------------------------------------------------------- chapter
   Each chapter is a tall block. `.sc-stage` pins to the top of the viewport
   for the whole block via position:sticky (native scroll — no JS scroll-
   jacking). Chapters after the first pull up by one viewport height so that,
   for exactly one viewport height of scrolling, the outgoing chapter and the
   incoming one are BOTH fully pinned in the same screen space — that shared
   window is what lets scroll.js cross-fade one into the other instead of
   cutting. See scroll.js's `render()` for the math. */
.sc-chapter {
  --sc-overlap: 100dvh;
  position: relative;
  width: 100%;
  z-index: 1;
}
.sc-chapter:not(:first-child) {
  margin-top: calc(-1 * var(--sc-overlap));
}

.sc-stage {
  position: sticky;
  top: 0;
  height: 100dvh;
  overflow: hidden;
  display: grid;
  grid-template-columns: 100%;
  align-content: center;
  justify-items: stretch;
  padding: clamp(18px, 3vh, 44px) clamp(20px, 4.4vw, 86px);
  background: var(--grad-stage);
  will-change: opacity, transform;
}

/* opacity/transform are written every frame by scroll.js for the crossfade
   and are intentionally NOT CSS-transitioned — they already track scroll
   continuously, and a competing CSS transition would just add lag. */
.sc-stage .scene-bg { transition: opacity 1.2s var(--t), transform 0s linear; }

/* -------------------------------------------------------------- first load */
.sc-boot {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center; gap: 20px;
  background: #0B0C0A;
  transition: opacity .5s ease;
}
.sc-boot.sc-gone { opacity: 0; pointer-events: none; }
.sc-boot-bar {
  width: min(240px, 40vw); height: 2px;
  background: rgba(255, 255, 255, .12);
  border-radius: 2px;
  overflow: hidden;
}
.sc-boot-bar i {
  display: block; height: 100%; width: 30%;
  background: linear-gradient(90deg, #D9B45A, #F7E7BC);
  animation: sc-boot-sweep 1.1s ease-in-out infinite;
}
@keyframes sc-boot-sweep {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(340%); }
}
.sc-boot p {
  font-size: 11px; letter-spacing: .28em; text-transform: uppercase;
  color: rgba(255, 255, 255, .32);
}

.sc-error {
  position: fixed; inset: 0; z-index: 210;
  display: grid; place-items: center; padding: 40px;
  background: #0B0C0A; text-align: center;
}
/* `hidden` is ONLY `display: none` in the UA stylesheet, so the `display: grid`
   above outranks it and the panel rendered over a perfectly working story —
   opaque, full-viewport, z-index 210. Any rule that sets `display` on an
   element you also toggle with the `hidden` attribute needs this companion. */
.sc-error[hidden] { display: none; }
.sc-error strong {
  display: block; color: var(--gold-hi); font-size: 20px; margin-bottom: 10px;
}
.sc-error p { max-width: 46ch; color: var(--paper-dim); font-size: 15px; line-height: 1.6; }

/* ------------------------------------------------------------- scroll hint */
.sc-hint {
  position: fixed;
  left: 50%;
  bottom: clamp(18px, 3vh, 34px);
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: var(--paper-faint);
  font-size: 11px;
  letter-spacing: .24em;
  text-transform: uppercase;
  opacity: 1;
  transition: opacity .5s var(--t);
  pointer-events: none;
}
.sc-hint.sc-gone { opacity: 0; }
.sc-hint-chev {
  width: 16px; height: 16px;
  border-right: 2px solid var(--gold);
  border-bottom: 2px solid var(--gold);
  transform: rotate(45deg);
  animation: sc-bob 1.6s ease-in-out infinite;
}
@keyframes sc-bob {
  0%, 100% { transform: rotate(45deg) translate(0, 0); opacity: .5; }
  50%      { transform: rotate(45deg) translate(5px, 5px); opacity: 1; }
}

/* --------------------------------------------------------- progress rail */
.sc-rail {
  position: fixed;
  right: clamp(10px, 2vw, 26px);
  top: 50%;
  transform: translateY(-50%);
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  max-height: 82vh;
  overflow: visible;
}
.sc-rail-dot {
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: none;
  padding: 4px 2px;
  margin: 0;
  cursor: pointer;
  color: var(--paper-faint);
  opacity: .65;
  transition: opacity .3s var(--t);
}
.sc-rail-dot:hover, .sc-rail-dot:focus-visible { opacity: 1; }
.sc-rail-dot:focus-visible { outline: 1px solid var(--gold); outline-offset: 4px; }

.sc-rail-label {
  font-size: 11px;
  letter-spacing: .13em;
  text-transform: uppercase;
  white-space: nowrap;
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: max-width .35s var(--t), opacity .25s var(--t);
}
.sc-rail-dot:hover .sc-rail-label,
.sc-rail-dot:focus-visible .sc-rail-label,
.sc-rail-dot.sc-current .sc-rail-label {
  max-width: 220px;
  opacity: 1;
}

.sc-rail-mark {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .28);
  border: 1px solid rgba(255, 255, 255, .35);
  flex: none;
  transition: all .35s var(--t);
}
.sc-rail-dot.sc-current { opacity: 1; }
.sc-rail-dot.sc-current .sc-rail-mark {
  background: var(--gold);
  border-color: var(--gold-hi);
  box-shadow: 0 0 0 4px rgba(228, 193, 105, .18);
  transform: scale(1.3);
}

@media (max-width: 720px) {
  .sc-rail { right: 8px; gap: 8px; }
  .sc-rail-dot.sc-current .sc-rail-label { max-width: 46vw; font-size: 10px; }
  .sc-rail-mark { width: 7px; height: 7px; }
}

/* -------------------------------------------------------- reduced motion
   theme.css already forces [data-reveal] transitions to ~instant and kills
   keyframe animations under .reduce-motion — reused here (see stage.js's
   own render() for the same class toggle) rather than inventing a second
   convention. Only the scroll-specific pieces need their own overrides. */
.reduce-motion .sc-hint-chev { animation: none !important; }
.reduce-motion .sc-stage .scene-bg { transform: none !important; }
