/* Elements that animate in start hidden, but only once JS is confirmed running
   (the .js class), so content never vanishes if the script fails. 0.001 instead of 0
   is Framer's trick: the layer stays composited and counts as painted for LCP. */
.js :is(
  [data-anim="fade-in"], [data-anim="slide-up"], [data-anim="hero-rise"], [data-anim="drop-in"],
  [data-anim="reveal-up"], [data-anim="reveal-side"], [data-anim="text-reveal"], [data-anim="char-rise"], [data-anim="char-appear"],
  [data-anim="reveal-stagger"] > *
) { opacity: 0.001; }

[data-anim="scroll-progress"] { transform-origin: 0 50%; transform: scaleX(0); }
[data-anim="image-zoom"] { overflow: hidden; }
[data-anim="ticker"] { overflow: hidden; }
[data-anim="hover-headline"] { position: relative; overflow: hidden; }
[data-anim="hover-headline"] [data-title] { position: absolute; inset-inline: 0; top: 0; width: fit-content; margin: 0 auto; white-space: pre; }
[data-anim="hover-headline"] [data-title=""] { position: relative; }  /* skew pivots on the text, not the full row */
[data-anim="hover-headline"] [data-title]:not([data-title=""]) { transform: translateY(240px) skewY(12deg); }
[data-anim="ticker"] > * { display: flex; width: max-content; }

.fa-mask { display: inline-block; overflow: hidden; vertical-align: top; padding-bottom: 0.08em; margin-bottom: -0.08em; }
.fa-mask > span { display: inline-block; will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  .js [data-anim], .js [data-anim] > * { opacity: 1 !important; }
}
