/* ═══════════════════════════════════════════════════════════════════════════
 * 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;
  }
}

/* ══ FORM CONTROLS — dark by default (2026-08-07) ═══════════════════════════
   MEASURED CAUSE. 19 pages load Tailwind via
   `cdn.tailwindcss.com?plugins=forms`, and that plugin ships:

     [type="text"], [type="number"], [type="date"], select, textarea, …
       { background-color: #fff }

   an ATTRIBUTE selector at specificity (0,2,0). Every page-local class rule
   (`.cell-input`, `.modal input`) is (0,1,0) and LOSES — so inputs rendered
   white while the page's light text stayed light. On the tutorial editor the
   values were invisible; on Edit Company the whole form was white-on-white.
   Reported by the user 2026-08-07 on two unrelated pages, which is what showed
   it was a platform defect rather than a page defect.

   FIXED ONCE, HERE (F-58). theme.css is loaded by all 19 affected pages, so the
   fix cannot drift and a new page inherits it. Matching the same attribute
   selectors keeps specificity equal, and this stylesheet loads AFTER the CDN,
   so it wins on order — no !important, which would block legitimate overrides.

   Do NOT fix this per page. A page-local rule reintroduces the drift. */
:root [type="text"], :root [type="email"], :root [type="url"],
:root [type="password"], :root [type="number"], :root [type="date"],
:root [type="datetime-local"], :root [type="month"], :root [type="search"],
:root [type="tel"], :root [type="time"], :root [type="week"], :root [multiple],
:root input:where(:not([type])), :root textarea, :root select {
  background-color: #141218;
  color: #e6e0e9;
  border-color: #3a3835;
}

/* Placeholders must read as hints, not as entered values — the Edit Company
   dialog was mistaken for a filled form because they looked identical. */
:root input::placeholder, :root textarea::placeholder { color: #7f7a86; opacity: 1; }

:root [type="text"]:focus, :root [type="email"]:focus, :root [type="url"]:focus,
:root [type="password"]:focus, :root [type="number"]:focus, :root [type="date"]:focus,
:root [type="datetime-local"]:focus, :root [type="search"]:focus,
:root [type="tel"]:focus, :root [type="time"]:focus,
:root input:where(:not([type])):focus, :root textarea:focus, :root select:focus {
  background-color: #1c1a20;
  border-color: #e7c365;
  outline: 2px solid #e7c365;
  outline-offset: 1px;
}

:root input:disabled, :root textarea:disabled, :root select:disabled {
  background-color: #101014; color: #6e6a72; cursor: not-allowed;
}

/* The native date picker icon is a dark glyph, invisible on a dark field. */
::-webkit-calendar-picker-indicator { filter: invert(0.75); cursor: pointer; }

/* Checkboxes and radios are excluded above (no [type] match), so the forms
   plugin still styles them — they were already legible and are left alone. */
