/* ==========================================================================
   reduced_motion.css — the app-wide answer to "I asked you to stop moving"
   --------------------------------------------------------------------------
   Phase 8.1. Forty-nine reduced-motion blocks were scattered across the
   sheets, and the audit found two (research.css, scout.css) with infinite
   animations and no guard at all. Per-sheet guards will always lag whoever
   adds the next @keyframes; a single rule that cannot be forgotten will not.

   Deliberately NOT `animation: none`. An animation with `fill: both` supplies
   an element's resting appearance — the landing reveal is opacity 0 until its
   animation says otherwise — and cancelling it outright leaves that content
   invisible, which is a worse accessibility outcome than the motion was.
   Collapsing the duration instead lands every animation on its final frame
   immediately: the end state is reached, the movement is not seen.

   Loaded last so it wins on order as well as on !important; the per-sheet
   guards stay, because several of them do something more considered than
   this blanket (a different layout, a static fallback image).
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  /* Why `:is(*, #oc-rm)` and not plain `*`.
     -------------------------------------------------------------------------
     !important settles a conflict by specificity first and load order second,
     and a universal selector has none. Four rules in analysts.css, chat.css
     and motion.css set a 320–440ms sheet duration with !important on a class
     — inside a max-width query, not a reduced-motion one — so on a phone they
     would beat a plain `* { ... !important }` and animate anyway.

     :is() takes the specificity of its most specific argument, so
     `:is(*, #oc-rm)` matches every element exactly as `*` does while counting
     as an id. #oc-rm is not an element and never will be; it is there to set
     the weight. This is the one place in the app where that is worth doing,
     because "the reader asked the page to stop moving" is not a rule any
     component gets to outrank. */
  :is(*, #oc-rm),
  :is(*, #oc-rm)::before,
  :is(*, #oc-rm)::after,
  :is(*, #oc-rm)::backdrop {
    /* 0.01ms, not 0: a zero-duration animation fires no events, and code that
       waits for animationend (or OcOverlay.settle) would wait forever. */
    animation-duration: 0.01ms !important;
    animation-delay: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0.01ms !important;
  }

  :is(html, #oc-rm),
  :is(html, #oc-rm):focus-within {
    scroll-behavior: auto !important;
  }

  /* Scroll-driven animations are not "motion" in the vestibular sense — the
     page only moves when the reader moves it — but a reveal tied to scroll
     position still animates, so it is switched off at the source instead:
     every such rule in landing.css sits inside prefers-reduced-motion:
     no-preference. Nothing to do here. */
}
