/* Fawkes and Co. — homepage scroll journey engine styles
   Reuses design tokens defined in styles.css (:root). Load order matters:
   journey.css must load after styles.css. */

/* styles.css has two same-specificity rules for header.site (sticky/z-40 at
   the top of the file, then position:relative/z-2 later in the "paper grain
   layering" block) — the later one wins the cascade, so the header currently
   is NOT sticky and sits below any full-viewport fixed element. That was
   invisible until now because nothing else on the page was fixed + opaque.
   The journey canvas is exactly that, so it would otherwise cover the header
   entirely. Restoring the header's own documented z-40/sticky rule here
   (loaded after styles.css, homepage-only) is the minimal integration fix
   required to satisfy "header remains usable during the journey" — it does
   not touch styles.css or any other page. */
header.site {
  position: sticky;
  z-index: 40;
}

/* ── NAV HIDDEN DURING THE JOURNEY ──────────────────────────────────────
   Robin (2026-07-22): "when loading/going through the feature section,
   remove the nav bar and only have it appear after we've finished showing
   the featured videos." Reuses the exact signal that already fires the
   hero intro beat in site.js: journey.js toggles `journey--hidden` on
   #journey at the spacer end, on every render frame, at any scroll speed
   (including a straight jump to the end). site.js's "Nav hidden during the
   scroll journey" block watches that and sets `journey-in-progress` /
   `journey-done` on <body> -- see site.js for the full trigger logic
   (MutationObserver primary, "already past it on load" catch-up path,
   immediate reveal if MutationObserver is unsupported so the header is
   never stranded hidden behind a signal the browser can't watch for).
   Base header.site (above, and in styles.css) is ALWAYS the normal, fully
   visible sticky header -- everything below is opt-in behind the JS-added
   class, so: no-JS (class never added) shows the header normally; a page
   with no .journey element never gets `journey-in-progress` in the first
   place (site.js only adds it when it finds one) and this stylesheet
   itself is homepage-only, so work/*.html is untouched twice over; and if
   the reveal signal genuinely never fires, that only matters while the
   journey is still legitimately playing -- the header stays hidden behind
   the still-opaque canvas either way, same as before this change existed.
   Entering the hidden state is instant (transition: none) because
   `journey-in-progress` lands before first paint, behind the brand loader
   -- there is nothing visible to fade out of. Leaving it (`journey-done`)
   is what animates, via the transition on the base header.site rule below
   winning the cascade once the more specific hidden rule stops matching --
   same pattern as the hero intro beat's .hero--intro in styles.css.
   opacity + visibility (not display), so the header stays measurable
   (offsetHeight, --header-h) throughout and never collapses layout -- see
   the hero's calc(...- var(--header-h)) math in styles.css, unaffected.
   visibility:hidden also removes the header's links from the tab order
   while hidden (not just invisible-but-focusable); pointer-events:none
   backs that up for pointer/touch. The header stays in the DOM the whole
   time, so nothing is lost once revealed. */
header.site {
  transition: opacity 0.35s ease;
}
body.journey-in-progress header.site {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: none;
}
@media (prefers-reduced-motion: reduce) {
  /* Still hides during the journey and appears after -- just snaps
     instead of fading, per Robin's own reduced-motion rule elsewhere on
     this site (no motion, not no-op). */
  header.site { transition: none; }
}

.journey {
  position: fixed;
  inset: 0;
  z-index: 3; /* below header.site (40, restored above) and nav-overlay (90), above main/footer (2) */
  overflow: hidden;
  background: var(--paper);
  pointer-events: none;
  transition: opacity 0.4s ease;
}
.journey--hidden {
  opacity: 0;
  visibility: hidden;
}
.journey__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.journey__spacer {
  position: relative;
  height: 0; /* set by journey.js; stays 0 with no JS, so no blank scroll region */
}

