/* =========================================================================
   121 Brokers design tokens — Krayin implementation
   -------------------------------------------------------------------------
   GENERATED FROM the design-system mirror. Do not edit values by hand.
   Source : .claude/design-system/colors_and_type.css  (sha256 1912a3a71155809f)
   Synced : 2026-08-08
   Owner  : design-system-agent

   Changing a value here without changing it in Claude Design forks the design
   system. Update the design, re-sync the mirror, then regenerate this file.
   ========================================================================= */

/* ---- Poppins ------------------------------------------------------------
   Subset of the family: only the weights the type scale actually uses
   (400/500/600/700/800/900 + one italic). The full 18-face family lives in
   the mirror; shipping all of it would cost 3 MB for weights nothing renders.
   Paths resolve through the Theme package's Vite build directory.          */
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 400; src: url("../fonts/Poppins-Regular.ttf")    format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: italic; font-weight: 400; src: url("../fonts/Poppins-Italic.ttf")     format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 500; src: url("../fonts/Poppins-Medium.ttf")     format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 600; src: url("../fonts/Poppins-SemiBold.ttf")   format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 700; src: url("../fonts/Poppins-Bold.ttf")       format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 800; src: url("../fonts/Poppins-ExtraBold.ttf")  format("truetype"); font-display: swap; }
@font-face { font-family: "Poppins"; font-style: normal; font-weight: 900; src: url("../fonts/Poppins-Black.ttf")      format("truetype"); font-display: swap; }

