/* AppRoster — motion layer. Loaded after style.css.
   Keyframes, transitions, IntersectionObserver hooks live here.
   Everything inside the reduced-motion media query at the bottom is
   the canonical disable: respect the user's OS-level setting. */

/* === Reveal-on-scroll base === */
.reveal {
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity 600ms ease-out,
    transform 600ms ease-out;
  will-change: opacity, transform;
}
.reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* === Hero marquee animation === */
@keyframes marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
.marquee-track {
  animation: marquee 60s linear infinite;
}
.marquee:hover .marquee-track {
  animation-play-state: paused;
}

/* === §02 phone cross-fade between states === */
.iu-phone .pm-state {
  transition: opacity 200ms ease-out;
}
.iu-phone .pm-state.is-leaving {
  opacity: 0;
}

/* === Reduced motion: collapse all transitions to instant === */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .marquee-track {
    animation: none;
  }
  [data-count] {
    font-size: 0;          /* hide the live "0" textContent */
  }
  [data-count]::before {
    content: attr(data-prefix) attr(data-count);
    font-size: 32px;
    font-weight: 900;
    letter-spacing: -1.5px;
  }
  .feature-card::before,
  .feature-card::after {
    transition: none;
  }
  .iu-phone .pm-state { transition: none; }
  .plan-stack::before,
  .plan-stack::after,
  .plan.featured {
    transition: none;
  }
}
