/* ============================================================
 * stm-baseline.css — STM document baseline (TOK-22, framework-agnostic)
 * ============================================================
 * The CssBaseline analog: the generated theme CSS defines custom properties
 * only — THIS sheet applies them to the document. Hand-authored source lives
 * at dist/baseline/stm-baseline.css and is mirrored byte-for-byte into the
 * Blazor RCL (wwwroot/css/utilities/) by transform-tokens.js, guarded by
 * check:bridgemirror — never edit the mirror.
 *
 * Load AFTER the generated theme CSS (it consumes --stm-* vars), in every
 * document that renders STM components. Framework notes:
 *   - Blazor: loaded alongside stm-base.css (which now carries ONLY the
 *     self-hosted Geist @font-face rules — asset URLs are RCL-relative and
 *     cannot live in this shared file).
 *   - React: MUI consumers already get an equivalent via stmTheme +
 *     CssBaseline; this sheet is for plain/CSS-only consumers and keeps the
 *     two legs' floors identical.
 *
 * Contents are tokens-only: box-sizing, body defaults, color-scheme
 * (native controls follow [data-theme] — TOK-22), a zero-specificity
 * :focus-visible fallback ring (TOK-31 recipe), the reduced-motion floor
 * (A11Y-19 / ADR-019; TOK-16 policy = respect the system setting), and the
 * opt-in .stm-scrollbar recipe (TOK-32).
 * ============================================================ */

html {
  box-sizing: border-box;
}

*, *::before, *::after {
  box-sizing: inherit;
}

/* ------------------------------------------------------------
 * The document floor OWNS tracking (#563). Without the letter-spacing line
 * below, the HOST's baseline decides it: MUI's CssBaseline writes a 0.00938em
 * tracking onto body from its body1 variant (0.15px at 16px), while Blazor
 * inherits the initial value — so the same string measured ~0.9px wider in
 * React and the two legs disagreed at a wrap or truncation boundary. It binds
 * the core tracking STEP rather than a body-composite sub-property: 13
 * component composites alias the body role, so declaring letterSpacing there
 * would emit 13 vars nobody binds (#311's exact complaint). A brand retunes
 * the floor by overriding the step. packages/react/stmTheme.ts carries the
 * MUI-side twin of this declaration — keep the two in lockstep.
 * ------------------------------------------------------------ */
body {
  margin: 0;
  font-family: var(--stm-typography-body-font-family);
  font-size: var(--stm-typography-body-font-size);
  font-weight: var(--stm-typography-body-font-weight);
  line-height: var(--stm-typography-body-line-height);
  letter-spacing: var(--stm-typography-letterSpacing-normal); /* #563 — see note above */
  color: var(--stm-color-onSurface);
  background-color: var(--stm-color-pageBackground);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  transition: background-color var(--stm-motion-duration-base) var(--stm-motion-easing-standard, ease), color var(--stm-motion-duration-base) var(--stm-motion-easing-standard, ease); /* TOK-120: the 137-site easing sweep missed this file (outside the lint scan sets) */
}

/* ------------------------------------------------------------
 * color-scheme (TOK-22 / TOK-23) — native controls (scrollbars, form
 * controls, <select> popups) follow the STM mode instead of the OS default.
 * data-theme is the same attribute the theme CSS switches on, written by
 * useStmColorScheme / StmThemeService (TOK-23).
 * ------------------------------------------------------------ */
:root {
  color-scheme: light;
  /* TOK-44 (owner 2026-08-14): native form-control accents (checkbox/radio/
   * range/progress that no Stm* component wraps) follow brand primary instead
   * of UA blue. Wrapped controls override this with their own painted chrome. */
  accent-color: var(--stm-color-primary);
}

[data-theme="dark"] {
  color-scheme: dark;
}

/* ------------------------------------------------------------
 * Text selection (TOK-44, owner 2026-08-14) — brand-tinted highlight.
 * selectionText aliases onSurface and selectionBackground has a dark
 * override, so both flip with [data-theme] like everything else.
 * ------------------------------------------------------------ */
::selection {
  background-color: var(--stm-color-selectionBackground);
  color: var(--stm-color-selectionText);
}

/* ------------------------------------------------------------
 * Focus-visible fallback ring (TOK-31 recipe, flat-control mode).
 * :where() keeps specificity at ZERO, so any component's own focus
 * treatment (MUI, Telerik, scoped CSS) wins without !important games.
 * This is the floor for bare/unstyled interactive elements only.
 * ------------------------------------------------------------ */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--stm-border-focusRingWidth) solid var(--stm-color-focusRing);
  outline-offset: var(--stm-border-focusRingOffset);
}