:root {
  /* ---- PRIMITIVES — escape hatches. Components must not reference these. */
  --green-50:#e6f9ef;  --green-100:#b8edd0; --green-200:#7bdfa9; --green-300:#3dcd82;
  --green-400:#14b96b; --green-500:#00a959; --green-600:#008f4a; --green-700:#00763d;
  --green-800:#005c2f; --green-900:#004423;

  --ink-50:#f6f7f8;  --ink-100:#eceef1; --ink-200:#d6dae0; --ink-300:#b3bac3;
  --ink-400:#8a929e; --ink-500:#5f6770; --ink-600:#404750; --ink-700:#2d3239;
  --ink-800:#1f2429; --ink-900:#14181c;

  /* Extrapolated one step past ink-900 - not a Claude Design ramp step. It is
     already declared at Admin/tailwind.config.js:43 with this exact comment
     and is what Tailwind's dark:bg-gray-950 already paints on this page (the
     measured dark <body> background is rgb(13,16,19)). Lives in :root, not
     .dark, because primitives are mode-independent - see
     .claude/design-system/DARK-MODE-RULINGS.md D2.1. */
  --ink-950:#0d1013;

  --white:#ffffff; --cream:#fbfbf9; --mist:#f3f6f4;

  /* ---- SEMANTIC — this is what components reference. */
  /* success references the primitive, exactly as the source does — if the brand
     green changes, success must follow it. Hardcoding #00a959 here would break
     that link the first time the palette moves. */
  --success:var(--green-500); --warning:#f6a624; --danger:#d8413a; --info:#2c7ee0;

  --bg:var(--white); --bg-alt:var(--cream); --bg-tint:var(--mist); --bg-invert:var(--ink-900);

  --fg:var(--ink-700); --fg-strong:var(--ink-900); --fg-muted:var(--ink-500);
  --fg-on-dark:#ffffff; --fg-on-brand:#ffffff;

  /* ---- EXTENSION — the --fg- / --ui- namespace split. RATIFIED by design-system-agent,
     2026-08-23; the ruling and every measurement behind it are in
     .claude/design-system/ACCESSIBILITY-AMENDMENTS.md (A1).

     THE INVARIANT THE NAMESPACE NOW CARRIES: every --fg-* token is safe as text
     at any size this product uses. Non-text foregrounds live under --ui-*.

     WHY A RENAME RATHER THAN A COMMENT. #8a929e as body text was found in FIVE
     places on the leads list alone (column headings 3.14:1, "No status" 3.14,
     stats-bar labels 3.03, rail eyebrows 3.03, .cx-facet--elsewhere 3.14) -
     while this codebase already stated the rule in two separate CSS comments
     and applied it to exactly one element. Documentation had already been tried
     and had already failed. `--fg-subtle` reads as "a step quieter than muted";
     nothing in that name says "illegal as text", and `--ui-subtle` on an 11px
     label is wrong on sight.

     THERE IS NO SIZE AT WHICH #8a929e IS LEGAL TEXT HERE: "large" begins at
     18.66px bold / 24px regular and this product's meta type is 10.5-13px. */

  /* Non-text foreground. #8a929e is 3.14:1 on white - it clears the 3:1 bar of
     SC 1.4.11 and no text bar at any size. Icons, rules, disabled controls,
     decorative glyphs. Never `color:` on rendered copy - use --fg-muted. */
  --ui-subtle:var(--ink-400);

  /* DEPRECATED alias - the mirror still ships --fg-subtle, and
     _adherence.oxlintrc.json enumerates it among the 96 source tokens, so
     dropping it now would fork the lint contract. No new call sites. Remove at
     the sync that lands --ui-subtle upstream, or 2026-09-30, whichever is
     first. Gate, since this repo has no stylelint:
       git grep -nE "color:\s*var\(--(ui-subtle|fg-subtle)\)" -- '*.css' '*.blade.php'
     Any hit is a defect. */
  --fg-subtle:var(--ui-subtle);

  --brand:var(--green-500); --brand-hover:var(--green-600);
  --brand-press:var(--green-700); --brand-soft:var(--green-100);

  /* ---- EXTENSION — not in the source DS. See KRAYIN-RECONCILIATION.md.
     The brand green fails WCAG AA against white at normal text size: 3.08:1
     both ways (white on green, and green as text on white). It passes the 3:1
     bar for UI components and large text, which is what a marketing site
     mostly needed — a data-dense CRM pairs it with 14px text constantly.

     --brand-strong is the AA-safe brand surface: 5.74:1 against white in
     either direction. Use it ANYWHERE brand green meets body-size text.
     --brand stays green-500 for decorative work — borders, chart fills,
     progress bars — where 3:1 is the correct bar and the surface is white.
     NOT focus indicators: 3:1 is the right bar for them, but green-500 measures
     2.65 on ink-100, 2.83 on mist, 2.87 on ink-50 and 2.97 on cream, and this
     product's chrome is cream and mist. See --focus-outline. */
  --brand-strong:var(--green-700);
  --brand-strong-hover:var(--green-800);
  --brand-strong-press:var(--green-900);

  /* ---- EXTENSION — the grid header band. DATA-TABLE-RULINGS.md LV1.1.A
     (GC1, 2026-09-24). Every Theme grid's `.cx-grid-head` and the Manage
     columns dialog's header preview paint from these four, which is why they
     live here on :root rather than inside `.cx-datagrid-body`.
     SAME IN LIGHT AND DARK — `.dark` must NOT repoint them: white on
     green-700 is 5.74:1 in both themes, and green-500 (--brand) would fail
     at 3.08:1. Text 5.74 · band vs dark --bg 3.11 · resize bar 3.35 ·
     border 1.42 (decorative). */
  --grid-head-bg:var(--brand-strong);
  --grid-head-fg:var(--fg-on-brand);
  --grid-head-border:var(--brand-strong-hover);
  --grid-head-resize:color-mix(in srgb, var(--grid-head-fg) 65%, transparent);

  /* ---- EXTENSION — brand-as-copy, split from brand-as-fill. PROPOSED by
     design-system-agent 2026-08-23 and ratified FOR IMPLEMENTATION on this
     branch only (full ratification is still pending crm-design-system-architect
     + crm-design-director); see .claude/design-system/DARK-MODE-RULINGS.md
     (D0, D3).

     One green cannot serve both roles once dark mode exists: brand AS TEXT
     needs to lighten on a dark surface (green-700 measures 3.11:1 on
     #14181c, fails 4.5), but brand AS A FILL under white text must stay dark
     (green-700+white is 5.74:1 and correct; green-300+white would be 2.05).
     Flipping --brand-strong itself was rejected — it drives Krayin's
     COMPILED bg-brandColor / text-brandColor utilities (eleven files), which
     cannot follow a custom property, so flipping it would put a mint DS
     button beside a dark-green Krayin button on the same toolbar.
     --brand-strong / --brand / --fg-on-brand all stay put.

     --brand-text is the brand as RENDERED COPY: links, the active saved-view
     tab, the lead-name link, the breadcrumb link. Light value equals what
     those call sites already resolved to via --brand-strong, so adopting it
     changes no light pixel. */
  --brand-text:var(--green-700);

  /* ---- EXTENSION — chart palette. Not in the source DS, which was built from
     a marketing site and needs exactly one accent. Charts are the legitimate
     exception: a doughnut of revenue-by-source encodes IDENTITY, and identity
     needs distinct hues.

     Categorical order is FIXED — slot 1 is always the first series, never
     recycled, so a filter that removes a series never repaints the survivors.
     Validated (all six checks pass, light AND dark) — do not reorder or
     substitute by eye, re-run the validator:
       worst adjacent CVD  ΔE 23.7 deutan / 11.9 tritan
       normal-vision floor ΔE 25.2
       contrast vs surface all >= 3:1

     Slot 1 is green-700, not the brand green-500, for the same reason as
     --brand-strong: green-500 sits at exactly 3:1 and fails the lightness band. */
  --chart-1:var(--green-700);  /* brand */
  --chart-2:#2c7ee0;           /* info blue */
  --chart-3:var(--amber-700);  /* #b97908, unchanged. DECLINED: repointing this
                                  at --amber-800. The palette above passed a
                                  six-check CVD/ΔE validation and must not be
                                  substituted by eye; chart fills are non-text
                                  and clear 3:1. Re-run the validator first if
                                  amber-800 is ever wanted here. */
  --chart-4:#7a4fd8;           /* violet — from mockup 5a's pipeline meter */
  --chart-5:#d8413a;           /* danger red */

  /* Polarity pair. Won/Lost is not arbitrary identity, it is outcome, so it
     uses the status hues rather than categorical slots. Always shipped with a
     text label, never colour alone. */
  --chart-positive:var(--green-700);
  --chart-negative:#d8413a;

  /* Sequential ramp for magnitude (pipeline stages). One hue, light to dark —
     never a rainbow. */
  --chart-seq-1:var(--green-200); --chart-seq-2:var(--green-300);
  --chart-seq-3:var(--green-500); --chart-seq-4:var(--green-700);
  --chart-seq-5:var(--green-900);

  /* Chart furniture: recessive, so the data carries the emphasis. */
  --chart-grid:var(--divider);
  --chart-axis-text:var(--fg-muted);

  /* ---- EXTENSION — the status-tone ramps. RATIFIED by design-system-agent,
     2026-08-23; see ACCESSIBILITY-AMENDMENTS.md (A3).

     The source DS has NO amber ramp - only --warning (#f6a624, a meter and icon
     fill) - and no blue text step. The badge pairs #fef4e6/#b97908 and
     #eef4fd/#2c7ee0 live in CRM-Mockups.dc.html as literals, thirteen
     occurrences for amber alone, and #b97908 was a literal in three of this
     package's stylesheets for want of a token.

     THE DEFECT THEY FIX. `badge--amber` measured 3.33:1 at its real 10.5px/600
     and `badge--blue` 3.68:1 - both fail SC 1.4.3. Amber is the `in_progress`
     family, 8 of the 17 lead statuses, so it is the busiest cell on the busiest
     screen; blue is `new`, the status every lead enters through.

     BACKGROUNDS ARE UNCHANGED - they ripple into avatar chips, alert icons and
     facet rules, and the foreground alone closes the gap with headroom.

     THE TWO-STEP RAMP IS LOAD-BEARING, which is why one token cannot serve:
     -700 is the non-text step (3px family rules, alert glyphs, chart fills, all
     at the 3:1 bar) and -800 is the only step that carries text. */
  --amber-50:#fef4e6;
  --amber-700:#b97908;   /* fills, 3px family rules, icon glyphs — 3:1 bar */
  --amber-800:#8a5a00;   /* text — 5.45 on --amber-50, 5.93 white, 5.45 mist */

  /* Dark-only ramp steps, needed so --tone-amber-* / --tone-blue-* have
     somewhere to point under .dark (see D2). Values are DARK-MODE-RULINGS.md's
     own measurements (D2 / D6 table), not invented here: amber-900/-400 land
     the tone pair at 5.74:1 text-on-fill on a #14181c row, blue-900/-300 at
     6.08:1. */
  --amber-900:#5c3c04;   /* dark fill — .dark --tone-amber-bg */
  --amber-400:#f8b959;   /* dark text — .dark --tone-amber-fg, 5.74 on amber-900 */

  --blue-50:#eef4fd;
  --blue-700:#1b62b8;    /* text — 5.45 on --blue-50, 6.02 white */
  --blue-900:#0e2b4b;    /* dark fill — .dark --tone-blue-bg */
  --blue-300:#7dabec;    /* dark text — .dark --tone-blue-fg, 6.08 on blue-900 */

  --tone-amber-bg:var(--amber-50);  --tone-amber-fg:var(--amber-800);
  --tone-blue-bg:var(--blue-50);    --tone-blue-fg:var(--blue-700);

  /* ---- EXTENSION — the four remaining tone pairs, which close the six-colour
     tint set (green · blue · amber · purple · red · neutral). MAIL-RULINGS M8
     (the NAMES are ratified on crm-design-director's countersignature
     2026-09-12) and M14, which rules the pairs must land in this block before
     slice 2 paints a label. RATIFIED for implementation here, PROPOSED for
     upstream ratification in Claude Design — the same status the amber and
     blue pairs above carry.

     THREE OF THE FOUR INTRODUCE NO VALUE. green, neutral and red are exactly
     what .badge--green / .badge--neutral / .badge--red ship today
     (components.css:322, 301, 303), so the repointing of those badges — Task
     15's job, not this commit's — changes no pixel. Red's text step is
     already a token (--danger-text, #c92a2a light / #e8a0a0 dark, both from
     DARK-MODE-RULINGS D6) and is referenced rather than re-declared, so the
     hex keeps one definition site. A3's "lift red's four steps to
     --red-50/-700/-900/-300" is NOT done here: with no call site those four
     primitives would ship dead, and the lift is a no-value-change rename that
     belongs with the badge repoint.

     Every figure below is fg-on-bg, WCAG 2.x relative luminance, computed
     from these hex values, to two decimals. All four clear SC 1.4.3's 4.5:1
     for rendered copy and land inside the 4.63–8.08 band the shipped tones
     already occupy. */
  --tone-green-bg:var(--green-100);  --tone-green-fg:var(--green-800);    /* 6.25:1 */
  --tone-neutral-bg:var(--ink-100);  --tone-neutral-fg:var(--ink-600);    /* 8.08:1 */
  --tone-red-bg:#ffebeb;             --tone-red-fg:var(--danger-text);    /* 4.76:1 */

  /* COUNTERSIGNED by design-system-agent on 2026-09-18 (KANBAN-RULINGS
     K3.2 / finding K-F7). M8's binding condition — "until both pairs are
     countersigned, purple is selectable in no picker and painted in no row" —
     was already discharged by shipped code: the dark pair is declared below
     with its ΔE re-run reported, and --tone-purple-fg is painted as a tone
     carrier (mail-client.css:1091, mail-rules.css:356), as a badge
     (leads/view/panels/notes.blade.php:344, gallery.blade.php:123) and as a
     mailbox colour (Mail/src/Config/mailbox.php:87). NO VALUE CHANGED with
     this comment. Purple is now also the enquiry board's tone for
     `submitted_to_lender` and `passed_to_partner`. */
  /* The light pair is NOT new either: it is components.css:320's shipped
     .badge--purple, and #7a4fd8 is also --chart-4's violet. It is kept as a
     literal rather than var(--chart-4) so a tone never depends on a chart
     slot. 4.63:1 fg-on-bg; --fg (#2d3239) on this fill is 11.20:1 and the fg
     step is 5.33:1 on --bg, so M14's 3px bar clears SC 1.4.11 in light. The
     DARK pair is the value M8 refused to guess — see the .dark block, where
     the ΔE re-run this ruling requires is reported. M8's binding condition
     ("until both pairs are countersigned, purple is selectable in no picker
     and painted in no row", restated by M14) is DISCHARGED — see the
     countersignature above. */
  --tone-purple-bg:#f3ecfd;          --tone-purple-fg:#7a4fd8;            /* 4.63:1 */

  /* ---- EXTENSION — the danger TEXT step. MAIL-RULINGS finding A, ratified on
     crm-design-director's countersignature 2026-09-12. RATIFIED for
     implementation here, PROPOSED for upstream ratification in Claude Design —
     the same status the amber and blue ramps above carry.

     --danger (#d8413a) is 4.43:1 on --bg and 4.02:1 on dark --bg: it clears
     SC 1.4.11's 3:1 bar as a GLYPH or a FILL and fails SC 1.4.3's 4.5:1 as
     rendered copy in BOTH modes. Same split-role move as --brand-text (D3),
     and the reason a dot may be --danger while the word beside it may not.

     NEITHER VALUE IS NEW: #c92a2a is the shipped badge--red text colour
     (5.46:1 on white) and #e8a0a0 is DARK-MODE-RULINGS D6's measured dark red
     step (8.47:1 on dark --bg).

     Call sites write `color: var(--danger-text, #c92a2a)`. The fallback is
     LIGHT-ONLY - #c92a2a on dark --bg #14181c is 3.27:1 - so it protects
     against a missed publish in light mode only, and dark mode depends on
     this token itself being published. Never `color: var(--danger)` on copy;
     that grep is a gate crm-design-qa-engineer owns. */
  --danger-text:#c92a2a;

  --border:#e3e7ea; --border-strong:#c8ced5; --divider:#eef1f3;

  /* ---- EXTENSION — the focus indicator. RATIFIED by design-system-agent,
     2026-08-23; see ACCESSIBILITY-AMENDMENTS.md (A2).

     The source DS defines NO solid focus-outline colour at all - only
     --focus-ring, a translucent glow - and the one solid focus treatment in the
     mockup is a 2px solid --brand outline. Measured against the colour it
     is really drawn against, --brand clears SC 1.4.11's 3:1 bar on pure white
     by 0.08 and NOWHERE ELSE: 2.65 on the saved-view tab (ink-100), 2.83 on
     facet checkboxes (mist), 2.87 on a row action over a hovered row (ink-50),
     2.97 on a rail facet summary (cream).

     --focus-outline measured: 5.74 white · 5.54 cream · 5.35 ink-50 · 5.27 mist
     · 4.94 ink-100 · 4.39 green-100 · 3.62 border-strong.

     GEOMETRY IS A RULE, NOT A TOKEN: 2px solid, outline-offset 2px. Where an
     inset ring is unavoidable, the adjacent colour is the component's own fill
     - measure against that, not against the page.

     --focus-outline-invert is not decoration. Green-700 has nowhere to go
     inside a green or black fill (1.86:1 on --brand, 3.11:1 on --bg-invert);
     white is 3.08 and 17.84 there. Use it wherever the indicator lands INSIDE
     such a fill.

     A two-tone (inner light + outer dark) ring was considered and rejected as
     the default: it doubles the indicator's weight on an already dense grid,
     and --focus-outline-invert covers the only case that needed
     surface-independence. Available if a future surface defeats both. */
  --focus-outline:var(--green-700);
  --focus-outline-invert:var(--white);

  /* The translucent box-shadow halo. Role unchanged, value rebased onto
     green-700 so the halo and the outline stop disagreeing on hue. It carries
     no compliance of its own. */
  --focus-ring:color-mix(in srgb, var(--green-700) 45%, transparent);

  /* ---- EXTENSION — control-surface interaction states. Closes gaps G1/G2
     from the design-system-agent's combobox + calendar audit
     (form-controls/ds-spec.md); ratified FOR IMPLEMENTATION on this branch
     only, same pending-full-ratification status as --brand-text above.

     Two existing hover fills are PRIMITIVES that never flip under .dark —
     .menu__item (components.css, --ink-50) and .cx-menu-item
     (column-menu.blade.php, --ink-100) — so a menu row hovers near-white on
     a dark popover. --control-hover-bg is the semantic replacement: it is
     --bg-tint under another name, so it already inherits --bg-tint's own
     .dark repoint. Restated (same expression) under .dark below purely for
     the auditability reason --chart-grid / --chart-axis-text already are
     (compare line ~171-172 with ~343-344) — not because the value differs. */
  --control-hover-bg:var(--bg-tint);

  /* --brand-soft (green-100) is a primitive alias too — a "selected" fill
     built on it stays pale mint on a dark popover, the same failure mode as
     the hover fills above (see nav.css:239 / filter-panel.blade.php:1640 for
     the existing --brand-soft "soft selected" pairing this replaces).
     --control-selected-bg instead uses the color-mix formula this same
     audit already calls "theme-safe" for combobox/day-cell hover
     (ds-spec.md A.3 / B.3): it composites against whichever --bg is behind
     it, so light and dark both fall out of one expression — no new hex to
     measure or run through the chart validator. 16% matches the "one step
     past hover" weight the audit already specified for the pressed state
     (A.3), reused here for "selected" rather than inventing a third number. */
  --control-selected-bg:color-mix(in srgb, var(--brand) 16%, transparent);

  /* ---- EXTENSION — overlay scrims and the one sanctioned dialog blur.
     RATIFIED by crm-design-system-architect 2026-09-04; the ruling, its
     boundary and everything that stays forbidden are in
     .claude/design-system/DIALOG-RULINGS.md (M1).

     --overlay-scrim is not a new value: it is the literal that modals.css
     already carries twice (:66 ::backdrop, :75 the no-<dialog> fallback path)
     and that DESIGN-SYSTEM.md:97 specifies. Promoted to a token so the two
     call sites stop being a second definition site.

     --overlay-scrim-glass is the SAME scrim composed down, for the opt-in
     .modal--glass class only: with a 12px blur behind it the blur does the
     separating work the extra 15% of dim used to do. Neither scrim carries
     any compliance — the panel above it is opaque --bg, so every ratio inside
     a dialog is measured against that fill, not through the scrim. That is
     precisely why this is permitted where "avoid heavy glassmorphism" still
     stands: the prohibition targets translucent CONTENT surfaces, which make
     contrast unmeasurable. A translucent scrim under an opaque panel does not.

     --overlay-blur 12px is derived, not chosen. CSS blur(R) is a Gaussian of
     sigma R/2, so 12px is sigma 6px against 12.5px grid text whose x-height is
     ~6.5px: sigma at ~0.9x x-height fills every counter and destroys word
     shape. blur(8px) leaves word shapes legible and the grid keeps competing
     for attention; past blur(16px) the page stops reading as "the page behind"
     and the cost keeps rising for nothing. It is also the sanctioned
     sticky-header 10px (DESIGN-SYSTEM.md:97) plus one 2px step, so the product
     has two blur values and not a scale.

     MODE-INDEPENDENT ON PURPOSE — deliberately absent from .dark below. A
     scrim only ever darkens; lightening it in dark would invert its meaning,
     and restating an identical literal in .dark would create exactly the
     second definition site this block exists to remove. */
  --overlay-scrim:rgba(20,24,28,.45);
  --overlay-scrim-glass:rgba(20,24,28,.30);
  --overlay-blur:12px;

  /* ---- EXTENSION — the lit selected state. RATIFIED by
     crm-design-system-architect 2026-09-04; see DIALOG-RULINGS.md (M2).

     NO NEW VALUE IS INTRODUCED HERE. This is the recipe already shipping at
     modals.css:456-459 on .mode-card:has(input:checked), promoted to a token
     with its rgba(0,169,89,.14) literal replaced by a color-mix on --brand so
     it follows the brand and composites against whatever surface is behind it
     (a hardcoded brand rgba is the logged defect class in DARK-MODE-RULINGS).

     THE GEOMETRY IS THE BOUNDARY, not the colour: 0 spread, y-offset <= 2px,
     blur <= 10px, alpha <= 14%, hue --brand and no other. Spread is what makes
     a brand-tinted shadow read as neon; holding it at zero is what keeps this
     an ambient lift. --shadow-brand (28% at 28px) stays reserved for the
     primary CTA and is not available as a selection glow.

     DARK NEEDS NO REPOINT and gets none. --brand as the solid 1px rim measures
     3.08:1 on light --bg (#ffffff, the figure already recorded above) and
     5.74:1 on dark --bg (#14181c) — both clear SC 1.4.11's 3:1 non-text bar
     from one expression (WCAG relative-luminance formula computed from the raw
     hex; no render available in this worktree, stated rather than claimed).
     The translucent glow layer composites to a few sRGB units over a
     near-black ground and contributes almost nothing in dark — the same
     physics DARK-MODE-RULINGS D2 and task #52 documented for --shadow-*. That
     is accepted: in dark the state is carried by the solid rim and the fill.

     THE FOCUS RING IS UNAFFECTED AND ALWAYS WINS. --focus-outline (A2) is 2px
     solid at outline-offset 2px, 4.94-5.74:1, one lightness step darker/
     lighter than --brand. The glow may never occupy that 2px offset gap, so
     the compliance indicator and the decoration cannot merge. A selected
     element that is also focused renders both, neither altered. */
  --surface-selected-bg:var(--control-selected-bg);
  --surface-selected-border:var(--brand);
  --shadow-selected:inset 0 0 0 1px var(--brand), 0 2px 10px color-mix(in srgb, var(--brand) 14%, transparent);

  /* ---- TYPE */
  --font-display:"Poppins",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --font-body:"Poppins",-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;
  --font-mono:ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  /* Hero steps. The admin rarely uses these, but the login screen (5a) and any
     marketing-adjacent surface do — carried over verbatim so the set stays complete. */
  --t-display:clamp(2.75rem, 1.6rem + 3.5vw, 4.5rem);
  --t-h1:clamp(2.25rem, 1.55rem + 2.2vw, 3.25rem);
  --t-h2:clamp(1.75rem, 1.35rem + 1.3vw, 2.5rem);
  --t-h3:1.5rem; --t-h4:1.25rem; --t-h5:1.0625rem;
  --t-body-lg:1.125rem; --t-body:1rem; --t-body-sm:0.9375rem;
  --t-meta:0.8125rem; --t-mono:0.875rem;

  --lh-tight:1.1; --lh-snug:1.25; --lh-normal:1.5; --lh-loose:1.65;
  --ls-display:-0.02em; --ls-heading:-0.01em; --ls-eyebrow:0.08em;

  /* ---- SPACING — 4px base */
  --space-1:4px;   --space-2:8px;   --space-3:12px;  --space-4:16px;
  --space-5:20px;  --space-6:24px;  --space-8:32px;  --space-10:40px;
  --space-12:48px; --space-16:64px; --space-20:80px; --space-24:96px; --space-32:128px;

  /* ---- RADII — pill on primary CTA is a brand signature */
  --radius-xs:4px; --radius-sm:6px; --radius-md:10px;
  --radius-lg:16px; --radius-xl:24px; --radius-pill:999px;

  /* ---- SHADOWS — soft, never hard Material drops */
  --shadow-xs:0 1px 2px rgba(20,24,28,.05);
  --shadow-sm:0 2px 6px rgba(20,24,28,.06), 0 1px 2px rgba(20,24,28,.04);
  --shadow-md:0 8px 20px rgba(20,24,28,.08), 0 2px 4px rgba(20,24,28,.04);
  --shadow-lg:0 20px 40px rgba(20,24,28,.10), 0 4px 8px rgba(20,24,28,.05);
  --shadow-brand:0 12px 28px rgba(0,169,89,.28);

  /* ---- LAYOUT */
  --container:1200px;
  --gutter:clamp(20px, 4vw, 48px);

  /* ---- EXTENSION — the dialog width scale. RATIFIED by
     crm-design-system-architect 2026-09-04; see DIALOG-RULINGS.md (M3).

     The first four are the values modals.css:104-107 already hardcodes
     (sm 520 / md 560 detail / lg 640 form / xl 680 flow) — lifted here so the
     scale has ONE definition site. Repointing those four classes at these
     tokens is a zero-pixel change.

     --modal-w-workbench is the one addition: 880px for a TWO-PANE TRANSFER
     LIST (an available-fields list beside an ordered visible-columns list),
     which is a different layout class from the four single-column tiers, not
     a bigger form. At 680 with 24px padding and a 24px gap each pane gets
     304px, under the 320px minimum list width the system already accepts
     (SC 1.4.10's reflow target). It is admitted for the layout class, not for
     content volume — which is why it is named for that class rather than
     "2xl": a single-column form cannot claim to be a workbench.

     THE SCALE IS CLOSED AGAIN AT FIVE. There is no 1024, no full, no fluid,
     and no sixth tier. A surface that needs more than 880px is a PAGE, not a
     dialog — route it.

     RESPONSIVE (one breakpoint, derived, and it lives in modals.css because a
     custom property cannot be used in a media query condition): >=960px the
     tier is a fixed 880 (880 + 2x40 minimum gutter = 960); 768-959 the panel's
     existing max-width:94% governs; <768 it becomes a full-bleed sheet with
     the panes stacked. 768 is arithmetic: two 320px panes need
     0.94V - 48 padding - 24 gap >= 640, i.e. V >= 757.4, so 768 is the first
     standard step that holds. Mode-independent; nothing to repoint in .dark. */
  --modal-w-sm:520px;
  --modal-w-md:560px;
  --modal-w-lg:640px;
  --modal-w-xl:680px;
  --modal-w-workbench:880px;

  /* ---- MOTION */
  --ease:cubic-bezier(.2,.7,.2,1);
  --dur-fast:140ms; --dur-base:220ms; --dur-slow:420ms;

  /* ---- DENSITY — CRM-specific, not in the source DS.
     Admin screens are data-dense; the marketing scale is too airy for a
     50-row grid. Recorded as an extension, see KRAYIN-RECONCILIATION.md. */
  --row-height:44px;
  --row-padding-y:var(--space-3);

  /* Paired with .dark's color-scheme:dark below — task #47 item 2. Explicit
     in both directions so native chrome always follows the PAGE's .dark
     class rather than the OS preference (this product toggles theme via a
     cookie + class, not prefers-color-scheme, so the two can disagree). */
  color-scheme: light;
}

