/* ============================================================
   ShepherdXR Fanfare
   Film-strip reel aesthetic: soft-edged cels separated by shadow and
   gap rather than a bold outline. Tokens below are set from config.js
   at runtime (see fanfare.js:applyTheme).

   Plays as a full-screen layer on the home page (index.html), above
   the background video but below #scroll-container, so the hero's own
   logo + tagline sit on top of the reel. Everything is scoped to
   #fanfare-root so none of it leaks into the home page's styles.
   ============================================================ */

#fanfare-root {
  --bg: #0a0a0a;
  --fg: #ffffff;
  --accent: #7B2FBE;
  --accent-bright: #9340e0;
  --font-display: 'Playfair Display', serif;
  --font-body: 'Inter', sans-serif;
  --tile-height: 220px;
  --reel-angle: 0deg;
  --reel-gap: 3px;
  --tile-border-color: #9340e0;
  --tile-border-width: 4px;
  --handoff-fade: 450ms;
}

#fanfare-root {
  position: fixed;
  inset: 0;
  z-index: 2;
  overflow: hidden;
  background: var(--bg);
  font-family: var(--font-body);
  color: var(--fg);
  opacity: 1;
  transition: opacity var(--bg-fade, 900ms) ease;
}

/* Final beat: the whole layer fades away, leaving the home page's own
   background and hero exactly where they already are. */
#fanfare-root.fading-home {
  opacity: 0;
  pointer-events: none;
}

/* Skipped by the visitor (scroll, tap or key): same fade, just quicker. */
#fanfare-root.fading-home.is-skipped {
  transition-duration: 400ms;
}

/* While the intro plays: lock scrolling, hide the nav, and hold the
   hero's logo + tagline back until the reel beat fades them in. The
   head script in index.html sets .fanfare-on before first paint. */
html.fanfare-on,
html.fanfare-on body {
  overflow: hidden;
}

html.fanfare-on #global-nav {
  opacity: 0 !important;
  pointer-events: none !important;
}

/* The logo + tagline settle in from a slight scale-down, on the hero's
   own easing curve (style.css heroEntrance), rather than a flat fade.
   Opacity and transform only, on their own layer (will-change), so the
   graphics card does it without touching the main thread that drives the
   reel. (A blur used to be part of this; repainting it every frame
   stalled the reel, which showed as the reel jumping.) */
html.fanfare-on #beat-hero .beat-content {
  opacity: 0;
  transform: scale(0.94);
  animation: none;
  will-change: opacity, transform;
  transition:
    opacity var(--logo-fade, 700ms) ease,
    transform var(--logo-fade, 700ms) cubic-bezier(0.22, 1, 0.36, 1);
}

html.fanfare-on.fanfare-logo #beat-hero .beat-content {
  opacity: 1;
  transform: scale(1);
}

/* Once the intro is over, the hero must not replay its own entrance
   animation. The transition only shows after a skip, when the logo may
   not have arrived yet. */
html.fanfare-done #beat-hero .beat-content {
  opacity: 1;
  transform: none;
  animation: none;
  transition: opacity 400ms ease, transform 400ms ease;
}

/* ===== LOGO ALONE, THEN THE MISSION LINE ===== */

/* Until the closing moment (.fanfare-settled), the logo shows alone,
   moved to the exact centre of the screen (fanfare.js:centreLogo sets
   the offset), and the mission line and scroll hint are held back. At
   .fanfare-settled the logo glides up to its place on the home page and
   the mission line fades in underneath it. */
#beat-hero .brand-logo {
  transition: transform var(--logo-shift, 900ms) cubic-bezier(0.65, 0, 0.35, 1);
}

html.fanfare-on:not(.fanfare-settled) #beat-hero .brand-logo {
  transform: translate3d(var(--fanfare-logo-dx, 0px), var(--fanfare-logo-dy, 0px), 0);
}

html.fanfare-on #beat-hero .beat-tagline,
html.fanfare-on #beat-hero .scroll-hint {
  opacity: 0;
  transition: opacity var(--tagline-fade, 700ms) ease var(--tagline-delay, 250ms);
}

/* The arrow's own bounce animates its opacity, so it is switched off
   (not just faded) until the page is handed back. */
html.fanfare-on #beat-hero .scroll-indicator {
  opacity: 0;
  animation: none;
}

