/* ============================================================
   PBC DESIGN TOKENS  —  single source of truth
   ------------------------------------------------------------
   Phase 1 of the UI redesign. This file DEFINES VALUES ONLY.
   It contains no component rules and changes nothing on its own:
   loading it is visually inert until a stylesheet consumes a var.

   Brand: metallic navy · steel · silver. No warm accent (owner, 2026-07-22).
   Fonts: Manrope (headings) + Inter (body).
   Structure follows the references collected in
   PBC Mockup/Inspiration/ (light-first, airy, cards, colour
   used only to carry meaning).

   USAGE
     var(--pbc-brand-600)      not  #2C5F8C
     var(--pbc-space-4)        not  16px
     var(--pbc-radius-card)    not  16px

   ✅ NAMESPACE OVERLAP — RESOLVED in K-3 (2026-07-25).
     pbc-portal.css used to declare its own competing tokens on :root
     (colliding on --pbc-bg and --pbc-surface). Its :root block is gone; it
     now reads from this file. So this really is the single source of truth.

     ⚠ WHAT THAT MEANS NOW: the three CUSTOMER-FACING layouts (customer
     portal, invite, and the public /shared/{token} view link) render from
     these values. Retuning a surface, ink or border token changes the LIVE
     customer portal as well as the staff app — check both before shipping.
     Those layouts load this file ahead of pbc-portal.css; if that link is
     ever removed the portal renders with no colour at all.

   RULES
     - Never hardcode a hex, px spacing, or radius in new CSS.
     - Never redefine a --pbc-* token outside this file, except
       inside the dark-mode block below.
     - Additive only: add tokens, don't repurpose existing ones.
       Renaming a token is a breaking change for every consumer.
   ============================================================ */

