/* ==========================================================================
   animations.css — scroll reveals, entrances, micro-interactions
   All motion uses transform/opacity only (GPU-composited).
   Everything is disabled under prefers-reduced-motion (see bottom of file).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. SCROLL REVEAL
   Elements start hidden only when JS is active (html.js), so a no-JS
   visitor always sees full content.
   -------------------------------------------------------------------------- */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(30px) scale(.985);
  transition:
    opacity .78s var(--e-out),
    transform .78s var(--e-out);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal="left"]  { transform: translateX(-38px); }
.js [data-reveal="right"] { transform: translateX(38px); }
.js [data-reveal="scale"] { transform: scale(.93); }
.js [data-reveal="fade"]  { transform: none; }

/* Horizontal reveal offsets would otherwise widen the page while the element
   is still off-position. Clip at the section so the document never scrolls
   sideways, and drop to a vertical-only reveal on narrow screens. */
.section, .hero { overflow-x: clip; }

@media (max-width: 900px) {
  .js [data-reveal="left"],
  .js [data-reveal="right"] { transform: translateY(30px); }
}

.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Staggered children */
.js [data-stagger] > * {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity .68s var(--e-out), transform .68s var(--e-out);
}
.js [data-stagger].is-visible > *      { opacity: 1; transform: none; }
.js [data-stagger].is-visible > *:nth-child(1) { transition-delay: 0ms; }
.js [data-stagger].is-visible > *:nth-child(2) { transition-delay: 70ms; }
.js [data-stagger].is-visible > *:nth-child(3) { transition-delay: 140ms; }
.js [data-stagger].is-visible > *:nth-child(4) { transition-delay: 210ms; }
.js [data-stagger].is-visible > *:nth-child(5) { transition-delay: 280ms; }
.js [data-stagger].is-visible > *:nth-child(6) { transition-delay: 350ms; }
.js [data-stagger].is-visible > *:nth-child(7) { transition-delay: 420ms; }
.js [data-stagger].is-visible > *:nth-child(8) { transition-delay: 490ms; }
.js [data-stagger].is-visible > *:nth-child(n+9) { transition-delay: 560ms; }

/* --------------------------------------------------------------------------
   2. HERO ENTRANCE
   -------------------------------------------------------------------------- */
.js .hero__content > * {
  opacity: 0;
  transform: translateY(28px);
  animation: heroIn .95s var(--e-out) forwards;
}
.js .hero__content > *:nth-child(1) { animation-delay: .12s; }
.js .hero__content > *:nth-child(2) { animation-delay: .24s; }
.js .hero__content > *:nth-child(3) { animation-delay: .36s; }
.js .hero__content > *:nth-child(4) { animation-delay: .48s; }
.js .hero__content > *:nth-child(5) { animation-delay: .60s; }

@keyframes heroIn { to { opacity: 1; transform: none; } }

.js .hero__float {
  opacity: 0;
  animation: floatIn 1s var(--e-out) .8s forwards,
             float 8s ease-in-out 1.8s infinite;
}
@keyframes floatIn { to { opacity: 1; } }

/* --------------------------------------------------------------------------
   3. 3D TILT
   Set by JS as --tilt-x / --tilt-y on the card.
   -------------------------------------------------------------------------- */
.tilt-scene { perspective: 1100px; }

.js .svc {
  transform:
    perspective(1100px)
    rotateX(var(--tilt-x, 0deg))
    rotateY(var(--tilt-y, 0deg))
    translateY(var(--tilt-lift, 0px));
}
.js .svc:hover { --tilt-lift: -7px; box-shadow: var(--sh-xl); }

/* --------------------------------------------------------------------------
   4. STAR FILL-IN
   -------------------------------------------------------------------------- */