html.fanfare-on.fanfare-settled #beat-hero .beat-tagline,
html.fanfare-on.fanfare-settled #beat-hero .scroll-hint {
  opacity: 1;
}

/* ===== LIGHT SWEEP over the logo (fanfare.js:sweepLogo) ===== */

/* The shine is positioned over the logo inside the hero content, and
   masked by the logo image (set inline), so only the logo catches it. */
#beat-hero .beat-content {
  position: relative;
}

.fanfare-shine {
  position: absolute;
  pointer-events: none;
  background: linear-gradient(110deg,
    rgba(255, 255, 255, 0) 40%,
    rgba(255, 255, 255, 0.75) 50%,
    rgba(255, 255, 255, 0) 60%);
  background-size: 300% 100%;
  background-position: 100% 0;
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  animation: fanfare-shine var(--shine-duration, 800ms) cubic-bezier(0.45, 0, 0.25, 1) forwards;
}

@keyframes fanfare-shine {
  from { background-position: 100% 0; }
  to   { background-position: 0% 0; }
}

/* ===== PAN LAYER ===== */

/* Sized and positioned entirely via inline styles set every frame in
   fanfare.js (runPanBeat) — this is the one "hero" box that shrinks
   from a screen-filling crop down to a real reel tile's exact rect.
   Carries the rainbow border only while it's this — once it hands off
   to the reel tile (fanfare.js:runReelFocus), the border goes with it,
   marking this box as "the one thing the camera is tracking" only for
   as long as it's actually moving. Same 7-stop earthy palette as
   tree/index.html's selected-topic treatment. The rainbow is painted on
   the border only (a dark padding-box layer covers the inside), so it
   can never flash across the screen while the first clip loads. It is
   static: animating it repainted the whole, screen-sized box every frame.

   Starts invisible and fades up from black (.is-open, the opener) once
   fanfare.js has sized it, so nothing shows before it is in place. */
#pan-hero {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 5;
  box-sizing: border-box;
  border: 4px solid transparent;
  border-radius: 10px;
  background:
    linear-gradient(var(--bg), var(--bg)) padding-box,
    linear-gradient(90deg, #e0554f, #e0a53f, #d6c93f, #6fb35a, #4f9bbf, #6f6fd6, #b355c9, #e0554f) border-box;
  box-shadow: 0 16px 32px -14px rgba(0,0,0,0.7);
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--open-fade, 600ms) ease;
}

#pan-hero.is-open {
  opacity: 1;
}

/* After .is-open in the file, so it wins: the fade-out at the handoff. */
#pan-hero.hidden {
  opacity: 0;
  pointer-events: none;
  transition-duration: var(--handoff-fade, 375ms);
}

.pan-tile {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--fade-duration, 700ms) ease;
  will-change: opacity;
}

.pan-tile.active {
  opacity: 1;
}

/* Same grade as the reel tiles (.reel-tile video), so there is no tone
   shift when the box lands on its tile. */
.pan-tile img,
.pan-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: saturate(0.92) brightness(0.9);
  transform: scale(1);
  transition: transform 2400ms cubic-bezier(0.2, 0.6, 0.3, 1);
  will-change: transform;
}

/* Opener: a slow push-in while the reel loads... */
#pan-hero.is-open .pan-tile img,
#pan-hero.is-open .pan-tile video {
  transform: scale(1.04);
}

/* ...which relaxes back out during the pull-out, so the box lands showing
   exactly the crop its reel tile shows. */
#pan-hero.is-panning .pan-tile img,
#pan-hero.is-panning .pan-tile video {
  transform: scale(1);
  transition-duration: var(--pan-duration, 2000ms);
}

/* Slight dark grade so the pan footage feels graded, not raw. Fades out
   over the last stretch of the pull-out (.is-landing), since the reel
   tile it lands on has none. */
#pan-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 45%, rgba(10,10,10,0) 40%, rgba(10,10,10,0.55) 100%);
  pointer-events: none;
  transition: opacity 600ms ease;
}

#pan-hero.is-landing::after {
  opacity: 0;
}

/* ===== REEL LAYER ===== */

