/* ============ MOTION ============ */

/* --- Word-by-word reveal --- */
.reveal {
  text-indent: 0 !important;
}
.reveal-line {
  display: inline-block;
  overflow: hidden;
  vertical-align: top;
}
.reveal-word {
  display: inline-block;
  transform: translateY(110%);
  opacity: 0;
  transition: transform .9s cubic-bezier(.2,.7,.2,1), opacity .9s ease;
  will-change: transform;
}
.reveal-word--space { width: .28em; }
.reveal.is-revealed .reveal-word {
  transform: translateY(0);
  opacity: 1;
}

/* --- Clip-path image reveal ---
   Only hide the image while we're waiting on the observer / before load.
   Once the element gets `.is-revealed` (or we hit the fallback) the image
   slides into view. The arm class is added by JS so SSR/no-JS clients
   never see a clipped image. */
.clip-reveal {
  overflow: hidden;
}
.clip-reveal.clip-armed > img,
.clip-reveal.clip-armed > picture > img {
  clip-path: inset(0 0 100% 0);
  transform: scale(1.06);
  transition: clip-path 1.3s cubic-bezier(.2,.7,.2,1), transform 1.6s cubic-bezier(.2,.7,.2,1);
  will-change: clip-path, transform;
}
.clip-reveal.is-revealed > img,
.clip-reveal.is-revealed > picture > img {
  clip-path: inset(0 0 0 0);
  transform: scale(1);
}

/* --- Magnetic buttons --- */
.magnet {
  display: inline-flex;
  transition: transform .25s cubic-bezier(.2,.7,.3,1);
  will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
  .reveal-word { transform: none !important; opacity: 1 !important; transition: none !important; }
  .clip-reveal > img { clip-path: none !important; transform: none !important; transition: none !important; }
  .magnet { transform: none !important; }
}
