/* Stacking-cards sheets — loaded from index.html behind
   media="(min-width: 1280px) and (min-height: 880px)".

   It lives outside the inlined critical CSS on purpose. Measured: folding these rules into
   index.html cost mobile 80ms of FCP and 4 Lighthouse points for a feature phones never
   render. A media-mismatched stylesheet is fetched at low priority and never blocks the
   first paint, so phones now pay nothing on the critical path.

   Design notes live in src/components/StackPanels.tsx. The short version:
     stack-depth  transform only  -> compositor
     stack-dim    opacity only    -> compositor
     stack-hide   visibility only -> main thread, one discrete flip
   Blink refuses to composite a keyframe effect that touches a non-compositable property,
   so `visibility` must not be folded into stack-depth.

   `position: sticky` sits inside the @supports guard: without scroll-driven animations
   there is no depth cue and no `visibility` fix, so such browsers get the plain page. */

.stack { position: relative; }
.stack-panel__dim { display: none; }
.stack-rail { display: none; }

@supports (animation-timeline: view()) {
  .stack-rail { display: flex; }

  /* a sheet references a timeline declared on a following sibling, so the names must be
     hoisted into a shared scope or they would not resolve */
  .stack {
    timeline-scope: --sp0, --sp1, --sp2, --sp3, --sp4, --sp5,
                    --sp6, --sp7, --sp8, --sp9, --sp10, --sp11;
  }

  .stack-panel {
    position: sticky;
    top: 0;
    min-height: 100svh;
    background: #23282F; /* dark rim revealed as the sheet shrinks */
  }

  .stack-panel__inner {
    position: relative;
    display: flex;
    align-items: center;
    min-height: 100svh;
    /* The navbar is fixed and opaque. A sheet pinned at top:0 centres its content in the
       whole viewport, so on the taller sheets the heading ended up behind the navbar.
       Reserve its height; StackPanels subtracts the same padding when it checks that a
       sheet fits. Keep --stack-nav-h in sync with the Navbar's height. */
    --stack-nav-h: 6.25rem;
    padding-top: var(--stack-nav-h);
    padding-bottom: 1.5rem;
    overflow: hidden;
    transform-origin: 50% 0%;
    will-change: transform;
    animation: stack-depth linear both;
    animation-range: entry 0% entry 100%;
  }

  .stack-panel__content {
    animation: stack-hide linear both;
    animation-range: entry 0% entry 100%;
  }

  .stack-panel__dim {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 30;
    background: #05070D;
    opacity: 0;
    pointer-events: none;
    animation: stack-dim linear both;
    animation-range: entry 0% entry 100%;
  }

  .stack > .stack-panel:nth-child(1) { view-timeline-name: --sp0; }
  .stack > .stack-panel:nth-child(2) { view-timeline-name: --sp1; }
  .stack > .stack-panel:nth-child(3) { view-timeline-name: --sp2; }
  .stack > .stack-panel:nth-child(4) { view-timeline-name: --sp3; }
  .stack > .stack-panel:nth-child(5) { view-timeline-name: --sp4; }
  .stack > .stack-panel:nth-child(6) { view-timeline-name: --sp5; }
  .stack > .stack-panel:nth-child(7) { view-timeline-name: --sp6; }
  .stack > .stack-panel:nth-child(8) { view-timeline-name: --sp7; }
  .stack > .stack-panel:nth-child(9) { view-timeline-name: --sp8; }
  .stack > .stack-panel:nth-child(10) { view-timeline-name: --sp9; }
  .stack > .stack-panel:nth-child(11) { view-timeline-name: --sp10; }
  .stack > .stack-panel:nth-child(12) { view-timeline-name: --sp11; }

  /* sheet N is pushed back by sheet N+1 entering the viewport */
  .stack > .stack-panel:nth-child(1) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp1; }
  .stack > .stack-panel:nth-child(2) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp2; }
  .stack > .stack-panel:nth-child(3) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp3; }
  .stack > .stack-panel:nth-child(4) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp4; }
  .stack > .stack-panel:nth-child(5) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp5; }
  .stack > .stack-panel:nth-child(6) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp6; }
  .stack > .stack-panel:nth-child(7) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp7; }
  .stack > .stack-panel:nth-child(8) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp8; }
  .stack > .stack-panel:nth-child(9) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp9; }
  .stack > .stack-panel:nth-child(10) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp10; }
  .stack > .stack-panel:nth-child(11) :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation-timeline: --sp11; }

  /* nothing covers the last sheet */
  .stack > .stack-panel:last-child :is(.stack-panel__inner, .stack-panel__content, .stack-panel__dim) { animation: none; }
}

/* Sheets settle like slides. Without this the scroller can rest halfway through a transition,
   which reads as a half-finished page — and leaves focusable controls behind the covering
   sheet. `scroll-snap-stop: always` also stops a fast flick from skipping a sheet entirely.

   The attribute is set by StackPanels only while the pile is running, so nothing snaps on
   phones, under reduced motion, or on any other page.

   The footer needs its own snap position: under `mandatory` a scroller must always come to
   rest on one, so without it the browser would drag the user back onto the last sheet and
   the footer could never be reached. */
html[data-stack-snap='true'] {
  scroll-snap-type: y mandatory;
}
html[data-stack-snap='true'] .stack-panel {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
html[data-stack-snap='true'] footer {
  scroll-snap-align: start;
}

/* Escape hatch: StackPanels measures the sheets and turns the pile off when any of them is
   taller than the viewport (long localization, raised minimum font size, page zoom). */
.stack-root[data-fits='false'] .stack-rail { display: none; }
.stack-root[data-fits='false'] .stack-panel { position: static; min-height: 0; background: none; }
.stack-root[data-fits='false'] .stack-panel__inner { min-height: 0; overflow: visible; animation: none; }
.stack-root[data-fits='false'] .stack-panel__content { animation: none; visibility: visible; }
.stack-root[data-fits='false'] .stack-panel__dim { display: none; }

/* perspective() lives inside the transform list so no ancestor `perspective` is needed */
@keyframes stack-depth {
  from { transform: perspective(2200px) translateY(0) scale(1) rotateX(0deg); }
  to { transform: perspective(2200px) translateY(-42px) scale(0.88) rotateX(7deg); }
}
@keyframes stack-hide {
  from { visibility: visible; }
  to { visibility: hidden; }
}
@keyframes stack-dim {
  from { opacity: 0; }
  to { opacity: 0.72; }
}

/* No pile at all: sheets covering each other is disorienting even when nothing animates,
   and a pinned-but-covered sheet would still hold focusable controls off-screen.
   (StackPanels also refuses to render the pile under this preference.) */
@media (prefers-reduced-motion: reduce) {
  .stack-panel { position: static; min-height: 0; background: none; }
  .stack-panel__inner { position: relative; min-height: 0; overflow: visible; animation: none; }
  .stack-panel__content { animation: none; visibility: visible; }
  .stack-panel__dim { display: none; }
  .stack-rail { display: none; }
}