/* =========================================================================
   DARK MODE — PROPOSED, see .claude/design-system/DARK-MODE-RULINGS.md (D2).
   Re-points SEMANTIC tokens only, onto existing ink/green/amber/blue ramp
   steps. Primitives (--ink-*, --green-*, --amber-*, --blue-*) are NEVER
   re-pointed here — the chart palette and its CVD validation sit on top of
   them, and re-pointing a primitive would silently repaint every chart.
   Anything not listed below is unchanged in dark: --brand, --brand-strong,
   --brand-strong-hover, --brand-strong-press, --fg-on-brand, --fg-on-dark,
   every --grid-head-* token (GC1),
   every --chart-* slot, every primitive, every non-colour token. See D3/D6.

   Light mode is untouched by this block: no :root value above is edited.
   ========================================================================= */
.dark {
  --bg:var(--ink-900);             /* #14181c  card / grid / raised panels   */
  --bg-alt:var(--ink-950);         /* #0d1013  page base                     */
  --bg-tint:var(--ink-800);        /* #1f2429  hover / press tint            */
  --bg-invert:var(--white);        /* the "opposite of the page" surface     */

  --fg:var(--ink-300);             /* #b3bac3  body copy                     */
  --fg-strong:var(--white);        /* #ffffff  headings, emphasis            */
  --fg-muted:var(--ink-400);       /* #8a929e  secondary copy                */
  /* ink-500 (#5f6770) is 2.73:1 on --bg-tint — fails SC 1.4.11 there. Only
     use --ui-subtle for NON-TEXT foregrounds on --bg / --bg-alt (3.11 /
     3.33:1). A non-text foreground drawn on --bg-tint must step up to
     --fg-muted (4.98:1) instead. Same caveat shape as --brand on cream/mist
     in light. */
  --ui-subtle:var(--ink-500);      /* #5f6770  NON-TEXT ONLY. See caveat.    */
  --fg-subtle:var(--ui-subtle);    /* deprecated alias, follows it           */

  --border:var(--ink-700);         /* #2d3239                                */
  --border-strong:var(--ink-600);  /* #404750                                */
  /* ink-700, NOT ink-800 (MAIL-RULINGS finding U, 2026-09-14). --bg-tint is
     ink-800 in dark, so a divider on ink-800 was byte-identical to the hover
     fill drawn over it — 1.00:1 — and a list row lost its separator at the
     exact moment the pointer or focus arrived on it (measured on
     mail-client.css's .mc-row, whose border-bottom is --divider and whose
     hover background is --control-hover-bg = --bg-tint). ink-700 is the
     nearest ramp step off ink-800 that U names and is already the dark
     --border, so no colour and no primitive is introduced. Measured after:
     divider on --bg-tint 1.20:1 (was 1.00), on --bg 1.37:1; light's own
     divider-on-tint pairing is 1.04:1, so dark now separates MORE strongly
     than light does. Separators are decorative and carry no state, so SC
     1.4.11's 3:1 does not apply — D2's own "--border / --divider are
     deliberately near-invisible" clause, which no ramp step could satisfy
     without turning a hairline into a rule. */
  --divider:var(--ink-700);        /* #2d3239  see finding U                 */

  --brand-text:var(--green-300);   /* #3dcd82  see D3                        */
  --focus-outline:var(--green-300);
  --focus-outline-invert:var(--ink-900);
  --focus-ring:color-mix(in srgb, var(--green-300) 45%, transparent);

  --chart-grid:var(--divider);
  --chart-axis-text:var(--fg-muted);

  --tone-amber-bg:var(--amber-900); --tone-amber-fg:var(--amber-400);
  --tone-blue-bg:var(--blue-900);   --tone-blue-fg:var(--blue-300);

  /* ---- EXTENSION — the four remaining tone pairs, dark twins. MAIL-RULINGS
     M8 / M14. RATIFIED for implementation here, PROPOSED for upstream
     ratification in Claude Design.

     Three of the four are DARK-MODE-RULINGS D6's own measured steps, already
     shipping as literals inside components.css's .dark variants — green
     #004423/#7bdfa9, neutral --ink-800/--ink-300, red #5d1512/#e8a0a0 — so
     nothing here is a new value and nothing changes visually. Red's text step
     follows --danger-text, which this same block repoints to #e8a0a0.

     Figures are fg-on-bg, WCAG 2.x relative luminance, two decimals. */
  --tone-green-bg:var(--green-900);   --tone-green-fg:var(--green-200);   /* 7.01:1 */
  --tone-neutral-bg:var(--ink-800);   --tone-neutral-fg:var(--ink-300);   /* 7.99:1 */
  --tone-red-bg:#5d1512;              --tone-red-fg:var(--danger-text);   /* 6.30:1 */

  /* PROPOSED — awaiting design-system-agent countersignature (M8) */
  /* The one pair with no provenance: there is no purple ramp anywhere and M8
     refused to guess it. Derived by holding --chart-4's hue (258.8) and
     applying the blue-700 -> blue-900 / -300 lightness moves, then measured:

       fg on bg ....................... 6.65:1  (inside the 5.74–7.99 band the
                                                 other five dark pairs occupy)
       dark --fg #b3bac3 on this fill .. 7.83:1
       fg on --bg #14181c ............. 7.73:1   - M14's 3px bar clears
       fg on --bg-tint #1f2429 ........ 6.78:1   - SC 1.4.11 at rest and hover

     M8's required ΔE re-run against dark --tone-blue-bg (#0e2b4b), CIEDE2000:
     NORMAL VISION 12.87, DEUTAN 5.71 (Vienot 1999 simulation). M8's stated
     floor of 23.7 deutan IS NOT MET AND IS NOT MEETABLE: re-running the same
     metric over the chart palette it was taken from gives --chart-2 vs
     --chart-4 at 21.59 normal / 5.74 deutan, i.e. the validated set's own
     blue-vs-violet adjacency sits where this pair does, and the shipped light
     purple/blue fills measure 7.71 / 1.86. Blue and purple are hue neighbours
     that deuteranopia collapses at ANY chroma; a fill 22% light cannot beat
     it. Separation in both modes therefore rests on luminance and on the
     label's own text, not on hue — which is what design-system-agent must
     countersign or overrule (restate the floor, or drop the sixth colour).
     Until then this pair is PROPOSED and purple is painted nowhere. */
  --tone-purple-bg:#2c165a;           --tone-purple-fg:#b5a0e3;           /* 6.65:1 */

  /* ---- EXTENSION — the danger TEXT step, dark twin. MAIL-RULINGS finding A.
     RATIFIED for implementation here, PROPOSED for upstream ratification in
     Claude Design. #e8a0a0 is DARK-MODE-RULINGS D6's measured dark red step:
     8.47:1 on dark --bg #14181c, against --danger's own 4.02:1 there, which
     fails SC 1.4.3. The light value #c92a2a is 3.27:1 here, so this block is
     not optional - a publish that lands the module stylesheet without
     tokens.css leaves every danger-toned line in dark mode at 3.27:1. */
  --danger-text:#e8a0a0;

  /* Same expressions as :root — both already self-adapt (--control-hover-bg
     carries --bg-tint's own repoint above; the --control-selected-bg
     color-mix composites against whichever --bg it sits on). Restated here
     only to match the chart-grid / chart-axis-text precedent of listing
     every themed token in this block, not because either value changes. */
  --control-hover-bg:var(--bg-tint);
  --control-selected-bg:color-mix(in srgb, var(--brand) 16%, transparent);

  /* ---- DELIBERATELY ABSENT, so the next reader does not "fix" it by adding
     them (DIALOG-RULINGS.md M1/M2/M3):

       --overlay-scrim / --overlay-scrim-glass / --overlay-blur
           A scrim only ever darkens. Lightening one in dark inverts its
           meaning, and it carries no compliance in either mode (the panel over
           it is opaque --bg). Restating the identical literal here would only
           create a second place to forget to edit.
       --surface-selected-bg / --surface-selected-border / --shadow-selected
           All three already self-adapt: the first follows --control-selected-bg
           (restated above, same expression), and --brand as a solid 1px rim is
           3.08:1 on light --bg and 5.74:1 on dark --bg — both clear SC
           1.4.11's 3:1 non-text bar from one expression.
       --modal-w-*
           Geometry, not colour. Mode-independent by construction. */

  /* ---- ELEVATION, task #47 item 1. --shadow-md is a light-mode recipe: a
     near-black shadow (rgba(20,24,28,.08)) reads as depth only because it
     darkens a LIGHTER ground by contrast. On the collapsed-rail flyout its
     fill is --bg (#14181c) sitting over a backdrop that is ALSO near-black
     (the sidebar's dark:bg-gray-900 / the page's --bg-alt #0d1013), so the
     identical rgba(20,24,28,..) shadow composites to a delta of a few sRGB
     units — invisible on most displays. Making the same shadow darker or
     more opaque does not fix this: darkening an already-dark blend against
     an already-dark ground is still dark-on-dark, just a different shade of
     invisible.

     The fix is a light-SOURCED edge instead of a dark-sourced one: a 1px
     solid inset rim in --ui-subtle (ink-500, #5f6770). Solid, not
     translucent, so the rendered colour is exact and doesn't depend on
     compositing against an unknown backdrop. Contrast is anchored to the
     panel's OWN fill (--bg, #14181c) rather than to whatever sits behind
     it, because the backdrop varies (sidebar rail vs. page body vs. a
     hovered row) and the fill is the one surface that's always known.
     ink-500-on-#14181c is 3.11:1 — already measured and ratified in
     .claude/design-system/DARK-MODE-RULINGS.md D2 (Playwright/Chromium
     render, WCAG relative-luminance calc) as the pass figure for
     --ui-subtle on --bg — reused here rather than re-measured, and
     independently re-derived by hand for this change (WCAG contrast
     formula, ink-500 #5f6770 vs ink-900 #14181c → 3.108:1) as a cross-check;
     both agree to 2 decimals. Clears SC 1.4.11's 3:1 non-text bar for a
     UI-component boundary. --ui-subtle is the token already reserved for
     exactly this role — non-text foreground, never body copy — so no new
     colour is introduced.

     The soft rgba(20,24,28,..) blur layers are left byte-for-byte as they
     are in light mode: not darkened, not made more opaque. They were never
     the broken mechanism, and touching them was the instinct this item
     explicitly rules out. Light mode is untouched — this whole block is
     .dark-scoped. */
  --shadow-md: inset 0 0 0 1px var(--ui-subtle), 0 8px 20px rgba(20,24,28,.08), 0 2px 4px rgba(20,24,28,.04);

  /* ---- task #52. --shadow-xs and --shadow-sm never got the item-1 fix
     above and have the identical failure: .card--surface (background:--bg,
     box-shadow:--shadow-xs — components.css:466) is the shared recipe for
     the three new leads-list surfaces (filter rail, results table, sticky
     stats bar), and .card--tight (record.css:268-271, same --shadow-xs) is
     the record page's rail-card variant. Both render with NO perceivable
     edge in dark, for the reason D2/#47 already named: a near-black rgba
     blur over a near-black ground composites to a few sRGB units of delta —
     true regardless of which of the three shadow tokens carries it.

     Same fix, not a second invention: a 1px solid inset rim in --ui-subtle,
     anchored to the panel's own (always-opaque) fill rather than to the
     backdrop. Every current consumer of these two tokens paints its own
     background as --bg or --white (checked by reading every call site:
     .card--surface, .card--tight, .card, .record, .kanban-card,
     .panel-card, nav.css:455, modals.css:390, leads-enquiries.css:67 —
     none is --bg-tint), so the inset rim always composites onto --bg,
     regardless of what sits behind the element on the page.

     MEASURED (Python, WCAG relative-luminance formula, from the raw hex —
     no render available in this worktree; said explicitly rather than
     claimed): ink-500 #5f6770 solid vs --bg #14181c = 3.109712932810902:1;
     vs --bg-alt #0d1013 (also the measured admin-canvas/<body> colour per
     D2's own render) = 3.3259486790929347:1. Both figures match what D2's
     table already ratified for --ui-subtle on these two grounds (3.11 /
     3.33), reused rather than re-measured because the colour and both
     grounds are unchanged from D2. Both clear SC 1.4.11's 3:1 non-text bar.
     ink-500 is 2.73:1 on --bg-tint and would fail there, per D2's own
     caveat — moot for these two tokens because no current consumer fills
     with --bg-tint (see call-site list above).

     A Python sweep of the same rim at reduced opacity (90/85/80/75/70/65/
     60/50/40% of ink-500 alpha-blended onto --bg) put every step at 2.76:1
     or below — i.e. there is no translucent version of this rim that still
     clears 3:1; only the fully solid colour does, with 0.11:1 of headroom
     on --bg. So opacity is not an available lever for a compliance-critical
     edge on either token, and width is left at 1px for the same reason md
     used 1px: a thicker or thinner line of an already-compliant colour
     doesn't change its contrast ratio, so varying it would buy a cosmetic
     difference backed by no measurement.

     WEIGHT IS PRESERVED, NOT COLLAPSED — by leaving the lever it already
     lived on alone. The xs/sm/md distinction was never the rim (identical,
     3:1-compliant, on all three); it was always the surrounding rgba blur,
     untouched here exactly as md left it untouched: xs keeps its one 2px/
     .05 layer, sm keeps its two layers (6px/.06 + 2px/.04), md keeps its
     two (20px/.08 + 4px/.04). That ordering composites to near-zero in the
     one worst case D2 documented (near-black fill over a near-black
     canvas) but is real and measurably graded the moment either sits over
     anything lighter than --bg — a lighter dark surface, a future ground,
     print — exactly as it already was in light mode. */
  --shadow-xs: inset 0 0 0 1px var(--ui-subtle), 0 1px 2px rgba(20,24,28,.05);
  --shadow-sm: inset 0 0 0 1px var(--ui-subtle), 0 2px 6px rgba(20,24,28,.06), 0 1px 2px rgba(20,24,28,.04);

  /* ---- task #47 item 2. Tells the UA to render native chrome (incl. the
     default scrollbar track/thumb where scrollbar-color isn't set, and any
     future form control that doesn't get bespoke styling) in the dark
     palette instead of following the OS. Declared here, at the same scope
     as every other .dark repoint, so it is inherited by the whole
     document — the concrete defect (nav.css's .nav__scroll) is fixed via
     explicit scrollbar-color there, and this is the ancestor-level fix the
     audit found missing ("no color-scheme on that element or any
     ancestor"). */
  color-scheme: dark;
}