:root{

  /* ==========================================================
     1. BRAND RAMP — metallic navy → steel → silver
     600 is the primary brand colour (buttons, links, active nav).
     ========================================================== */
  --pbc-brand-950:#0F2236;   /* deepest navy — sidebar foot        */
  --pbc-brand-900:#16293E;   /* navy — dark surfaces               */
  --pbc-brand-800:#1C3A5A;   /* headings, sidebar head             */
  --pbc-brand-700:#21496E;   /* primary hover                      */
  --pbc-brand-600:#2C5F8C;   /* PRIMARY BRAND                      */
  --pbc-brand-500:#5E84AC;   /* steel — secondary accents          */
  --pbc-brand-300:#9FB7D1;   /* light steel — muted on dark        */
  --pbc-brand-200:#C6CFD9;   /* silver — dividers on dark          */
  --pbc-brand-100:#EAF1F8;   /* tint — selected row, icon chip bg  */

  /* Brand colour used as TEXT or a 1px accent ON a surface (active tab,
     link hover, current-step marker, modal icon). brand-600 is a mid-navy:
     correct on white, but only 2.2:1 on the dark surface. This token flips
     in dark mode so brand-coloured text stays legible. Use it for ink;
     use brand-600 for fills that carry white text. */
  --pbc-brand-accent:var(--pbc-brand-600);

  /* NO WARM ACCENT. Owner chose "option G" (2026-07-22): the gold family
     (#E0A82E / #FBEFD6) is removed entirely and the brand carries
     selection + highlight on its own.
       highlight / selected row  -> --pbc-surface-active (brand tint)
       highlight text or border  -> --pbc-brand-accent
       "needs attention"         -> the warning pill (semantic, not decorative)

     ⚠ TWO RULES THIS CHOICE MAKES LOAD-BEARING:
     1. NEVER put brand-500 steel (#5E84AC) as TEXT on the navy sidebar —
        it is 2.98:1, unreadable. Sidebar text uses --pbc-sidebar-ink /
        --pbc-sidebar-ink-strong, which are 7.8:1 and 10.2:1.
     2. NEVER fill a control with brand-500 steel and put white on it —
        that is 3.91:1, below AA. Solid fills use --pbc-brand-600 (6.73:1). */

  /* ==========================================================
     2. SEMANTIC — colour ONLY ever carries meaning.
     Each has: 600 text · 500 mark · 100 tint · border.
     ========================================================== */
  --pbc-success-600:#256F53;
  --pbc-success-500:#2F8F6B;
  --pbc-success-100:#E4F2EC;
  --pbc-success-border:#B9DBCC;

  /* Deepened from #E0A82E/#FBEFD6, which the owner rejected (2026-07-22).
     Warning CANNOT become blue/steel — "In progress" would then be
     indistinguishable from "New". Amber is also the universal caution
     convention. So this stays amber, just less acidic: text-on-tint
     improves 4.8 -> 5.4. This is the only warm colour left in the system. */
  --pbc-warning-600:#7F5A14;
  --pbc-warning-500:#C08A2B;
  --pbc-warning-100:#F7EEDC;
  --pbc-warning-border:#E4C88C;

  /* Owner, 2026-07-25: "the red is currently looking red orange, which is
     wrong — it should be a brighter red." Both retuned to a PURE red with the
     orange cast taken out. Re-measured, and every ratio held or improved:
       danger-600 #9C382F -> #B01818   on white 6.95 -> 7.02 · on its own tint 5.72
       danger-500 #C0473C -> #D92B2B   on white 4.99 -> 4.85 (still AA for text,
                                       and well above the 3:1 bar for graphics)
     500 is the MARK colour (icons, dots, fills, count badges); 600 is INK. */
  --pbc-danger-600:#B01818;
  /* ⚠ OWNER-SPECIFIED EXACT VALUE (2026-07-29): #FA003F.
     Supersedes the previous owner value #FF0800 (2026-07-25), which read as a
     red-orange; this one carries a crimson/pink cast instead.
     It is a light red — 4.09:1 on white (up slightly from #FF0800's 3.97) — so
     it is usable as a MARK (icons, dots, borders: graphics need 3:1) and for
     LARGE text (the 32px dashboard number needs 3:1), but NOT under white
     labels and NOT for small red text, both of which need 4.5:1. Those two
     cases therefore use --pbc-danger-600 instead; see the notes on
     .pbc-btn--danger, .pbc-count--danger and .pbc-req in pbc-components.css.
     Do not "simplify" by pointing those back at 500 — it drops them below AA. */
  --pbc-danger-500:#FA003F;
  --pbc-danger-700:#8A1212;   /* danger-button hover, since 600 is now its base */
  --pbc-danger-100:#F6E4E2;
  --pbc-danger-border:#E8BDB8;
  /* ⚠ OWNER-SPECIFIED MATCH (2026-08-02): the dashboard's Overdue and Critical
     tiles must be "exactly the same red" as the Critical / overdue badges in the
     Cases Needing Attention list DIRECTLY BELOW THEM on the same screen. Those
     badges are still legacy Bootstrap `.badge.bg-danger` (from
     components/priority-badge + due-date-badge, unconverted), and nothing in the
     PBC layer restyles them — so their red is Bootstrap's own
     `--bs-danger-rgb: 220,53,69`. This token pins that value so the component
     layer stays free of hardcoded hex.
     ⚠ It is deliberately NOT --pbc-danger-500: that token is the owner's exact
     #FA003F (2026-07-29) and also paints the chat unread count, the calendar
     now-indicator and invalid-field borders, none of which were in scope.
     Measured, and it IMPROVES on 500 in light: 4.53:1 on the white tile (vs
     4.09) and 3.26:1 on the dark tile (vs 3.62) — both above the 3:1 bar the
     32px number (large text) and the icon (graphic) need, so it needs no
     dark-mode override, exactly like --pbc-danger-500.
     ⚠ When those two badges are converted at K-5, retire this token and point
     the badges and the tiles at ONE value — do not let them drift apart again. */
  --pbc-danger-alert:#DC3545;

  --pbc-info-600:#21496E;
  --pbc-info-500:#2C5F8C;
  --pbc-info-100:#EAF1F8;
  --pbc-info-border:#C3D7E9;

  --pbc-neutral-600:#5B6A7B;   /* on hold / inactive / draft — AA  */
  --pbc-neutral-500:#8492A4;
  --pbc-neutral-100:#F4F7FB;
  --pbc-neutral-border:#DEE6EF;

  /* ==========================================================
     3. SURFACES — light mode is the default and the priority.
     ========================================================== */
  --pbc-bg:#E9EEF4;            /* app canvas behind cards         */
  --pbc-surface:#FFFFFF;       /* cards, panels, modals           */
  --pbc-surface-soft:#F4F7FB;  /* inset areas, table headers      */
  --pbc-surface-sunken:#EDF2F7;/* wells, code blocks              */
  --pbc-surface-hover:#F4F7FB; /* row / nav hover                 */
  --pbc-surface-active:#EAF1F8;/* row selected                    */

  /* ── Striped-list row states (K-4.4, owner-approved 2026-07-28) ──────────
     A deliberate THREE-STEP ladder for lists that alternate row shading.
     ⚠ Do NOT be tempted to reuse --pbc-surface-soft for the stripe and
     --pbc-surface-hover for the cursor row: those two are the SAME colour
     (#F4F7FB), so hovering a shaded row would change nothing at all.
     The step up to hover is deliberately larger than the step into the
     stripe, so the cursor row is obvious without the striping shouting.
     Measured: white>stripe 1.09, stripe>hover 1.11, white>hover 1.22.
     ⚠ --pbc-ink-faint is NOT safe on the hover row (4.33:1, below AA).
     Small text on a stripeable row must be --pbc-ink-muted or darker. */
  --pbc-row-stripe:#F1F5FA;    /* every second row                */
  --pbc-row-hover:#E0EAF6;     /* row under the cursor            */
  --pbc-overlay:rgba(15,34,54,.44); /* modal scrim                */

  /* Diagonal brand gradient — the customer-portal topbar (and any future
     branded header band). Added K-3 (2026-07-25) when pbc-portal.css was
     migrated onto these tokens; the value is the portal's existing gradient,
     byte-identical, so nothing rendered differently.
     ⚠ ITS LAST STOP IS STEEL, so white text over that end is only 3.91:1 —
     below AA. Do NOT use this behind body text. Use the deep variant below. */
  --pbc-brand-gradient:linear-gradient(135deg,#16293E 0%,#2C5F8C 60%,#5E84AC 100%);

  /* Deep brand gradient — SAFE FOR WHITE TEXT. Every stop is brand-600 or
     darker, so white is >= 6.73:1 anywhere on it. Added K-4 (2026-07-25) for
     the login brand panel; use this for any large brand surface that carries
     copy. Composed from the ramp so it retunes with the brand. */
  --pbc-brand-gradient-deep:linear-gradient(160deg,
      var(--pbc-brand-950) 0%,
      var(--pbc-brand-800) 45%,
      var(--pbc-brand-600) 100%);

  /* Translucent chips/dividers sitting ON a brand or navy surface (the login
     brand panel, any future gradient band). Added K-4 (2026-07-25) so the
     component layer never needs a raw rgba(). They are white-based on purpose:
     they must read against every stop of the brand ramp, so they cannot be a
     solid colour from it. */
  --pbc-on-brand-fill:rgba(255,255,255,.10);
  --pbc-on-brand-border:rgba(255,255,255,.30);

  /* Sidebar is its own surface family (dark in both modes). */
  --pbc-sidebar-bg:linear-gradient(180deg,#1C3A5A 0%,#0F2236 100%);
  --pbc-sidebar-ink:#9FB7D1;
  --pbc-sidebar-ink-strong:#EAF1F8;
  --pbc-sidebar-hover:rgba(94,132,172,.12);
  /* §K A3 / NV-1 D (§14.336, 2026-08-18) — WAS .20, AND .20 WAS THE BUG.
     Against the .12 hover directly above it, .20 composites to 1.09:1 — and
     1.00 is "identical". The owner could not tell which page they were on
     because there was almost nothing to tell. .38 reads 1.34:1 against hover
     while the label stays 6.68:1 on the fill.
     ⚠ NV-1 D is this value AND the edge bar on `.pbc-nav__item.is-active` /
     `#sidebar-nav .nav-link:not(.collapsed)` in pbc-components.css. The tint
     ALONE is option NV-1 A, which is not what was chosen — never ship one
     without the other.
     ★ There is deliberately no dark override: the sidebar keeps this navy
     gradient in both themes, so one value serves both. */
  --pbc-sidebar-active:rgba(94,132,172,.38);
  --pbc-sidebar-border:rgba(255,255,255,.07);

  /* ==========================================================
     CHAT — the one place a NON-brand blue is deliberate
     ==========================================================
     ★ OWNER DECISION (2026-07-29): messages the user SENDS, and the send
     button, keep the brighter blue the chat screen has always used. Every
     other blue in chat moves to the brand family. This is not a leftover —
     it is a choice, so it gets a named token instead of a stray hex.

     White on #4154F1 measures 5.58:1, so it carries white text safely.
     The hover step is deliberately DARKER (7.13:1), never lighter: going
     lighter is what breaks white labels (see the brand-500 note above).

     ⚠ These replace `var(--pbc-primary, #4154f1)`, which appeared 10 times
     in pbc-chat.css. `--pbc-primary` HAS NEVER EXISTED as a token, so all
     ten were silently rendering their fallback. Anyone defining
     `--pbc-primary` later would have changed chat's colours by accident. */
  --pbc-chat-mine:#4154F1;
  --pbc-chat-mine-hover:#3444D6;
  --pbc-chat-mine-tint:rgba(65,84,241,.08);
  --pbc-chat-mine-tint-strong:rgba(65,84,241,.12);
  /* Secondary text ON a filled brand/bright surface — a dimmed white, never a
     grey. A mid grey on a saturated fill lands near 2:1 and disappears.
     ⚠ .82 was the first try and measures 4.30:1 on the bright chat blue — under
     AA. .90 is the setting: 4.84:1 on the bright blue (the binding case, since
     it is lighter than brand-600) and 5.81:1 on brand-600. Do not lower it. */
  --pbc-ink-on-brand-soft:rgba(255,255,255,.90);

  /* ★ OWNER REQUEST (2026-07-29), REBUILT IN K-4.6a (2026-07-30): a one-to-one
     conversation and a group conversation must be tellable apart by their
     picture. These are the tile colours shown when a conversation has no photo
     of its own — two members of the brand family, one step apart, so the
     difference is obvious at 42px without either looking like an error.
     ⚠ What sits on the tile is the conversation's INITIALS, bold white, per the
     approved mockup (`PBC Mockup/chat-options.html`, option 1). The first
     attempt drew an icon pictogram instead and the owner rejected it on sight.
     Never a glyph.
     Now ALIASES rather than repeated hex: the mockup's values were exactly
     brand-600 / brand-800, so pointing at those keeps one source of truth and
     lets a brand change carry the avatars with it.
     White initials measure 6.73:1 on brand-600 and 11.65:1 on brand-800, and
     stay above AA under the matte overlay (4.74:1 / 7.37:1 at the overlay's
     lightest stop — the binding case). */
  --pbc-chat-avatar-direct:var(--pbc-brand-600);   /* one-to-one */
  --pbc-chat-avatar-group:var(--pbc-brand-800);    /* groups     */

  /* ==========================================================
     4. INK — text hierarchy is carried by COLOUR, not size.
     ========================================================== */
  --pbc-ink-heading:#1C3A5A;
  --pbc-ink-body:#46566B;
  /* Darkened from the mockup values (#6B7A8D / #8492A4), which failed
     WCAG AA for small text — faint scored only 2.72:1 on the app canvas.
     Current ratios (body / muted / faint):
       on white   7.49 / 6.03 / 5.26
       on canvas  6.42 / 5.17 / 4.51   — all AA for small text. */
  --pbc-ink-muted:#566476;   /* secondary line under a title      */
  --pbc-ink-faint:#606D7F;   /* timestamps, meta, placeholders    */
  --pbc-ink-on-brand:#FFFFFF;
  --pbc-ink-disabled:#A9B4C2;

  /* ==========================================================
     5. BORDERS
     ----------------------------------------------------------
     ★ DARKENED 2026-08-08 ON THE OWNER'S INSTRUCTION (§K K-4.26,
     §14.294): "the outlines of boxes in the program are too light
     … all outlines should be darker!" They picked OPTION D from the
     four-strength gallery `PBC Mockup/border-strength-options.html`
     (B and C were the quieter steps; D was chosen deliberately).

       was #DEE6EF -> now #9AAABD   1.26:1 -> 2.37:1 on a white card
       was #C6CFD9 -> now #7A8DA4   1.58:1 -> 3.40:1
       was #EDF2F7 -> now #C2CEDB   1.13:1 -> 1.60:1

     ⚠ ALL THREE MOVE TOGETHER AND THEIR ORDER IS LOAD-BEARING:
     subtle < default < strong. Flattening them would lose the
     difference between a minor separator inside a card and the edge
     of the card itself. Reverting the whole decision = putting the
     three "was" values (and the dark alphas below) back; nothing
     else in the app needs editing, because everything reads these.

     ⚠ The tinted borders of the semantic family — success/warning/
     danger/info/neutral -border — are NOT part of this and were left
     alone: each is tuned to sit on its own tint, and the neutral one
     shares the OLD default hex by coincidence, not by reference.
     ========================================================== */
  --pbc-border:#9AAABD;         /* default hairline               */
  --pbc-border-strong:#7A8DA4;  /* emphasised divider             */
  --pbc-border-subtle:#C2CEDB;  /* inside-card separators         */
  --pbc-border-width:1px;

  /* ==========================================================
     6. SPACING — 4px base, 8px rhythm. Use these, never raw px.
     ========================================================== */
  --pbc-space-0:0;
  --pbc-space-px:1px;
  --pbc-space-0-5:2px;
  --pbc-space-1:4px;
  --pbc-space-1-5:6px;
  --pbc-space-2:8px;
  --pbc-space-2-5:10px;      /* nav item / compact row y-padding  */
  --pbc-space-3:12px;
  --pbc-space-4:16px;
  --pbc-space-5:20px;
  --pbc-space-6:24px;
  --pbc-space-8:32px;
  --pbc-space-10:40px;
  --pbc-space-12:48px;
  --pbc-space-16:64px;
  --pbc-space-20:80px;

  /* Composite spacing — keeps rhythm consistent across screens. */
  --pbc-card-pad:28px;
  --pbc-card-pad-lg:32px;
  --pbc-page-pad-x:44px;
  --pbc-page-pad-y:40px;
  --pbc-row-pad-y:17px;       /* airy list rows (see references)  */
  --pbc-cell-pad-y:15px;      /* table / matrix cells             */
  --pbc-stack-gap:18px;       /* default gap between siblings     */
  --pbc-section-gap:36px;     /* between page sections            */

  /* ==========================================================
     7. TYPOGRAPHY
     ========================================================== */
  --pbc-font-heading:'Manrope','Inter',-apple-system,BlinkMacSystemFont,sans-serif;
  --pbc-font-body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
  --pbc-font-mono:ui-monospace,SFMono-Regular,'SF Mono',Menlo,monospace;

  /* Scale bumped one step at owner request (2026-07-22): the first pass
     read too small, especially in dense screens like the permission
     matrix. Roughly +1px on body sizes, +2–4px on headings. Control
     heights, row padding, icons and avatars were bumped to match — type
     alone would have looked cramped inside unchanged controls. */
  --pbc-text-xs:12.5px;   /* meta, badges                         */
  --pbc-text-sm:13.5px;   /* secondary line, table meta           */
  --pbc-text-base:15px;   /* body / controls                      */
  --pbc-text-md:15.5px;   /* comfortable reading body             */
  --pbc-text-lg:17.5px;   /* card titles                          */
  --pbc-text-xl:20px;     /* section titles                       */
  --pbc-text-2xl:25px;    /* page title                           */
  --pbc-text-3xl:32px;    /* screen hero                          */

  --pbc-leading-tight:1.2;
  --pbc-leading-snug:1.35;
  --pbc-leading-normal:1.5;
  --pbc-leading-relaxed:1.65;

  --pbc-weight-normal:400;
  --pbc-weight-medium:500;
  --pbc-weight-semibold:600;
  --pbc-weight-bold:700;
  --pbc-weight-heading:800;

  --pbc-tracking-tight:-.02em;  /* headings                       */
  --pbc-tracking-normal:0;
  --pbc-tracking-caps:.06em;    /* UPPERCASE section labels       */

  /* ==========================================================
     8. RADIUS
     ========================================================== */
  --pbc-radius-xs:6px;
  --pbc-radius-sm:8px;
  --pbc-radius-btn:10px;
  --pbc-radius-chip:12px;
  --pbc-radius-card:16px;
  --pbc-radius-modal:16px;
  --pbc-radius-pill:999px;

  /* ==========================================================
     9. ELEVATION — subtle. Depth comes from borders first.
     ========================================================== */
  --pbc-shadow-xs:0 1px 2px rgba(15,34,54,.05);
  --pbc-shadow-sm:0 1px 2px rgba(15,34,54,.06),0 1px 3px rgba(15,34,54,.05);
  --pbc-shadow-md:0 4px 14px rgba(15,34,54,.08),0 1px 3px rgba(15,34,54,.05);
  --pbc-shadow-lg:0 18px 44px rgba(15,34,54,.16),0 6px 14px rgba(15,34,54,.07);
  --pbc-shadow-popover:0 12px 32px rgba(15,34,54,.14),0 2px 6px rgba(15,34,54,.06);

  /* ==========================================================
     9b. BUTTON FINISH — "matte metal"
     ----------------------------------------------------------
     Owner decision 2026-07-29, chosen from PBC Mockup/button-options.html:
     shape #1 "Ribbon" (which is just --pbc-radius-btn, already 10px, so the
     SHAPE did not change) in the MATTE finish — soft top-to-bottom shading,
     a fine light lip on the top edge, no gloss and no hover sheen. The shiny
     variant was rejected.

     Deliberately COLOUR-AGNOSTIC. This is a translucent overlay, not a
     palette: laid over whatever background-color a button already carries,
     it shapes that colour into a soft metal band WITHOUT changing its hue.
     That is why one pair of tokens can finish primary, success, danger,
     warning, secondary and dark identically, in light mode and dark mode,
     across both the design-system buttons (.pbc-btn--*) and the ~136 legacy
     Bootstrap screens — with no per-colour gradients to keep in sync.

     Consumed by exactly three places; grep `--pbc-btn-matte` to find them:
       pbc-components.css  → .pbc-btn--primary / --danger
       pbc-theme.css       → body.pbc-skin  filled .btn-*   (light mode)
       dark-mode.css       → body.dark-mode filled .btn-*   (dark mode)
     NEVER apply it to a button with no fill (outline / ghost / light /
     .pbc-btn--inverse) — there is no colour underneath for the overlay to
     shape, so it just prints grey shading onto white.

     To retire the finish app-wide, set both of these to `none` — every
     consumer goes flat again with no other edit. */
  --pbc-btn-matte:linear-gradient(180deg,
      rgba(255,255,255,.15)   0%,
      rgba(255,255,255,.04)  32%,
      rgba(0,0,0,.05)        56%,
      rgba(0,0,0,.24)       100%);
  --pbc-btn-matte-lip:inset 0 1px 0 rgba(255,255,255,.22),
                      inset 0 -1px 0 rgba(0,0,0,.18);

  /* ==========================================================
     10. FOCUS — visible, keyboard-first, never removed.
     ========================================================== */
  --pbc-focus-ring-color:rgba(44,95,140,.28);
  --pbc-focus-ring-width:4px;
  --pbc-focus-ring:0 0 0 var(--pbc-focus-ring-width) var(--pbc-focus-ring-color);
  --pbc-focus-outline-color:var(--pbc-brand-600);
  --pbc-focus-outline-offset:2px;

  /* ==========================================================
     11. MOTION — short, and honoured only when the user allows.
     ========================================================== */
  --pbc-duration-instant:80ms;
  --pbc-duration-fast:150ms;
  --pbc-duration-base:220ms;
  --pbc-duration-slow:320ms;
  --pbc-ease-standard:cubic-bezier(.2,0,0,1);
  --pbc-ease-out:cubic-bezier(0,0,.2,1);
  --pbc-ease-in:cubic-bezier(.4,0,1,1);
  --pbc-transition:var(--pbc-duration-fast) var(--pbc-ease-standard);

  /* ==========================================================
     12. LAYOUT
     ========================================================== */
  --pbc-sidebar-w:256px;
  --pbc-sidebar-w-collapsed:72px;
  --pbc-rail-w:60px;          /* icon rail in 3-column shell      */
  --pbc-list-w:320px;         /* context list in 3-column shell   */
  --pbc-topbar-h:62px;
  --pbc-chat-footer-h:61px;   /* the page footer, so chat can size itself */
  --pbc-content-max:1280px;
  /* The FOUR pop-up widths — owner decision P-8 option B (§14.295, 2026-08-08).
     The width is meant to TELL you what kind of window it is before you read it:
       sm  a question      — "are you sure?", discard, not-approve
       md  a form          — add a department, edit a user, change a password
       lg  a table/picker  — dashboard lists, imports, member pickers
       xl  columns of switches — the request-type Configure window, phase imports
     ⚠ xl is the size that gets over-used. Anything that genuinely needs more room
     than lg is usually a PAGE, not a pop-up. The owner was shown that warning and
     still wanted the fourth size for the switch matrices — use it only there. */
  --pbc-modal-w-sm:420px;
  --pbc-modal-w:560px;
  --pbc-modal-w-lg:760px;
  --pbc-modal-w-xl:1000px;

  /* ==========================================================
     13. Z-INDEX — named, so nothing invents its own 99999.
     ========================================================== */
  --pbc-z-base:0;
  --pbc-z-sticky:20;
  --pbc-z-dropdown:1000;
  --pbc-z-overlay:1040;
  --pbc-z-modal:1050;
  --pbc-z-popover:1060;
  /* The house "are you sure?" dialog (P-3 A). ⚠⚠ It MUST out-rank Bootstrap's own
     modal, which sits at 1055 with its backdrop at 1050 — the dialog's whole job is
     to be answerable while a Bootstrap window is open behind it (the "Not approve"
     case). 1070 also stays under --pbc-z-toast, so a message still lands on top. */
  --pbc-z-dialog:1070;
  --pbc-z-toast:1080;

  /* ==========================================================
     14. CONTROL SIZING
     ========================================================== */
  --pbc-control-h-sm:36px;
  --pbc-control-h:44px;
  --pbc-control-h-lg:52px;
  --pbc-icon-sm:17px;
  --pbc-icon:20px;
  --pbc-icon-lg:24px;
  --pbc-avatar-sm:32px;
  --pbc-avatar:40px;
  --pbc-avatar-lg:48px;
  --pbc-tick:20px;            /* checkbox / radio box             */
  --pbc-switch-w:46px;        /* toggle track                     */
  --pbc-switch-h:26px;
  --pbc-matrix-col:104px;     /* permission matrix column width   */
  --pbc-stat-icon:46px;       /* dashboard tile icon (owner: bigger) */

  /* ==========================================================
     15. CALL SURFACES — §K K-4.OVERLAYS (2026-08-01)
     ==========================================================
     The call UI is the one part of the app that must look the SAME in
     light and dark, for two different reasons. Read both before editing.

     (a) ★★ THE ANSWER/DECLINE FILLS MUST NOT FLIP WITH THE THEME.
     In the dark block below, --pbc-success-600 becomes #7FD3B2 and
     --pbc-danger-600 becomes #F2A3A3. Those are INK colours, for text and
     badges on a tinted chip. Used as a BUTTON FILL you get a pastel green
     Answer button and a pale pink Decline — which is exactly the defect
     already logged against .pbc-btn--danger. A call's green and red are
     safety-critical and are pinned to the LIGHT values of the ramp here,
     in both themes, so they can never be re-pointed by accident.

     (b) VIDEO FURNITURE IS DARK IN BOTH THEMES. Dark chrome around a
     moving picture is not "dark mode" — it is what you put around video.

     ⚠ THE NAVY CALL SURFACE IS **NOT** --pbc-brand-gradient-deep. That
     gradient's lightest stop is brand-600, where the caption ink this card
     needs (--pbc-sidebar-ink) measures 3.26:1. --pbc-call-surface stops at
     brand-800, where the same ink is 5.64:1 and white is 11.65:1 — it is
     the sidebar's own ramp, so every pairing on it is already proven.  */
  --pbc-call-accept:#256F53;          /* = light success-600 · white 6.04:1 */
  --pbc-call-accept-hover:#1B5540;
  --pbc-call-decline:#B01818;         /* = light danger-600  · white 7.02:1 */
  --pbc-call-decline-hover:#8A1212;   /* = light danger-700                 */
  --pbc-call-defer:#5B6A7B;           /* = light neutral-600 · white 5.54:1 */
  --pbc-call-defer-hover:#46566B;
  /* mic-muted / camera-off. warning-600 flips to a light gold in dark, so
     the light value is pinned too. ⚠ --pbc-warning-500 was the first try
     and is 3.04:1 against white — too thin to rely on. */
  --pbc-call-muted:#7F5A14;           /* = light warning-600 · white 6.22:1 */

  --pbc-call-surface:linear-gradient(160deg,
      var(--pbc-brand-800) 0%,
      var(--pbc-brand-950) 100%);
  --pbc-call-room:var(--pbc-brand-950);   /* the video room's canvas   */
  --pbc-call-tile:var(--pbc-brand-900);   /* one participant's tile    */

  /* ⚠ THE CALL-TYPE BADGE IS PINNED SILVER-ON-NAVY, and that is only safe
     because the owner chose the NAVY card (A2), which is navy in BOTH
     themes. If a light call card is ever reintroduced, the badge needs a
     theme-flipping PAIR instead: brand-600 with a white glyph is 6.73:1 on
     a white card, but that card's surface goes navy in dark mode and the
     badge falls to 2.20:1. No single fill reads on both. */

  /* Translucents. A translucent cannot be derived from a solid token —
     the same reason --pbc-on-brand-fill is a literal. */
  --pbc-scrim-call:rgba(15,34,54,.86);    /* behind a ringing call     */
  --pbc-scrim-video:rgba(15,34,54,.72);   /* under the video controls  */
  --pbc-scrim-tile:rgba(15,34,54,.66);    /* a tile's name plate       */
  --pbc-shadow-up:0 -4px 20px rgba(15,34,54,.28);
  --pbc-on-brand-fill-hover:rgba(255,255,255,.22);
  --pbc-call-pulse:rgba(44,95,140,.45);   /* = brand-600 @ .45 */
  --pbc-call-pulse-0:rgba(44,95,140,0);
  --pbc-call-ring:rgba(37,111,83,.5);     /* = call-accept @ .5 */
  --pbc-call-ring-0:rgba(37,111,83,0);
}

/* ============================================================
   DARK MODE
   Scoped to a body class so it cannot affect light mode. Only
   surface/ink/border tokens are re-pointed — the brand ramp,
   spacing, type and radius stay identical.

   ⚠ TWO HOOKS ON PURPOSE (fixed K-3, 2026-07-25):
     body.dark-mode  = what the REAL APP writes. Both master
                       layouts render <body class="dark-mode">
                       from users.dark_mode, and dark-mode.css
                       is built on that class.
     body.dark       = what the standalone galleries toggle
                       (PBC Mockup/tokens.html + components.html).
   Before this fix only `body.dark` was listed, so dark mode was
   correct in the gallery and silently dead inside the app.
   Keep both — and see the STATE.md warning about reading tokens
   from getComputedStyle(document.body), never documentElement.
   ============================================================ */
body.dark,
body.dark-mode{
  /* chat: the bright "my message" blue holds up on a dark canvas as-is
     (white on it is 5.58:1 either way), but the quote tints have to lift or
     they vanish into the dark bubble. */
  --pbc-chat-mine-tint:rgba(120,136,255,.16);
  --pbc-chat-mine-tint-strong:rgba(120,136,255,.24);

  --pbc-bg:#0E1F32;
  --pbc-surface:#16293E;
  --pbc-surface-soft:#142A43;
  --pbc-surface-sunken:#11243A;
  --pbc-surface-hover:rgba(94,132,172,.10);
  --pbc-surface-active:#21425F;
  /* dark twins of the striped-row ladder — same intent: the hover step is
     bigger than the stripe step. ⚠ Dark mode is currently defeated app-wide by
     pbc-theme.css force-painting the canvas light, so these cannot be judged
     on screen until that is fixed (logged as a carry-over). */
  --pbc-row-stripe:#1A3049;
  --pbc-row-hover:#23405C;
  --pbc-overlay:rgba(0,0,0,.58);

  --pbc-ink-heading:#EAF1F8;
  --pbc-ink-body:#CDD9E8;
  --pbc-ink-muted:#9FB7D1;
  --pbc-ink-faint:#7E90A6;
  --pbc-ink-disabled:#5E7085;

  /* ★ Option D's dark twins (2026-08-08, §14.293). In dark the outline is a
     translucent LIGHT line over the surface, so "darker" here means "more
     visible" — the alphas go UP. was .16 / .28 / .10.
     Composited over --pbc-surface #16293E: 2.35 : 3.20 : 1.81 (light side 2.37
     : 3.40 : 1.60), so the two themes read at the same strength. */
  --pbc-border:rgba(159,183,209,.40);
  --pbc-border-strong:rgba(159,183,209,.55);
  --pbc-border-subtle:rgba(159,183,209,.28);

  --pbc-brand-100:#21425F;
  --pbc-brand-accent:var(--pbc-brand-300);  /* see note in :root */

  /* The dark reds follow the light family off its orange cast (2026-07-25):
     the ink went salmon -> a cleaner red-pink, and the border now derives from
     the new danger-500 instead of the retired #C0473C. */
  --pbc-success-100:#16352A;  --pbc-success-600:#7FD3B2;  --pbc-success-border:rgba(47,143,107,.4);
  --pbc-warning-100:#3A2F18;  --pbc-warning-600:#E8B455;  --pbc-warning-border:rgba(192,138,43,.45);
  --pbc-danger-100:#3A201D;   --pbc-danger-600:#F2A3A3;   --pbc-danger-border:rgba(217,43,43,.45);
  --pbc-info-100:#21425F;     --pbc-info-600:#9FC4E4;     --pbc-info-border:rgba(94,132,172,.4);
  --pbc-neutral-100:#142A43;  --pbc-neutral-600:#9FB7D1;  --pbc-neutral-border:rgba(159,183,209,.18);

  --pbc-shadow-xs:0 1px 2px rgba(0,0,0,.30);
  --pbc-shadow-sm:0 1px 3px rgba(0,0,0,.30);
  --pbc-shadow-md:0 6px 18px rgba(0,0,0,.32);
  --pbc-shadow-lg:0 20px 46px rgba(0,0,0,.45);
  --pbc-shadow-popover:0 14px 34px rgba(0,0,0,.42);

  --pbc-focus-ring-color:rgba(159,183,209,.38);

}

/* ============================================================
   ACCESSIBILITY — respect the OS "reduce motion" setting.
   Collapses every token-driven duration to ~0 without any
   component needing to know about it.
   ============================================================ */
@media (prefers-reduced-motion:reduce){
  :root{
    --pbc-duration-instant:1ms;
    --pbc-duration-fast:1ms;
    --pbc-duration-base:1ms;
    --pbc-duration-slow:1ms;
  }
}
