/* =====================================================================
   RIA — CINEMATIC ZOOM FX
   Apple/Awwwards-grade camera-zoom effects across the landing.

   Pattern: every key element ("zoom subject") has its scale + opacity
   driven by --zoom-progress (0..1) set by JS based on its position
   within the viewport. The element zooms IN from far away as it enters
   the viewport, hits scale 1 when centred, and zooms OUT (with a
   slight blur) as it leaves.

   Bell curve interpolation in JS:
     - entering (top 0.5 → 0.5 viewport): scale 0.4 → 1.0, blur 4 → 0
     - centred  (0.5 viewport): scale 1.0, blur 0
     - leaving  (0.5 viewport → -0.5): scale 1.0 → 1.4, blur 0 → 4, opacity 1 → 0.55

   Plus three more specific effects:
     • Hero display zooms in 0.5 → 1 on first paint (one-time intro)
     • Final READY display does a punch-zoom 0.4 → 1.05 → 1 on entry
     • Every stage-change triggers a "punch" pulse on the active motif
   ===================================================================== */


/* ── Common: any element tagged `data-zoom-subject` reads CSS vars
        --zoom-scale and --zoom-blur and --zoom-alpha. Defaults below
        keep the element neutral when JS hasn't kicked in yet. ────────── */
[data-zoom-subject] {
  --zoom-scale: 1;
  --zoom-blur: 0;
  --zoom-alpha: 1;
  /* IMPORTANT: only set transition on properties that can ANIMATE
     without overriding scene-specific transforms — scale alone is
     fine; we compose it via CSS custom property in scene transform
     declarations. */
}


/* ── HERO display intro zoom ─────────────────────────────────────────── */
/* The hero H1 grows from scale(0.5) blur(8px) to full size on page load.
   We hold the intro for 1.4 s. Once the scrollytelling kicks in the
   normal split-text reveal takes over. */
.hero h1 {
  animation: hero-zoom-in 1.4s cubic-bezier(0.16, 1, 0.3, 1) both;
  transform-origin: center center;
}
@keyframes hero-zoom-in {
  0%   { transform: scale(0.55); filter: blur(8px); opacity: 0; }
  60%  { opacity: 1; }
  85%  { transform: scale(1.025); filter: blur(0); }
  100% { transform: scale(1); filter: blur(0); opacity: 1; }
}