/* ------------------------------------------------------------
 * Reduced-motion — theme-level knob (TOK-16, owner decision 2026-07-09;
 * supersedes the earlier no-opt-out stance of A11Y-19/ADR-019).
 *
 * `data-stm-motion` on <html> selects the policy, MUI v9-style:
 *   (absent) / "system" — follow prefers-reduced-motion (the default);
 *   "never"             — never reduce (an app that owns its motion a11y
 *                         story can keep animating under OS reduction);
 *   "always"            — always reduce, regardless of the OS setting
 *                         (kiosk/e-ink/screenshot rigs).
 *
 * The reset itself is unchanged (Andy Bell et al.): 0.01ms (not 0) keeps
 * animationend/transitionend firing so JS that waits on them doesn't hang.
 * It neutralises EVERY animation/transition (incl. Telerik/vendor and
 * consumer markup); per-component guards remain as defense-in-depth.
 * ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-stm-motion="never"]),
  :root:not([data-stm-motion="never"]) *,
  :root:not([data-stm-motion="never"]) *::before,
  :root:not([data-stm-motion="never"]) *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

:root[data-stm-motion="always"],
:root[data-stm-motion="always"] *,
:root[data-stm-motion="always"] *::before,
:root[data-stm-motion="always"] *::after {
  animation-duration: 0.01ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: 0.01ms !important;
  scroll-behavior: auto !important;
}

/* ------------------------------------------------------------
 * Responsive display/h1/h2 steps (TOK-27, owner decision 2026-07-09:
 * per-breakpoint steps, not clamp()). Only the three display roles scale —
 * h3–h6 and body stay put (M3 compact precedent). Steps are assigned FROM
 * the --stm-fontSize ramp vars, so brand size hooks (RETUR's larger
 * 2xl/3xl/4xl) flow through automatically. @media needs literals: 768px =
 * primitives.size.viewport.md, 640px = viewport.sm — keep in sync if the
 * viewport tokens ever change.
 * ------------------------------------------------------------ */
@media (max-width: 767.98px) { /* below primitives.size.viewport.md (768px) */
  :root {
    --stm-typography-display-font-size: var(--stm-fontSize-4xl);
    --stm-typography-heading1-font-size: var(--stm-fontSize-5xl);
    --stm-typography-heading2-font-size: var(--stm-fontSize-4xl);
  }
}

@media (max-width: 639.98px) { /* below primitives.size.viewport.sm (640px) */
  :root {
    --stm-typography-display-font-size: var(--stm-fontSize-3xl);
    --stm-typography-heading1-font-size: var(--stm-fontSize-4xl);
    --stm-typography-heading2-font-size: var(--stm-fontSize-3xl);
  }
}

/* ------------------------------------------------------------
 * .stm-scrollbar — opt-in themed scrollbars (TOK-32).
 * Standard scrollbar-color first (Firefox + Chromium 121+); WebKit
 * pseudo-elements as the fallback for older Chromium/Safari. Opt-in by
 * class — the DS never restyles the document scrollbar uninvited
 * (Mud themes scrollbars by default; we deliberately don't).
 * ------------------------------------------------------------ */
.stm-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: var(--stm-color-outlineVariant) var(--stm-color-surfaceVariant);
}

.stm-scrollbar::-webkit-scrollbar {
  width: var(--stm-size-scrollbarWidth); /* TOK-121 */
  height: var(--stm-size-scrollbarWidth);
}

.stm-scrollbar::-webkit-scrollbar-track {
  background: var(--stm-color-surfaceVariant);
}

.stm-scrollbar::-webkit-scrollbar-thumb {
  background: var(--stm-color-outlineVariant);
  border-radius: calc(var(--stm-size-scrollbarWidth) / 2); /* TOK-121 */
  border: var(--stm-border-width-thick) solid var(--stm-color-surfaceVariant); /* TOK-121 */
}

.stm-scrollbar::-webkit-scrollbar-thumb:hover {
  background: var(--stm-color-outline);
}

/* ------------------------------------------------------------
 * .stm-u-visually-hidden — screen-reader-only text (issue #68).
 * The standard clip pattern: the element stays in the accessibility
 * tree (labels an otherwise-empty column header, names an icon-only
 * control's context) but paints nothing. Framework-agnostic; both
 * legs load this sheet, so React renderHeader spans and Blazor
 * HeaderTemplate spans share the ONE class name (/stm-convert-safe).
 * ------------------------------------------------------------ */
.stm-u-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px; /* stm-lint-ok:raw-dimension -- the visually-hidden clip recipe; -1px is the pattern, not a spacing decision */
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