.journey__text {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(24px, 4vw, 56px) var(--gutter) clamp(48px, 8vw, 96px);
  /* 2026-07-22 (Robin): "remove all dark overlays of transparency or
     darkness and just keep the full videos 100%." The F-402 scrim pair
     that used to live here (two stacked linear-gradients over rgba(26,
     24, 20, ...) -- a bottom "to top" scrim and a top "to bottom" scrim,
     see git history for the exact stops) is gone. No background, no
     ::before/::after, no filter/brightness/vignette anywhere on
     .journey/.journey__canvas/.journey__text -- the footage renders at
     100%, undimmed. This is a deliberate, requested regression on F-402's
     own contrast fix: with the scrim gone, .journey__meta and
     .journey__location drop back below the 4.5:1 AA threshold on light
     chapters (measured; see /build evidence table for the per-chapter
     numbers). Robin has explicitly chosen clean footage over that ratio.
     Do NOT re-add a scrim/panel/box to "fix" the contrast -- the only
     lever left is the text-shadow below, which darkens the glyphs
     themselves, not the frame behind them. */
}
.journey__meta {
  position: absolute;
  top: clamp(96px, 12vh, 140px);
  right: var(--gutter);
  margin: 0;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  /* 2026-07-22: was var(--paper) (Lrel 0.852, WCAG 4.5:1 ceiling ~0.15) --
     bumped to true white for the extra headroom the adaptive scheme needs
     (see the .journey--dark block below: the light and dark states share a
     razor-thin safe overlap around Lrel 0.175-0.183, and only work at all
     if BOTH colours sit close to the true white/black extremes). Measured:
     var(--paper) failed 04-threshold-coast/05-craft mid-chapter points that
     this clears -- see /build evidence table. */
  color: #ffffff;
  /* 2026-07-22: scrim removed above, so this is the only darkening left --
     glyph-only, not the frame. Tightened vs the pre-scrim-removal shadow
     (closer blur radii, higher alpha) to hold the glyph edges against
     undimmed footage. Does not move the WCAG contrast ratio (that's
     measured against the rendered background pixel, not the shadow) --
     see /build evidence table for the honest per-chapter numbers. */
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(0, 0, 0, 0.7), 0 1px 12px rgba(0, 0, 0, 0.55);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
.journey__copy { max-width: 640px; }
.journey__location {
  margin: 0 0 10px;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  /* F-402 gave this brass (#e3c789, Lrel 0.59) to read as brand, not paper.
     2026-07-22: dropped for true white (matches .journey__meta above) --
     brass's own WCAG ceiling (~0.09) is below several chapters' measured
     mid-transition luminance (0.095-0.14), so it was failing before the
     luminance-adaptive dark theme even had a chance to take over. This is
     the DEFAULT/light-theme colour only -- see the .journey--dark block
     below for the dark-theme override that applies over bright footage. */
  color: #ffffff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(0, 0, 0, 0.65), 0 1px 12px rgba(0, 0, 0, 0.5);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
.journey__title {
  margin: 0 0 14px;
  font-family: var(--serif);
  font-weight: 500;
  font-variant: small-caps;
  letter-spacing: 0.03em;
  font-size: clamp(34px, 6vw, 68px);
  line-height: 1.05;
  color: var(--paper);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65), 0 2px 24px rgba(0, 0, 0, 0.5);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}
.journey__desc {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.6vw, 19px);
  line-height: 1.5;
  color: rgba(244, 237, 225, 0.9);
  max-width: 46ch;
  padding-top: 16px;
  border-top: 1px solid rgba(244, 237, 225, 0.32);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55), 0 1px 14px rgba(0, 0, 0, 0.45);
  transition: color 0.3s ease, text-shadow 0.3s ease;
}

/* ── 2026-07-22: luminance-adaptive caption theme ──────────────────────────
   Robin's hard requirement stands: no scrim/gradient/overlay/backdrop-filter
   comes back. The only lever left is the text's own colour + shadow, so
   journey.js samples the CANVAS pixels actually behind each caption group
   (bottom-left .journey__copy: location+title+desc, and top-right
   .journey__meta, sampled and switched INDEPENDENTLY of each other -- see
   journey.js updateCaptionTheme) and toggles this ONE modifier class,
   .journey--dark, on whichever element's sampled region reads bright.
   Default (no class) is the existing cream/brass theme above, correct for
   the dark parts of the footage. This block is the ink theme for the
   bright parts.

   .journey__location and .journey__meta go all the way to true white/true
   black (not --paper/--ink) on purpose: at 11px with normal weight they are
   the tightest constraint in the whole overlay, and a flat text colour
   cannot beat ~4.58:1 against a real-world midtone background no matter
   which side you pick -- true white/black is what makes journey.js's
   per-sample "pick whichever of these two candidates has higher contrast
   right now" decision (see updateRegionTheme) correct BY CONSTRUCTION at
   every possible background luminance (see the /build evidence table for
   the derivation). Using the branded --paper (Lrel 0.852) or --ink (Lrel
   0.009) instead would reopen a real unsafe gap. .journey__title and
   .journey__desc keep --ink/--paper: they are "large text" (title) or not
   part of the WCAG-gated pair (desc), so they have a much wider safe margin
   and can stay on-brand. journey.js's THEME_HARD_FLOOR/THEME_SWITCH_MARGIN
   are the matching decision constants -- change the colours here and that
   derivation needs re-checking. */
