/* Content settles in on first view. Nothing loops, nothing moves on its own. */
[data-reveal] {
  opacity: 0;
  transform: translate(var(--enter-x, 0), 14px);
  transition: opacity 560ms var(--ease), transform 620ms var(--ease);
  transition-delay: var(--delay, 0ms);
}
[data-reveal].is-revealed { opacity: 1; transform: none; }

/* Children arrive in sequence off a single observer, rather than one each. */
[data-stagger] > * {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 520ms var(--ease), transform 520ms var(--ease);
}
[data-stagger].is-revealed > * { opacity: 1; transform: none; }
[data-stagger].is-revealed > *:nth-child(1) { transition-delay: 0ms; }
[data-stagger].is-revealed > *:nth-child(2) { transition-delay: 80ms; }
[data-stagger].is-revealed > *:nth-child(3) { transition-delay: 160ms; }
[data-stagger].is-revealed > *:nth-child(4) { transition-delay: 240ms; }

.hero [data-intro] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
  transition-delay: var(--delay, 0ms);
}
.is-ready .hero [data-intro] { opacity: 1; transform: none; }

/* The hero phones keep their layout transforms, so they animate opacity only. */
.hero-shot .device { opacity: 0; transition: opacity 700ms var(--ease); transition-delay: var(--delay, 0ms); }
.is-ready .hero-shot .device { opacity: 1; }

/* JS clones the track, so -50% lands exactly on the seam. */
@keyframes slide {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ---------- Feature phones ----------
   Each phone drifts against its column as the row passes, so the section reads
   as depth rather than four stacked screenshots. Driven off the scroll position
   itself, not a scroll listener, so there is nothing to throttle and nothing to
   jank. Browsers without view() timelines simply get the entrance and no drift. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .feature-shot .device {
      animation: phone-pass linear both;
      animation-timeline: view();
    }
  }
}

@keyframes phone-pass {
  from { transform: translateY(var(--drift, 30px))            rotate(var(--tilt, -2deg)); }
  to   { transform: translateY(calc(var(--drift, 30px) * -1)) rotate(calc(var(--tilt, -2deg) * -1)); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal], [data-stagger] > *, .hero [data-intro] { opacity: 1 !important; transform: none !important; }
  .feature-shot .device { animation: none; transform: none; }
  /* Nothing to scroll past, so let the names wrap and sit still. */
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee-track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    row-gap: 0.55rem;
  }
}
