/* Page-wide scroll-reveal: images and text blocks fade in (some also rise slightly)
   the first time they cross into view, once each (see js/reveal.js). Deliberately NOT
   applied to the hero (its own WebGL/video system already IS the entrance),
   .video-transition (same), or TRUST-BAND's .trust-band__card/.trust-band__mini-collage
   (those already animate in via the scroll-drift cluster-to-spread effect — a second
   fade on top would fight it).

   Two variants: .reveal (opacity + translateY) for elements with no transform of their
   own, and .reveal-fade (opacity only) for elements that already use `transform:
   translateX(-50%)` for centering — adding a translateY there would silently replace
   that centering instead of combining with it, since an element only has one
   `transform` value. */

.reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1), transform 0.9s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.reveal-fade {
  opacity: 0;
  transition: opacity 0.9s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity;
}
.reveal-fade.is-visible {
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
  /* NOT `transform: none` here — that is the exact bug this class exists to avoid.
     .reveal-fade is applied to elements that already carry their own
     `transform: translateX(-50%)` centering (hero headings/subs, stat blocks), so
     zeroing transform here silently un-centers them and pushes them off-screen —
     the same one-transform-per-element trap described above, just reached via the
     reduced-motion path instead. This class never animates transform anyway, so it
     has nothing to reset. */
  .reveal-fade {
    opacity: 1;
    transition: none;
  }
}

/* Images (2026-08-28, per Arina: "when they disappear on top they squeeze or fade
   out"): unlike .reveal/.reveal-fade above (one-shot — revealed once, then left alone),
   .img-reveal keeps observing and toggles on every crossing (js/reveal.js), so an image
   plays its entrance again each time it's scrolled back into view:
     - default (never yet seen, or scrolled back below the viewport without ever
       entering): faded down and slightly small, waiting to rise in.
     - .is-visible (currently on screen): fully visible, resting scale.
     - .img-reveal--exit (scrolled back UP, off the TOP of the viewport): fades out
       while squeezing down (opacity + scale, not the entrance's translateY) — a
       distinct, quicker exit rather than just reversing the entrance.
   Excludes TRUST-BAND's cards/mini-collage (own drift animation, see scroll-drift.js)
   and the true background images (.closing__bleed/.closing__scrim) — see js/reveal.js
   for the exact selector list. */
.img-reveal {
  opacity: 0;
  transform: translateY(28px) scale(0.96);
  transition: opacity 0.8s cubic-bezier(0.22, 1, 0.36, 1), transform 0.8s cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}
.img-reveal.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
}
.img-reveal.img-reveal--exit {
  opacity: 0;
  transform: translateY(-16px) scale(0.9);
  transition: opacity 0.5s ease, transform 0.5s ease;
}

@media (prefers-reduced-motion: reduce) {
  .img-reveal {
    opacity: 1;
    transform: none;
    transition: none;
  }
}