.journey__meta.journey--dark {
  color: #000000;
  text-shadow: 0 1px 2px rgba(244, 237, 225, 0.85), 0 0 6px rgba(244, 237, 225, 0.6), 0 1px 10px rgba(244, 237, 225, 0.42);
}
.journey__copy.journey--dark .journey__location {
  color: #000000;
  text-shadow: 0 1px 2px rgba(244, 237, 225, 0.85), 0 0 6px rgba(244, 237, 225, 0.6), 0 1px 10px rgba(244, 237, 225, 0.42);
}
.journey__copy.journey--dark .journey__title {
  color: var(--ink);
  text-shadow: 0 1px 3px rgba(244, 237, 225, 0.55), 0 2px 20px rgba(244, 237, 225, 0.4);
}
.journey__copy.journey--dark .journey__desc {
  color: var(--ink-2);
  border-top-color: rgba(26, 24, 20, 0.28);
  text-shadow: 0 1px 3px rgba(244, 237, 225, 0.5), 0 1px 12px rgba(244, 237, 225, 0.35);
}

@media (max-width: 540px) {
  .journey__meta { top: 88px; font-size: 10px; }
  .journey__desc { max-width: 34ch; }
}

/* ── F-401 / N-408 (phase 4 QA fix): journey no-JS + accessible fallbacks ── */

/* N-408: standard visually-hidden-but-screen-reader-visible pattern.
   #journeyA11y is populated by journey.js (buildA11yFallback, reading
   CHAPTER_DEFS directly -- see journey.js for why that keeps this in sync
   automatically) and sits OUTSIDE the aria-hidden .journey canvas stage, so
   AT users get the chapter copy without any visible duplicate rendering
   layered over the canvas. */
.journey__a11y {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* F-401: with JS disabled the canvas never paints and .journey/.journey__
   spacer are force-hidden (see the <head> noscript rule in index.html), so
   this block -- real markup that only ever exists in the DOM when
   scripting is disabled, per how <noscript> works -- takes its place: each
   chapter's still (the existing -960.webp responsive variant, not the
   1600px original) stacked with its title/location/description, in
   chapter order. Copy here is a static, hand-authored duplicate of the
   same five chapters in journey.js CHAPTER_DEFS -- unavoidable, since no
   JS runs in this state to build it from the single source of truth the
   way #journeyA11y above does. Both files carry a comment pointing at this
   one; if CHAPTER_DEFS copy ever changes, this block needs the matching
   manual edit. */
.journey__noscript {
  padding: clamp(32px, 8vw, 96px) var(--gutter);
  background: var(--paper);
}
.journey__noscript-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.journey__noscript-item {
  max-width: 720px;
  margin: 0 auto clamp(48px, 10vw, 96px);
}
.journey__noscript-item:last-child { margin-bottom: 0; }
.journey__noscript-item img {
  width: 100%;
  height: auto;
  display: block;
  margin: 0 0 20px;
}
.journey__noscript-location {
  /* Matches the site's own .eyebrow idiom (small-caps sans label on paper) --
     var(--ink-3), not var(--brass)/var(--walnut): this block sits on the
     light --paper background, not over a photo, so it doesn't have the
     F-402 contrast problem and can just reuse the existing convention. */
  margin: 0 0 8px;
  font-family: var(--sans);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.journey__noscript-title {
  margin: 0 0 10px;
  font-family: var(--serif);
  font-weight: 500;
  font-variant: small-caps;
  letter-spacing: 0.03em;
  font-size: clamp(28px, 5vw, 44px);
  line-height: 1.1;
  color: var(--ink);
}
.journey__noscript-desc {
  margin: 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: clamp(15px, 1.6vw, 18px);
  line-height: 1.5;
  color: var(--ink-2);
}

@media (prefers-reduced-motion: reduce) {
  .journey { transition: none; }
  /* Luminance-adaptive theme is a legibility fix, not motion -- it still
     applies under reduced motion (see journey.js, sampling is unaffected by
     prefersReduced), but the 0.3s colour crossfade IS motion, so make the
     flip instant here instead of skipping it. */
  .journey__meta,
  .journey__location,
  .journey__title,
  .journey__desc {
    transition: none;
  }
}
