/* ==========================================================================
   animations.css — keyframes + motion utilities
   Motion is the design here (DESIGN.md). Entrances use --ease; anything that
   should feel springy uses --spring and overshoots once, never more.
   Everything is neutralised under prefers-reduced-motion in style.css.
   ========================================================================== */

/* ---- sticker drop: weight, overshoot, settle. Never a fade. ------------- */
@keyframes sticker-drop {
  0%   { opacity: 0; transform: translateY(-70px) rotate(-16deg) scale(.6); }
  60%  { opacity: 1; transform: translateY(6px) rotate(3deg) scale(1.05); }
  100% { opacity: 1; transform: translateY(0) rotate(-2deg) scale(1); }
}
.anim-sticker { animation: sticker-drop 1.1s var(--spring) both; }

/* ---- word-by-word headline: rises from behind a mask with rotation ------ */
@keyframes word-up {
  from { transform: translateY(110%) rotate(6deg); }
  to   { transform: translateY(0) rotate(0); }
}
/* ---- HERO OPENING (pure CSS, driven by the .opening class in hero.js) ----
   The headline reveal no longer depends on GSAP tweening: each word rises from
   behind its clip on a per-word animation-delay (--wd), so it always plays. */
@keyframes hw-rise { from { transform: translateY(115%); } to { transform: translateY(0); } }
@keyframes hs-rise { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: none; } }
@keyframes fade-up {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

/* ---- live pulse dot ----------------------------------------------------- */
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: .4; transform: scale(.7); }
}

/* ---- hero video slow scale drift so it is never frozen ------------------ */
@keyframes drift {
  0%   { transform: scale(1.06) translate(0, 0); }
  100% { transform: scale(1.16) translate(-2%, -2%); }
}

/* ---- marquee / ticker slide -------------------------------------------- */
@keyframes marquee { to { transform: translateX(-50%); } }
@keyframes marquee-rev { from { transform: translateX(-50%); } to { transform: translateX(0); } }

/* ---- drifting glow orb -------------------------------------------------- */
@keyframes float-glow { to { transform: translate(-60px, 70px) scale(1.15); } }

/* ---- scroll hint sweep -------------------------------------------------- */
@keyframes sweep { to { transform: translateX(100%); } }

/* ==========================================================================
   OPENING SEQUENCE — a transparent layer holding the centred logo.
   The pop / hold / flight is one GSAP timeline in hero.js; the hero photo
   underneath is visible from frame 1, so there is never a blank screen.
   ========================================================================== */
.loader {
  position: fixed; inset: 0; z-index: var(--z-loader);
  background: transparent; display: grid; place-items: center;
  pointer-events: none;
}
.loader.done { opacity: 0; visibility: hidden; }
/* centre logo: bigger on mobile (viewport-relative), capped on desktop. Light
   logo variant so it reads on the dark hero; strong shadow lifts it off the photo. */
.loader-logo { width: clamp(190px, 52vw, 240px); filter: drop-shadow(0 18px 44px rgba(0, 0, 0, .45)); }
/* pre-state: hidden until GSAP pops it in, so it never flashes at full size first */
.js-hero .loader-logo { opacity: 0; }

/* ==========================================================================
   MOTION UTILITY CLASSES (used across steps)
   ========================================================================== */
.will-move { will-change: transform, opacity; }
.tilt-l { transform: rotate(-3deg); }
.tilt-r { transform: rotate(2.5deg); }

/* reduced-motion: opening sequence must resolve to a complete static page */
@media (prefers-reduced-motion: reduce) {
  .loader { display: none !important; }
  .anim-sticker, .loader-logo { animation: none !important; }
}
