/* ==========================================================================
   RPEES — ANIMATION LAYER
   CSS owns the *initial* state of anything GSAP will animate, so nothing
   flashes before JS boots. GSAP owns the transitions themselves.
   Load last.
   ========================================================================== */

/* --------------------------------------------------------------------------
   01. PRE-ANIMATION STATES
   Applied only while <html> carries data-motion="full". If JS never runs, or
   motion is reduced, these selectors don't match and everything is visible.
   -------------------------------------------------------------------------- */
[data-motion="full"] [data-reveal]      { opacity: 0; transform: translateY(24px); }
[data-motion="full"] [data-split]       { opacity: 0; }
[data-motion="full"] [data-clip] > img,
[data-motion="full"] [data-clip]        { clip-path: inset(0 0 100% 0); }
[data-motion="full"] [data-fade]        { opacity: 0; }

/* Word wrappers created by the splitter. */
.split-line { display: block; overflow: hidden; }
.split-word { display: inline-block; will-change: transform; }

/* Parallax layers get their own compositor layer only while in view.
   animations.js adds and removes .is-active on ScrollTrigger enter/leave. */
[data-parallax].is-active,
[data-scale].is-active { will-change: transform; }


/* --------------------------------------------------------------------------
   02. HERO LOADER
   -------------------------------------------------------------------------- */
.hero-loader {
  position: absolute; inset: 0; z-index: var(--z-loader);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--s-5);
  background: var(--c-forest-deep); color: var(--c-ivory);
  transition: opacity var(--d-slow) var(--e-out), visibility var(--d-slow);
}
.hero-loader[hidden] { display: flex; opacity: 0; visibility: hidden; }
.hero-loader__text { font-family: var(--font-display); font-size: var(--t-display-s); }
.hero-loader__track { width: min(280px, 60vw); height: 1px; background: var(--line-on-dark-soft); }
.hero-loader__bar { display: block; height: 100%; width: 0; background: var(--c-sand); transition: width .28s linear; }
.hero-loader__pct { font-family: var(--font-util); font-size: var(--t-label); letter-spacing: var(--ls-label); color: var(--c-sand); }


/* --------------------------------------------------------------------------
   03. HERO CANVAS + SCROLL INDICATOR
   -------------------------------------------------------------------------- */
.hero { position: relative; height: 100svh; overflow: hidden; background: var(--c-forest-deep); }
.hero__canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.hero__grain, .hero__vignette { position: absolute; inset: 0; pointer-events: none; }
.hero__vignette { background: var(--vignette); }

.hero__beats { position: absolute; inset: 0; pointer-events: none; }
.hero__beats > * { pointer-events: auto; }
.hero__beat {
  position: absolute; inset: auto 0 auto 0; top: 50%; transform: translateY(-50%);
  padding-inline: var(--gutter); color: var(--c-ivory); text-align: center;
  pointer-events: none;
}
.hero__beat > * { pointer-events: auto; }

.scroll-cue {
  position: absolute; left: 50%; bottom: clamp(24px, 4vh, 48px); transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: var(--s-3);
  color: var(--c-ivory); font-family: var(--font-util);
  font-size: var(--t-label); letter-spacing: var(--ls-label);
}
.scroll-cue__line { width: 1px; height: 44px; background: var(--line-on-dark); position: relative; overflow: hidden; }
.scroll-cue__line::after {
  content: ""; position: absolute; left: 0; top: 0; width: 1px; height: 14px; background: var(--c-ivory);
  animation: cue-drift 2.6s var(--e-in-out) infinite;
}
.scroll-cue__count { color: var(--c-sand); }

@keyframes cue-drift { 0% { transform: translateY(-14px); } 60%,100% { transform: translateY(44px); } }


/* --------------------------------------------------------------------------
   04. AMBIENT — mist drift
   One shared keyframe. Used on at most two sections in the whole site.
   -------------------------------------------------------------------------- */
.mist {
  position: absolute; inset: -12% -18%; pointer-events: none; z-index: 2;
  background: radial-gradient(58% 42% at 30% 62%, rgba(247,243,234,.30), transparent 68%),
              radial-gradient(48% 36% at 74% 44%, rgba(232,236,233,.24), transparent 66%);
  filter: blur(14px);
  animation: mist-drift 46s ease-in-out infinite alternate;
}
@keyframes mist-drift {
  from { transform: translate3d(-2%, 1%, 0) scale(1);    opacity: .85; }
  to   { transform: translate3d(3%, -2%, 0) scale(1.09); opacity: 1; }
}


/* --------------------------------------------------------------------------
   05. REDUCED MOTION — the whole contract in one block
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .mist, .scroll-cue__line::after { animation: none; }
  .hero { height: auto; }
  .hero__canvas { display: none; }
  .hero__poster { display: block; }
  .hero__beat { position: static; transform: none; padding-block: var(--s-7); }
}

[data-motion="reduced"] [data-reveal],
[data-motion="reduced"] [data-split],
[data-motion="reduced"] [data-fade] { opacity: 1 !important; transform: none !important; }
[data-motion="reduced"] [data-clip] { clip-path: none !important; }
[data-motion="reduced"] .mist { display: none; }

/* Poster is hidden whenever the canvas is live. */
.hero__poster { display: none; position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
[data-motion="reduced"] .hero__poster,
.hero[data-fallback="true"] .hero__poster { display: block; }
.hero[data-fallback="true"] .hero__canvas { display: none; }


/* --------------------------------------------------------------------------
   06. HERO WITHOUT MOTION
   When there is no scroll story at all — reduced motion, save-data, no JS —
   the five beats are absolutely positioned on top of one another and become an
   unreadable pile. Lay them out in normal flow instead, so the hero degrades
   to a plain poster with the copy stacked under it.

   This does NOT apply to [data-fallback], where the pin and the beat timeline
   are still running over a static poster and the absolute positioning is
   still correct.
   -------------------------------------------------------------------------- */
[data-motion="reduced"] .hero,
.hero[data-nojs="true"] {
  height: auto;
  min-height: 100svh;
  display: flex;
  align-items: center;
}
[data-motion="reduced"] .hero__beat,
.hero[data-nojs="true"] .hero__beat {
  position: static;
  transform: none;
  opacity: 1 !important;
  padding-block: var(--s-5);
}
[data-motion="reduced"] .hero > .container,
[data-motion="reduced"] .hero__beat + .hero__beat { margin-top: 0; }

/* Stack them in one centred column rather than letting each one fill the box. */
[data-motion="reduced"] .hero__beats,
.hero[data-nojs="true"] .hero__beats {
  position: relative; z-index: 4;
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(12px, 2vh, 28px);
  width: 100%;
}
[data-motion="reduced"] .scroll-cue { display: none; }

/* The beats are revealed by the scrubbed hero timeline. Hiding them in CSS as
   well means they can never flash over an empty stage in the window between
   first paint and the engine booting. [data-motion="reduced"] and the no-JS
   fallback both override this further down. */
[data-motion="full"] .hero__beat { opacity: 0; }
