/* ==========================================================================
   intro.css — the page arriving
   --------------------------------------------------------------------------
   You reach this screen from the concepts front door, so the first thing it
   does is the first thing anyone sees. Everything used to be painted in one
   frame: app bar, hero plate, five rails and the footer all simply there.
   Nothing was wrong with any single element — it was that they arrived
   together, which reads as a page snapping into place rather than opening.

   So the load is staged, from the top down, in the order someone reads it:
   the bar, the hero's plate, then each rail in turn, then the footer. The
   hero's own metadata is NOT touched here — js/hero.js already resolves the
   logo, meta, synopsis and buttons on their own stagger, and running a
   second entrance over that would fight it.

   HOW IT IS SCOPED, and why it matters: everything lives under
   `.page.is-entering`, a class js/app.js puts on at load and takes off once
   the longest animation has finished. It cannot be a permanent rule with
   `animation-fill-mode: both`, because the final keyframe would stay
   applied and pin `transform: none` onto the cards — which would silently
   kill the hover zoom, the rail's paging translate, and the preview morph.
   With the class removed at the end, the elements are left in their own
   natural state and every later transform behaves as if this file did not
   exist.

   The delays are cumulative but short: the whole sequence is done in about
   1.1s, because this is a page opening, not a title card.
   ========================================================================== */

:root {
  --intro-dur:   560ms;         /* one element's own travel               */
  --intro-step:  90ms;          /* between rails                          */
  --intro-card:  45ms;          /* between cards inside a rail            */
  --intro-ease:  cubic-bezier(0.22, 0.72, 0.24, 1);
}

/* Nothing is hidden before the class lands: if the stylesheet loads and
   the script does not, the page is simply the page. Only `.is-entering`
   introduces the from-state, and it is applied in the same frame. */

@keyframes intro-drop {
  from { opacity: 0; transform: translateY(-10px); }
  to   { opacity: 1; transform: none; }
}

@keyframes intro-rise {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}

/* The plate settles out of a whisper of over-scale, the same gesture the
   hero's own slides use when they change — so arriving and advancing feel
   like the same screen. */
@keyframes intro-plate {
  from { opacity: 0; transform: scale(1.035); }
  to   { opacity: 1; transform: none; }
}

@keyframes intro-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}


/* ---- the sequence -------------------------------------------------------- */

.page.is-entering .app-bar {
  animation: intro-drop var(--intro-dur) var(--intro-ease) both;
}

.page.is-entering .hero__stage {
  animation: intro-plate 760ms var(--intro-ease) 60ms both;
}

/* The pagination and the mute control belong to the hero but are not part
   of the metadata stagger, so they would otherwise be the one thing that
   pops while everything else resolves. */
.page.is-entering .hero__tray,
.page.is-entering .hero__control--mute {
  animation: intro-fade var(--intro-dur) linear 520ms both;
}

/* Rails, top to bottom. :nth-of-type counts .rail among its siblings, and
   the branded rail is a different element, so it carries its own delay
   rather than being part of the count. */
.page.is-entering .rail,
.page.is-entering .rail-branded {
  animation: intro-rise var(--intro-dur) var(--intro-ease) both;
}

.page.is-entering .rail:nth-of-type(1) { animation-delay: 300ms; }
.page.is-entering .rail:nth-of-type(2) { animation-delay: calc(300ms + var(--intro-step)); }
.page.is-entering .rail:nth-of-type(3) { animation-delay: calc(300ms + var(--intro-step) * 2); }
.page.is-entering .rail-branded        { animation-delay: calc(300ms + var(--intro-step) * 3); }
.page.is-entering .rail:nth-of-type(4) { animation-delay: calc(300ms + var(--intro-step) * 4); }

.page.is-entering .footer {
  animation: intro-fade var(--intro-dur) linear 700ms both;
}

/* Cards inside the first rail only. Staggering every rail's cards made the
   page feel like it was dealing itself out; the rail the eye lands on
   first is the one worth the detail, and the rest arrive as a row. The
   delay is on top of the rail's own, so a card can never precede it. */
.page.is-entering .rail:nth-of-type(1) .rail__track > * {
  animation: intro-rise 480ms var(--intro-ease) both;
}

.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(1) { animation-delay: 360ms; }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(2) { animation-delay: calc(360ms + var(--intro-card)); }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(3) { animation-delay: calc(360ms + var(--intro-card) * 2); }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(4) { animation-delay: calc(360ms + var(--intro-card) * 3); }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(5) { animation-delay: calc(360ms + var(--intro-card) * 4); }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(6) { animation-delay: calc(360ms + var(--intro-card) * 5); }
.page.is-entering .rail:nth-of-type(1) .rail__track > *:nth-child(n+7) { animation-delay: calc(360ms + var(--intro-card) * 6); }


/* ---- reduced motion ------------------------------------------------------
   No travel and no stagger. The page is simply present, which is the
   correct answer to "I do not want things moving", not a slower version of
   the same sequence. */
@media (prefers-reduced-motion: reduce) {
  .page.is-entering .app-bar,
  .page.is-entering .hero__stage,
  .page.is-entering .hero__tray,
  .page.is-entering .hero__control--mute,
  .page.is-entering .rail,
  .page.is-entering .rail-branded,
  .page.is-entering .rail .rail__track > *,
  .page.is-entering .footer {
    animation: none;
  }
}