.js .stars[data-animate] svg {
  opacity: 0;
  transform: scale(.4) rotate(-25deg);
}
.js .stars[data-animate].is-visible svg {
  animation: starPop .48s var(--e-out) forwards;
}
.js .stars[data-animate].is-visible svg:nth-child(1) { animation-delay: .05s; }
.js .stars[data-animate].is-visible svg:nth-child(2) { animation-delay: .12s; }
.js .stars[data-animate].is-visible svg:nth-child(3) { animation-delay: .19s; }
.js .stars[data-animate].is-visible svg:nth-child(4) { animation-delay: .26s; }
.js .stars[data-animate].is-visible svg:nth-child(5) { animation-delay: .33s; }

@keyframes starPop {
  0%   { opacity: 0; transform: scale(.4) rotate(-25deg); }
  60%  { opacity: 1; transform: scale(1.22) rotate(4deg); }
  100% { opacity: 1; transform: scale(1) rotate(0); }
}

/* --------------------------------------------------------------------------
   5. FLOATING DECOR
   -------------------------------------------------------------------------- */
.float-slow { animation: float 11s ease-in-out infinite; }
.float-med  { animation: float 8s  ease-in-out infinite; }
.float-fast { animation: float 6s  ease-in-out infinite; }
.float-delay-1 { animation-delay: -2.5s; }
.float-delay-2 { animation-delay: -5s; }

/* --------------------------------------------------------------------------
   6. PARALLAX LAYERS
   translate3d values are written by JS in rAF.
   -------------------------------------------------------------------------- */
[data-parallax] { will-change: transform; }

/* --------------------------------------------------------------------------
   7. MICRO-INTERACTIONS
   -------------------------------------------------------------------------- */
/* Magnetic buttons — offsets set by JS */
.js .btn[data-magnetic] {
  transform: translate(var(--mx, 0px), calc(var(--my, 0px) + var(--lift, 0px)));
  transition: transform .28s var(--e-out), box-shadow var(--t-med) var(--e-out);
}
.js .btn[data-magnetic]:hover { --lift: -3px; }

/* Copy-to-clipboard tick */
.copy-btn { position: relative; }
.copy-btn .tick {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  border-radius: inherit;
  background: var(--ok); color: #fff;
  opacity: 0; transform: scale(.85);
  transition: opacity var(--t-fast) var(--e-out), transform var(--t-fast) var(--e-out);
  pointer-events: none;
}
.copy-btn.is-copied .tick { opacity: 1; transform: none; }

/* Underline sweep for text links */
.sweep { position: relative; }
.sweep::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -2px;
  height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: 100% 50%;
  transition: transform var(--t-med) var(--e-out);
}
.sweep:hover::after { transform: scaleX(1); transform-origin: 0 50%; }

/* Page-load reveal curtain */
.preload {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  background: var(--surface-deep);
  transition: transform .7s var(--e-out), opacity .5s var(--e-out);
}
.preload.is-done {
  transform: translateY(-100%);
  opacity: 0;
  pointer-events: none;
}
.preload img { width: 84px; height: 84px; animation: preloadPulse 1.3s ease-in-out infinite; }
@keyframes preloadPulse {
  0%, 100% { transform: scale(1);    opacity: .85; }
  50%      { transform: scale(1.09); opacity: 1; }
}

/* --------------------------------------------------------------------------
   8. REDUCED MOTION — full opt-out
   Content must remain visible and functional with zero movement.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }

  /* Force every reveal-state element fully visible and unmoved */
  .js [data-reveal],
  .js [data-stagger] > *,
  .js .hero__content > *,
  .js .hero__float,
  .js .stars[data-animate] svg {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }

  /* Kill parallax, drift, tilt, magnetism */
  [data-parallax],
  .js .svc,
  .js .btn[data-magnetic],
  .float-slow, .float-med, .float-fast,
  .hero__float, .split__badge,
  .hero__scroll .line,
  .mobile-bar .wa::after,
  .preload img {
    transform: none !important;
    animation: none !important;
  }

  .preload { display: none !important; }
}
