/* ============================================================
   motion — the one file that decides whether anything is allowed
   to move. It declares no animation of its own; components own
   their keyframes, this owns the policy.

   Load it LAST. It is a policy layer, so it deliberately
   overrides components, and the three rules below are the only
   honest !important on this page.

   The order of the three matters:
     1. inside a scene, a loop is paused
     2. the shared observer starts it while the scene is on screen
     3. the reader's stop button beats both

   (A cascade layer would express this without !important. That is
   the better long-term shape, but it means wrapping all nine
   stylesheets at once; noted, not done.)

   The contract every animated component obeys:

     - looping animation is declared under `.js [data-scene]`,
       never bare. No JS means no loop, and no loop means the
       scene sits in its finished state — the same state reduced
       motion gets, and the same state a printout gets.
     - the scene element carries `data-scene`. Nothing else is
       needed: motion.js finds it and observes it.
     - rows that stagger carry `--i` (0, 1, 2 …) so delays come
       out of one calc() instead of one rule per child.
     - only `transform` and `opacity` are animated.
   ============================================================ */

/* Every selector below is written three times — the element, then
   `::before` and `::after`. A pseudo-element is not matched by `*`,
   and the Channel Management scene puts real motion on them: a
   row's lift, a press ring's ground, a sidebar row's hover. Without
   the two extra lines those keep running through the pause AND
   through `prefers-reduced-motion`, which is exactly what this
   policy exists to prevent. */

/* 1 · off screen costs nothing */
.js [data-scene],
.js [data-scene]::before,
.js [data-scene]::after,
.js [data-scene] *,
.js [data-scene] *::before,
.js [data-scene] *::after            { animation-play-state: paused !important; }

/* 2 · on screen, it runs */
.js [data-scene].is-visible,
.js [data-scene].is-visible::before,
.js [data-scene].is-visible::after,
.js [data-scene].is-visible *,
.js [data-scene].is-visible *::before,
.js [data-scene].is-visible *::after { animation-play-state: running !important; }

/* 3 · WCAG 2.2.2 — twelve scenes loop on their own, past five
   seconds, right beside the text. That has to be stoppable, and
   the stop must beat everything above it. */
:root[data-motion="paused"] [data-scene],
:root[data-motion="paused"] [data-scene]::before,
:root[data-motion="paused"] [data-scene]::after,
:root[data-motion="paused"] [data-scene] *,
:root[data-motion="paused"] [data-scene] *::before,
:root[data-motion="paused"] [data-scene] *::after,
:root[data-motion="paused"] .marquee-track { animation-play-state: paused !important; }

/* The OS setting is not a preference to negotiate with. */
@media (prefers-reduced-motion: reduce) {
  [data-scene],
  [data-scene]::before,
  [data-scene]::after,
  [data-scene] *,
  [data-scene] *::before,
  [data-scene] *::after { animation: none !important; transition: none !important; }
}

/* ---------- the stop button ----------
   Lives in the footer's legal row, not the nav — the header is a
   landing page's three links and a CTA. Same row as the copyright
   line, so it reads as a page-level control rather than a feature.
   Hidden until JS is there to make it work: a dead control is
   worse than none. */

.motion-toggle {
  margin-inline-start: auto;
  display: none;
  align-items: center;
  gap: var(--s-2);
  font: inherit;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-2);
  background: none;
  border: 1px solid var(--line);
  border-radius: 50px;
  padding: 5px 12px 5px 10px;
  cursor: pointer;
}
.js .motion-toggle:not([hidden]) { display: inline-flex; }
.motion-toggle:hover { color: var(--text); border-color: var(--line-strong, var(--line)); }
.motion-toggle:focus-visible { outline: 2px solid var(--cta); outline-offset: 2px; }

.motion-ico { position: relative; width: 9px; height: 10px; flex: 0 0 auto; }
.motion-ico::before,
.motion-ico::after {
  content: "";
  position: absolute;
  top: 0;
  width: 3px;
  height: 10px;
  border-radius: 1px;
  background: currentColor;
}
.motion-ico::before { inset-inline-start: 0; }
.motion-ico::after  { inset-inline-end: 0; }

/* Paused: the glyph becomes play, because that is what pressing
   it does next. */
:root[data-motion="paused"] .motion-ico::after { display: none; }
:root[data-motion="paused"] .motion-ico::before {
  inset-inline-start: 1px;
  width: 0;
  height: 0;
  background: none;
  border-inline-start: 8px solid currentColor;
  border-block: 5px solid transparent;
}

/* The footer row wraps rather than crowding, so the label stays
   at every width now — it only used to go because the nav was
   tight below 1024. */
@media (max-width: 599px) {
  .motion-toggle { margin-inline-start: 0; }
}

/* Intersection alone cannot detect a hidden fixed frame, a collapsed hero
   group, or a background tab. These gates also cover nested scene roots. */
:root[data-page-hidden] [data-scene],
:root[data-page-hidden] [data-scene]::before,
:root[data-page-hidden] [data-scene]::after,
:root[data-page-hidden] [data-scene] *,
:root[data-page-hidden] [data-scene] *::before,
:root[data-page-hidden] [data-scene] *::after,
:root [inert] [data-scene],
:root [inert] [data-scene] *,
:root [inert] [data-scene] *::before,
:root [inert] [data-scene] *::after,
:root [data-scene] [inert] *,
:root [data-scene] [inert] *::before,
:root [data-scene] [inert] *::after { animation-play-state: paused !important; }

:root[data-motion="paused"] [data-scene] *,
:root[data-motion="paused"] [data-scene] *::before,
:root[data-motion="paused"] [data-scene] *::after { transition: none !important; }