.hero p,
.hero .hero-cta-row,
.hero .scroll-indicator {
  animation: hero-zoom-in-soft 1.2s cubic-bezier(0.16, 1, 0.3, 1) 0.35s both;
}
.hero p             { animation-delay: 0.45s; }
.hero .hero-cta-row { animation-delay: 0.55s; }
.hero .scroll-indicator { animation-delay: 0.75s; }
@keyframes hero-zoom-in-soft {
  0%   { transform: scale(0.85); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}


/* ── Scene-3D camera zoom: motif scales 0.4 → 1 → 1.4 across viewport ─ */
/* The transform here is layered ON TOP of whatever each scene's own
   transform applies. We use !important on the scale because the
   per-scene transforms already include rotate/translate; we use a
   wrapper attribute pattern so the *inner* element gets the scale. */

/* For elements that DON'T have their own conflicting transform: */
.zoom-subject {
  transform: scale(var(--zoom-scale));
  filter: blur(calc(var(--zoom-blur) * 1px));
  opacity: var(--zoom-alpha);
  transform-origin: center center;
  transition: filter 0.18s linear;
  will-change: transform, filter, opacity;
}

/* For the 3D paper, orb, etc., we apply zoom via a parent wrapper
   created by JS (`.zoom-wrap`). That way the inner element keeps
   its scene-specific 3D rotation, while the wrapper handles the
   camera-zoom scale + blur. */
.zoom-wrap {
  display: inline-block;          /* shrink-wrap the wrapped subject */
  transform: scale(var(--zoom-scale));
  filter: blur(calc(var(--zoom-blur) * 1px));
  opacity: var(--zoom-alpha);
  transform-origin: center center;
  transition: filter 0.18s linear;
  will-change: transform, filter, opacity;
}


/* ── Stage-change "punch zoom": when a scene's stage flips, the
        currently-active motif gets a brief scale 0.92 → 1.04 → 1
        pulse (~0.55 s) to add impact. JS toggles `.punch-zoom`. ──────── */
.punch-zoom {
  animation: punch-zoom 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes punch-zoom {
  0%   { transform: scale(1); }
  35%  { transform: scale(0.94); }
  70%  { transform: scale(1.06); }
  100% { transform: scale(1); }
}


/* ── Final READY display punch-zoom on entry ─────────────────────────── */
/* Triggered by JS when .ready-cta first enters the viewport. */
.ready-display.is-zooming-in {
  animation: ready-punch-in 1.05s cubic-bezier(0.34, 1.42, 0.64, 1) both;
}
@keyframes ready-punch-in {
  0%   { transform: scale(0.4); opacity: 0; letter-spacing: -0.025em; }
  55%  { opacity: 1; }
  78%  { transform: scale(1.06); }
  100% { transform: scale(1); opacity: 1; letter-spacing: -0.055em; }
}


/* ── Scene-level scroll camera FX ─────────────────────────────────────
   Each .scene-3d / .scroll-scene / .pipeline-scene reads four CSS
   variables set by landing-zoom-fx.js every scroll tick:

     --scene-zoom        : 1 → 1.06 → 1 bell curve (centre swells)
     --scene-alpha       : 0 → 1 → 0 smoothstep at the first/last 10%
                           of the scene's scroll budget — smooth fade
     --scene-edge-scale  : 0.94 → 1 → 0.94 — gentle scale at edges
     --scene-edge-y      : +Y at entry, -Y at exit — vertical drift

   Together these produce a clean CROSSFADE between adjacent sticky
   scenes: the leaving one fades + drifts up while the entering one
   fades in from below — no more abrupt cuts.
   ───────────────────────────────────────────────────────────────── */
.scene-3d[data-scene-progress],
.scroll-scene[data-scene-progress],
.pipeline-scene[data-scene-progress] {
  --scene-zoom: 1;
  --scene-alpha: 1;
  --scene-edge-scale: 1;
  --scene-edge-y: 0px;
}
.scene-3d[data-scene-progress] .scene-3d-track,
.scroll-scene[data-scene-progress] .scroll-scene-track,
.pipeline-scene[data-scene-progress] .pipeline-track {
  /* Compose all four — scale combines the bell-curve zoom and the
     edge scale; translateY is the edge drift. Opacity is the fade. */
  transform:
    translateY(var(--scene-edge-y, 0px))
    scale(calc(var(--scene-zoom, 1) * var(--scene-edge-scale, 1)));
  transform-origin: center center;
  opacity: var(--scene-alpha, 1);
  will-change: transform, opacity;
}

/* Overlap adjacent scenes by ~10vh so the leaving scene's fade-out
   and the entering scene's fade-in happen IN THE SAME viewport —
   that's what makes the transition feel like a crossfade rather
   than a cut. The negative margin doesn't change the scroll budget,
   just lets the next scene start while the previous is still
   fading. */
.scene-3d + .scene-3d,
.scene-3d + .scroll-scene,
.scene-3d + .pipeline-scene,
.scroll-scene + .scene-3d,
.scroll-scene + .scroll-scene,
.scroll-scene + .pipeline-scene,
.pipeline-scene + .scene-3d,
.pipeline-scene + .scroll-scene,
.pipeline-scene + .pipeline-scene {
  margin-top: -10vh;
}


/* ── Background depth-tilt: subtle perspective tilt of the body bg
        based on scroll progress (CSS var set by JS). Adds the "camera
        moving through space" feel. ──────────────────────────────────── */
body {
  --bg-tilt-x: 0;
  --bg-tilt-y: 0;
}
.ria-grid-bg {
  transform: rotateX(calc(var(--bg-tilt-y) * 2deg))
             rotateY(calc(var(--bg-tilt-x) * 2deg));
  transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}


/* ── Reduced motion ──────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .hero h1,
  .hero p,
  .hero .hero-cta-row,
  .hero .scroll-indicator,
  .punch-zoom,
  .ready-display.is-zooming-in,
  .zoom-wrap,
  .zoom-subject,
  .scene-3d[data-scene-progress] .scene-3d-track,
  .scroll-scene[data-scene-progress] .scroll-scene-track,
  .pipeline-scene[data-scene-progress] .pipeline-track,
  .ria-grid-bg {
    animation: none !important;
    transform: none !important;
    filter: none !important;
    opacity: 1 !important;
    transition: none !important;
  }
  .scene-departing { filter: none !important; opacity: 1 !important; }
}


/* ── Mobile: lighter scales (less aggressive zoom) ───────────────────── */
@media (max-width: 700px) {
  /* Slightly less dramatic hero intro on phones — page often loads
     scrolled or mid-route. */
  .hero h1 {
    animation: hero-zoom-in-mobile 1.1s cubic-bezier(0.16, 1, 0.3, 1) both;
  }
  @keyframes hero-zoom-in-mobile {
    0%   { transform: scale(0.75); opacity: 0; filter: blur(4px); }
    100% { transform: scale(1); opacity: 1; filter: blur(0); }
  }
  /* Tame the scene-track zoom on phones — less GPU. */
  .scene-3d[data-scene-progress] .scene-3d-track,
  .scroll-scene[data-scene-progress] .scroll-scene-track,
  .pipeline-scene[data-scene-progress] .pipeline-track {
    transform: scale(calc(0.95 + (var(--scene-zoom, 1) - 1) * 0.5));
  }
}
