/* ═══════════════════════════════════════════════════════════════════════════
 * theme.css — CANONICAL design tokens.  F-43.1e / F-44.6.
 *
 * Single definition point. NO page may name a font family directly; every
 * consumer uses var(--font-*).  Changing a font is then one edit here instead
 * of ~40 files.
 *
 * This finishes the direction F-06 already recorded ("theme.js — forward"),
 * rather than opening a new one.
 *
 * WHY THIS EXISTS (measured 2026-07-29):
 *   Inter + JetBrains Mono were already the de-facto system on every page, but
 *   nothing wrote it down, so the edges frayed:
 *     - 4 different Google-Fonts weight-set variants across 40 pages, so
 *       font-weight:500/600 rendered as browser-SYNTHETIC weight on some pages
 *       and real on others;
 *     - loto_pump.html — the LIVE LOTO simulation page — declared JetBrains
 *       Mono 28x and Inter 2x while loading NO font <link> at all, so it
 *       rendered entirely in system fallbacks;
 *     - no Arabic font was ever loaded; the ticker fell back to 'Arial'.
 * ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Type families (F-43.1c) ─────────────────────────────────────────────
   * mono : process values, tags, faceplates, timers.  TABULAR FIGURES — every
   *        digit the same width, so 72.4 -> 9.1 never shifts the layout. This
   *        is why Honeywell/Yokogawa/AVEVA use monospace for live values.
   * ui   : chrome, prose, forms, nav, buttons.
   * ar   : Arabic ticker text ONLY (F-40.5). Inter and JetBrains Mono have no
   *        Arabic coverage; Noto Sans Arabic is the standard companion face.
   */
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --font-ui:   'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --font-ar:   'Noto Sans Arabic', 'Inter', 'Arial', sans-serif;
}

/* ── Tabular figures for numeric UI chrome (F-43.1c refinement) ─────────────
 * Inter's default figures are proportional. Anywhere a number changes in place
 * — KPIs, scores, counts, timers — it must not reflow. Apply .tnum (or the
 * property directly) to those elements.
 * Most teams miss this; in a data-dense UI it is the highest-impact typography
 * fix after family choice. */
.tnum,
.kpi-value,
.score-value,
[data-numeric] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

/* ── Arabic / RTL scope (F-40.5) ────────────────────────────────────────────
 * Arabic is confined to the tutorial ticker. NOTHING else in the product is
 * RTL — critically, the P&ID canvas is NEVER inside an RTL scope, because a
 * P&ID is an engineering drawing: flow direction and valve positions are
 * physical truth, not reading order. Mirroring it would put every valve on the
 * wrong side. */
[dir='rtl'],
.ticker-ar {
  font-family: var(--font-ar);
}

/* Equipment tags stay LTR inside Arabic prose (F-40.4). ticker.js wraps them
 * in <bdi> automatically; this pins the family so a tag never renders in the
 * Arabic face. */
bdi {
  font-family: var(--font-mono);
  unicode-bidi: isolate;
  direction: ltr;
}

/* ── Focus visibility (F-43 v2.0 §F-43.7, K1–K4) ────────────────────────────
 * Measured 2026-07-30: ZERO :focus-visible rules and ZERO focus styles on
 * buttons across all 48 pages, while 20 pages had :hover. A keyboard or
 * switch-device user could not see what was selected — on pages whose buttons
 * open valves, acknowledge alarms and submit isolation certificates.
 *
 * :focus-visible (not :focus) so a mouse click does not leave a ring behind;
 * the browser decides when the indicator is warranted.
 *
 * Gold on dark measures 10.97:1 — far above the 3:1 WCAG minimum for a
 * non-text indicator (§F-43.6). outline-offset keeps it clear of the border.
 *
 * :where() keeps specificity at 0, so any page-level focus style still wins.
 */
:where(button, [role='button'], a, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--focus-ring, #e7c365);
  outline-offset: 2px;
  border-radius: inherit;
}

/* K2 — outline:none is permitted ONLY with a visible replacement. Inputs in
 * this codebase already pair it with a border-colour change, which is correct
 * practice and is left alone. */

/* ── Reduced motion (§F-43.12, M1–M3) ───────────────────────────────────────
 * M2 IS THE NON-OBVIOUS RULE: safety-critical signalling is EXEMPT. A blinking
 * unacknowledged alarm (F-35 first-out) is INFORMATION, not decoration. A naive
 * reduced-motion implementation disables all animation and would silently
 * remove an alarm indication — a safety regression.
 */
@media (prefers-reduced-motion: reduce) {
  *:not(.alarm-blink):not(.first-out):not([data-alarm-active]) {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
