/* RootOS design tokens — the one vocabulary for every web surface (D48).
 *
 * Beacon, Pulse, Bridge, the Mothership, the marketing landing page and the
 * Bridge scan page had grown SIX token vocabularies for the same handful of
 * ideas: --surface/--surface-2 against --surface-1/--surface-2; five different
 * names (--muted, --text-dim, --text-2, --faint, --dim) for two or three roles;
 * three ambers (#ffb020, #f0a13a, #f5a623) for one brand. Single sign-on across
 * apps that look like four vendors still feels like four apps, so this lands
 * before the shell, not after.
 *
 * Every colour here that can carry text is measured against --bg, --surface AND
 * --surface-2, in BOTH themes, to WCAG AA (4.5:1). The ratios in the comments are
 * the worst of those three, and `packages/ui/test/tokens.test.ts` recomputes them
 * from this file on every run — so a future edit that breaks contrast fails the
 * suite instead of shipping. That guard exists because contrast has already
 * regressed here twice: the 2026-07-12 audit (4.3) had to darken the light-theme
 * amber, and Bridge independently rediscovered the same class of bug in --faint.
 *
 * Load this BEFORE the app stylesheet. Apps keep their own :root block for
 * genuinely app-specific tokens (perio severity, fact tags, the record chrome)
 * and must not redefine anything here.
 */

:root {
  color-scheme: dark;

  /* ---- surfaces ------------------------------------------------------------
   * #0c1219 rather than beacon-web's old #0e1116: Pulse, Bridge and beacon-web's
   * OWN landing page were already on it, so the app chrome was the odd one out —
   * Beacon disagreed with its own marketing site across a sign-in. */
  --bg: #0c1219;
  --surface: #131c26;
  --surface-2: #18232f;
  --surface-hover: rgba(255, 255, 255, 0.06);

  --border: #223040;
  --border-strong: #33465c;
  --border-soft: #1b2634;

  /* ---- text ----------------------------------------------------------------
   * Three steps, deliberately. The old five names collapsed to two or three roles
   * anyway, and one of them (the Mothership's --text-dim, #6b7784) measured
   * 3.83:1 on its own surface — below AA, across eleven `color:` rules. */
  --text: #e7edf3;        /* 13.49 */
  --text-dim: #9fb0c0;    /*  7.15 — secondary prose, labels */
  --text-faint: #7a8b9c;  /*  4.54 — table headers, timestamps, eyebrows */

  /* ---- brand ---------------------------------------------------------------
   * The beacon light. #ffb020 is the marketing site's amber and the product's
   * namesake; the Mothership's #f0a13a and Pulse/Bridge's #f5a623 were drifted
   * approximations of it, not decisions.
   *
   * Brand is IDENTITY — wordmarks, the beacon glyph, focus rings. It is not the
   * "act here" colour; see --accent. Keeping those apart matters most in Beacon,
   * where amber already carries caution three times over (--warn, perio
   * --sev-mid, --tag-operational): an amber primary button would put "press me"
   * and "be careful" in the same hue on a clinical charting surface. */
  --brand: #ffb020;       /*  8.70 as text */
  --brand-soft: #ffc95c;
  --brand-deep: #d98a12;
  --on-brand: #1a1204;    /* 10.14 on a --brand fill */

  /* ---- interactive ---------------------------------------------------------
   * Two tokens, because one cannot do both jobs. beacon-web shipped a single
   * --accent (#4f8cff) used BOTH as text on dark AND as .primary-btn's fill under
   * white text — and the fill measured 3.22:1, below AA, on the flagship app's
   * primary action. A blue light enough to read on #0c1219 is too light to sit
   * under white text, and vice versa. So:
   *   --accent       links, icons, borders, active nav — reads ON dark
   *   --accent-solid button fills — white text reads ON it */
  --accent: #6ea3ff;        /* 6.32 as text */
  --accent-solid: #2a63cc;  /* 5.59 under --on-accent-solid */
  --on-accent-solid: #ffffff;

  /* ---- semantic ------------------------------------------------------------
   * One name per meaning. --ok absorbs the old --good/--success-text, --bad the
   * old --bad and the *text* uses of --record. */
  --ok: #57c98a;    /* 7.67 */
  --warn: #e8c39a;  /* 9.62 — desaturated tan, deliberately unlike --brand's
                     *        saturated amber, so caution never reads as brand */
  --bad: #f08a8a;   /* 6.60 */
  --info: #9dc4e8;  /* 8.71 */

  /* Recording red is a FILL and a border — the record dot, the live button, the
   * meter. It is not a text colour: at 4.37:1 on --surface it failed AA in the
   * five places beacon-web used it as error text, which now use --bad. */
  --record: #e5484d;

  /* ---- geometry ------------------------------------------------------------ */
  --radius: 10px;
  --radius-lg: 14px;
  --radius-pill: 999px;
  --shadow: 0 24px 60px -28px rgba(0, 0, 0, 0.7);

  /* ---- depth ---------------------------------------------------------------
   * A panel used to be one flat fill and a 1px border, which is why a screen of
   * them read as a spreadsheet rather than as a product. Three tokens carry the
   * whole treatment, so a card is lit the same way in every app:
   *
   *   --card-grad  a top-down sheen, laid OVER --surface (background accepts a
   *                gradient and a colour in one declaration)
   *   --card-edge  the hairline along a panel's top edge, drawn as an inset
   *                shadow rather than a border so it lights one edge only
   *   --card-cast  the shadow it sits on — two stops, a contact shadow and a
   *                soft cast, which is what separates "lifted" from "outlined"
   *
   * Deliberately subtle. These are read all day at a front desk, and a dashboard
   * whose every card announces itself is exhausting by the third hour. */
  --card-grad: linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0) 42%);
  --card-edge: inset 0 1px 0 rgba(255, 255, 255, 0.07);
  --card-cast: 0 1px 2px rgba(0, 0, 0, 0.30), 0 10px 26px -14px rgba(0, 0, 0, 0.60);

  /* The beacon light, as the room the app sits in. A single wash at the top of
   * the page in the brand hue — the one place the amber is allowed to be
   * atmosphere rather than identity, because it carries no meaning and marks
   * nothing. Low enough alpha that it never competes with a --warn chip. */
  --page-glow: radial-gradient(1200px 460px at 50% -220px, rgba(255, 176, 32, 0.075), transparent 72%);

  /* ---- type ---------------------------------------------------------------- */
  --sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  --mono: ui-monospace, 'SF Mono', 'JetBrains Mono', 'Cascadia Code', Menlo, monospace;
  --serif: ui-serif, 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
}

