/* ==========================================================================
   animations.css — motion-only rules. Loaded last so it can override.

   The important rule here is what is NOT in this file: no element is hidden
   with CSS. Every "from" state is set by GSAP at runtime, so if the CDN is
   slow or blocked the page is simply a static, complete, readable site rather
   than a screen of invisible content.
   ========================================================================== */

/* ---------- GPU hints, applied only while an element is in motion ----------
   will-change is added by JS through .is-animating and removed on complete,
   so no layer is promoted for the whole life of the page. */
.is-animating { will-change: transform, opacity; }

/* Long-lived scrubbed layers earn a permanent hint. */
.hero__group,
.hero__skyline,
.hero__roses,
.rail.is-pinned .rail__track { will-change: transform; }

/* ---------- the ambient drift of the decorative art ----------
   Kept in CSS rather than GSAP: it is an idle loop with no scroll dependency,
   so the compositor can run it without touching the main thread. */
@keyframes drift-y {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -12px, 0); }
}
@keyframes drift-y-soft {
  0%, 100% { transform: translate3d(0, 0, 0); }
  50%      { transform: translate3d(0, -7px, 0); }
}
@keyframes twinkle {
  0%, 100% { opacity: .35; transform: scale(.94); }
  50%      { opacity: 1;   transform: scale(1); }
}
/* The glints are mirrored in the design, so their idle loop has to carry the
   flip through or the keyframe would reset it. */
@keyframes twinkle-flip {
  0%, 100% { opacity: .35; transform: scaleX(-1) scale(.94); }
  50%      { opacity: 1;   transform: scaleX(-1) scale(1); }
}
@keyframes cue-travel {
  0%       { transform: scaleY(0);  transform-origin: top center;    opacity: 0; }
  40%      { transform: scaleY(1);  transform-origin: top center;    opacity: 1; }
  60%      { transform: scaleY(1);  transform-origin: bottom center; opacity: 1; }
  100%     { transform: scaleY(0);  transform-origin: bottom center; opacity: 0; }
}

/* The drift is applied to a wrapper-free element only where the element's own
   transform is not already spoken for by layout. */
.is-drifting     { animation: drift-y 9s var(--ease-soft) infinite; }
.is-drifting--sm { animation: drift-y-soft 7s var(--ease-soft) infinite; }

.passes__star { animation: twinkle 5.5s ease-in-out infinite; }
.passes__star--b { animation-delay: -1.8s; animation-duration: 6.5s; }
.passes__star--c { animation-delay: -3.4s; animation-duration: 4.8s; }

.glint { animation: twinkle-flip 6s ease-in-out infinite; }
.glint--b { animation-delay: -2.2s; }
.glint--c { animation-delay: -4.1s; }

.hero__cue-line { animation: cue-travel 2.6s var(--ease-soft) infinite; }

/* ---------- interactive states that belong to motion, not to the design ----
   Only properties GSAP does not touch are transitioned here. Every element
   whose transform is scrubbed or tweened is left to its JS owner. */
.reel { transition: box-shadow var(--dur-slow) var(--ease-out); }
.reel--main:hover { box-shadow: 0 34px 90px rgba(0, 0, 0, .7); }

/* ==========================================================================
   Reduced motion — a complete, still version of the same page.

   The scroll-linked reveals are disabled in JS (which skips Lenis, the WebGL
   layer and every scrub, and paints the final state immediately). These rules
   deal with the CSS-owned half: the idle loops and the hover transitions.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }

  .is-drifting, .is-drifting--sm,
  .passes__star, .glint, .hero__cue-line { animation: none; }

  /* Nothing is left mid-reveal. */
  .split__line { overflow: visible; }
  .qa__a { height: auto; }
  .qa__a[hidden] { display: none; }

  .hero__atmosphere { display: none; }
  .cursor { display: none !important; }
  body.has-custom-cursor,
  body.has-custom-cursor a,
  body.has-custom-cursor button { cursor: auto; }
}
