/* ══════════════════════════════════════════════════════════════════════
   THE TWO GUARANTEES EVERY SHELL OWES — Enterprise Audit 7.5
   ══════════════════════════════════════════════════════════════════════
   A keyboard user must always be able to see where they are, and a person
   who has asked their OS for less motion must not be made to watch things
   move. Neither is a component's decision, so neither lives in a component
   stylesheet.

   This file is linked by EVERY shell — the admin/staff app (via erp.css),
   the parent portal, the login page, the public website and the legal
   pages. The last four load none of the app's CSS, which is exactly how
   the public site kept an infinite pulse animation and a smooth-scrolling
   <html> through a reduced-motion request: the safety net was real, and it
   only covered two shells out of five.

   It is written to work with NO other stylesheet present, so every token is
   read with a literal fallback. Where variables.css IS loaded, the token
   wins and carries the dark theme with it.
   ══════════════════════════════════════════════════════════════════════ */


/* ── 1 · The keyboard focus ring ──────────────────────────────────────────
   ONE ring, app-wide. `:focus-visible` keeps it off mouse and touch, so a
   clicked button stays clean; every custom control in this app (.att-pill,
   .kid, .hw-tab, .erp-dd-opt) is a real <button>, so one rule reaches them.

   `:is()` and NOT `:where()`, and that is the whole point of this rule.
   `:where()` contributes zero specificity, which left the ring at 0-1-0 —
   the same weight as any single-class component rule, and losing every tie
   to the ones that came later in the cascade. Twenty-eight of them said
   `outline: none` for a tidier look, and none of them knew they were also
   answering for the keyboard. Measured: every text input, every select and
   every textarea in the admin app, plus the global header search on 48
   screens, had no focus indicator at all.

   `:is()` takes the weight of its heaviest branch ([tabindex] → 0-1-0) and
   the rule lands at 0-2-0. A component can still deliberately replace the
   ring — a rule of its own at 0-2-0 or above still wins, and several do,
   for good reasons — but it can no longer erase it by accident.

   The colour is --focus-ring and only --focus-ring: a ring is measured
   against WCAG 1.4.11 (3:1 against what it is painted on), which the tint
   tokens do not meet.

   It sets the OUTLINE and nothing else. The rule it replaced also set
   `border-radius`, which is not part of an outline — it is the control's own
   shape, and rewriting it on focus made every control whose radius was not 9px
   visibly change shape the moment a keyboard reached it. A pill button squared
   off. The parent portal had already patched one instance of that by restating
   the radius on `.kid:focus-visible`, which is the bug leaving a footprint. An
   outline follows the element's own border-radius on its own; there was never
   anything to restate. */
:is(a, button, input, select, textarea, summary,
    [role="button"], [tabindex], [contenteditable=""],
    [contenteditable="true"]):focus-visible {
  outline: 2px solid var(--focus-ring, #0b2a5b);
  outline-offset: 2px;
}


/* ── 2 · Reduced motion ───────────────────────────────────────────────────
   The app carries dozens of scoped `@media (prefers-reduced-motion)` blocks,
   but scattered fallbacks are impossible to keep exhaustive. This single
   universal rule is the safety net: when the OS asks for reduced motion,
   every transition/animation/smooth-scroll collapses to a near-instant tick.

   0.01ms rather than 0 so JS that waits on `transitionend`/`animationend`
   (drawers, the receipt modal) still fires its completion events.

   `animation-delay` is zeroed too, which the earlier version of this guard
   did not do. A staggered list — `animation: rowIn .3s calc(var(--i)*60ms)
   both` — collapses its DURATION to nothing but then sits in the `both`
   fill's opening frame for the whole delay, so a 30-row table stayed blank
   for 1.8 seconds and then appeared all at once. Zero motion, and slower
   than the animation it replaced.

   CSS cannot reach a scroll animation that JavaScript asked for by name:
   `scrollIntoView({behavior:'smooth'})` beats `scroll-behavior: auto` here,
   because the explicit argument wins over the stylesheet. erp_motion.js
   covers that half. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
}
