/* ANIMATION PAUSE (issue #1599): the stylesheet half of
 * client/js/animation-pauser.js. Every infinite animation on something that
 * cannot be seen stops ticking; `animation-play-state: paused` keeps its phase
 * and it resumes where it was.
 *
 * 1. `data-anim-offscreen` is written by the pauser on an element that left the
 *    viewport (scrolled out, inside a collapsed fold, display: none). !important
 *    because every component's own `animation:` shorthand resets play-state.
 * 2. A `visibility: hidden` cover is not reported by an IntersectionObserver, so
 *    the covers are listed here, each beside where it is defined: the menu page
 *    cover (web/src/lib/menu-page/menu-page.css, the same list), an inactive
 *    terminal tab body (a hidden group pane, `.oc-tabpane-hidden`, drawn by lib/zone-shell/ZonePane.svelte), and the terminal
 *    parking shelf (web/src/opscenter/cells/terminal-live/parking.ts), and the foot bar's
 *    hidden measuring copy (TerminalFoot.svelte `.oc-tf-measure`, issue #1821: its effort
 *    animations paint nothing, so they ran on the main thread and forced frames). */

@layer legacy {
/* AMBIENT JOIN (Carnivore round 3, B12): how client/js/ambient-ticker.js finds the things it steps. A looping decoration
 * (the selected terminal's ring, the signed-out spiral) has NO infinite animation, because any running one keeps the
 * compositor producing frames at the display rate. Instead it carries a ONE-MILLISECOND finite animation named
 * `amb-join-<animation type id>`; the ticker hears its `animationstart`, then writes `--amb-step` on that element every 250 ms.
 * The keyframes are empty on purpose: the animation only has to exist. Under `data-motion="off"` and Reduce Motion the
 * blanket `animation: none` rules never start it, so nothing joins. */
@keyframes amb-join-dialog-glow {}
@keyframes amb-join-avatar-spiral {}

[data-anim-offscreen],
[data-anim-offscreen]::before,
[data-anim-offscreen]::after,
[data-anim-host][data-anim-offscreen] *,
[data-anim-host][data-anim-offscreen] *::before,
[data-anim-host][data-anim-offscreen] *::after,
:is(
    body.menu-page-open > .screen,
    body.menu-page-open > .header,
    body.menu-page-open #session-notes-panel,
    body.menu-page-open .config-editor-picker-overlay,
    .oc-tabpane-hidden,
    .oc-tf-measure,
    [data-parked-terminals]
) *,
:is(
    body.menu-page-open > .screen,
    body.menu-page-open > .header,
    body.menu-page-open #session-notes-panel,
    body.menu-page-open .config-editor-picker-overlay,
    .oc-tabpane-hidden,
    .oc-tf-measure,
    [data-parked-terminals]
) *::before,
:is(
    body.menu-page-open > .screen,
    body.menu-page-open > .header,
    body.menu-page-open #session-notes-panel,
    body.menu-page-open .config-editor-picker-overlay,
    .oc-tabpane-hidden,
    .oc-tf-measure,
    [data-parked-terminals]
) *::after {
    animation-play-state: paused !important;
}

/* One rule for the whole app: an animation is removed outright, never merely paused. The pseudo-elements are
 * spelled out because a pseudo-element is not valid inside :is(). */
:root[data-motion="off"] *,
:root[data-motion="off"] *::before,
:root[data-motion="off"] *::after {
    animation: none !important;
}
}