[data-density="compact"] {
  --row-height:34px;
  --row-padding-y:var(--space-2);
}

[data-pm-density="compact"] {
  --row-height:34px;
  --row-padding-y:var(--space-2);
}

/* Respect the user's motion preference — the DS mandates subtle motion,
   and "subtle" for someone with vestibular sensitivity means none. */
@media (prefers-reduced-motion: reduce) {
  :root { --dur-fast:0ms; --dur-base:0ms; --dur-slow:0ms; }
  *, *::before, *::after {
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important; scroll-behavior:auto !important;
  }
}

/* The same switch, set by the user on the Appearance page (PROFILE-MENU-
   RULINGS.md PM15): a verbatim twin of the media block above, keyed on
   <html data-reduce-motion="on"> (written by the head-prefs script), so the
   user's setting and the OS setting behave identically everywhere. "off"
   declares nothing - it never overrides an OS `reduce`. */
:root[data-reduce-motion="on"] { --dur-fast:0ms; --dur-base:0ms; --dur-slow:0ms; }
:root[data-reduce-motion="on"] *,
:root[data-reduce-motion="on"] *::before,
:root[data-reduce-motion="on"] *::after {
  animation-duration:.01ms !important; animation-iteration-count:1 !important;
  transition-duration:.01ms !important; scroll-behavior:auto !important;
}
