/* =====================================================================
   PRAXIS TOKENS — the single source of the EHSQ-E foundation layer.

   Generated 2026-08-12 from the values 11 pages were each carrying in their
   own :root block. Those 11 copies agreed on 70 of 75 tokens; the five they
   disagreed on are resolved here and marked inline.

   WHY THIS FILE EXISTS
   Every page except four was self-supplying the base palette in its own
   <style>, so "the value of --praxis-radius-md" was a fact about which page you
   were on. This file is now the only place the foundation is declared.

   LOAD ORDER — this file FIRST, then praxis-core.css:
       <link rel="stylesheet" href="praxis-tokens.css" />
       <link rel="stylesheet" href="praxis-core.css" />
   praxis-core.css layers the Praxis light overrides, the dark remaps and the
   --px-* material tokens on top, scoped to body[data-variant="praxis"] — a
   higher specificity than the :root below, so it wins regardless of order.
   Keeping the order anyway means the cascade reads the way it behaves.

   Values are the RESOLVED ones measured in-browser across 27 pages x 2
   themes, not what any single source file claimed.
   ===================================================================== */
:root{
  /* Neutrals */
  --praxis-color-neutral-05:#f4f5f6;
  --praxis-color-neutral-10:#edf0f2;
  --praxis-color-neutral-100:#202a35;
  --praxis-color-neutral-15:#dadfe4;
  --praxis-color-neutral-20:#c8cfd7;
  --praxis-color-neutral-30:#adb8c4;
  --praxis-color-neutral-40:#8898a9;
  --praxis-color-neutral-50:#718499;
  --praxis-color-neutral-60:#4d657f;
  --praxis-color-neutral-70:#465c74;
  --praxis-color-neutral-80:#37485a;
  --praxis-color-neutral-90:#2a3846;
  --praxis-color-white:#ffffff;

  /* Hue scales */
  --praxis-color-blue-10:#edf0fd;
  --praxis-color-blue-50:#6882ef;
  /* #4766eb in the EHSQ-E base; Praxis tunes it down one notch so the
     solution-accent icons (Create New groups, .admin-banner) sit beside the
     teal without competing. Was declared under the variant, which froze
     --praxis-color-status-info at the base value. */
  --praxis-color-blue-60:#4361c4;
  --praxis-color-green-10:#e6f3ee;
  --praxis-color-green-60:#098b53;
  --praxis-color-orange-10:#fdf2e6;
  --praxis-color-orange-60:#ef8100;
  --praxis-color-pink-50:#e82e8b;
  --praxis-color-pink-60:#e30072;
  --praxis-color-pink-90:#810041;
  /* Solution accent, Praxis-only — no purple ramp in the EHSQ-E base. */
  --praxis-color-purple-60:#805ad5;
  --praxis-color-red-10:#fceaeb;
  --praxis-color-red-50:#e7535c;
  --praxis-color-red-60:#e22d38;
  --praxis-color-teal-10:#e8f3f3;
  --praxis-color-teal-20:#c8e1e3;
  --praxis-color-teal-50:#4499a0;
  --praxis-color-teal-60:#1b838b;
  --praxis-color-teal-70:#176f76;
  --praxis-color-teal-80:#135d63;
  --praxis-color-yellow-10:#fdf9e6;
  --praxis-color-yellow-50:#f2d02e;
  --praxis-color-yellow-90:#887100;

  /* Semantic — text / surface / border / interactive */
  /* Praxis strokes are lighter than the base neutral-20 (#c8cfd7): the shell
     leans on lit edges and shadow for separation, so a hairline that strong
     reads as a drawn box. */
  --praxis-color-border-default:#E2E5E9;
  --praxis-color-border-focus:var(--praxis-color-teal-50);
  /* WCAG 1.4.11: this is the control-boundary token (checkbox boxes, input
     underlines, --px-check-stroke), so it has to clear 3:1 against the surface
     it sits on. neutral-40 measured 2.95:1 on white — a rounding error short.
     Repointed to neutral-50 (3.84:1 white, 3.36:1 on surface-subtle, 4.09:1 on
     the dark card) rather than editing the neutral-40 rung, because
     --praxis-color-text-disabled resolves to the same rung and must not move
     with it. Audited 2026-08-20. */
  --praxis-color-border-strong:var(--praxis-color-neutral-50);
  --praxis-color-interactive-active:var(--praxis-color-teal-80);
  --praxis-color-interactive-default:var(--praxis-color-teal-60);
  --praxis-color-interactive-hover:var(--praxis-color-teal-70);
  --praxis-color-surface-default:var(--praxis-color-white);
  --praxis-color-surface-subtle:var(--praxis-color-neutral-10);
  --praxis-color-text-disabled:var(--praxis-color-neutral-40);
  --praxis-color-text-inverse:var(--praxis-color-white);
  --praxis-color-text-link:var(--praxis-color-teal-60);
  /* Praxis ink is a slate rather than the base neutrals, to match the
     layered slate surfaces. Both are literals, not rungs: nothing else
     should move if the neutral ramp is retuned. */
  --praxis-color-text-primary:#2F4051;
  --praxis-color-text-secondary:#5D6977;
  --praxis-color-text-tertiary:#616f7e;   /* promoted from page-local; one value */

  /* Semantic — status */
  --praxis-color-status-danger:var(--praxis-color-red-60);
  --praxis-color-status-info:var(--praxis-color-blue-60);
  --praxis-color-status-success:var(--praxis-color-green-60);
  /* orange-60 is 2.69:1 on white — it fails 1.4.11 as an icon, dot or 2px state
     border, which is what this token is for. orange-70 is 3.64:1 and still reads
     as orange. For warning TEXT use --praxis-tone-warning-fg, not this. */
  --praxis-color-status-warning:var(--praxis-color-orange-70);

  /* Typography */
  --praxis-type-font-sans:'Gilroy','Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif;
  --praxis-type-size-base:0.875rem;
  --praxis-type-size-lg:1.125rem;
  --praxis-type-size-md:1rem;
  --praxis-type-size-sm:0.8125rem;
  --praxis-type-size-xl:1.25rem;
  --praxis-type-size-xs:0.75rem;

  /* Spacing */
  --praxis-space-12:.75rem;
  --praxis-space-16:1rem;
  --praxis-space-24:1.5rem;
  --praxis-space-32:2rem;
  --praxis-space-4:.25rem;
  --praxis-space-8:.5rem;

  /* Radius */
  --praxis-radius-full:9999px;
  --praxis-radius-lg:16px;   /* Praxis 8/12/16 — the value that already renders on all 27 pages */
  --praxis-radius-md:12px;   /* Praxis 8/12/16 — the value that already renders on all 27 pages */
  --praxis-radius-sm:8px;   /* Praxis 8/12/16 — the value that already renders on all 27 pages */

  /* Elevation */
  /* Praxis elevation is a hairline plus a contact shadow, not a soft drop —
     the lit-edge material depends on the .5px ring. */
  --praxis-elevation-1:0 0 0 .5px rgba(16,36,58,.05),0 1px 2px rgba(16,36,58,.04);
  --praxis-elevation-2:0 1px 3px 0 rgb(32 42 53 / .1), 0 1px 2px -1px rgb(32 42 53 / .06);
  --praxis-elevation-3:0 4px 6px -1px rgb(32 42 53 / .1), 0 2px 4px -2px rgb(32 42 53 / .06);
  --praxis-elevation-4:0 10px 15px -3px rgb(32 42 53 / .1), 0 4px 6px -4px rgb(32 42 53 / .05);

  /* Motion */
  /* normal/slow existed only inside praxis-filters.css's adapter block; promoted
     here when that adapter was removed, values unchanged. */
  --praxis-motion-normal:180ms;
  --praxis-motion-slow:260ms;
  --praxis-ease-default:cubic-bezier(.32,.72,0,1);   /* Praxis spring — already renders on all 27 pages */
  --praxis-motion-fast:120ms;   /* DECISION 2026-08-12: 120ms canonical (was 100ms on 7 pages) */
  --praxis-motion-slowest:420ms;  /* the one --dur-* step with no equivalent here */

  /* Layout constants promoted from page <head>s, 2026-08-13. Each was identical
     everywhere it appeared, so it was a shared decision written down N times. */
  --praxis-record-rail-w:300px;  /* .record__guide / .record__tree; narrows at breakpoints */
  --praxis-control-h:32px;       /* compact action control height */

  /* ============ Completed from praxis-chrome-legacy.css, 2026-08-12 ============
     praxis-chrome-legacy.css was the only definition of these, and just 4 of 27
     pages load it — so --praxis-color-border-subtle (used unguarded in
     praxis-mazlan.css) resolved to nothing on the other 23. A foundation
     layer has to carry the whole ramp, not the subset the current screens
     happen to use. */

  /* Chrome metrics */
  --praxis-navrail-width:56px;
  --praxis-navrail-width-expanded:240px;

  /* Elevation semantics — mapped onto the --px-* materials below so any
     component that references --praxis-elevation-* inherits the lit-edge
     look. card and card-raised deliberately share --praxis-card; the
     raised TIER is --px-card-raised and is opt-in per component. */
  --praxis-elevation-card:var(--praxis-card);
  --praxis-elevation-card-raised:var(--praxis-card);
  --praxis-elevation-popover:var(--px-overlay);

  /* Palette rungs completed from the EHSQ-E base */
  --praxis-color-blue-100:#202e6a;
  --praxis-color-blue-20:#d3dafa;
  --praxis-color-blue-30:#b0bdf6;
  --praxis-color-blue-40:#8b9ff2;
  --praxis-color-blue-70:#3c57c8;
  --praxis-color-blue-80:#3248a7;
  --praxis-color-blue-90:#283a86;
  --praxis-color-green-100:#043f25;
  --praxis-color-green-20:#c4e3d6;
  --praxis-color-green-30:#95cdb5;
  --praxis-color-green-40:#64b693;
  --praxis-color-green-50:#35a072;
  --praxis-color-green-70:#087647;
  --praxis-color-green-80:#06633b;
  --praxis-color-green-90:#054f2f;
  --praxis-color-orange-100:#6c3a00;
  --praxis-color-orange-20:#fbe1c2;
  --praxis-color-orange-30:#f8c991;
  --praxis-color-orange-40:#f5b05e;
  --praxis-color-orange-50:#f2982e;
  --praxis-color-orange-70:#cb6e00;
  --praxis-color-orange-80:#aa5c00;
  --praxis-color-orange-90:#884a00;
  --praxis-color-pink-10:#fce6f1;
  --praxis-color-pink-100:#660033;
  --praxis-color-pink-20:#f8c2dd;
  --praxis-color-pink-30:#f391c2;
  --praxis-color-pink-40:#ed5ea6;
  --praxis-color-pink-70:#c10061;
  --praxis-color-pink-80:#a10051;
  --praxis-color-red-100:#661419;
  --praxis-color-red-20:#f8cdcf;
  --praxis-color-red-30:#f3a5a9;
  --praxis-color-red-40:#ed7b82;
  --praxis-color-red-70:#c02630;
  --praxis-color-red-80:#a02028;
  --praxis-color-red-90:#811a20;
  --praxis-color-teal-100:#0c3b3f;
  --praxis-color-teal-30:#9dcacd;
  --praxis-color-teal-40:#6fb1b6;
  --praxis-color-teal-90:#0f4b4f;
  --praxis-color-yellow-100:#6c5900;
  --praxis-color-yellow-20:#fbf1c2;
  --praxis-color-yellow-30:#f8e691;
  --praxis-color-yellow-40:#f5db5e;
  --praxis-color-yellow-60:#efc600;
  --praxis-color-yellow-70:#cba800;
  --praxis-color-yellow-80:#aa8d00;

  /* Radius completed */
  --praxis-radius-card:12px;   /* Praxis 8/12/16 geometry, not the base 20px */
  --praxis-radius-xl:16px;

  /* Semantic colour completed */
  --praxis-color-border-subtle:var(--praxis-color-neutral-10);
  --praxis-color-surface-muted:var(--praxis-color-neutral-10);

  /* Spacing completed */
  --praxis-space-20:1.25rem;
  --praxis-space-40:2.5rem;
  --praxis-space-48:3rem;

  /* Typography completed */
  --praxis-type-size-2xl:1.5rem;
  --praxis-type-size-2xs:0.6875rem;
  --praxis-type-size-3xl:1.875rem;

  /* Chrome geometry. --praxis-appbar-h was previously --appbar-height, defined only in
     two page <head>s and in the legacy chrome sheet, while three shared component
     sheets referenced it — so every other page fell through to a hard-coded 64px
     fallback. Canonicalised 2026-08-12. praxis-admin.css still declares the local
     --appbar-h / --navrail-w / --adminnav-w trio for its own grid maths. */
  --praxis-appbar-h:64px;

  /* Drawer motion. The Mazlan drawer's transitions referenced --dur-base,
     --ease-spring and --ease-spring-soft with NO fallback, and those three were
     defined only in contextual-awareness.html — so on every other page the
     declarations were invalid at computed-value time and the drawer had no
     transition at all. Values taken from that page, where the motion was correct. */
  --praxis-motion-drawer:280ms;
  --praxis-ease-spring:cubic-bezier(.34,1.56,.64,1);
  --praxis-ease-spring-soft:cubic-bezier(.22,1,.36,1);

  /* The superseded --praxis-status-* / --praxis-encoding-* families that used to sit
     here were kept 'for parity with the EHSQ-E base'. That base is defunct, so parity
     with it is not a reason. Nothing referenced them; pruned 2026-08-12. */

  /* ============ Centralised from page <head>s, 2026-08-13 ============
     Extracting Praxis surfaced 75 custom properties that pages were defining
     for themselves. Most were aliases for tokens that already existed here
     (--s-16 for --praxis-space-16, --t-sm for --praxis-type-size-sm, and so
     on) and were simply deleted at the call site. The families below were
     not aliases: they are real design decisions that had no canonical home,
     so several pages each invented their own copy and the copies drifted.
     ================================================================== */

  /* Motion: see --praxis-motion-* above. The canonical scale is 120/180/260,
     and the page-level --d-* vocabulary was that same scale under another name.
     The competing --dur-* vocabulary on one page mapped exactly onto
     motion-normal (180) and motion-drawer (280); only its slowest step had no
     equivalent, so --praxis-motion-slowest is defined beside the others. */

  --praxis-ease-spring-out:cubic-bezier(.5,0,.75,0);
  --praxis-ease-spring-bouncy:cubic-bezier(.175,.885,.32,1.275);

  /* Quick-rail motion. Seven pages defined this identically, which is about as
     clear a signal as a token gets. The rail's WIDTH is deliberately not here:
     it was genuinely different on every page (100% / 260px / 300px), so it
     stays a per-page decision. */
  --praxis-rail-duration:480ms;
  --praxis-rail-ease:cubic-bezier(.34,.01,.1,1);
  --praxis-rail-travel:-56px;

  /* Profile-menu motion, from the two pages that animate it. */
  --praxis-menu-duration:520ms;
  --praxis-menu-ease:cubic-bezier(.4,0,.2,1);

  /* Glass material. A frosted translucent surface used by drawers and floating
     panels on three pages, each with its own slightly different recipe. These
     are the light values; praxis-core.css remaps them for dark. */
  --praxis-glass-bg:rgba(255,255,255,.5);
  --praxis-glass-drawer:rgba(255,255,255,.82);
  --praxis-glass-border:rgba(255,255,255,.6);
  --praxis-glass-blur:blur(22px) saturate(1.8);
  --praxis-glass-inset:inset 0 1px 0 rgba(255,255,255,.6);
  --praxis-glass-sheen:linear-gradient(135deg,rgba(255,255,255,.45),rgba(255,255,255,0));
  --praxis-glass-shadow:0 10px 32px -14px rgba(16,26,40,.45);
  --praxis-glass-hover:rgba(255,255,255,.28);
  --praxis-glass-on:rgba(27,131,139,.16);

  /* Status tones — the paired background/foreground used by status chips and
     badges. Two pages defined these, one in literals and one in var()s that
     disagreed with the literals. Resolved to the palette references. */
  --praxis-tone-neutral-bg:var(--praxis-color-neutral-15);
  --praxis-tone-neutral-fg:var(--praxis-color-neutral-70);
  --praxis-tone-info-bg:var(--praxis-color-blue-10);
  --praxis-tone-info-fg:var(--praxis-color-blue-70);
  --praxis-tone-success-bg:var(--praxis-color-green-10);
  --praxis-tone-success-fg:var(--praxis-color-green-70);
  --praxis-tone-warning-bg:var(--praxis-color-orange-10);
  --praxis-tone-warning-fg:var(--praxis-color-orange-90);   /* -70 is 3.30:1 on orange-10; -90 is 6.28:1 */
  --praxis-tone-danger-bg:var(--praxis-color-red-10);
  --praxis-tone-danger-fg:var(--praxis-color-red-70);

  /* ============ The --px-* material layer, moved here 2026-08-26 ============
     These are the surfaces and shadows that carry the Praxis look. They were
     declared under body[data-variant="praxis"] in praxis-core.css, which had
     two costs: a reader who grepped this file for --px-surface concluded it did
     not exist, and any :root token that aliased one of them computed against
     the value this file declared rather than the one that rendered.
     ================================================================== */

  /* Praxis surface/material palette (LIGHT) */
  --px-page:#F0F2F4; --px-surface:#ffffff; --px-surface-2:#F4F6F8; --px-tool:#ffffff;
  --px-drawer:#ffffff;  /* shared drawer/panel surface (Mazlan + filter); dark deepens to navy */
  --px-chip:#EEF1F4; --px-glass:rgba(255,255,255,.82); --px-hover:rgba(16,36,58,.025); --px-dot:rgba(16,36,58,.11);
  /* Gap between a toolbar band and the first card of page content. One token
     because it was set independently per section and drifted: 8px on the record
     page, 6px on the admin pages and profile. Not theme-dependent. */
  --px-toolbar-gutter:16px;
  /* Form-field fill. Fields carry no border, so this is the whole affordance —
     it has to read as a step off --px-surface without going dark enough to
     fight the value inside it. Shared by the record fields (.rfield) and the
     admin/profile fields (.admin-field), which is why it lives here. */
  --px-field:#EEF1F4; --px-field-hover:#E6EAEF;
  /* --px-hover is 2.5% — deliberately faint for large row targets, but invisible
     on a small raised tool. Buttons use this stronger wash instead. */
  --px-hover-btn:rgba(16,36,58,.075);
  --px-scroll:rgba(16,36,58,.28); --px-scroll-hover:rgba(16,36,58,.45);
  --praxis-card:0 0 0 .5px rgba(16,36,58,.06),0 1px 1.5px rgba(16,36,58,.045),0 10px 28px -14px rgba(16,36,58,.10),inset 0 .5px 0 rgba(255,255,255,.7);
  --px-tool-shadow:0 0 0 .5px rgba(16,36,58,.07),0 1px 2px rgba(16,36,58,.05);
  --px-tool-shadow-hover:0 0 0 .5px rgba(16,36,58,.09),0 2px 8px -2px rgba(16,36,58,.16);
  --px-overlay:0 0 0 .5px rgba(16,36,58,.06),0 2px 6px rgba(16,36,58,.06),0 18px 38px -16px rgba(16,36,58,.18);
  --px-edge:rgba(255,255,255,.6);

  /* Elevation TIERS — a single card shadow can't express hierarchy, so a page
     of cards reads as one flat plane. These flank --praxis-card (unchanged, so
     nothing that already uses it moves) to give a page a subject and a support
     cast. Additive only; opt in per component.
       rail   ← recedes: tighter, shallower, no long throw
       card   ← --praxis-card, the default
       raised ← the subject: wider spread, longer throw, brighter lit edge */
  --px-card-rail:0 0 0 .5px rgba(16,36,58,.055),0 1px 1px rgba(16,36,58,.035),inset 0 .5px 0 rgba(255,255,255,.6);
  --px-card-raised:0 0 0 .5px rgba(16,36,58,.07),0 1px 2px rgba(16,36,58,.05),0 2px 6px -2px rgba(16,36,58,.06),0 24px 48px -22px rgba(16,36,58,.20),inset 0 .5px 0 rgba(255,255,255,.85);

  /* primary button — refined teal with lit edge (used by Submit / Create New /
     Reassign task on the record page and the quick-actions on the workspace)

     WCAG 1.4.3 — white on the whole fill, not just the bottom of it. The stops
     were #1f8f97 → #1b838b, which put --px-primary-fg (#fff) at 3.86:1 over the
     top of the gradient and exactly 4.50:1 over the bottom: the label failed
     across the upper half of every primary button in the app.

     Both stops moved down, not just the top one. The old bottom stop was
     already at the 4.50 threshold, so any top lighter than it fails and any top
     darker than it inverts the gradient — the fix has to shift the pair. The
     original step between stops is preserved, so the lit-edge shading reads the
     same, just a slightly deeper teal: 5.00:1 at the top, 5.88:1 at the bottom.

     Not --praxis-color-teal-60 (#1b838b): that token also carries text and
     borders, where it is measured against a light background and is fine.
     Only the fill needed to move. */
  --px-primary-grad:linear-gradient(180deg,#197b83,#156f77);
  --px-primary-fg:#fff;
  --px-primary-shadow:0 0 0 .5px rgba(16,36,58,.2),0 1px 2px rgba(16,36,58,.15),0 8px 18px -8px rgba(25,123,131,.5),inset 0 .5px 0 rgba(255,255,255,.28);
  /* Dots stop short of the top chrome: the grid running up behind the toolbar
     and page header made them read as part of the header rather than the page.
     Page colour is composited over the dots down to --px-dot-clear, then fades
     out over 48px. Fixed attachment, so the stop is a viewport coordinate and
     pages set it to their own chrome height. */
  --px-dot-clear:192px;

}