/* Light theme. Not a tint of the dark one — every value is independently
 * measured, because the naive approach (lighten the surfaces, keep the accents)
 * is exactly what produced the 2.90:1 amber the 2026-07-12 audit had to fix.
 *
 * Two tokens invert their relationship with white here: --brand and
 * --accent-solid both take white text on light, where --brand takes near-black
 * on dark. That is what --on-brand / --on-accent-solid exist for — so a button
 * rule never hardcodes a text colour that is only right in one theme. */
:root[data-theme='light'] {
  color-scheme: light;

  --bg: #f4f6f9;
  --surface: #ffffff;
  --surface-2: #eef1f6;
  --surface-hover: rgba(18, 22, 29, 0.05);

  --border: #d8dee7;
  --border-strong: #b9c2cf;
  --border-soft: #e6eaf0;

  --text: #12161d;        /* 16.01 */
  --text-dim: #4a5568;    /*  6.65 */
  --text-faint: #5d687a;  /*  4.98 */

  /* Amber cannot survive the trip: #ffb020 measures 1.99:1 on white. The brand
   * mark keeps its hue by going deep rather than bright. */
  --brand: #8a5a00;       /* 5.24 as text */
  --brand-soft: #9a6400;
  --brand-deep: #7a5000;
  --on-brand: #ffffff;    /* 5.93 on a --brand fill */

  --accent: #1f5fd6;        /* 5.06 as text */
  --accent-solid: #1f5fd6;  /* 5.73 under white — one value does both jobs here,
                             * because a blue readable on white is already dark
                             * enough to carry white text */
  --on-accent-solid: #ffffff;

  --ok: #187036;   /* 5.44 */
  --warn: #8a5a13; /* 5.22 */
  --bad: #b3282e;  /* 5.69 */
  --info: #1b4a86; /* 7.83 */

  --record: #c62f35;

  --shadow: 0 24px 60px -30px rgba(40, 50, 60, 0.28);

  /* Depth, restated rather than inherited. On a light ground the sheen runs the
   * other way (white lifts a surface off #f4f6f9, where on dark it was white
   * lifting off near-black), the top hairline is opaque white, and the cast is
   * a cool grey — a black shadow on a light theme reads as dirt. */
  --card-grad: linear-gradient(180deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0) 55%);
  --card-edge: inset 0 1px 0 rgba(255, 255, 255, 0.9);
  --card-cast: 0 1px 2px rgba(28, 38, 54, 0.06), 0 10px 24px -16px rgba(28, 38, 54, 0.22);

  /* Warmer and slightly stronger than the dark theme's: the same alpha over a
   * near-white ground is invisible. Still well under a tint anyone would call
   * yellow. */
  --page-glow: radial-gradient(1200px 460px at 50% -220px, rgba(255, 176, 32, 0.13), transparent 72%);
}

/* Light is opt-in via `[data-theme="light"]`, NOT via prefers-color-scheme.
 *
 * Following the OS preference automatically was the first thing tried here and it
 * is wrong today: beacon-web is the only app with a theme toggle, so on a
 * light-mode machine Pulse, Bridge and the Mothership would all flip to light
 * with no control to flip them back — and Bridge in particular argued for dark
 * deliberately, as a tool worked at a front desk all day.
 *
 * So dark stays the default everywhere and the light values above wait for a
 * control. beacon-web's toggle already sets the attribute; the shell takes over
 * suite-wide in Phase 3 (D48), at which point honouring the OS preference as the
 * *initial* value — with the toggle able to override it — becomes the right
 * behaviour and belongs in the shell's theme logic, not here. */