#reel-layer {
  position: absolute;
  /* This overhang exists purely so a rotated grid (REEL_ANGLE != 0)
     doesn't show gaps at its corners once tilted. It costs real rows —
     computeRowCount (fanfare.js) pads for exactly this much extra
     vertical space — which is dead weight while REEL_ANGLE is 0 (no
     rotation, nothing to cover). Raise this back toward -15vh/-15vw
     (and computeRowCount's buffer to match) if REEL_ANGLE is ever set
     away from 0. */
  inset: -3vh -3vw;
  z-index: 0;
  opacity: 0;
  transform: rotate(var(--reel-angle));
  transition: opacity var(--handoff-fade, 450ms) ease;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--reel-gap);
}

#reel-layer.visible {
  opacity: 1;
  z-index: 2;
}

/* Overrides the fast handoff-fade transition-duration with the slower,
   deliberate one used for the final fade — same opacity toggle
   (.visible removed), just a different pace for a different moment. */
#reel-layer.fading-home {
  transition-duration: var(--reel-fade, 600ms);
}

.reel-row {
  position: relative;
  height: var(--tile-height);
  overflow: hidden;
  flex-shrink: 0;
}

.reel-track {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  display: flex;
  will-change: transform;
}

.reel-tile {
  position: relative;
  height: 100%;
  flex-shrink: 0;
  box-sizing: border-box;
  border: var(--tile-border-width) solid var(--tile-border-color);
  border-radius: 10px;
  /* Depth comes from a soft drop shadow, not a bold border — this is
     what separates tiles from the background without the "budget card
     grid" look a heavy coloured outline gives. */
  box-shadow: 0 16px 32px -14px rgba(0,0,0,0.7);
  overflow: hidden;
  background: #111;
}

.reel-tile img,
.reel-tile video {
  display: block;
  height: 100%;
  width: auto;
  object-fit: cover;
  filter: saturate(0.92) brightness(0.9);
}

/* Live tiles get a solid black frame — thick as the rainbow border on
   #pan-hero — distinct from the hairline on static tiles, so the eye
   can find real motion among the still ones, like a viewfinder frame
   around whatever's actually playing. */
.reel-tile.is-live {
  border: 4px solid #000;
}

.reel-tile.reel-tile--logo {
  background: #f4f2f6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 1.5rem;
}

.reel-tile.reel-tile--logo img {
  width: auto;
  height: 46%;
  object-fit: contain;
  filter: none;
}

.reel-tile.reel-tile--stat,
.reel-tile.reel-tile--quote {
  background: #150c1c;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 1.75rem;
  min-width: 260px;
}

.reel-tile.reel-tile--stat .stat-value {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.4rem);
  color: var(--accent-bright);
  line-height: 1;
  margin-bottom: 0.4rem;
}

.reel-tile .tile-label,
.reel-tile .quote-author {
  font-family: var(--font-body);
  font-weight: 300;
  font-size: 0.72rem;
  letter-spacing: 0.03em;
  color: rgba(255,255,255,0.55);
}

.reel-tile .quote-text {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(0.95rem, 1.6vw, 1.15rem);
  line-height: 1.35;
  color: rgba(255,255,255,0.85);
  margin-bottom: 0.5rem;
}

.reel-tile--placeholder {
  outline: 1px dashed rgba(255,255,255,0.3);
  outline-offset: -6px;
}

/* ===== REEL OVERLAY — legibility gradient for the logo/tagline ===== */

/* Same gradient recipe as the home page's own #video-overlay (style.css),
   so this reads as the same treatment continuing, not a new one. */
#reel-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  background:
    linear-gradient(to bottom,
      rgba(10, 10, 10, 0.6) 0%,
      rgba(10, 10, 10, 0.4) 40%,
      rgba(10, 10, 10, 0.4) 60%,
      rgba(10, 10, 10, 0.65) 100%
    );
  opacity: 0;
  transition: opacity var(--logo-fade, 900ms) ease;
  pointer-events: none;
}

#reel-overlay.visible {
  opacity: 1;
}

/* ===== ACCESSIBILITY ===== */

/* index.html doesn't start the fanfare for reduced-motion visitors at
   all; this is a backstop in case that check is ever bypassed. */
@media (prefers-reduced-motion: reduce) {
  .reel-track { transition: none !important; }
  .pan-tile img, .pan-tile video { transform: none !important; transition: none !important; }
  .fanfare-shine { display: none; }
}

@media (max-width: 700px) {
  #fanfare-root { --tile-height: 170px; }
}
