/*
 * Heale — default theme variables (Heale Charte 2026)
 *
 * Two layers:
 *   1. The design palette — 23 named color primitives (--color-*).
 *   2. The app's consumed tokens (--brand-*, --sidebar-*, --dash-*, etc.),
 *      each MAPPED to a palette primitive. Component rules in global.css only
 *      ever reference the consumed tokens (never raw hex), so a palette tweak
 *      here re-skins the whole Heale app without touching global.css.
 *
 * Only the Heale theme carries the cream / Plus-Jakarta redesign; other
 * white-labels (property-finder, backoffice) set their own tokens and are
 * unaffected — the global.css base defaults preserve their historical look.
 */

:root {
  /* ── 1. Palette (Heale Charte 2026) ──────────────────────────────── */
  --color-navy-700: #0A3373;
  --color-navy-800: #0F2F6D;
  --color-blue-400: #4374F3;
  --color-blue-600: #1D4ED8;
  --color-blue-200: #B9C9EA;
  --color-blue-50:  #E8EFFC;

  --color-cream-50:  #FAF6F0;
  --color-cream-100: #FBF7F1;
  --color-sand-200:  #F2EDE5;
  --color-sand-300:  #EEE8DF;
  --color-sand-400:  #E9E4DC;
  --color-sand-500:  #E9D5C9;

  --color-ink-900:   #1C1A17;
  --color-ink-700:   #4A4640;
  --color-ink-400:   #8D8579;
  --color-slate-700: #334155;

  --color-coral-500: #FB7A5C;
  --color-coral-300: #FFA586;
  --color-coral-50:  #FDF1EC;
  --color-rust-600:  #C2542E;
  --color-green-500: #3A8A5F;
  --color-gold-500:  #E3B341;

  /* ── 2. Consumed tokens (mapped to the palette) ──────────────────── */

  /* Brand */
  --brand-primary:      var(--color-navy-700);
  --brand-primary-dark: var(--color-navy-800);
  --brand-secondary:    var(--color-blue-400);
  --brand-accent:       var(--color-coral-500);
  --brand-bg:           var(--color-cream-50);
  --brand-radius:       0.625rem;
  --brand-font:         "Plus Jakarta Sans";
  --app-font:           var(--font-jakarta);

  /* Dashboard shell — cream surface everywhere */
  --dash-root-bg:          var(--color-cream-50);
  --dash-topbar-bg:        var(--color-cream-50);
  --dash-body-bg:          var(--color-cream-50);
  --dash-topbar-sep-color: transparent;

  /* Page title / subtitle / role badge / bell (§5) */
  --dash-topbar-title-size:     28px;
  --dash-topbar-title-tracking: -0.02em;
  --dash-topbar-title-color:    var(--color-ink-900);
  --dash-topbar-date-color:     var(--color-ink-400);
  --dash-topbar-badge-size:     9.5px;
  --dash-topbar-badge-radius:   8px;
  --dash-topbar-badge-color:    var(--color-rust-600);
  --dash-topbar-badge-bg:       color-mix(in srgb, var(--color-coral-500) 13%, transparent);
  /* The INFORMATIONAL badge — a neutral fact, not a role and not a verdict.
     Navy on blue-50: §1's informational pair, and deliberately none of the §12
     status tones (each carries a verdict) nor blue-400 (which belongs to
     controls). See `.dash-topbar-badge--info` in global.css. */
  --dash-topbar-badge-info-color: var(--color-navy-700);
  --dash-topbar-badge-info-bg:    var(--color-blue-50);
  /* The same informational pair, for a panel's "you may read, not edit" line
     (`.panel-readonly-note`). Read-only is not a failure, so it must not borrow
     any §12 status tone. */
  --panel-readonly-note-color:    var(--color-navy-700);
  --panel-readonly-note-bg:       var(--color-blue-50);
  --dash-bell-size:      40px;
  --dash-bell-bg:        #ffffff;
  --dash-bell-border:    transparent;
  --dash-bell-color:     var(--color-ink-700);
  --dash-bell-shadow:    0 2px 10px rgba(28, 26, 23, 0.05);
  --dash-bell-dot-color: var(--color-coral-500);

  /* Cards (§8) — white fill, no border, warm soft shadow */
  --dash-stat-border:           transparent;
  --dash-stat-radius:           16px;
  --dash-stat-shadow:           0 2px 10px rgba(28, 26, 23, 0.05);
  /* §8 floating elevation — a card that acts lifts under the pointer. */
  --dash-stat-shadow-hover:     0 3px 14px rgba(28, 26, 23, 0.06);
  --hr-dash-recent-card-border: transparent;
  --hr-dash-recent-card-radius: 16px;
  --hr-dash-recent-card-shadow: 0 2px 10px rgba(28, 26, 23, 0.05);
  --hr-dash-recent-head-border: var(--color-sand-300);
  /* A card that sits directly ON the page body and must still read as a block
     (`/hr/quotes/new`'s "Using your company information" + "What happens next").
     Deliberately NOT `--modal-total-bg`: that is §8's INNER-CELL tone — cream-50
     inside a WHITE card, which is where all ~28 of its other consumers live —
     and this body IS cream-50, so a card painted with it disappears into the
     page. One step up the sand ramp instead, which is what sand-200 is for. */
  --hr-dash-recent-card-tinted-bg: var(--color-sand-200);

  /* Right-docked overlay panel (§8 overlay shadow + §13 overlay variant) —
     the leftward warm-black shadow is the only thing lifting the Task Manager
     detail panel off the page (no border). Width is the top of §13's
     400–430px range. */
  --tm-detail-overlay-width:  430px;
  --tm-detail-overlay-shadow: -18px 0 44px -8px rgba(28, 26, 23, 0.16);

  /* Skeleton / shimmer placeholders — warm sand tones, deepened via color-mix
     so the pulse stays visibly distinct from the cream-50 page bg (#FAF6F0)
     and white card fills, rather than reading as sand-200/300 alone would. */
  --ui-shimmer-bg:      color-mix(in srgb, var(--color-sand-300) 94%, black 6%);
  --ui-shimmer-bg-dark: color-mix(in srgb, var(--color-sand-400) 88%, black 12%);

  /* Shared checkbox (`.ui-check`). Unchecked is a §9 field edge — white fill,
     sand-400 hairline — and checked is the §6 primary blue with a white tick, so
     a ticked box reads as the same "on" blue as a primary action. 16px / 4.5px
     radius: the Charte's small rounded square, sized to sit level with a 13.5px
     row title without dominating it. Unchecked disabled follows §6/§9 (sand-200
     fill, never an opacity fade).

     Ticked-but-locked and DERIVED are §2 tinted surfaces instead: blue-50 fill
     (the palette's own pale blue, already this app's "blue, but not actionable"
     tone) with a blue-200 edge and the FULL blue-400 as the tick. A white tick on
     a pale fill would be invisible, and the point of both states is that the box
     still reads unambiguously ON. They keep separate tokens because the states
     are only coincidentally identical: derived = "someone else ticked this",
     locked = "you may not touch this". */
  --ui-check-size:                      16px;
  --ui-check-radius:                    4.5px;
  --ui-check-bg:                        #ffffff;
  --ui-check-border:                    var(--color-sand-400);
  --ui-check-border-hover:              var(--color-blue-400);
  --ui-check-bg-checked:                var(--color-blue-400);
  --ui-check-glyph:                     #ffffff;
  --ui-check-bg-disabled:               var(--color-sand-200);
  --ui-check-border-disabled:           var(--color-sand-400);
  --ui-check-bg-checked-disabled:       var(--color-blue-50);
  --ui-check-border-checked-disabled:   var(--color-blue-200);
  --ui-check-glyph-checked-disabled:    var(--color-blue-400);
  --ui-check-bg-derived:                var(--color-blue-50);
  --ui-check-border-derived:            var(--color-blue-200);
  --ui-check-glyph-derived:             var(--color-blue-400);

  /* Metric cards */
  --dash-stat-value-color:    var(--color-ink-900);
  --dash-stat-value-size:     30px;
  --dash-stat-value-weight:   800;
  --dash-stat-value-tracking: -0.02em;
  --dash-stat-label-color:    var(--color-ink-400);
  --dash-stat-label-weight:   700;
  --dash-stat-label-tracking: 0.06em;

  /* Tables (§10) — fill-less header (mockup override of the sand-200 band);
     the sand-300 bottom divider below still separates it from the rows. */
  --hr-dash-recent-th-bg:        transparent;
  --hr-dash-recent-th-size:      9.5px;
  --hr-dash-recent-th-weight:    700;
  --hr-dash-recent-th-tracking:  0.05em;
  --hr-dash-recent-th-color:     var(--color-ink-400);
  --hr-dash-recent-row-border:   var(--color-sand-300);
  --hr-dash-recent-td-padding:   14px 24px;
  /* THE standard ROW / list-item hover across the whole app (tables, Task
     Manager rows, member-form + Contact Center rail rows, quote-wizard rows) —
     cream-50, the same warm tone as the page background. Control/button hovers
     are a separate concern and keep their own tokens. */
  --hr-dash-recent-row-hover-bg: var(--color-cream-50);
  --hr-dash-recent-name-color:   var(--color-ink-900);
  --ins-pol-num-color:           var(--color-navy-700);
  /* §3 text roles on the card/table chrome. These four were the last cool-grey
     literals left in the shared table family (the th / name / border / hover
     tokens above were mapped in earlier phases) — every table in the app reads
     them, which is exactly why they belong in the theme rather than in a
     page-scoped override. */
  --hr-dash-recent-title-color:    var(--color-ink-900);
  --hr-dash-recent-subtitle-color: var(--color-ink-400);
  --hr-dash-recent-td-color:       var(--color-ink-700);
  --hr-dash-recent-id-color:       var(--color-ink-400);
  --hr-dash-recent-empty-color:    var(--color-sand-400);
  --dash-stat-sub-color:           var(--color-ink-400);
  /* Expanded parent row / its nested child rows (HR census families, quote
     wizard categories) — warm neutrals, not the historical cool blue. */
  --hr-dash-recent-tr-expanded-bg:  var(--color-cream-50);
  --hr-dash-recent-tr-dependent-bg: var(--color-sand-200);
  /* Census family tree connector (`.census-tree`) — the hairline that joins a
     dependant to its employee. Sand-400 rather than the sand-300 row divider so
     the trunk stays legible where it crosses one. */
  --census-tree-line: var(--color-sand-400);

  /* Quote wizard members list — a row the user has TICKED. Blue, not the cream
     above: cream-50 is this app's neutral "expanded / hovered" tone (it is
     literally `--hr-dash-recent-row-hover-bg`), so a cream selected row is
     indistinguishable from a hover and reads as nothing at all. Selection in
     this card is already blue (the checkbox's accent, the navy filter pill), and
     blue-50 is the pale-blue "active/selected surface" this app already uses for
     exactly that meaning (`--sidebar-subitem-bg-active`, `--cc-blue-tint-bg`,
     `--pw-badge-bg`) — §2 strength (≈blue-400 @16%), which a repeatedly-toggled
     checkbox list needs to stay legible, where §12's fainter 6% wash is tuned
     for a single focused Task Manager row. */
  --qw-mem-row-selected-bg: var(--color-blue-50);

  /* Quote wizard — Requested benefits (`.qw-benefits-*`). The step's row list
     is a plain label/control table now, so it takes the app's own hairline and
     text tones instead of the cool greys it was authored with. */
  --qw-benefits-divider:        var(--color-sand-300);
  --qw-benefits-label-color:    var(--color-ink-700);
  --qw-benefits-meta-color:     var(--color-ink-400);
  --qw-benefits-tick-color:     var(--color-ink-400);
  --qw-benefits-control-border: var(--color-sand-400);
  --qw-benefits-rail-bg:        var(--color-sand-300);

  /* Status badges (§12) — tinted surface (token @ ~14%) + full-token text */
  --dash-status-weight:         600;
  --dash-status-approved-color: var(--color-green-500);
  --dash-status-approved-bg:    color-mix(in srgb, var(--color-green-500) 14%, transparent);
  --dash-status-pending-color:  var(--color-gold-500);
  --dash-status-pending-bg:     color-mix(in srgb, var(--color-gold-500) 16%, transparent);
  --dash-status-inactive-color: var(--color-ink-400);
  --dash-status-inactive-bg:    color-mix(in srgb, var(--color-ink-400) 14%, transparent);
  --dash-status-rejected-color: var(--color-rust-600);
  --dash-status-rejected-bg:    color-mix(in srgb, var(--color-rust-600) 14%, transparent);
  /* `info` and `action` were the two §12 states this block never mapped, so every
     consumer of them (the `Auto` quote tag, the insurer board's column accents, the
     `.dash-status--action` pill) fell through to `global.css`'s BASE fallbacks —
     `#2563eb` and `#9a3412`, neither of which is one of the 23 tokens. Mapped now:
     `info` is blue-400 (§12 "open"), `action` is coral-500 (§12 "action needed",
     which is exactly what coral is the brand accent FOR). */
  --dash-status-info-color:     var(--color-blue-400);
  --dash-status-info-bg:        color-mix(in srgb, var(--color-blue-400) 14%, transparent);
  --dash-status-action-color:   var(--color-coral-500);
  --dash-status-action-bg:      color-mix(in srgb, var(--color-coral-500) 14%, transparent);

  /* Modals (.modal-*) — title/close chrome (§12/§16). Scoped to just these
     two tokens rather than the whole `.modal-*` family (most of it — inputs,
     totals below — isn't part of this pass). */
  --modal-title-color:        var(--color-ink-900);
  --modal-close-border-width: 1px;
  --modal-close-border-color: var(--color-sand-400);
  --modal-close-radius:       10px;
  /* §6: a primary CTA is blue-400 wherever it appears — a dialog footer is no
     exception. Same pair as `--hr-dash-recent-btn-primary-*` so the two can't
     read as different kinds of "primary". */
  --modal-btn-primary-bg:             var(--color-blue-400);
  --modal-btn-primary-bg-hover:       var(--color-blue-600);
  --modal-btn-primary-hover-opacity:  1;

  /* Dialogs (.dialog-*) — the shared confirm/alert/prompt primitive
     (src/components/ui/dialog.tsx). §2 tinted surfaces for the header icon and
     §6 rust-600 for the destructive confirm CTA. */
  --dialog-danger-color:       var(--color-rust-600);
  --dialog-danger-color-hover: var(--color-rust-600);
  --dialog-danger-bg:          color-mix(in srgb, var(--color-rust-600) 14%, transparent);
  --dialog-success-color:      var(--color-green-500);
  --dialog-success-bg:         color-mix(in srgb, var(--color-green-500) 14%, transparent);
  --dialog-info-color:         var(--color-blue-400);
  --dialog-info-bg:            color-mix(in srgb, var(--color-blue-400) 14%, transparent);
  --dialog-text-color:         var(--color-ink-700);
  --dialog-items-bg:           var(--color-cream-50);

  /* §8 right-docked overlay shadow — the document preview slide-over. */
  --doc-preview-overlay-shadow: -18px 0 44px -8px rgba(28, 26, 23, 0.16);

  /* Shared "soft inset panel" tint (§8) — Create Invoice totals, the quote
     category picker, the claim decision amount, and every Task Manager
     metadata/comment-bubble cell all consume this ONE token already (see
     `--modal-total-bg`'s call sites in global.css), so retuning it to
     cream-50/ink-900 here is one consistent Charte correction, not a
     Task-Manager-only tweak. */
  --modal-total-bg:    var(--color-cream-50);
  --modal-total-color: var(--color-ink-900);

  /* Template library (§3 body tone) — the QUIET half of a preview row, opposite
     the value which reads `--modal-total-color` above because the row IS one of
     those inner cells. A dedicated token, not `--hr-dash-recent-td-color`: that
     one's signed-off meaning is "table BODY CELL", which a modal pane's listing
     only resembles, and borrowing it would put this modal inside the blast
     radius of every retint of every `<td>` in the app. Same call, and the same
     reason, as `--qro-see-text-color` and the dozen other per-family body tones
     below. */
  --tl-preview-label-color: var(--color-ink-700);

  /* `/hr/quotes` request blocks (§3 body tone) — the inputs strip's value chips
     and the problem items beside the CTA. One token for both because they are one
     feature introduced together and read as one voice; split it the day they
     genuinely diverge.

     A dedicated token for the same reason as `--tl-preview-label-color` directly
     above, and this one was caught rather than reasoned: both rules first read
     `--hr-dash-recent-td-color` — ink-700 here, so it LOOKED right — and
     `hr-dashboard-charte-2026.test.ts`'s US-HRD.1.6 failed, because that token's
     signed-off meaning is "table BODY CELL" and neither a list item nor a chip is
     one. The guard's recorded consumer set is unchanged by this feature. */
  --qd-block-text-color: var(--color-ink-700);

  /* The fix-in-place list's dependant SUB-ROW name (§3 body tone) — one emphasis
     step below the family name that titles its row. Its own token, not
     `--hr-dash-recent-td-color`, for the reason recorded two blocks up and caught
     the same way: the span lives inside `.hr-dash-recent-td--name`, so it is
     overriding the name tone rather than inheriting the body-cell one, and
     borrowing that token would drag a name in the name column along with every
     `<td>` retint in the app. Not folded into `--qd-block-text-color` either —
     that one is scoped to the request blocks' chips and problem items, and a
     person's name in a table is a different voice. */
  --qd-fix-subrow-name-color: var(--color-ink-700);

  /* The insurer quote surfaces' NEUTRAL tag — the `Basic` marker on the new-request
     list row (`.iqn-tag--basic`) and on the quoting board card (`.qk-card-tag--basic`).
     §1's tag surface: sand-200 fill, body ink label. It is a PRODUCT marker (which
     quotation form the company used), not a status, so it carries no semantic hue —
     that would make it compete with the state pill beside it.

     Its own pair rather than `--hr-dash-recent-card-tinted-bg` + `--hr-dash-recent-td-color`,
     which is what both rules first read because sand-200 + ink-700 is what they resolve
     to here so it LOOKED right — the third time this exact mistake has been caught by
     `hr-dashboard-charte-2026.test.ts`'s US-HRD.1.6, after `--tl-preview-label-color`
     and `--qd-block-text-color` two blocks up. The td token's signed-off meaning is
     "table BODY CELL" and a 9.5px uppercase pill is not one; the tinted-bg token's is
     "a read-only summary CARD sitting on the page". Borrowing either would put this tag
     inside the blast radius of every `<td>` retint, and of every tinted-card retint, in
     the app. Named `-neutral-` like `--ins-claim-tag-neutral-*`, the same call on the
     claims surfaces; NOT folded into those, because a claims token painting a quotes
     tag is the same reach one family over. The guard's recorded consumer set is
     unchanged by this feature. */
  --quote-tag-neutral-bg:    var(--color-sand-200);
  --quote-tag-neutral-color: var(--color-ink-700);

  /* Task Manager (§12/§16) — detail-panel micro-labels, tag pill, and the
     upload dropzone. Dedicated tokens (not the app-wide `--ins-pol-subtext-color`)
     so this pass stays scoped to Task Manager's own surfaces. */
  --tm-detail-label-color: var(--color-ink-400);
  /* "Action needed" section — coral-500 wash + rust-600 label, the same
     tint-surface/deeper-text pairing the role badge and every status pill use. */
  --tm-action-section-bg:  color-mix(in srgb, var(--color-coral-500) 8%, white);
  --tm-action-label-color: var(--color-rust-600);
  --task-tag-bg:           var(--color-sand-200);
  --task-tag-color:        var(--color-slate-700);
  --tu-dropzone-border:    var(--color-blue-400);
  --tu-dropzone-bg:        var(--color-cream-50);
  --tu-dropzone-icon-bg:   color-mix(in srgb, var(--color-blue-400) 12%, transparent);
  --tu-muted-color:        var(--color-ink-400);
  --tu-doc-row-border:     var(--color-sand-400);

  /* Insurer Assistant (`.asst-*`) — a chat surface reusing the Charte's existing
     vocabulary: blue-50 for the user's own bubble (the only tinted one), navy
     identifiers for rehydrated task links, a cream-50 inner cell for the
     confirmation card (§8), and the standard rust/green semantic pair for its
     outcome lines. */
  --asst-text-color:        var(--color-ink-700);
  --asst-title-color:       var(--color-ink-900);
  --asst-muted-color:       var(--color-ink-400);
  --asst-text-size:         13px;
  --asst-meta-size:         11.5px;
  --asst-label-size:        9.5px;
  --asst-user-bubble-bg:    var(--color-blue-50);
  --asst-user-bubble-color: var(--color-navy-700);
  --asst-user-bubble-radius: 16px;
  --asst-ref-color:         var(--color-navy-700);
  --asst-card-bg:           var(--color-cream-50);
  --asst-event-bg:          var(--color-cream-50);
  --asst-event-color:       var(--color-ink-400);
  --asst-card-icon-bg:      color-mix(in srgb, var(--color-blue-400) 12%, transparent);
  --asst-card-icon-color:   var(--color-blue-400);
  --asst-ok-color:          var(--color-green-500);
  --asst-error-color:       var(--color-rust-600);
  --asst-error-bg:          color-mix(in srgb, var(--color-rust-600) 12%, transparent);
  --asst-chip-bg:           #ffffff;
  --asst-chip-border:       var(--color-sand-400);
  --asst-chip-color:        var(--color-navy-700);
  --asst-chip-bg-hover:     var(--color-sand-200);
  --asst-composer-bg:       var(--color-cream-50);
  --asst-composer-border:   var(--color-sand-400);

  /* Policy detail — term-progress strip (§5/§8), activity feed, info cards.
     The strip is just the bar now (its premium/dates/status cells moved into
     the header subtitle): ink-400 section label, ink-900 remaining-term label
     with a gold "expiring soon" tone, sand track, navy fill. */
  --pol-summary-label-color:   var(--color-ink-400);
  --pol-summary-value-color:   var(--color-ink-900);
  --pol-summary-bar-track:     var(--color-sand-300);
  --pol-summary-bar-fill:      var(--color-navy-700);
  --ins-pol-activity-icon-bg:    var(--color-sand-200);
  --ins-pol-activity-icon-color: var(--color-navy-700);
  --ins-pol-activity-text-color: var(--color-ink-900);
  --ins-pol-activity-time-color: var(--color-ink-400);
  --cmp-card-title-size:  16px;
  --cmp-card-title-color: var(--color-ink-900);

  /* Label/value rows shared by the policy Company + Benefits tabs. The form
     field's own label tone is `--field-label-color` below (field contract); this
     one is the benefits-row label, which is not a form control. */
  --ins-pol-field-label-color: var(--color-ink-400);
  --bnf-row-value-color:       var(--color-ink-900);
  --bnf-row-name-color:        var(--color-ink-700);
  --bnf-row-meta-color:        var(--color-ink-400);

  /* Document rows (§16) — warm neutral pad, green "received" tint, sand
     hairlines and sand-bordered row controls. */
  --mf-doc-row-border:        var(--color-sand-300);
  --mf-doc-row-filled-bg:     var(--color-cream-50);
  --mf-doc-icon-bg:           var(--color-sand-200);
  --mf-doc-icon-color:        var(--color-ink-400);
  --mf-doc-icon-filled-bg:    color-mix(in srgb, var(--color-green-500) 14%, white);
  --mf-doc-icon-filled-color: var(--color-green-500);
  --mf-doc-name-color:        var(--color-ink-900);
  --mf-doc-sub-color:         var(--color-ink-400);
  --mf-doc-label-color:       var(--color-ink-400);
  --mf-doc-btn-radius:        999px;
  --mf-doc-btn-border:        var(--color-sand-400);
  --mf-doc-btn-color:         var(--color-slate-700);
  --mf-doc-btn-bg-hover:      var(--color-sand-200);
  --mf-doc-subtitle-color:    var(--color-ink-400);
  --mf-doc-bar-track:         var(--color-sand-300);

  /* ── THE FIELD CONTRACT (§9) ────────────────────────────────────────────
     Heale opts the WHOLE app into the Charte field standard. These tokens are
     the only place the standard is expressed: `global.css`'s base rules for
     every field variant (`.ins-pol-input`, `.modal-input`, `.modal-textarea`,
     the `<Combobox>` trigger, `<DateField>`, `<PhoneField>`, the search pill)
     read them with their pre-Charte values as fallbacks, so `property-finder`
     and `backoffice` — which map none of this — keep their historical look.
     See the "THE FIELD CONTRACT" comment block in global.css for what each
     token means.

     §9: a cream-50 FILL with NO visible border (the fill IS the boundary — the
     border stays `transparent` rather than 0-width so focus can paint into it
     without shifting the box), ink-900 value, and a DEEPER sand-200 fill with
     ink-400 text when the field is locked. `--field-hairline` is the separate,
     visible 1px used by field-adjacent chrome (dropdown panels, the date
     roller, group outlines, the in-field phone separator).

     HOVER (§6 "control hover" = sand-200): because the field is borderless here,
     hover is a FILL shift and `--field-hover-border` stays `transparent`. Painting
     a sand edge onto an otherwise borderless control on hover — which is what the
     old `--field-hairline` hover read did — looks like a glitch, not an
     affordance. Only click-to-open triggers read these two. */
  --field-bg:                var(--color-cream-50);
  --field-border:            transparent;
  --field-hairline:          var(--color-sand-400);
  --field-color:             var(--color-ink-900);
  --field-placeholder-color: var(--color-ink-400);
  --field-disabled-bg:       var(--color-sand-200);
  --field-disabled-color:    var(--color-ink-400);
  --field-disabled-opacity:  1;   /* the sand fill IS the disabled signal (§6/§9) */
  --field-height:            44px;
  --field-radius:            10px;
  --field-padding-x:         14px;
  --field-padding-y:         12px;
  --field-font-size:         14px;
  --field-textarea-min-height: 92px;
  --field-focus-border:      var(--color-blue-400);
  --field-focus-ring:        0 0 0 3px color-mix(in srgb, var(--color-blue-400) 15%, transparent);
  --field-hover-bg:          var(--color-sand-200);
  --field-hover-border:      transparent;
  --field-label-color:       var(--color-ink-400);
  --field-label-size:        10px;
  --field-label-gap:         8px;
  --field-grid-gap:          16px 24px;

  /* ── Settings surfaces (`/settings`, `/hr/company-settings`) ──────────────
     The controls come free from the field contract above; these dress what
     surrounds them. Charte: §8 borderless card with the warm shadow, §3 card
     title / section label, §9 label above the field, §6 buttons, §2 tinted
     "Enabled" surface. Every one of these has a pre-Charte fallback in
     global.css, so no other brand moves. */
  --settings-card-border:        transparent;
  --settings-card-radius:        16px;
  --settings-card-shadow:        var(--hr-dash-recent-card-shadow);
  --settings-card-title-size:    17px;
  --settings-card-title-weight:  800;
  --settings-card-title-color:   var(--color-ink-900);
  --settings-card-sub-size:      12.5px;
  --settings-card-sub-color:     var(--color-ink-400);

  /* Size + tone already arrive via --field-label-*; these three are the case. */
  --settings-label-weight:       700;
  --settings-label-transform:    uppercase;
  --settings-label-tracking:     0.06em;

  --settings-hint-size:          11.5px;
  --settings-hint-color:         var(--color-ink-400);

  --settings-section-label-size:     10px;
  --settings-section-label-color:    var(--color-ink-400);
  --settings-section-label-tracking: 0.06em;

  --settings-btn-height:            44px;
  --settings-btn-padding-x:         22px;
  --settings-btn-radius:            999px;
  --settings-btn-size:              13px;
  --settings-btn-weight:            700;
  --settings-btn-bg:                var(--color-blue-400);
  --settings-btn-bg-hover:          var(--color-blue-600);
  --settings-btn-disabled-opacity:  0.45;
  --settings-btn-outline-color:     var(--color-navy-700);
  --settings-btn-outline-border:    1.2px solid var(--color-navy-700);
  --settings-btn-outline-bg-hover:  var(--color-cream-50);
  --settings-btn-danger-color:      var(--color-rust-600);
  --settings-btn-danger-border:     1.2px solid var(--color-rust-600);
  --settings-btn-danger-bg-hover:   color-mix(in srgb, var(--color-rust-600) 10%, transparent);

  /* Inner cells inside a card (§8): cream-50, radius 12, no border. */
  --settings-panel-bg:            var(--color-cream-50);
  --settings-panel-border:        transparent;
  --settings-panel-radius:        12px;
  --settings-mfa-row-title-color: var(--color-ink-900);
  --settings-ok-color:            var(--color-green-500);
  --settings-ok-bg:               color-mix(in srgb, var(--color-green-500) 16%, transparent);

  /* Census member editor — Details / Insurance / Documents tab content. */
  --mf-card-body-padding:       18px 24px 24px;

  /* Card head: a 19px Bold ink-900 title, and nothing else. The maquette's
     40px blue-tint glyph pad was removed by explicit product decision after
     review, so `--mf-card-icon-*` / `--mf-card-head-gap` are gone with it (see
     `<SectionCard>`'s JSDoc). */
  --mf-card-title-size:  19px;

  /* Policy card detail rows (§3 label / value tones) */
  --mf-coverage-desc-color:  var(--color-ink-700);
  --mf-coverage-label-color: var(--color-ink-400);
  --mf-coverage-value-color: var(--color-ink-900);
  --mf-coverage-rows-border: var(--color-sand-300);
  /* Wide enough for "Requested coverage start date" on one line — the 168px
     default wrapped it and broke the card's single alignment line. */
  --mf-coverage-label-width: 216px;
  --mf-coverage-row-gap:     10px;
  --mf-hist-link-color:      var(--color-ink-400);

  /* "Pending save" chip — §12 waiting state as a §2 tinted surface (no border:
     §8's no-border rule, the tint is the separation). */
  --mf-staged-chip-bg:     color-mix(in srgb, var(--color-gold-500) 16%, transparent);
  --mf-staged-chip-color:  var(--color-gold-500);
  --mf-staged-chip-border: transparent;

  /* Quiet inline text buttons (Change / Remove / Cancel in the Policy card) */
  --mf-ghost-btn-radius:           999px;
  --mf-ghost-btn-color:            var(--color-slate-700);
  --mf-ghost-btn-bg-hover:         var(--color-sand-200);
  --mf-ghost-btn-danger-color:     var(--color-rust-600);
  --mf-ghost-btn-danger-bg-hover:  color-mix(in srgb, var(--color-rust-600) 10%, transparent);

  /* Destructive/validation text — §1's rust-600; the pre-Charte red is retired */
  --mf-req-color:            var(--color-coral-500);   /* §9: required = coral asterisk */
  --mf-error-radius:         12px;
  --mf-error-bg:             color-mix(in srgb, var(--color-rust-600) 12%, transparent);
  --mf-error-color:          var(--color-rust-600);
  --modal-field-error-color: var(--color-rust-600);

  /* Document preview slide-over (`<DocPreviewPanel>`) */
  --mf-preview-border:              var(--color-sand-300);
  --mf-preview-title-color:         var(--color-ink-900);
  --mf-preview-body-bg:             var(--color-cream-50);
  --mf-preview-fallback-icon-color: var(--color-ink-400);
  --mf-icon-btn-radius:             10px;
  --mf-icon-btn-border:             var(--color-sand-400);
  --mf-icon-btn-color:              var(--color-ink-700);
  --mf-icon-btn-bg-hover:           var(--color-sand-200);

  /* Two-layer coverage badge (§2) — COVERED / NOT COVERED tinted surfaces and
     their lifecycle sub-label. Consumed by every surface that renders
     <CoverageStatus>/<CoverageStatusDetail> (census list, member editor,
     employee dashboard), which is the point: one matrix, one set of tones. */
  --cov-covered-bg:         color-mix(in srgb, var(--color-green-500) 14%, transparent);
  --cov-covered-color:      var(--color-green-500);
  --cov-not-bg:             color-mix(in srgb, var(--color-rust-600) 14%, transparent);
  --cov-not-color:          var(--color-rust-600);
  --cov-state-color:        var(--color-ink-400);
  --cov-detail-state-color: var(--color-ink-900);

  /* Advisory notice (§12 pending/waiting) — gold tint + gold icon, ink body */
  --mf-warn-bg:         color-mix(in srgb, var(--color-gold-500) 14%, white);
  --mf-warn-border:     color-mix(in srgb, var(--color-gold-500) 32%, white);
  --mf-warn-color:      var(--color-ink-700);
  --mf-warn-icon-color: var(--color-gold-500);
  --mf-warn-cat-color:  var(--color-rust-600);

  /* Add-member wizard step rail (§6 selected control, §12 completed) — navy-700
     for the step you're on, green-500 for the ones behind it, sand/ink for the
     ones ahead. Deliberately NOT reusing `--brand-success` (unmapped here, so it
     falls back to the retired success hex — see `.qw-step-dot--completed`). */
  --mfw-step-dot-bg:                  var(--color-sand-200);
  --mfw-step-dot-color:               var(--color-ink-400);
  --mfw-step-dot-active-bg:           var(--color-navy-700);
  --mfw-step-dot-completed-bg:        var(--color-green-500);
  --mfw-step-label-color:             var(--color-ink-400);
  --mfw-step-label-active-color:      var(--color-navy-700);
  --mfw-step-connector-bg:            var(--color-sand-300);
  --mfw-step-connector-completed-bg:  var(--color-green-500);

  /* Floating menus (§8) — no border, the soft shadow carries them; the item
     separator keeps its own sand hairline. */
  --dropdown-border:    transparent;
  --dropdown-sep-color: var(--color-sand-300);
  --dropdown-shadow:    0 3px 14px rgba(28, 26, 23, 0.06);
  --dropdown-item-color: var(--color-slate-700);
  /* A destructive menu item is §6's rejection tone, like every other
     destructive control here — without this it falls back to the retired §1
     error red, which is exactly the drift a "Remove from request" item sitting
     one line under "Reset plan" cannot afford. */
  --dropdown-item-danger-color:    var(--color-rust-600);
  --dropdown-item-danger-bg-hover: color-mix(in srgb, var(--color-rust-600) 10%, transparent);

  /* Tooltip (§8 floating elevation) — ink surface with the warm cream label so
     it reads as part of the palette rather than a stock black bubble. */
  --tooltip-bg:     var(--color-ink-900);
  --tooltip-color:  var(--color-cream-50);
  --tooltip-shadow: 0 3px 14px rgba(28, 26, 23, 0.18);

  /* A claims-board column the caller may not drop into: the muted counterpart of
     the brand-navy `--can-drop` outline (§12 "cancelled / unavailable = ink-400"),
     with the header's lock glyph in the same metadata tone as every other §3
     section-level marker. */
  --ins-claim-col-locked-outline: var(--color-sand-400);
  --ins-claim-col-lock-color:     var(--color-ink-400);

  /* ── Claims & pre-approvals boards (`/insurer/claims`) ──────────────────
     The Charte has no kanban section of its own (§11 is unbuilt), so the board
     is expressed entirely in existing primitives: the column is chrome (dot +
     label + count, tone underline), the CARD is a §8 card (white, no border,
     soft warm shadow), every state is a §2 tinted surface, and the tones map
     onto the palette's semantics. These are the ONLY place the board's colours
     are decided — `global.css` just reads them.

     Why a dedicated `--ins-claim-tone-*` set rather than `--brand-warning` /
     `--brand-success`: those two stay unmapped on purpose (see `.qw-step-dot`),
     so mapping them would silently reskin every screen that still rides their
     §1-retired fallbacks. */
  --ins-claim-tone-coral: var(--color-coral-500);
  --ins-claim-tone-blue:  var(--color-blue-400);
  --ins-claim-tone-amber: var(--color-gold-500);
  --ins-claim-tone-navy:  var(--color-navy-700);
  --ins-claim-tone-green: var(--color-green-500);
  --ins-claim-tone-red:   var(--color-rust-600);

  /* Board panel = §8 inner cell (cream-50 inside the white card). */
  --ins-claim-board-bg: var(--color-cream-50);

  /* Column chrome */
  --ins-claim-col-title-size:  13px;
  --ins-claim-col-title-color: var(--color-ink-900);
  --ins-claim-col-count-bg:    var(--color-sand-200);
  --ins-claim-col-count-color: var(--color-ink-400);
  --ins-claim-col-empty-border: var(--color-sand-400);

  /* §8 card: no border, the shadow carries it (hover only deepens it — the
     border must stay transparent so hovering can't draw one back in). */
  --ins-claim-card-border:        transparent;
  --ins-claim-card-border-hover:  transparent;
  --ins-claim-card-radius:        14px;
  --ins-claim-card-shadow:        0 2px 10px rgba(28, 26, 23, 0.05);
  --ins-claim-card-shadow-hover:  0 3px 14px rgba(28, 26, 23, 0.1);

  /* §12 "action needed" = a 3px coral left rule and nothing else, so the tint
     and the surrounding border are both neutralised here. */
  --ins-claim-overdue-bg:         #ffffff;
  --ins-claim-overdue-border:     transparent;
  --ins-claim-overdue-rule-width: 3px;
  --ins-claim-overdue-rule-color: var(--color-coral-500);
  --ins-claim-alert-bg:           color-mix(in srgb, var(--color-coral-500) 14%, transparent);
  --ins-claim-alert-color:        var(--color-rust-600);

  /* §12 selection = blue-400 marker + blue-400 @0.06 wash — the live drop
     target, deliberately a different vocabulary from the coral alert above. */
  --ins-claim-drop-over-outline: var(--color-blue-400);
  --ins-claim-drop-over-bg:      color-mix(in srgb, var(--color-blue-400) 6%, transparent);

  /* §3 text roles on the card / board / detail chrome */
  --ins-claim-ref-color:           var(--color-navy-700);
  --ins-claim-title-color:         var(--color-ink-900);
  --ins-claim-member-color:        var(--color-ink-900);
  --ins-claim-amount-color:        var(--color-ink-900);
  --ins-claim-body-color:          var(--color-ink-700);
  --ins-claim-muted-color:         var(--color-ink-400);
  --ins-claim-divider-color:       var(--color-sand-300);
  --ins-claim-relation-color:      var(--color-rust-600);
  --ins-claim-rejected-sep-color:  var(--color-rust-600);
  --ins-claim-tag-neutral-bg:      var(--color-sand-200);
  --ins-claim-tag-neutral-color:   var(--color-slate-700);

  /* §12 "waiting on X" = gold-500 */
  --ins-claim-waiting-bg:    color-mix(in srgb, var(--color-gold-500) 16%, transparent);
  --ins-claim-waiting-color: var(--color-gold-500);

  /* Claim/pre-approval info card. The metadata cells sit in ONE row (see
     `.ins-claim-info-grid`) — this is the gap between them. The identity row's
     reference takes the §3 body tone (it is a value, not a title) and the type
     heading takes navy-700; the ageing pill reuses `--ins-claim-alert-*`
     (coral @14% + rust-600), the same pair as the board's overdue marker. */
  --ins-claim-info-grid-gap:      12px;
  --ins-claim-info-ref-color:     var(--color-ink-700);
  --ins-claim-info-title-color:   var(--color-navy-700);
  --ins-claim-metaline-sep-color: var(--color-sand-400);

  /* Board decision popups (§8 floating elevation). */
  --ins-claim-modal-radius: 16px;
  --ins-claim-modal-shadow: 0 3px 14px rgba(28, 26, 23, 0.06), 0 18px 44px -8px rgba(28, 26, 23, 0.16);

  /* Buttons & pills (§6, §7) */
  --hr-dash-recent-btn-radius:                999px;
  --hr-dash-recent-btn-padding:               11px 20px;
  --hr-dash-recent-btn-weight:                700;
  --hr-dash-recent-btn-primary-bg:            var(--color-blue-400);
  --hr-dash-recent-btn-primary-bg-hover:      var(--color-blue-600);
  --hr-dash-recent-btn-primary-hover-opacity: 1;
  --hr-dash-recent-btn-primary-shadow:        0 2px 8px rgba(67, 116, 243, 0.25);
  --hr-dash-recent-btn-outline-border:        var(--color-navy-700);
  --hr-dash-recent-btn-outline-border-width:  1.2px;
  --hr-dash-recent-btn-outline-color:         var(--color-navy-700);
  --hr-dash-recent-btn-outline-bg-hover:      var(--color-cream-50);

  /* "Filters (N)" trigger pill (`<FilterPanel>`) — a fully-rounded 40px control
     with a navy-700 hairline and a very light blue-400 tint (~#F2F5FE): light
     enough to read as a neutral control, tinted enough not to disappear into a
     white card the way a white-filled pill does. Navy label + funnel, per §6's
     secondary/control colour. */
  --filter-trigger-height:    40px;
  --filter-trigger-padding-x: 18px;
  --filter-trigger-font-size: 13px;
  --filter-trigger-border:    var(--color-navy-700);
  --filter-trigger-color:     var(--color-navy-700);
  --filter-trigger-bg:        color-mix(in srgb, var(--color-blue-400) 6%, #ffffff);
  --filter-trigger-bg-hover:  color-mix(in srgb, var(--color-blue-400) 12%, #ffffff);

  /* Search field (§9) — "the same field as a pill (radius 999) with a 14px
     ink-400 magnifier". One shared component (`.ins-pol-search`), so these five
     tokens restyle every search box in the app at once (Policies, Companies,
     Census, Claims, Task Manager, Contact Center rail, quotes, HR pages…). */
  --ins-pol-search-radius:            999px;
  --ins-pol-search-height:            44px;
  --ins-pol-search-bg:                var(--color-cream-50);
  --ins-pol-search-border:            var(--color-sand-400);
  --ins-pol-search-icon-color:        var(--color-ink-400);
  --ins-pol-search-placeholder-color: var(--color-ink-400);
  --ins-pol-search-input-color:       var(--color-ink-900);

  /* Sub-screen tabs (§7) — `<FilterTabs variant="underline">`: sand-300
     full-width divider, ink-400 Medium inactive labels, navy-700 Bold active
     label with a 2px navy-700 underline, 26px between tabs and 12px bottom
     padding so the underline hugs the label instead of a wide padded block.
     Shared by the Task Manager list + both quote-detail tab rows. */
  --tabs-underline-divider:           var(--color-sand-300);
  --tabs-underline-gap:               26px;
  --tabs-underline-seg-padding:       8px 0 12px;
  --tabs-underline-seg-color:         var(--color-ink-400);
  --tabs-underline-seg-weight:        500;
  --tabs-underline-seg-active-color:  var(--color-navy-700);
  --tabs-underline-seg-active-weight: 700;
  --tabs-underline-active-color:      var(--color-navy-700);
  --tabs-underline-count-color:       var(--color-ink-400);
  --tabs-underline-count-size:        11.5px;
  /* Explicit colour replaces the base's opacity dimming (the pill variant still
     needs that trick, so it stays as the un-overridden default). */
  --tabs-underline-count-opacity:     1;

  /* Filter pills — white / sand-bordered inactive, navy active */
  --ins-pol-seg-bg:       #ffffff;
  --ins-pol-seg-color:    var(--color-navy-700);
  --ins-pol-seg-border:   1.2px solid var(--color-sand-400);
  --ins-pol-seg-bg-hover: var(--color-sand-200);

  /* Pagination (secondary buttons) */
  --ins-pol-pager-border:   var(--color-sand-400);
  --ins-pol-pager-color:    var(--color-slate-700);
  --ins-pol-pager-bg-hover: var(--color-cream-50);

  /* ── Sidebar (§4) — cream rail, NO vertical border ── */
  --sidebar-bg:                var(--color-cream-50);
  --sidebar-width:             240px;
  --sidebar-border-right:       none;
  --sidebar-nav-divider-border: 1px solid var(--color-sand-300);
  --sidebar-padding:            24px 0;

  --sidebar-logo-img-filter: none;
  --sidebar-logo-text-color: var(--color-navy-700);

  --sidebar-item-padding:      10px 10px 10px 12px;
  --sidebar-item-margin:       0 12px;
  --sidebar-item-margin-x:     12px;
  --sidebar-item-radius:       12px;
  --sidebar-item-font-size:    14px;
  --sidebar-item-gap:          10px;

  --sidebar-item-color:        var(--color-slate-700);
  --sidebar-item-color-active: #ffffff;
  --sidebar-item-bg-active:    var(--color-navy-700);
  --sidebar-item-bg-hover:     var(--color-sand-200);

  --sidebar-icon-color:        var(--color-ink-400);
  --sidebar-icon-color-active: #ffffff;

  --sidebar-subitem-padding:        8px 12px 8px 40px;
  --sidebar-subitem-font-size:      13px;
  --sidebar-subitem-color:          var(--color-ink-400);
  /* Softer than --sidebar-item-bg-active (solid navy-700): the pale blue-50
     tint used elsewhere for status-tint surfaces (--cc-blue-tint-bg,
     --pw-badge-bg, --emp-claim-badge-preapproval-bg), with navy-700 text for
     contrast. Keeps the sub-item a subtle "active within this section"
     marker instead of matching the parent's strong "you're in this section"
     fill 1:1 — the two were previously the identical navy and visually
     merged into one block. */
  --sidebar-subitem-color-active:   var(--color-navy-700);
  --sidebar-subitem-bg-active:      var(--color-blue-50);

  --sidebar-badge-bg:    var(--color-coral-500);
  --sidebar-badge-color: #ffffff;

  /* Footer: white profile card, radius 14, soft shadow, no border */
  --sidebar-footer-border:    none;
  --sidebar-footer-bg:        #ffffff;
  --sidebar-footer-radius:    14px;
  --sidebar-footer-shadow:    0 2px 10px rgba(28, 26, 23, 0.05);
  --sidebar-footer-margin:    8px 12px 12px;
  --sidebar-footer-color:     var(--color-slate-700);
  --sidebar-footer-sub-color: var(--color-ink-400);

  --sidebar-avatar-bg:    var(--color-blue-400);
  --sidebar-avatar-color: #ffffff;

  /* Legacy .page-header — keep its own hairline (decoupled from the rail border) */
  --page-header-border: 1px solid var(--color-sand-300);

  /* Contact Center (.cc-* in global.css) — was a pre-Charte styling island
     with every color hardcoded to cool greys/blues; retinted to the warm
     palette here so property-finder/backoffice (no override) keep the old
     look untouched via global.css's own hex fallbacks. */
  --cc-border-color:              var(--color-sand-300);
  --cc-icon-border-color:         var(--color-sand-400);
  --cc-input-border-color:        var(--color-sand-400);
  --cc-hover-bg:                  color-mix(in srgb, var(--color-sand-200) 70%, white);
  /* Conversation canvas = the page surface, so a white bubble reads as a card
     on it (§8) and needs no border. */
  --cc-surface-tint-bg:           var(--color-cream-50);
  --cc-blue-tint-bg:              var(--color-blue-50);
  --cc-attachment-pending-border: var(--color-blue-200);
  --cc-muted-color:               var(--color-ink-400);
  --cc-text-color:                var(--color-ink-900);
  /* §2/§12 tinted surface: coral-500 @14% fill, same token at 100% for the
     label. Both halves are declared here because global.css's `.cc-thread-new`
     now tokenises the label too — these values are exactly what it resolved to
     before, so nothing about Heale changes. */
  --cc-thread-new-bg:             color-mix(in srgb, var(--color-coral-500) 14%, transparent);
  --cc-thread-new-color:          var(--color-coral-500);

  /* Charte 2026 — phase 6. §6: disabled is 45% opacity, never a grey swap. */
  --cc-disabled-opacity:          .45;

  /* Icon controls (§13's 32px square close-button shape) + surfaces that were
     hardcoded white; they follow the card fill so a card restyle moves them. */
  --cc-icon-btn-size:             32px;
  --cc-icon-btn-radius:           10px;
  --cc-icon-btn-bg:               var(--hr-dash-recent-card-bg);
  --cc-chip-bg:                   var(--hr-dash-recent-card-bg);
  --cc-composer-bg:               var(--hr-dash-recent-card-bg);
  /* Idle send button: sand-200 (§1 control fill), not a cool grey. */
  --cc-send-idle-bg:              var(--color-sand-200);
  /* §6 primary blue with a white glyph — the value `.cc-send-btn--active` had
     inline before it was tokenised, restated so Heale keeps mapping every --cc-*
     token it reads (its own US-CC26.2.2 contract). */
  --cc-send-active-bg:            var(--color-blue-400);
  /* The `white` keyword, not a hex: this block is contract-tested to contain no
     hex value (US-CC26.2.4). */
  --cc-send-active-fg:            white;

  /* §3 titles are ink-900; navy-700 stays the identifier/selection tone. */
  --cc-title-color:               var(--color-ink-900);
  --cc-detail-title-size:         16px;
  --cc-detail-sub-size:           12px;

  /* Thread rail rows (scoped to `.cc-rail` in global.css — the base `.mf-*`
     rules are shared with the census rail and are never touched). */
  --cc-rail-list-gap:             2px;
  --cc-row-min-height:            56px;
  --cc-row-padding:               10px 12px;
  --cc-row-gap:                   10px;
  --cc-row-radius:                12px;
  --cc-row-name-size:             13.5px;
  --cc-row-name-weight:           700;
  --cc-row-sub-size:              12px;
  --cc-row-sub-gap:               2px;
  --cc-row-name-color:            var(--color-ink-900);
  /* §6: the fill carries the selected state — no outline on top of it. */
  --cc-row-active-shadow:         none;
  /* §6: navy-700 is the SELECTED-control tone. Kept distinct from the
     blue-400 "mine" bubble so selection and authorship never read alike. */
  --cc-row-active-bg:             color-mix(in srgb, var(--color-navy-700) 10%, transparent);
  --cc-avatar-size:               32px;
  --cc-avatar-radius:             50%;
  /* "New thread" — borderless tinted ghost row, blue-400 (§6 primary action). */
  --cc-add-justify:               flex-start;
  --cc-add-min-height:            44px;
  --cc-add-border:                none;
  --cc-add-bg:                    color-mix(in srgb, var(--color-blue-400) 10%, transparent);
  --cc-add-bg-hover:              color-mix(in srgb, var(--color-blue-400) 16%, transparent);
  --cc-add-color:                 var(--color-blue-400);

  /* Message bubbles — hue is the ONLY difference between the two sides. */
  --cc-msg-radius:                16px;
  --cc-msg-font-size:             13.5px;
  --cc-msg-time-size:             11px;
  --cc-msg-sender-color:          var(--color-navy-700);
  --cc-msg-mine-bg:               color-mix(in srgb, var(--color-blue-400) 12%, transparent);
  --cc-msg-theirs-bg:             var(--hr-dash-recent-card-bg);
  --cc-msg-theirs-border:         transparent;
  --cc-msg-shadow:                var(--hr-dash-recent-card-shadow);

  /* <ModuleDisabledState> — shared by Contact Center/Claims/Chatbot gates */
  --module-disabled-muted-color: var(--color-ink-400);
  --module-disabled-title-color: var(--color-ink-900);

  /* Insurer Policy Wizard (.pw-* in global.css) — decision D18, the one insurer
     view the Charte rollout skipped. Same shape as the Contact Center block
     above: global.css keeps the pre-Charte hex as each token's base fallback, so
     property-finder/backoffice are untouched, and Heale retints the whole board
     from here. Roles are documented at the .pw-* block in global.css. */
  --pw-panel-bg:          #ffffff;
  --pw-panel-border:      var(--color-sand-400);
  --pw-divider:           var(--color-sand-300);
  --pw-title-color:       var(--color-ink-900);
  --pw-value-color:       var(--color-ink-900);
  --pw-muted-color:       var(--color-ink-400);
  --pw-placeholder-color: var(--color-ink-400);
  --pw-notice-color:      var(--color-ink-400);
  --pw-control-bg:        #ffffff;
  --pw-control-border:    var(--color-sand-400);
  --pw-control-color:     var(--color-slate-700);
  --pw-control-bg-hover:  var(--color-sand-200);
  --pw-card-bg:           #ffffff;
  --pw-card-border:       var(--color-sand-400);
  --pw-card-bg-disabled:  var(--color-cream-50);
  --pw-badge-bg:          var(--color-blue-50);
  --pw-badge-color:       var(--color-navy-700);
  --pw-over-bg:           color-mix(in srgb, var(--color-blue-400) 6%, white);
  --pw-warning-color:     var(--color-gold-500);
  --pw-danger-color:      var(--color-rust-600);
  --pw-danger-bg:         color-mix(in srgb, var(--color-rust-600) 10%, white);

  /* <OfferPoliciesTable>'s "Next step" cell — metadata tone for "nothing to do
     yet", body tone for the read-only rule so it reads as a statement of fact. */
  --offer-pol-note-color:        var(--color-ink-400);
  --offer-pol-note-locked-color: var(--color-ink-700);

  /* HR dashboard — the coverage band + rail surface (`.hr-dash-grid`,
     `.hr-dash-band*`, `.hr-dash-ring*`, `.hr-dash-row*`, `.hr-dash-broker*` in
     global.css), and the only surface these tokens reach. Replaces the retired
     marketing-hero and dark-quick-action token families, whose rules are gone
     from global.css too.

     §8: no border on the band — the warm shadow carries it, 18px radius.
     §1: the band is navy-700 with the insurer panel in blue-400, so the two
     primaries sit side by side and the CTA stays blue-400 (never coral). */
  --hr-dash-grid-gap:                20px;
  --hr-dash-col-gap:                 18px;

  --hr-dash-band-bg:                 var(--color-navy-700);
  --hr-dash-band-radius:             18px;
  --hr-dash-band-radius-mobile:      14px;
  --hr-dash-band-shadow:             0 2px 10px rgba(28, 26, 23, 0.05);
  --hr-dash-band-padding:            26px 28px;
  --hr-dash-band-gap:                22px;
  --hr-dash-band-min-height:         168px;
  --hr-dash-band-title-size:         21px;
  --hr-dash-band-title-tracking:     -0.02em;
  --hr-dash-band-title-color:        #ffffff;
  --hr-dash-band-text-color:         color-mix(in srgb, #ffffff 72%, transparent);
  --hr-dash-band-cta-bg:             var(--color-blue-400);
  --hr-dash-band-cta-bg-hover:       var(--color-blue-600);
  --hr-dash-band-cta-color:          #ffffff;
  --hr-dash-band-cta-radius:         999px;
  --hr-dash-band-cta-padding:        11px 22px;
  --hr-dash-band-aside-bg:           var(--color-blue-400);
  --hr-dash-band-aside-width:        188px;
  --hr-dash-band-aside-padding:      22px;
  --hr-dash-band-logo-max-height:    56px;
  --hr-dash-band-insurer-color:      #ffffff;
  /* The loading twin keeps the band's geometry but flips to the card surface, so
     the dark-on-light shimmer bars stay legible. */
  --hr-dash-band-loading-bg:         var(--color-cream-100);

  --hr-dash-ring-size:               84px;
  --hr-dash-ring-width:              5;
  --hr-dash-ring-track-color:        color-mix(in srgb, #ffffff 20%, transparent);
  --hr-dash-ring-bar-color:          #ffffff;
  --hr-dash-ring-label-size:         19px;
  --hr-dash-ring-label-color:        #ffffff;

  --hr-dash-row-padding:             13px 20px;
  --hr-dash-row-border:              var(--color-sand-300);
  /* §2: the urgent row rule is the rejected token at 12%, not a flat pink. */
  --hr-dash-row-urgent-bg:           color-mix(in srgb, var(--color-rust-600) 12%, transparent);
  --hr-dash-row-title-color:         var(--color-ink-900);
  --hr-dash-row-sub-color:           var(--color-ink-400);
  --hr-dash-avatar-size:             34px;
  --hr-dash-avatar-bg:               color-mix(in srgb, var(--color-navy-700) 12%, transparent);
  --hr-dash-avatar-color:            var(--color-navy-700);

  --hr-dash-broker-media-height:     128px;
  --hr-dash-broker-media-bg:         linear-gradient(135deg, var(--color-blue-50) 0%, var(--color-cream-100) 100%);
  --hr-dash-broker-caption-bg:       #ffffff;
  --hr-dash-broker-caption-color:    var(--color-navy-700);
  --hr-dash-broker-body-padding:     18px 20px 20px;
  --hr-dash-broker-title-color:      var(--color-ink-900);
  --hr-dash-broker-text-color:       var(--color-ink-700);

  /* Employee dashboard (.emp-dash-* in global.css). The member card is the one
     gradient surface in the app: the Charte palette has no violet, so the
     mockup's blue->violet sweep is rendered blue-400 -> navy-700 (both §1
     tokens) rather than introducing a 24th colour. */
  --emp-dash-member-gradient:   linear-gradient(135deg, var(--color-blue-400) 0%, var(--color-navy-700) 100%);
  --emp-dash-member-color:      #ffffff;
  --emp-dash-member-shadow:     0 2px 10px rgba(28, 26, 23, 0.05);
  --emp-dash-row-border:        var(--color-sand-300);
  --emp-dash-title-color:       var(--color-ink-900);
  --emp-dash-body-color:        var(--color-ink-700);
  --emp-dash-muted-color:       var(--color-ink-400);

  /* Shared `.avatar-circle` primitive (employee dashboard family rows +
     the census members rail). */
  --avatar-circle-brand-bg:    color-mix(in srgb, var(--color-navy-700) 12%, transparent);
  --avatar-circle-brand-color: var(--color-navy-700);
  --avatar-circle-muted-bg:    var(--color-sand-200);
  --avatar-circle-muted-color: var(--color-ink-700);

  /* Census MEMBERS rail (.mf-rail) — Charte restyle: borderless cream panel,
     tinted selection, blue ghost add-action. */
  --mf-rail-bg:            var(--color-cream-50);
  --mf-rail-radius:        14px;
  --mf-rail-active-bg:     color-mix(in srgb, var(--color-blue-400) 10%, transparent);
  --mf-rail-name-color:    var(--color-ink-900);
  --mf-rail-sub-color:     var(--color-ink-400);
  --mf-rail-add-bg:        color-mix(in srgb, var(--color-blue-400) 10%, transparent);
  --mf-rail-add-bg-hover:  color-mix(in srgb, var(--color-blue-400) 16%, transparent);
  --mf-rail-add-color:     var(--color-blue-400);

  /* Employee claims / pre-approvals list (.emp-claim-* / .emp-empty* in
     global.css). This surface was never retinted during the Charte rollout, so
     every cell was still rendering on global.css's pre-Charte cool-grey
     fallbacks (#18181b / #374151 / #9ca3af / #cbd5e1) while its siblings — the
     HR census list and the offer/policies tables — had moved to the warm
     palette. Mapping the tokens here is the whole fix; no rule in global.css
     needed a colour change. */
  --emp-claim-ref-color:              var(--color-navy-700);   /* §10 identifiers are navy */
  --emp-claim-treatment-color:        var(--color-ink-700);
  --emp-claim-cell-color:             var(--color-ink-700);
  --emp-claim-amount-color:           var(--color-ink-900);
  --emp-claim-amount-currency-color:  var(--color-ink-400);
  --emp-claim-updated-color:          var(--color-ink-400);
  --emp-claim-chevron-color:          var(--color-ink-400);
  --emp-claim-badge-bg:               var(--color-sand-200);
  --emp-claim-badge-color:            var(--color-ink-700);
  /* The pre-approval tag was violet (#ede9fe/#6d28d9) — off-palette entirely;
     the Charte's own accent tint for "related/secondary" is blue-50 + navy. */
  --emp-claim-badge-preapproval-bg:    var(--color-blue-50);
  --emp-claim-badge-preapproval-color: var(--color-navy-700);

  /* Welcome-state cards (.emp-empty*) */
  --emp-empty-title-color:       var(--color-ink-900);
  --emp-empty-desc-color:        var(--color-ink-700);
  --emp-empty-option-bg:         var(--color-cream-50);
  --emp-empty-option-border:     transparent;
  --emp-empty-option-title-color: var(--color-ink-900);
  --emp-empty-option-desc-color: var(--color-ink-400);

  /* Quote request overview (sketch 10) — an unfinished category is "pending"
     (§12 gold-500), never an error: nothing is broken, something is simply not
     filled in yet. Same tone family as `--mf-warn-*`, which is why neither
     reaches for the unmapped `--brand-warning` (that falls back to the retired
     warning hex, §1). */
  --qro-row-incomplete-rule: var(--color-gold-500);
  --qro-row-incomplete-bg:   color-mix(in srgb, var(--color-gold-500) 12%, white);

  /* Complete but not validated — informational, so §12's "open" blue-400 rather
     than the gold above: the category is finished, it is simply awaiting the
     one confirmation the wizard's Validate step writes. */
  --qro-row-unvalidated-rule: var(--color-blue-400);
  --qro-row-unvalidated-bg:   color-mix(in srgb, var(--color-blue-400) 7%, white);
  --qro-pill-unvalidated-color: var(--color-blue-400);
  --qro-pill-unvalidated-bg:    color-mix(in srgb, var(--color-blue-400) 14%, transparent);


  /* The verdict banner's badge: the state token fills the circle, so the glyph
     inside it is the only white thing on the surface. */
  --qro-hero-badge-color: #ffffff;

  /* "What insurers will see" is body copy (§3 ink-700), not a card title — its
     own token so restyling headings never repaints the disclosure promise. */
  --qro-see-text-color: var(--color-ink-700);

  /* Broadcast rail. The insurer avatar is an identifier, so it wears navy-700
     (§1 "identifiers"), not the blue-400 reserved for actions. */
  --qro-avatar-bg:    var(--color-navy-700);
  --qro-avatar-color: #ffffff;

  /* Post-submit status band (`<RequestStatusBand>`): a start date, a currency,
     an offer count. Those are §3 VALUES, so ink-900 — not the navy
     `--qro-window-value`, which is a headline figure. Its own token for the same
     reason `--doclink-static-color` has one: the shared title token's consumer
     set is signed off and must not grow. */
  --qrb-fact-value-color: var(--color-ink-900);

  /* The response-window inset — an informational inner cell, so blue-400 at a
     surface strength rather than a §2 status tint (it states a fact, it is not
     a verdict). */
  --qro-window-bg: color-mix(in srgb, var(--color-blue-400) 8%, transparent);

  /* A licence with no scan behind it — a value, so §3's ink-900 "titles and
     values" tone, on a token of its own (the shared title token's consumer set
     is signed off and must not grow). */
  --doclink-static-color: var(--color-ink-900);

  /* "Continue anyway" — the acknowledge concession on a failing final check,
     wherever it appears (the check row AND the readiness hero, which offers the
     same pair of ways out). It IS a button, but the §6 "unselected control"
     tone (white fill, sand-400 hairline, slate-700 label) rather than the navy
     secondary beside it, so accepting a failing check never looks more inviting
     than fixing it. */
  --ack-btn-border:   var(--color-sand-400);
  --ack-btn-color:    var(--color-slate-700);
  --ack-btn-bg-hover: var(--color-sand-200);

  /* "Save as draft" — the rail's fallback. Same geometry as the send CTA above
     it so the block reads as one column of actions, in a plain GREY rather than
     the blue reserved for the action that actually sends.
     A slate mix, not sand: the §1 warm neutrals are near-white against a white
     card, so a sand fill read as a hole in the surface rather than as a filled
     control. slate-700 is the palette's only cool neutral, so the ramp is mixed
     from it — no new hex, and the tone is unmistakably grey. */
  --qro-draft-bg:       color-mix(in srgb, var(--color-slate-700) 12%, white);
  --qro-draft-color:    var(--color-slate-700);
  --qro-draft-bg-hover: color-mix(in srgb, var(--color-slate-700) 18%, white);

  /* ── The insurer decision screen's hero band (`.iqd-hero`) ──
     The one dark surface in the quotes area, so its text tones cannot come from
     the page's ink scale — ink-900 on navy is unreadable. navy-700 is §1's
     "brand / identifiers" primary, and the muted role on it is blue-200 (the
     palette's own pale blue), never a white at reduced opacity, which would
     drift with the fill. White is spelled literally for the same reason
     `--qro-hero-badge-color` and `--qro-avatar-color` are: the palette has no
     white primitive, and inventing one for three tokens would enter the 23-token
     Charte set through the back door. */
  --iqd-hero-bg:          var(--color-navy-700);
  --iqd-hero-title-color: #ffffff;
  --iqd-hero-value-color: #ffffff;
  --iqd-hero-label-color: var(--color-blue-200);
  /* The response countdown chip (`<RespondByChip>`), on BOTH its surfaces —
     the navy hero and the offer wizard's cream header. Urgent = coral, §1's
     brand accent for "action needed": a STATE, never a CTA; the chip is not
     clickable on either surface.

     On navy the neutral tone is a white wash of the fill it sits on, so it
     reads as an inset rather than a control; on the light header it is the §2
     tinted surface of navy-700, the same shape every other status pill wears. */
  --respond-chip-bg:           color-mix(in srgb, var(--color-navy-700) 10%, transparent);
  --respond-chip-color:        var(--color-navy-700);
  --respond-chip-urgent-bg:    color-mix(in srgb, var(--color-coral-500) 14%, transparent);
  --respond-chip-urgent-color: var(--color-rust-600);
  --respond-chip-navy-bg:           color-mix(in srgb, #ffffff 14%, transparent);
  --respond-chip-navy-color:        #ffffff;
  --respond-chip-navy-urgent-bg:    color-mix(in srgb, var(--color-coral-500) 24%, transparent);
  --respond-chip-navy-urgent-color: var(--color-coral-300);

  /* The selected group row (§12: blue-400 left rule + a 6% wash). Deliberately
     the FAINT 6%, not `--qw-mem-row-selected-bg`'s blue-50: this list holds one
     focused row at a time, which is the Task Manager case §12 tunes that wash
     for, not the repeatedly-toggled checkbox list blue-50 exists for. */
  --iqd-cat-row-selected-rule: var(--color-blue-400);
  --iqd-cat-row-selected-bg:   color-mix(in srgb, var(--color-blue-400) 6%, transparent);

  /* ── The offer wizard's Build step (`.obw-*`) ──
     Cover / decline is a BINARY ANSWER, not a verdict. Covered is green-500
     (§12 "covered", the same green the coverage badge wears); declined is
     ink-400, §12's neutral — deliberately NOT rust-600, which this app spends
     on a rejection. An insurer who does not cover optical has answered the
     question, not failed it. */
  --obw-control-bg:            #ffffff;
  --obw-answer-border:         var(--color-sand-400);
  --obw-cover-color:           var(--color-ink-400);
  --obw-cover-covered-bg:      var(--color-green-500);
  --obw-cover-covered-color:   #ffffff;
  --obw-cover-declined-bg:     var(--color-ink-400);
  --obw-cover-declined-color:  #ffffff;

  /* An outstanding row gets §12's 3px coral rule AND NOTHING ELSE — the cream
     wash that used to sit under every requested row was, at forty benefits,
     most of the table and therefore signalled nothing. The two `--obw-req-*`
     tokens outlived the "Required" pill they were minted for (the priority
     column replaced it); the recap's missing-document chip still reads them. */
  --obw-req-bg:            color-mix(in srgb, var(--color-coral-500) 13%, transparent);
  --obw-req-color:         var(--color-rust-600);
  --obw-outstanding-rule:  var(--color-coral-500);

  /* The unit WE render beside the numeric answer, so the insurer never types it. */
  --obw-unit-color:        var(--color-ink-400);

  /* A sentinel ("Not applicable", "Other") is a legitimate answer that sits
     BELOW the primary one in weight. Selected, it used to take
     `--ins-pol-seg-active-bg` — solid navy-700 — which made it heavier than the
     blue-400 primary action elsewhere on the page. It is an outline chip on
     sand-400 now, and selection tints it to sand-200 instead of inverting it. */
  --obw-sentinel-border:          var(--color-sand-400);
  --obw-sentinel-color:           var(--color-ink-400);
  --obw-sentinel-selected-bg:     var(--color-sand-200);
  --obw-sentinel-selected-border: var(--color-sand-400);
  --obw-sentinel-selected-color:  var(--color-ink-900);

  --obw-ask-color:         var(--color-navy-700);
  --obw-ask-absent-color:  var(--color-ink-400);
  --obw-save-ok-color:     var(--color-green-500);
  --obw-save-error-color:  var(--color-rust-600);

  /* ── The live score: priority, verdict, and the panel that reads them ──
     Every chip below is a §2 tinted surface — the tone at 12–16% for the fill,
     the SAME tone at full strength for the label. Priority is the company's
     requirement, so a must-have wears navy-700 (§1 "identifiers, selected
     control"), not a semantic colour: it is not a status.

     The verdict vocabulary has no "below". Ranking two differing terms needs a
     per-benefit direction of generosity — lower is better for a co-payment,
     worse for an annual limit — and nothing in the schema carries one, so a
     difference gets gold-500 (§12 "pending / waiting", i.e. needs a human) and
     never a green or a red implying which side won. A DECLINED must-have is
     different: no ranking is needed to know the offer is short, so it takes the
     rust-600 the app spends on a refusal. */
  --obw-priority-must-bg:      color-mix(in srgb, var(--color-navy-700) 10%, transparent);
  --obw-priority-must-color:   var(--color-navy-700);
  --obw-priority-nice-bg:      var(--color-sand-200);
  --obw-priority-nice-color:   var(--color-ink-700);

  --obw-verdict-meets-bg:      color-mix(in srgb, var(--color-green-500) 14%, transparent);
  --obw-verdict-meets-color:   var(--color-green-500);
  --obw-verdict-differs-bg:    color-mix(in srgb, var(--color-gold-500) 16%, transparent);
  --obw-verdict-differs-color: var(--color-gold-500);
  --obw-verdict-blocking-bg:   color-mix(in srgb, var(--color-rust-600) 12%, transparent);
  --obw-verdict-blocking-color: var(--color-rust-600);
  --obw-verdict-bonus-bg:      color-mix(in srgb, var(--color-blue-400) 12%, transparent);
  --obw-verdict-bonus-color:   var(--color-blue-400);
  --obw-verdict-neutral-bg:    var(--color-sand-200);
  --obw-verdict-neutral-color: var(--color-ink-400);

  /* Row tone is a WASH, deliberately fainter than the chip that names it — the
     chip is the statement, the row tint only helps you find it. */
  --obw-row-blocking-bg:  color-mix(in srgb, var(--color-rust-600) 5%, transparent);
  --obw-row-differs-bg:   color-mix(in srgb, var(--color-gold-500) 7%, transparent);

  --obw-tab-dot-gap:   var(--color-coral-500);
  --obw-tab-dot-done:  var(--color-green-500);
  --obw-tab-dot-none:  var(--color-sand-400);

  --obw-fact-bg:       var(--color-cream-50);
  --obw-note-rule:     var(--color-sand-400);
  --obw-donut-track:   var(--color-sand-300);

  /* Login right panel */
  --login-right-bg:              rgb(220, 231, 253);
  /* Corner decoration. Was a hardcoded <img> inside <AuthBrandPanel>, so every
     other brand inherited it; Heale now opts in through the token instead.
     Reproduces the <img> exactly: the asset is square (547x547), so the img's
     `object-fit: contain` inside a 500x500 box and `background-size: 500px` both
     render 500x500, and the position tokens already default to the img's own
     `bottom: -220px; right: -80px`. */
  --login-right-decoration-image: url('/themes/heale/heale_icon.svg');
  --login-right-heading-color:   rgb(49, 104, 242);
  --login-right-heading-weight:  600;
  --login-right-heading-size:    40px;
}

/* ── `.fields-on-tint` — the field edge Heale needs on a tinted surface ────────
   The contract above runs the field BORDERLESS (`--field-border: transparent`)
   because the cream-50 fill IS the boundary — true while the control sits on a
   white card. On an inner cream surface (`--modal-total-bg`, a cream metadata
   cell, a tinted row strip) fill and backdrop are the same tone, the box
   disappears and a filled value reads as static label text, i.e. no affordance
   at all (§9). A container in that situation carries `.fields-on-tint`, which
   re-points both edge tokens at `--field-hairline` — the same visible sand-400
   1px this field family already draws around its dropdown panels and date
   roller, so no new colour enters the palette.

   It lives HERE and not in `global.css`: that file may only read the contract,
   never declare it, or an unmapped brand would stop rendering unchanged. See
   "THE FIELD CONTRACT" there for which brands opt in and why the other four do
   not. No `var()` fallback is needed — `--field-hairline` is declared
   unconditionally above, in the same file. Control layer only: the surface
   itself stays borderless (§8). */
.fields-on-tint {
  --field-border:       var(--field-hairline);
  --field-hover-border: var(--field-hairline);
}
