/* ============================================================
   Platinum 2.0 — Application Shell & Design System
   Layered on top of Bootstrap 5.3.3.

   Sections
     01. Tokens (color, spacing, radius, shadow, motion, z-index)
     02. Dark-mode token overrides
     03. Bootstrap variable bridges
     04. Reset / typography
     05. App shell layout
     06. Sidebar
     07. Topbar
     08. Impersonation banner
     09. Content area & breadcrumbs
     10. Page header
     11. Cards
     12. Tables
     13. Stat cards & KPI row
     14. Empty state
     15. Banners
     16. Dropdowns & notifications
     17. Tabs
     18. Tags & status chips
     19. Segmented control
     20. Filter bar
     21. Toolbar
     22. Section header
     23. Progress & stepper
     24. Skeleton loader
     25. Keyboard shortcut
     26. Command palette
     27. Drawer / sheet
     28. Toast
     29. Timeline / activity feed
     30. Forms
     31. Avatars & avatar group
     32. Detail layout
     33. Buttons polish
     34. Anonymous (auth) shell
     35. Mobile
     36. Print
     37. Reduced motion
   ============================================================ */

/* ── 01. Tokens ─────────────────────────────────────────────── */
:root {
  color-scheme: light;

  /* Brand navy — the exact ink of the Platinum wordmark
     (logos/logo-platinum-horizontal.svg, rgb(13,27,62)). This is the anchor
     colour for the sidebar and every "brand surface" in the app. */
  --pl-brand: #0d1b3e;

  /* Brand ink ramp + accents — the platinumsystem.com "H27" brand system.
     navy #0d1b3e is the anchor; ink/void sit under it so navy can read as a
     raised plane. Persimmon (coral) is the signature accent and stays scarce
     (≤10% of any surface); sky and sage are the supporting accents. */
  --pl-brand-void:  #060c1e;
  --pl-brand-ink:   #0a1330;
  --pl-brand-up:    #14244f;
  --pl-coral:       #e8593a;
  --pl-coral-dark:  #c94a2d;
  --pl-coral-light: #ffab96;
  --pl-coral-soft:  #fdeee9;
  --pl-sky:         #3b86bc;
  --pl-sky-light:   #8bbedd;
  --pl-sky-soft:    #ebf4fb;
  --pl-sage:        #7a9e8e;
  --pl-sage-light:  #a9cfbe;
  --pl-sage-soft:   #f0f5f2;
  /* Platform accent.
     WAS #6d5efc (violet) — an invented hue that entered when the .pacct
     directory kit was mistaken for "the reference". The reference is the
     public site (platinumsystem.com), whose palette is LOCKED to navy /
     coral / sky / sage and contains no violet at all.
     Aliased rather than deleted so the ~35 downstream consumers become
     on-brand immediately instead of falling back to an unstyled value. */
  --pl-accent-2:    var(--pl-sky);

  /* Primary scale — derived from the brand navy above. 900 IS the logo ink;
     600 is the lighter navy used for interactive elements (buttons, links,
     focus rings) so hover/active states still have somewhere to travel. */
  --pl-primary-50:  #eef2f9;
  --pl-primary-100: #d5deef;
  --pl-primary-200: #adbedd;
  --pl-primary-300: #7d97c6;
  --pl-primary-400: #5271ab;
  --pl-primary-500: #33528d;
  --pl-primary-600: #1e3c72;
  --pl-primary-700: #17305c;
  --pl-primary-800: #122549;
  --pl-primary-900: #0d1b3e;
  --pl-primary-950: #070f24;

  /* Aliases (existing — keep for back-compat) */
  --pl-primary:       var(--pl-primary-600);
  --pl-primary-hover: var(--pl-primary-700);
  --pl-primary-soft:  var(--pl-primary-50);
  --pl-primary-ring:  rgba(30, 60, 114, 0.18);

  /* Neutral scale — the brand "ice" ramp (white + cool blue-tinted greys from
     the marketing site: ice #f7fafd · ice-2 #edf4fb · hair #e3eaf2), running
     down into the brand ink (#0a1330) and void (#060c1e) at the deep end. */
  --pl-neutral-0:   #ffffff;
  --pl-neutral-50:  #f7fafd;
  --pl-neutral-100: #edf4fb;
  --pl-neutral-200: #e3eaf2;
  --pl-neutral-300: #c9d6e4;
  --pl-neutral-400: #93a5bd;
  --pl-neutral-500: #5f718c;
  --pl-neutral-600: #49596f;
  --pl-neutral-700: #364257;
  --pl-neutral-800: #1e2a44;
  --pl-neutral-900: #0a1330;
  --pl-neutral-950: #060c1e;

  /* Text */
  --pl-text:        var(--pl-neutral-900);
  /* was var(--pl-neutral-500) #5f718c — 4.48:1 on --pl-surface-alt, just under
     AA, and surface-alt is where muted text lives most: table headers, zebra
     rows, the segmented tab well, chips. #5c6d87 is the smallest step that
     clears 4.5 (4.74 on alt, 5.26 on surface, 5.02 on bg). The neutral ramp
     itself is unchanged — --pl-neutral-500 is still #5f718c. */
  --pl-text-muted:  #5c6d87;
  --pl-text-subtle: #5b6a86;        /* was var(--pl-neutral-400) #94a3b8 — failed WCAG AA on light surfaces */
  --pl-text-inverse: var(--pl-neutral-0);

  /* Surfaces */
  --pl-bg:           var(--pl-neutral-50);
  --pl-surface:      var(--pl-neutral-0);
  --pl-surface-alt:  var(--pl-neutral-100);
  /* Alias for tinted bands (zebra rows, chips, insight strips). Defined via
     --pl-surface-alt so the dark block re-themes it for free — do not give
     it a literal hex. */
  --pl-surface-2:    var(--pl-surface-alt);
  --pl-surface-elevated: var(--pl-neutral-0);
  --pl-surface-sunken:   var(--pl-neutral-100);
  --pl-overlay:      rgba(13, 27, 62, 0.45);

  /* Borders */
  --pl-border:        var(--pl-neutral-200);
  --pl-border-strong: var(--pl-neutral-300);
  --pl-border-hairline: rgba(13, 27, 62, 0.06);
  --pl-ring:          var(--pl-primary-ring);

  /* Status colors — mapped onto the brand semantics: success = sage,
     warning = persimmon-dark, info = sky. Solids are deepened just enough to
     keep white text ≥4.5:1; the soft/bg tints are the site's own. */
  --pl-success:      #4e7a66;
  --pl-success-50:   #f0f5f2;
  --pl-success-soft: #e2ede7;
  --pl-success-border: #c6dbd0;
  --pl-success-text: #3a5d4c;

  --pl-warning:      #c94a2d;
  --pl-warning-50:   #fdf4f0;
  --pl-warning-soft: #fdeee9;
  --pl-warning-border: #f6cfc2;
  --pl-warning-text: #a03a22;

  --pl-danger:       #dc2626;
  --pl-danger-50:    #fef2f2;
  --pl-danger-soft:  #fee2e2;
  --pl-danger-border: #fecaca;
  --pl-danger-text:  #991b1b;

  --pl-info:         #3579aa;
  --pl-info-50:      #f2f8fc;
  --pl-info-soft:    #ebf4fb;
  --pl-info-border:  #c6def0;
  --pl-info-text:    #2b6390;

  /* Shape — the brand is SQUARE-ish and calm.
     Measured off the public site: .h27-btn is 4px, .h27-card is 6px, the
     card icon tile is 8px. Nothing on the site exceeds 8px except a pill.
     The ramp below previously ran 4→24px and the semantic names below it
     said 10/14/18, which is why the product read as a rounded 2020-era SaaS
     app even after its colours were corrected. Everything now lands in the
     3–12px band, and the semantic names sit exactly on the site's values. */
  --pl-radius-xs:  3px;
  --pl-radius-sm:  4px;
  --pl-radius:     6px;
  --pl-radius-md:  6px;
  --pl-radius-lg:  8px;
  --pl-radius-xl:  8px;
  --pl-radius-2xl: 12px;
  --pl-radius-pill: 9999px;

  /* Reach for these by name, not for the numeric ramp. */
  --pl-radius-control: 4px;   /* buttons, chips, tab segments */
  --pl-radius-card:    6px;   /* cards, tab strips, panels */
  --pl-radius-tile:    8px;   /* header tiles, icon tiles */

  /* Shadows */
  --pl-shadow-xs:  0 1px 1px rgba(13, 27, 62, 0.04);
  --pl-shadow-sm:  0 1px 2px rgba(13, 27, 62, 0.05);
  --pl-shadow:     0 1px 3px rgba(13, 27, 62, 0.07), 0 1px 2px rgba(13, 27, 62, 0.04);
  --pl-shadow-md:  0 4px 6px -1px rgba(13, 27, 62, 0.08), 0 2px 4px -2px rgba(13, 27, 62, 0.05);
  --pl-shadow-lg:  0 10px 25px -10px rgba(13, 27, 62, 0.18);
  --pl-shadow-xl:  0 20px 35px -10px rgba(13, 27, 62, 0.22);
  --pl-shadow-2xl: 0 25px 50px -12px rgba(13, 27, 62, 0.28);
  --pl-shadow-inner: inset 0 1px 2px rgba(13, 27, 62, 0.05);

  /* Motion — the site settles rather than snaps. These were Material's curves
     (0.4,0,0.2,1) at 140ms, which read snappy and utilitarian; the brand's are
     a long decelerating ease that arrives softly. Durations are unchanged so
     nothing in the app suddenly feels sluggish. */
  --pl-ease:        cubic-bezier(0.16, 1, 0.3, 1);
  --pl-ease-out:    cubic-bezier(0.22, 0.61, 0.36, 1);
  --pl-ease-in:     cubic-bezier(0.4, 0, 1, 1);
  --pl-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --pl-dur-instant: 80ms;
  --pl-dur-fast:    140ms;
  --pl-dur-base:    220ms;
  --pl-dur-slow:    320ms;

  /* Z-index */
  --pl-z-sidebar:  1040;
  --pl-z-backdrop: 1045;
  --pl-z-topbar:   1030;
  --pl-z-dropdown: 1060;
  --pl-z-drawer:   1070;
  --pl-z-modal:    1080;
  --pl-z-toast:    1100;

  /* Typography */
  --pl-font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                  "Helvetica Neue", Arial, "Noto Sans", sans-serif,
                  "Apple Color Emoji", "Segoe UI Emoji";
  --pl-font-mono: "JetBrains Mono", "Fira Code", SFMono-Regular, Menlo, Monaco, Consolas, monospace;
  /* Display serif — DM Serif Display owns the big headlines on the marketing
     site; here it carries page titles and hero moments only. Inter keeps
     everything functional. */
  --pl-font-display: "DM Serif Display", "Iowan Old Style", Georgia, "Times New Roman", serif;

  --pl-fs-xs:   0.6875rem;  /* 11 */
  --pl-fs-sm:   0.75rem;    /* 12 */
  --pl-fs-base: 0.875rem;   /* 14 */
  --pl-fs-md:   0.9375rem;  /* 15 */
  --pl-fs-lg:   1rem;       /* 16 */
  --pl-fs-xl:   1.125rem;   /* 18 */
  --pl-fs-2xl:  1.25rem;    /* 20 */
  --pl-fs-3xl:  1.5rem;     /* 24 */
  --pl-fs-4xl:  1.875rem;   /* 30 */
  --pl-fs-5xl:  2.25rem;    /* 36 */

  /* Fluid display steps, ported from the site's scale and shrunk for a dense
     tool (the site's d1 tops out at 58px, which no application page can use).
     These are for hero/anon/empty-state headlines, not for table chrome. */
  --pl-d1: clamp(1.5rem, 2.4vw, 2.125rem);   /* 24 → 34 */
  --pl-d2: clamp(1.25rem, 1.8vw, 1.625rem);  /* 20 → 26 */
  --pl-d3: clamp(1.0625rem, 1.3vw, 1.25rem); /* 17 → 20 */

  --pl-fw-regular:  400;
  --pl-fw-medium:   500;
  --pl-fw-semibold: 600;
  --pl-fw-bold:     700;
  /* The eyebrow is weight 800. Without this token every eyebrow-ish rule in
     the tree hard-coded 800 or gave up and used 600. */
  --pl-fw-extrabold: 800;

  /* ── Name aliases ────────────────────────────────────────────────────
     Six token names are referenced across the tree that were never declared
     here. Every reference guarded itself with a fallback, so nothing looked
     broken — but each one silently froze a literal (#e7efff, #1d4ed8, 400)
     that no brand change could ever reach. Declaring them routes those
     consumers back through the token layer. */
  --pl-navy:            var(--pl-brand);
  --pl-border-subtle:   var(--pl-border-hairline);
  --pl-primary-subtle:  var(--pl-primary-soft);
  --pl-fw-normal:       var(--pl-fw-regular);
  --pl-mono:            var(--pl-font-mono);
  --pl-elevation-4:     var(--pl-surface-sunken);

  --pl-lh-tight:  1.2;
  --pl-lh-snug:   1.35;
  --pl-lh-base:   1.5;
  --pl-lh-relaxed: 1.625;

  /* Spacing scale (companion to Bootstrap) */
  --pl-space-0: 0;
  --pl-space-1: 0.25rem;
  --pl-space-2: 0.5rem;
  --pl-space-3: 0.75rem;
  --pl-space-4: 1rem;
  --pl-space-5: 1.25rem;
  --pl-space-6: 1.5rem;
  --pl-space-8: 2rem;
  --pl-space-10: 2.5rem;
  --pl-space-12: 3rem;
  --pl-space-16: 4rem;
  --pl-wizard-gap-x: clamp(0.75rem, 1.1vw, 1.25rem);
  --pl-wizard-gap-y: clamp(0.85rem, 1.3vw, 1.5rem);

  /* Layout — the content column is deliberately FLUID (.pl-content is
     width:100% with no cap), so there is no --pl-content-max here. A page that
     wants a reading measure caps itself; do not reintroduce a global cap. */
  --pl-sidebar-w:  260px;
  --pl-sidebar-rail-w: 76px;
  --pl-topbar-h:   56px;
  /* Readability measures — the two the kit already enforces, named so a new
     surface does not have to re-derive them (hint text 70ch, subtitles 64ch). */
  --pl-measure-prose: 70ch;
  --pl-measure-lede:  64ch;

  /* ── New: surfaces & elevation ────────────────────────────── */
  --pl-elevation-1: var(--pl-surface);
  --pl-elevation-2: var(--pl-surface);
  --pl-elevation-3: var(--pl-surface);

  /* ── New: glass / backdrop ─────────────────────────────────── */
  --pl-glass-bg: rgba(255, 255, 255, 0.72);
  --pl-glass-border: rgba(13, 27, 62, 0.08);
  --pl-backdrop-blur: 12px;

  /* ── New: native UI ─────────────────────────────────────────── */
  --pl-scrollbar-track: transparent;
  --pl-scrollbar-thumb: rgba(13, 27, 62, 0.18);
  --pl-scrollbar-thumb-hover: rgba(13, 27, 62, 0.32);
  --pl-selection-bg: var(--pl-primary-100);
  --pl-selection-fg: var(--pl-primary-900);
  --pl-focus-ring: var(--pl-primary-ring);
  --pl-focus-ring-offset-color: var(--pl-bg);
  --pl-accent: var(--pl-primary-600);

  /* ── New: text variants ────────────────────────────────────── */
  --pl-text-strong: var(--pl-neutral-900);
  /* (existing) --pl-text-inverse: var(--pl-neutral-0); — keep */

  /* ── New: "on solid" text (text on solid status/primary fills) ─ */
  --pl-on-primary: #ffffff;
  --pl-on-success: #ffffff;
  --pl-on-warning: #ffffff;
  --pl-on-danger:  #ffffff;
  --pl-on-info:    #ffffff;

  /* ── New: status icon colors (between solid and text) ──────── */
  --pl-success-icon: var(--pl-success);
  --pl-warning-icon: var(--pl-warning);
  --pl-danger-icon:  var(--pl-danger);
  --pl-info-icon:    var(--pl-info);

  /* ── New: extended palette ─────────────────────────────────── */
  --pl-primary-light: #33528d;        /* used in many gradients */

  /* DEPRECATED decorative hues.
     Purple and pink are not in the locked palette. They existed as first-class
     tokens, so surfaces kept reaching for them (pipeline_template, permissions_kit,
     role_matrix, the forms kit, dashboard chart tones). Aliased onto sky and
     coral so every existing consumer becomes on-brand with no edit; do not
     reference these names in new code. */
  --pl-purple:        var(--pl-sky);
  --pl-purple-soft:   var(--pl-sky-soft);
  --pl-purple-border: var(--pl-info-border);
  --pl-purple-text:   var(--pl-info-text);

  --pl-pink:          var(--pl-coral);
  --pl-pink-soft:     var(--pl-coral-soft);
  --pl-pink-border:   var(--pl-warning-border);
  --pl-pink-text:     var(--pl-warning-text);

  --pl-cyan:          #0891b2;
  --pl-cyan-soft:     #ecfeff;
  --pl-cyan-border:   #a5f3fc;
  --pl-cyan-text:     #0e7490;

  --pl-rating-star:   #f59e0b;

  --pl-code-bg:       #0a1330;        /* code blocks intentionally dark in both themes */
  --pl-code-fg:       #e3eaf2;

  /* ── New: links (separate from primary) ────────────────────── */
  --pl-link:       var(--pl-primary);
  --pl-link-hover: var(--pl-primary-hover);

  /* ── New: overlays ─────────────────────────────────────────── */
  --pl-overlay-strong: rgba(13, 27, 62, 0.6);
  --pl-overlay-light:  rgba(13, 27, 62, 0.25);

  /* ── New: shadow lift (sticky footers/floating bars) ───────── */
  --pl-shadow-lift: 0 -6px 18px rgba(13, 27, 62, 0.06), var(--pl-shadow-sm);

  /* ── New: input surface (slightly different from card surface) ─ */
  --pl-input-bg:        var(--pl-surface);
  --pl-input-bg-hover:  var(--pl-primary-50);

  /* ── New: tint family (auto-flip in dark — high-leverage) ──── */
  --pl-primary-tint:        var(--pl-primary-50);
  --pl-primary-tint-hover:  var(--pl-primary-100);
  --pl-primary-on-tint:     var(--pl-primary-700);
  --pl-success-tint:        var(--pl-success-soft);
  --pl-success-on-tint:     var(--pl-success-text);
  /* Completed the set — warning/danger/info had a -soft but no tint pair, so a
     soft-tint status chip had to reach for two different families depending on
     the tone. All five now read the same way: --pl-X-tint behind
     --pl-X-on-tint. Defined through -soft/-text, which the dark block already
     flips, so these need no dark override of their own. */
  --pl-warning-tint:        var(--pl-warning-soft);
  --pl-warning-on-tint:     var(--pl-warning-text);
  --pl-danger-tint:         var(--pl-danger-soft);
  --pl-danger-on-tint:      var(--pl-danger-text);
  --pl-info-tint:           var(--pl-info-soft);
  --pl-info-on-tint:        var(--pl-info-text);
  --pl-neutral-tint:        var(--pl-neutral-100);
  --pl-neutral-on-tint:     var(--pl-text-muted);
  --pl-icon-accent:         var(--pl-primary-600);

  /* ── New: the header-tile recipe (house style §4) ───────────
     56px / 18px radius / violet→navy gradient / white icon. It was hard-coded
     in .pl-page-header__icon, .pacct-head__tile and a dozen page-level style
     blocks; naming it means a tile is one token away instead of four values,
     and the gradient can be retuned in one place. */
  --pl-tile-size:     56px;
  /* The site paints planes flat and separates them with a hairline; it does
     not use gradient fills or blurred drop shadows on chrome. The tile is
     therefore the brand navy, flat, in both themes — which is also why its
     ink stays white in both. Do NOT reach for --pl-on-primary on a tile:
     that one flips to near-black in dark and would put dark ink on navy. */
  --pl-tile-gradient: var(--pl-primary-900);
  --pl-tile-shadow:   none;
  --pl-on-tile:       #ffffff;

  /* ── New: skeleton shimmer (must be visible in both themes) ── */
  --pl-skeleton-from: var(--pl-neutral-100);
  --pl-skeleton-via:  var(--pl-neutral-200);
  --pl-skeleton-to:   var(--pl-neutral-100);

  /* ── Bootstrap bridges (so .text-muted, .border, .modal, .dropdown etc. follow our theme) ─ */
  --bs-body-bg:                  var(--pl-bg);
  --bs-body-color:               var(--pl-text);
  --bs-emphasis-color:           var(--pl-text-strong);
  --bs-secondary-bg:             var(--pl-surface-alt);
  --bs-tertiary-bg:              var(--pl-surface-sunken);
  --bs-border-color:             var(--pl-border);
  --bs-border-color-translucent: var(--pl-border-hairline);
  --bs-link-color:               var(--pl-link);
  --bs-link-hover-color:         var(--pl-link-hover);
  --bs-secondary-color:          var(--pl-text-muted);
  --bs-tertiary-color:           var(--pl-text-subtle);
  --bs-heading-color:            var(--pl-text-strong);
  --bs-code-color:               var(--pl-danger-text);
  --bs-highlight-bg:             var(--pl-warning-soft);

  /* ── Bootstrap SEMANTIC bridge ───────────────────────────────────────
     Without these, every .text-bg-success / .bg-warning-subtle /
     .btn-outline-info / .text-danger in the tree renders STOCK Bootstrap
     5.3 — #0d6efd electric blue, #198754 emerald, #ffc107 amber, #0dcaf0
     cyan — inside a navy/sage/coral product. 75 templates were affected.
     The neutrals above were bridged in the 2026-08 pass; the semantics
     were missed, which is why "token-clean" pages still looked wrong. */
  --bs-primary:                  var(--pl-primary);
  --bs-primary-rgb:              30, 60, 114;
  --bs-secondary:                var(--pl-text-muted);
  --bs-success:                  var(--pl-success);
  --bs-success-rgb:              78, 122, 102;
  --bs-warning:                  var(--pl-warning);
  --bs-warning-rgb:              201, 74, 45;
  --bs-danger:                   var(--pl-danger);
  --bs-danger-rgb:               220, 38, 38;
  --bs-info:                     var(--pl-info);
  --bs-info-rgb:                 53, 121, 170;

  /* The -subtle / -emphasis / -border triplets back .text-bg-*, .bg-*-subtle
     and .text-*-emphasis, which the tree uses far more than the solids. */
  --bs-primary-bg-subtle:        var(--pl-primary-soft);
  --bs-primary-border-subtle:    var(--pl-primary-200);
  --bs-primary-text-emphasis:    var(--pl-primary-700);
  --bs-success-bg-subtle:        var(--pl-success-soft);
  --bs-success-border-subtle:    var(--pl-success-border);
  --bs-success-text-emphasis:    var(--pl-success-text);
  --bs-warning-bg-subtle:        var(--pl-warning-soft);
  --bs-warning-border-subtle:    var(--pl-warning-border);
  --bs-warning-text-emphasis:    var(--pl-warning-text);
  --bs-danger-bg-subtle:         var(--pl-danger-soft);
  --bs-danger-border-subtle:     var(--pl-danger-border);
  --bs-danger-text-emphasis:     var(--pl-danger-text);
  --bs-info-bg-subtle:           var(--pl-info-soft);
  --bs-info-border-subtle:       var(--pl-info-border);
  --bs-info-text-emphasis:       var(--pl-info-text);
  --bs-secondary-bg-subtle:      var(--pl-surface-alt);
  --bs-secondary-border-subtle:  var(--pl-border);
  --bs-secondary-text-emphasis:  var(--pl-text-muted);

  /* Bootstrap's own shape + focus ring, pulled onto the brand geometry. */
  --bs-border-radius:            var(--pl-radius);
  --bs-border-radius-sm:         var(--pl-radius-sm);
  --bs-border-radius-lg:         var(--pl-radius-lg);
  --bs-border-radius-xl:         var(--pl-radius-lg);
  --bs-border-radius-2xl:        var(--pl-radius-2xl);
  --bs-border-radius-pill:       var(--pl-radius-pill);
}

/* ── 02. Dark-mode token overrides ──────────────────────────── */
[data-theme="dark"] {
  color-scheme: dark;

  /* Text — bump subtle to pass WCAG */
  --pl-text:         #eef3f9;
  --pl-text-muted:   #93a5bd;
  --pl-text-subtle:  #8b9cb6;
  --pl-text-strong:  #ffffff;
  --pl-text-inverse: #0a1330;

  /* Surfaces — the brand ink ramp from the marketing site: the void
     (#060c1e) is the canvas, ink (#0a1330) the resting surface, the brand
     navy (#0d1b3e) one step up, navy-up (#14244f) the raised plane. */
  --pl-bg:               #060c1e;
  --pl-surface:          #0a1330;
  --pl-surface-alt:      #0d1b3e;
  --pl-surface-elevated: #14244f;
  --pl-surface-sunken:   #040814;
  --pl-elevation-1:      #0d1b3e;
  --pl-elevation-2:      #14244f;
  --pl-elevation-3:      #1b2f63;

  /* Borders — must be visible */
  --pl-border:          rgba(255, 255, 255, 0.12);
  --pl-border-strong:   rgba(255, 255, 255, 0.22);
  --pl-border-hairline: rgba(255, 255, 255, 0.06);

  /* Brand alias re-tuned for legibility on dark. The ink ramp swallows the
     navy scale, so dark mode accents ride on the sky tint (#8bbedd) — the
     marketing site's own on-dark accent — well above 4.5:1 on the void. */
  --pl-primary:        #8bbedd;
  --pl-primary-hover:  #a9d2e9;
  --pl-primary-soft:   rgba(59, 134, 188, 0.20);
  --pl-primary-ring:   rgba(139, 190, 221, 0.32);
  --pl-primary-light:  #8bbedd;
  --pl-on-primary:     #071626;

  /* Status solids — brand semantics with on-dark tints (sage-lt / coral-lt) */
  --pl-success:        #7a9e8e;
  --pl-success-soft:   rgba(122, 158, 142, 0.16);
  --pl-success-border: rgba(122, 158, 142, 0.35);
  --pl-success-text:   #a9cfbe;
  --pl-success-icon:   #a9cfbe;
  --pl-on-success:     #0a1a13;

  --pl-warning:        #e8593a;
  --pl-warning-soft:   rgba(201, 74, 45, 0.20);
  --pl-warning-border: rgba(232, 89, 58, 0.38);
  --pl-warning-text:   #ffab96;
  --pl-warning-icon:   #ffab96;
  --pl-on-warning:     #2b0d05;

  --pl-danger:         #ef4444;
  --pl-danger-soft:    rgba(220, 38, 38, 0.18);
  --pl-danger-border:  rgba(220, 38, 38, 0.35);
  --pl-danger-text:    #f87171;
  --pl-danger-icon:    #f87171;
  --pl-on-danger:      #2d0606;

  --pl-info:           #5fa3d0;
  --pl-info-soft:      rgba(59, 134, 188, 0.20);
  --pl-info-border:    rgba(59, 134, 188, 0.40);
  --pl-info-text:      #8bbedd;
  --pl-info-icon:      #8bbedd;
  --pl-on-info:        #06131e;

  /* The -50 tints are the palest step of each status ramp and several kits use
     them as a BACKGROUND (team_management, brand_wizard, the clinic toast).
     They were defined only in light, so in dark those surfaces stayed
     near-white with near-white text on them. Flip them to the same
     translucent wash the -soft step uses, one shade calmer. */
  --pl-success-50:     rgba(122, 158, 142, 0.10);
  --pl-warning-50:     rgba(201, 74, 45, 0.12);
  --pl-danger-50:      rgba(220, 38, 38, 0.11);
  --pl-info-50:        rgba(59, 134, 188, 0.12);

  /* Same defect in the brand accent family: the -soft steps are marketing-site
     paper tints (#fdeee9 / #ebf4fb / #f0f5f2) and read as white plates on the
     void. The solids themselves stay put — they are already on-dark legible. */
  --pl-coral-soft:     rgba(232, 89, 58, 0.16);
  --pl-sky-soft:       rgba(59, 134, 188, 0.16);
  --pl-sage-soft:      rgba(122, 158, 142, 0.16);

  /* Extended palette — deprecated purple/pink, aliased onto sky/coral to match
     the light block. See the note beside their light-mode declarations. */
  --pl-purple-soft:   rgba(59, 134, 188, 0.20);
  --pl-purple-border: rgba(59, 134, 188, 0.35);
  --pl-purple-text:   var(--pl-sky-light);

  --pl-pink-soft:     rgba(232, 89, 58, 0.18);
  --pl-pink-border:   rgba(232, 89, 58, 0.35);
  --pl-pink-text:     var(--pl-coral-light);

  --pl-cyan-soft:     rgba(8, 145, 178, 0.18);
  --pl-cyan-border:   rgba(8, 145, 178, 0.35);
  --pl-cyan-text:     #67e8f9;

  --pl-rating-star:   #fbbf24;
  --pl-code-bg:       #0a1120;
  --pl-code-fg:       #e3eaf2;

  /* Links — sky tint in dark */
  --pl-link:       #8bbedd;
  --pl-link-hover: #a9d2e9;

  /* Overlays */
  --pl-overlay:        rgba(3, 7, 20, 0.7);
  --pl-overlay-strong: rgba(0, 0, 0, 0.78);
  --pl-overlay-light:  rgba(3, 7, 20, 0.4);

  /* Glass */
  --pl-glass-bg:     rgba(10, 19, 48, 0.72);
  --pl-glass-border: rgba(255, 255, 255, 0.08);

  /* Shadows — cover ALL sizes (xs, sm, base, md, lg, xl, 2xl, inner) */
  --pl-shadow-xs:    0 1px 1px rgba(0, 0, 0, 0.35);
  --pl-shadow-sm:    0 1px 2px rgba(0, 0, 0, 0.4);
  --pl-shadow:       0 1px 3px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.3);
  --pl-shadow-md:    0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -2px rgba(0, 0, 0, 0.4);
  --pl-shadow-lg:    0 10px 25px -10px rgba(0, 0, 0, 0.6);
  --pl-shadow-xl:    0 20px 35px -10px rgba(0, 0, 0, 0.7);
  --pl-shadow-2xl:   0 25px 50px -12px rgba(0, 0, 0, 0.8);
  --pl-shadow-inner: inset 0 1px 2px rgba(0, 0, 0, 0.45);
  --pl-shadow-lift:  0 -6px 18px rgba(0, 0, 0, 0.45), var(--pl-shadow-sm);

  /* Native UI */
  --pl-accent:                   #8bbedd;
  --pl-focus-ring:               rgba(139, 190, 221, 0.40);
  --pl-focus-ring-offset-color:  var(--pl-bg);
  --pl-scrollbar-track:          transparent;
  --pl-scrollbar-thumb:          rgba(255, 255, 255, 0.14);
  --pl-scrollbar-thumb-hover:    rgba(255, 255, 255, 0.28);
  --pl-selection-bg:             rgba(59, 134, 188, 0.45);
  --pl-selection-fg:             #eef3f9;

  /* Inputs */
  --pl-input-bg:        rgba(255, 255, 255, 0.03);
  --pl-input-bg-hover:  rgba(59, 134, 188, 0.12);

  /* Tint family (auto-flips) */
  --pl-primary-tint:        rgba(59, 134, 188, 0.16);
  --pl-primary-tint-hover:  rgba(59, 134, 188, 0.28);
  --pl-primary-on-tint:     #8bbedd;
  --pl-success-tint:        rgba(122, 158, 142, 0.18);
  --pl-success-on-tint:     #a9cfbe;
  --pl-neutral-tint:        rgba(255, 255, 255, 0.06);
  --pl-icon-accent:         #8bbedd;

  /* Skeleton */
  --pl-skeleton-from: #0d1b3e;
  --pl-skeleton-via:  #1b2f63;
  --pl-skeleton-to:   #0d1b3e;

  /* Tile (DS-09, 2026-09-23). The flat navy tile (#0d1b3e) on the void
     (#060c1e) measured ~1.14:1 and was the same colour as --pl-surface-alt,
     so the header tile vanished on every alt band in dark. Raised to the
     brand-up step and edged with the theme hairline so it reads as a plane;
     ink stays white. */
  --pl-tile-gradient: var(--pl-brand-up);
  --pl-tile-shadow:   inset 0 0 0 1px var(--pl-border);

  /* Bootstrap -rgb bridges follow the solids they bridge. Without these,
     .bg-primary / .bg-opacity-* / .text-bg-* and the .btn focus ring painted
     light-mode navy on ink while --pl-primary had flipped to sky. */
  --bs-primary-rgb:  139, 190, 221;
  --bs-success-rgb:  122, 158, 142;
  --bs-warning-rgb:  232, 89, 58;
  --bs-danger-rgb:   239, 68, 68;
  --bs-info-rgb:     95, 163, 208;
}

/* ── Theme-swap transition lock (toggled by PL.theme JS) ────── */
html.pl-theme-switching *,
html.pl-theme-switching *::before,
html.pl-theme-switching *::after {
  transition: none !important;
  animation-duration: 0s !important;
}

/* ── 03. Bootstrap variable bridges ─────────────────────────── */
.btn-primary {
  --bs-btn-bg: var(--pl-primary);
  --bs-btn-color: var(--pl-on-primary);
  --bs-btn-border-color: var(--pl-primary);
  --bs-btn-hover-bg: var(--pl-primary-hover);
  --bs-btn-hover-color: var(--pl-on-primary);
  --bs-btn-hover-border-color: var(--pl-primary-hover);
  --bs-btn-active-bg: var(--pl-primary-hover);
  --bs-btn-active-color: var(--pl-on-primary);
  --bs-btn-active-border-color: var(--pl-primary-hover);
  --bs-btn-disabled-bg: var(--pl-primary);
  --bs-btn-disabled-color: var(--pl-on-primary);
  --bs-btn-disabled-border-color: var(--pl-primary);
}
.btn-outline-primary {
  --bs-btn-color: var(--pl-primary);
  --bs-btn-border-color: var(--pl-primary);
  --bs-btn-hover-bg: var(--pl-primary);
  --bs-btn-hover-color: var(--pl-on-primary);
  --bs-btn-hover-border-color: var(--pl-primary);
  --bs-btn-active-bg: var(--pl-primary);
  --bs-btn-active-color: var(--pl-on-primary);
  --bs-btn-active-border-color: var(--pl-primary);
  --bs-btn-disabled-color: var(--pl-primary);
  --bs-btn-disabled-border-color: var(--pl-primary);
}
.btn-primary, .btn-outline-primary {
  /* Reads the bridge so the ring follows the theme (sky in dark). */
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
}

/* Secondary / light — neutral surfaces */
.btn-secondary {
  --bs-btn-bg: var(--pl-surface-alt);
  --bs-btn-color: var(--pl-text);
  --bs-btn-border-color: var(--pl-border-strong);
  --bs-btn-hover-bg: var(--pl-surface-elevated);
  --bs-btn-hover-color: var(--pl-text);
  --bs-btn-hover-border-color: var(--pl-border-strong);
  --bs-btn-active-bg: var(--pl-surface-elevated);
  --bs-btn-active-color: var(--pl-text);
  --bs-btn-active-border-color: var(--pl-border-strong);
  --bs-btn-disabled-bg: var(--pl-surface-sunken);
  --bs-btn-disabled-color: var(--pl-text-subtle);
  --bs-btn-disabled-border-color: var(--pl-border);
}
.btn-light {
  --bs-btn-bg: var(--pl-surface);
  --bs-btn-color: var(--pl-text);
  --bs-btn-border-color: var(--pl-border);
  --bs-btn-hover-bg: var(--pl-surface-alt);
  --bs-btn-hover-color: var(--pl-text);
  --bs-btn-hover-border-color: var(--pl-border-strong);
  --bs-btn-active-bg: var(--pl-surface-alt);
  --bs-btn-active-color: var(--pl-text);
  --bs-btn-active-border-color: var(--pl-border-strong);
  --bs-btn-disabled-bg: var(--pl-surface-sunken);
  --bs-btn-disabled-color: var(--pl-text-subtle);
  --bs-btn-disabled-border-color: var(--pl-border);
}

/* Status solid buttons */
.btn-success {
  --bs-btn-bg: var(--pl-success);
  --bs-btn-color: var(--pl-on-success);
  --bs-btn-border-color: var(--pl-success);
  --bs-btn-hover-bg: var(--pl-success);
  --bs-btn-hover-color: var(--pl-on-success);
  --bs-btn-hover-border-color: var(--pl-success);
  --bs-btn-active-bg: var(--pl-success);
  --bs-btn-active-color: var(--pl-on-success);
  --bs-btn-active-border-color: var(--pl-success);
  --bs-btn-disabled-bg: var(--pl-success);
  --bs-btn-disabled-color: var(--pl-on-success);
  --bs-btn-disabled-border-color: var(--pl-success);
  --bs-btn-focus-shadow-rgb: 78, 122, 102;
}
.btn-warning {
  --bs-btn-bg: var(--pl-warning);
  --bs-btn-color: var(--pl-on-warning);
  --bs-btn-border-color: var(--pl-warning);
  --bs-btn-hover-bg: var(--pl-warning);
  --bs-btn-hover-color: var(--pl-on-warning);
  --bs-btn-hover-border-color: var(--pl-warning);
  --bs-btn-active-bg: var(--pl-warning);
  --bs-btn-active-color: var(--pl-on-warning);
  --bs-btn-active-border-color: var(--pl-warning);
  --bs-btn-disabled-bg: var(--pl-warning);
  --bs-btn-disabled-color: var(--pl-on-warning);
  --bs-btn-disabled-border-color: var(--pl-warning);
  --bs-btn-focus-shadow-rgb: 201, 74, 45;
}
.btn-danger {
  --bs-btn-bg: var(--pl-danger);
  --bs-btn-color: var(--pl-on-danger);
  --bs-btn-border-color: var(--pl-danger);
  --bs-btn-hover-bg: var(--pl-danger);
  --bs-btn-hover-color: var(--pl-on-danger);
  --bs-btn-hover-border-color: var(--pl-danger);
  --bs-btn-active-bg: var(--pl-danger);
  --bs-btn-active-color: var(--pl-on-danger);
  --bs-btn-active-border-color: var(--pl-danger);
  --bs-btn-disabled-bg: var(--pl-danger);
  --bs-btn-disabled-color: var(--pl-on-danger);
  --bs-btn-disabled-border-color: var(--pl-danger);
  --bs-btn-focus-shadow-rgb: 220, 38, 38;
}
.btn-info {
  --bs-btn-bg: var(--pl-info);
  --bs-btn-color: var(--pl-on-info);
  --bs-btn-border-color: var(--pl-info);
  --bs-btn-hover-bg: var(--pl-info);
  --bs-btn-hover-color: var(--pl-on-info);
  --bs-btn-hover-border-color: var(--pl-info);
  --bs-btn-active-bg: var(--pl-info);
  --bs-btn-active-color: var(--pl-on-info);
  --bs-btn-active-border-color: var(--pl-info);
  --bs-btn-disabled-bg: var(--pl-info);
  --bs-btn-disabled-color: var(--pl-on-info);
  --bs-btn-disabled-border-color: var(--pl-info);
  --bs-btn-focus-shadow-rgb: 53, 121, 170;
}

/* Outline status buttons */
.btn-outline-secondary {
  --bs-btn-color: var(--pl-text);
  --bs-btn-border-color: var(--pl-border-strong);
  --bs-btn-hover-bg: var(--pl-surface-alt);
  --bs-btn-hover-color: var(--pl-text);
  --bs-btn-hover-border-color: var(--pl-border-strong);
  --bs-btn-active-bg: var(--pl-surface-alt);
  --bs-btn-active-color: var(--pl-text);
  --bs-btn-active-border-color: var(--pl-border-strong);
  --bs-btn-disabled-color: var(--pl-text-subtle);
  --bs-btn-disabled-border-color: var(--pl-border);
}
.btn-outline-light {
  --bs-btn-color: var(--pl-text);
  --bs-btn-border-color: var(--pl-border);
  --bs-btn-hover-bg: var(--pl-surface-alt);
  --bs-btn-hover-color: var(--pl-text);
  --bs-btn-hover-border-color: var(--pl-border-strong);
  --bs-btn-active-bg: var(--pl-surface-alt);
  --bs-btn-active-color: var(--pl-text);
  --bs-btn-active-border-color: var(--pl-border-strong);
  --bs-btn-disabled-color: var(--pl-text-subtle);
  --bs-btn-disabled-border-color: var(--pl-border);
}
.btn-outline-success {
  --bs-btn-color: var(--pl-success-text);
  --bs-btn-border-color: var(--pl-success);
  --bs-btn-hover-bg: var(--pl-success);
  --bs-btn-hover-color: var(--pl-on-success);
  --bs-btn-hover-border-color: var(--pl-success);
  --bs-btn-active-bg: var(--pl-success);
  --bs-btn-active-color: var(--pl-on-success);
  --bs-btn-active-border-color: var(--pl-success);
  --bs-btn-disabled-color: var(--pl-success-text);
  --bs-btn-disabled-border-color: var(--pl-success);
  --bs-btn-focus-shadow-rgb: 78, 122, 102;
}
.btn-outline-warning {
  --bs-btn-color: var(--pl-warning-text);
  --bs-btn-border-color: var(--pl-warning);
  --bs-btn-hover-bg: var(--pl-warning);
  --bs-btn-hover-color: var(--pl-on-warning);
  --bs-btn-hover-border-color: var(--pl-warning);
  --bs-btn-active-bg: var(--pl-warning);
  --bs-btn-active-color: var(--pl-on-warning);
  --bs-btn-active-border-color: var(--pl-warning);
  --bs-btn-disabled-color: var(--pl-warning-text);
  --bs-btn-disabled-border-color: var(--pl-warning);
  --bs-btn-focus-shadow-rgb: 201, 74, 45;
}
.btn-outline-danger {
  --bs-btn-color: var(--pl-danger-text);
  --bs-btn-border-color: var(--pl-danger);
  --bs-btn-hover-bg: var(--pl-danger);
  --bs-btn-hover-color: var(--pl-on-danger);
  --bs-btn-hover-border-color: var(--pl-danger);
  --bs-btn-active-bg: var(--pl-danger);
  --bs-btn-active-color: var(--pl-on-danger);
  --bs-btn-active-border-color: var(--pl-danger);
  --bs-btn-disabled-color: var(--pl-danger-text);
  --bs-btn-disabled-border-color: var(--pl-danger);
  --bs-btn-focus-shadow-rgb: 220, 38, 38;
}
.btn-outline-info {
  --bs-btn-color: var(--pl-info-text);
  --bs-btn-border-color: var(--pl-info);
  --bs-btn-hover-bg: var(--pl-info);
  --bs-btn-hover-color: var(--pl-on-info);
  --bs-btn-hover-border-color: var(--pl-info);
  --bs-btn-active-bg: var(--pl-info);
  --bs-btn-active-color: var(--pl-on-info);
  --bs-btn-active-border-color: var(--pl-info);
  --bs-btn-disabled-color: var(--pl-info-text);
  --bs-btn-disabled-border-color: var(--pl-info);
  --bs-btn-focus-shadow-rgb: 53, 121, 170;
}

/* Dark mode: button-color refinements */
[data-theme="dark"] .btn-primary {
  --bs-btn-color:        var(--pl-on-primary);
  --bs-btn-hover-color:  var(--pl-on-primary);
  --bs-btn-active-color: var(--pl-on-primary);
}
[data-theme="dark"] .btn-light {
  --bs-btn-bg:                  var(--pl-surface-alt);
  --bs-btn-color:               var(--pl-text);
  --bs-btn-border-color:        var(--pl-border);
  --bs-btn-hover-bg:            var(--pl-surface-elevated);
  --bs-btn-hover-color:         var(--pl-text);
  --bs-btn-hover-border-color:  var(--pl-border-strong);
  --bs-btn-active-bg:           var(--pl-surface-elevated);
  --bs-btn-disabled-bg:         var(--pl-surface-sunken);
  --bs-btn-disabled-color:      var(--pl-text-subtle);
}
[data-theme="dark"] .btn-secondary {
  --bs-btn-bg:                  var(--pl-surface-alt);
  --bs-btn-color:               var(--pl-text);
  --bs-btn-border-color:        var(--pl-border-strong);
  --bs-btn-hover-bg:            var(--pl-surface-elevated);
  --bs-btn-hover-color:         var(--pl-text);
  --bs-btn-hover-border-color:  var(--pl-border-strong);
}
[data-theme="dark"] .btn:disabled,
[data-theme="dark"] .btn.disabled { opacity: 0.55; }

/* Bootstrap utility overrides for dark mode */
[data-theme="dark"] .bg-white  { background-color: var(--pl-surface) !important; color: var(--pl-text) !important; }
[data-theme="dark"] .bg-light  { background-color: var(--pl-surface-alt) !important; color: var(--pl-text) !important; }
[data-theme="dark"] .bg-body   { background-color: var(--pl-bg) !important; }
[data-theme="dark"] .bg-body-tertiary,
[data-theme="dark"] .bg-body-secondary { background-color: var(--pl-surface-alt) !important; }
[data-theme="dark"] .text-dark { color: var(--pl-text) !important; }
[data-theme="dark"] .text-black { color: var(--pl-text-strong) !important; }
[data-theme="dark"] .text-body-secondary { color: var(--pl-text-muted) !important; }
[data-theme="dark"] .shadow-sm { box-shadow: var(--pl-shadow-sm) !important; }
[data-theme="dark"] .shadow    { box-shadow: var(--pl-shadow) !important; }
[data-theme="dark"] .shadow-lg { box-shadow: var(--pl-shadow-lg) !important; }
[data-theme="dark"] .border    { border-color: var(--pl-border) !important; }
[data-theme="dark"] .border-top, [data-theme="dark"] .border-bottom,
[data-theme="dark"] .border-start, [data-theme="dark"] .border-end { border-color: var(--pl-border) !important; }
[data-theme="dark"] hr { border-color: var(--pl-border); opacity: 1; }

a { color: var(--pl-link); text-decoration: none; }
a:hover { color: var(--pl-link-hover); }

/* ── 04. Reset / typography ─────────────────────────────────── */
html, body { height: 100%; }
body {
  background: var(--pl-bg);
  color: var(--pl-text);
  font-family: var(--pl-font-sans);
  font-size: var(--pl-fs-base);
  line-height: var(--pl-lh-base);
  font-feature-settings: "cv02", "cv03", "cv04", "cv11", "ss01";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}
.tabular-nums, .pl-num { font-variant-numeric: tabular-nums; }

h1, h2, h3, h4, h5, h6 {
  color: var(--pl-text);
  font-weight: var(--pl-fw-semibold);
  letter-spacing: -0.011em;
  line-height: var(--pl-lh-tight);
}
h1 { font-size: var(--pl-fs-3xl); font-weight: var(--pl-fw-bold); }
h2 { font-size: var(--pl-fs-2xl); font-weight: var(--pl-fw-bold); }
h3 { font-size: var(--pl-fs-xl); }
h4 { font-size: var(--pl-fs-lg); }
h5 { font-size: var(--pl-fs-md); }
h6 { font-size: var(--pl-fs-base); }

.text-muted { color: var(--pl-text-muted) !important; }
.text-subtle { color: var(--pl-text-subtle) !important; }
.label-caps {
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pl-text-subtle);
}

/* Focus — ONE ring for the kit (2026-09-23). A crisp 2px outline in the
   primary plus a soft --pl-focus-ring halo (the token flips to sky in dark).
   .btn is named so this beats Bootstrap's own .btn:focus-visible, which zeroes
   the outline; form controls keep their :focus ring (§05, higher specificity,
   by design). Component rules that need to keep an inset hairline under the
   ring (a.pl-stat, a.pl-kpi) restate the shadow with both layers. */
.btn:focus-visible, a:focus-visible, button:focus-visible, input:focus-visible,
select:focus-visible, textarea:focus-visible, summary:focus-visible,
[tabindex]:focus-visible, :focus-visible {
  outline: 2px solid var(--pl-primary);
  outline-offset: 2px;
  box-shadow: 0 0 0 3px var(--pl-focus-ring);
}
.form-control, .form-select {
  /* background-COLOR, not the `background` shorthand: the shorthand resets
     background-repeat/position/size, which wipes the .form-select dropdown
     chevron's no-repeat and makes the SVG tile across the whole field. */
  background-color: var(--pl-surface);
  color: var(--pl-text);
  border-color: var(--pl-border);
}
.form-control:focus, .form-select:focus {
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
  background-color: var(--pl-surface);
  color: var(--pl-text);
}
.form-control::placeholder { color: var(--pl-text-subtle); }
.form-label { font-weight: var(--pl-fw-medium); font-size: var(--pl-fs-base); color: var(--pl-text); }

/* ── Native UI: selection, scrollbars, accent, autofill ────── */
::selection      { background: var(--pl-selection-bg); color: var(--pl-selection-fg); }
::-moz-selection { background: var(--pl-selection-bg); color: var(--pl-selection-fg); }

html { scrollbar-color: var(--pl-scrollbar-thumb) var(--pl-scrollbar-track); scrollbar-width: thin; }
::-webkit-scrollbar { width: 7px; height: 7px; }
::-webkit-scrollbar-track { background: var(--pl-scrollbar-track); }
::-webkit-scrollbar-thumb {
  background: var(--pl-scrollbar-thumb);
  border-radius: 999px;
  border: 1px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--pl-scrollbar-thumb-hover);
  background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: transparent; }

/* Accent on native controls */
input, textarea, select, progress { accent-color: var(--pl-accent); }

/* Autofill */
input:-webkit-autofill,
textarea:-webkit-autofill,
select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--pl-input-bg) inset;
  -webkit-text-fill-color: var(--pl-text);
  caret-color: var(--pl-text);
  transition: background-color 5000s ease-in-out 0s;
}
[data-theme="dark"] input:-webkit-autofill,
[data-theme="dark"] textarea:-webkit-autofill,
[data-theme="dark"] select:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 1000px var(--pl-surface-alt) inset;
}

/* Dark mode: native date/time picker indicator inversion */
[data-theme="dark"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="time"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="datetime-local"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="month"]::-webkit-calendar-picker-indicator,
[data-theme="dark"] input[type="week"]::-webkit-calendar-picker-indicator {
  filter: invert(1) brightness(0.85);
  opacity: 0.7;
}

/* Dark mode: Bootstrap form-select chevron.
   Repeat/position/size are restated here (not just background-image): surfaces
   that swap in the dark chevron without Bootstrap's base .form-select rule
   (e.g. wizards loading brand_wizard.css) would otherwise tile the SVG across
   the whole field. */
[data-theme="dark"] .form-select {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%238c9bb3' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 0.75rem center;
  background-size: 16px 12px;
}

/* Disabled controls */
.form-control:disabled,
.form-select:disabled,
.form-check-input:disabled {
  background-color: var(--pl-surface-sunken);
  color: var(--pl-text-subtle);
  border-color: var(--pl-border);
  cursor: not-allowed;
}

/* ── 05. App shell layout ───────────────────────────────────── */
/* Pre-paint state restore (see the sidebar bootstrap in base.html): freeze all
   motion until the first frame is on screen, so a restored collapsed sidebar
   appears already collapsed instead of sliding shut on every page load. */
.pl-boot *,
.pl-boot *::before,
.pl-boot *::after {
  transition: none !important;
  animation: none !important;
}
.pl-app {
  display: grid;
  grid-template-columns: var(--pl-sidebar-w) 1fr;
  min-height: 100vh;
  transition: grid-template-columns var(--pl-dur-base) var(--pl-ease);
}
.pl-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

/* ── 06. Sidebar ────────────────────────────────────────────── */
/* Brand navy gradient — anchored on the logo ink #0d1b3e (var(--pl-brand),
   logos/logo-platinum-horizontal.svg). A slightly lifted navy at the top
   settles into the exact brand navy, then deepens to near-black with a soft
   fade-out at the bottom. */
.pl-sidebar {
  /* A FLAT ink plane. The site builds contrast by stacking solid bands
     (.h27-act--ink / --void) and separating them with a hairline; it uses no
     gradient fills and no drop shadows on chrome anywhere. A vertical navy
     gradient under a 12px black shadow is the 2018-2020 admin-template
     signature and was the single most dating detail in the shell. */
  background: var(--pl-brand-ink);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  box-shadow: none;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
  z-index: var(--pl-z-sidebar);
  display: flex;
  flex-direction: column;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.08) transparent;
}
.pl-sidebar::-webkit-scrollbar { width: 3px; }
.pl-sidebar::-webkit-scrollbar-track { background: transparent; }
.pl-sidebar::-webkit-scrollbar-thumb { background-color: rgba(255, 255, 255, 0.08); border-radius: var(--pl-radius-pill); }
.pl-sidebar::-webkit-scrollbar-thumb:hover { background-color: rgba(255, 255, 255, 0.2); }

/* The bottom fade existed to hide the seam where the sidebar gradient met the
   viewport edge. The plane is flat now, so there is no seam and the fade only
   dimmed the last nav item. Removed. */

.pl-sidebar__brand {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0 1rem;
  height: var(--pl-topbar-h);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  font-weight: var(--pl-fw-bold);
  font-size: 1.375rem;
  color: #fff;
  text-decoration: none;
  letter-spacing: 0.04em;
  flex-shrink: 0;
}
.pl-sidebar__brand:hover { color: #fff; }

/* Two cuts of the same logo: the horizontal wordmark when the sidebar is
   expanded, the icon-only mark in the collapsed rail. Exactly one is visible
   at a time — the rail swap lives in the collapsed block further down. */
.pl-sidebar__brand-wordmark {
  height: 26px;
  width: auto;
  max-width: 100%;
  display: block;
  flex: 0 1 auto;
  min-width: 0;
  object-fit: contain;
  object-position: left center;
  transition: transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__brand-mark {
  height: 30px;
  width: 30px;
  display: none;
  flex-shrink: 0;
  object-fit: contain;
  transition: transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__brand:hover .pl-sidebar__brand-wordmark,
.pl-sidebar__brand:hover .pl-sidebar__brand-mark { transform: scale(1.04); }
.pl-sidebar__brand-tier {
  margin-left: auto;
  font-size: 0.5625rem;
  line-height: 1;
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  padding: 0.1rem 0.375rem;
}
.pl-sidebar__brand:hover .pl-sidebar__brand-tier {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}

.pl-sidebar__tenant {
  margin: 0.5rem 0.75rem;
  padding: 0.5rem 0.625rem;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--pl-radius);
  display: flex; align-items: center; gap: 0.5rem;
  font-size: var(--pl-fs-sm);
  color: rgba(255, 255, 255, 0.92);
  cursor: pointer;
  transition: background-color var(--pl-dur-fast) var(--pl-ease);
  text-decoration: none;
}
.pl-sidebar__tenant:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}
.pl-sidebar__tenant .bi { color: rgba(255, 255, 255, 0.75); }
.pl-sidebar__tenant-name {
  flex: 1 1 auto;
  font-weight: var(--pl-fw-semibold);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.pl-sidebar__tenant-tier {
  font-size: var(--pl-fs-xs);
  color: rgba(255, 255, 255, 0.6);
  text-transform: capitalize;
}

.pl-sidebar__search {
  padding: 0 0.75rem 0.5rem;
  position: relative;
}
.pl-sidebar__search input {
  width: 100%;
  height: 32px;
  padding: 0 0.625rem 0 2rem;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--pl-radius-sm);
  font-size: var(--pl-fs-sm);
  color: #fff;
}
.pl-sidebar__search input::placeholder { color: rgba(255, 255, 255, 0.5); }
.pl-sidebar__search input:focus {
  background: rgba(255, 255, 255, 0.1);
  /* A 25%-alpha sky ring was all but invisible against the navy rail. The
     replacement ring for a cancelled outline has to be readable on the surface
     it actually sits on, which here is the darkest plane in the app. */
  border-color: var(--pl-sky-light);
  box-shadow: 0 0 0 3px rgba(139, 190, 221, 0.45);
  outline: none;
}
.pl-sidebar__search .bi {
  position: absolute; left: 1.375rem; top: 50%;
  transform: translateY(-50%);
  color: rgba(255, 255, 255, 0.55); font-size: 0.85rem;
  pointer-events: none;
}

.pl-sidebar__nav {
  padding: 0.25rem 0.5rem 1rem;
  flex: 1 1 auto;
}
.pl-sidebar__section-label {
  padding: 0.875rem 0.875rem 0.25rem;
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-bold);
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.55);
  text-transform: uppercase;
  display: flex; align-items: center; gap: 0.375rem;
}
.pl-sidebar__section-label .bi { font-size: 0.75rem; opacity: 0.6; }

.pl-sidebar__group { margin-top: 0.125rem; }
.pl-sidebar__group-label {
  padding: 0.5rem 0.875rem 0.25rem;
  font-size: 0.625rem;
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.12em;
  color: rgba(255, 255, 255, 0.4);
  text-transform: uppercase;
  display: flex; align-items: center; justify-content: space-between;
  cursor: default; user-select: none;
  border-radius: var(--pl-radius-sm);
}
/* The plain label is a non-interactive caption (cursor:default, no tabindex),
   so cancelling its outline costs nothing. The [data-pl-group-toggle] variant
   below IS a control, and this blanket rule was silently stripping its focus
   ring too — a keyboard user collapsing a nav group had no indicator. */
.pl-sidebar__group-label:focus { outline: none; }
.pl-sidebar__group-label:focus-visible { outline: none; }
.pl-sidebar__group-label[data-pl-group-toggle]:focus-visible {
  /* The rail is the brand navy in both themes, so the ring is on-dark ink, not
     --pl-primary-ring (which is tuned for light surfaces). */
  box-shadow: 0 0 0 2px rgba(139, 190, 221, 0.65);
}
/* Collapsible section header — interactive variant (e.g. SUBSCRIPTIONS). */
.pl-sidebar__group-label[data-pl-group-toggle] {
  cursor: pointer;
  transition: color var(--pl-dur-fast) var(--pl-ease),
              background-color var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__group-label[data-pl-group-toggle]:hover {
  color: rgba(255, 255, 255, 0.75);
  background: rgba(255, 255, 255, 0.04);
}
.pl-sidebar__group-label[data-pl-group-toggle]:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.3); outline-offset: -2px;
}
/* Caret: hidden on plain labels, shown + rotating on collapsible headers. */
.pl-sidebar__group-label .caret { display: none; }
.pl-sidebar__group-label[data-pl-group-toggle] .caret {
  display: inline-block;
  font-size: 0.6rem;
  color: rgba(255, 255, 255, 0.35);
  transition: transform var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__group-label[data-pl-group-toggle]:hover .caret { color: rgba(255, 255, 255, 0.7); }
.pl-sidebar__group.is-collapsed > .pl-sidebar__group-label[data-pl-group-toggle] .caret {
  transform: rotate(-90deg);
}
.pl-sidebar__group.is-collapsed .pl-sidebar__items { display: none; }

/* ── Nested sidebar groups (two-level menus, e.g. Digital Presence) ── */
.pl-sidebar__group-icon {
  display: inline-block;
  font-size: 0.75rem;
  margin-right: 0.4rem;
  opacity: 0.7;
  vertical-align: -1px;
}
.pl-sidebar__group--nested {
  margin-top: 0.125rem;
}
/* Category rows: icon sits in the same fixed 20px column as leaf-item icons
   so every glyph in the sidebar lines up vertically. */
.pl-sidebar__group-label--nested > span {
  display: flex; align-items: center; gap: 0.625rem;
  min-width: 0; overflow: hidden;
}
.pl-sidebar__group-label--nested .pl-sidebar__group-icon {
  font-size: 1.1rem;
  width: 20px;
  text-align: center;
  margin-right: 0;
  opacity: 0.85;
  flex-shrink: 0;
  vertical-align: baseline;
}
.pl-sidebar__group-label--nested {
  /* Look like a regular .pl-sidebar__item row — including the 3px active rail
     a link reserves, so branch and leaf glyphs share one vertical column. */
  margin-left: 1px;
  border-left: 3px solid transparent;
  padding: 0.4375rem 0.75rem 0.4375rem 0.875rem;
  font-size: var(--pl-fs-md);
  font-weight: var(--pl-fw-medium);
  letter-spacing: normal;
  color: rgba(255, 255, 255, 0.85);
  text-transform: none;
  border-radius: var(--pl-radius-sm);
  cursor: pointer; user-select: none;
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.625rem;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__group-label--nested:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
}
.pl-sidebar__group-label--nested:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.3); outline-offset: -2px;
}
.pl-sidebar__group-label--nested .caret {
  display: inline-block;
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.5);
  transition: transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__group-label--nested:hover .caret { color: rgba(255, 255, 255, 0.85); }
.pl-sidebar__group--nested.is-collapsed > .pl-sidebar__group-label--nested .caret {
  transform: rotate(-90deg);
}
.pl-sidebar__items--nested {
  margin-left: 1.125rem;
  padding-left: 0.375rem;
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.pl-sidebar__items--nested .pl-sidebar__item {
  padding-left: 0.5rem;
  font-size: var(--pl-fs-base);
  color: rgba(255, 255, 255, 0.7);
  position: relative;
}
.pl-sidebar__items--nested .pl-sidebar__item:hover,
.pl-sidebar__items--nested .pl-sidebar__item.is-active {
  color: #fff;
}
/* Every row carries its own icon — a glyph names the destination faster than a
   bullet, and the indent rail already carries the depth cue. Nested glyphs step
   down one notch from the top-level 1.1rem so hierarchy still reads at a glance. */
.pl-sidebar__items--nested .pl-sidebar__item > .bi {
  display: inline-block;
  font-size: 1rem;
  width: 18px;
  color: rgba(255, 255, 255, 0.62);
}
.pl-sidebar__items--nested .pl-sidebar__item:hover > .bi,
.pl-sidebar__items--nested .pl-sidebar__item.is-active > .bi { color: #fff; }

/* ── Item-level sub-menus (third level, e.g. Communications ▸ Compose) ──
   The parent row sits in the same icon column as its sibling links (same glyph
   size, same indent) and only the caret marks it as expandable; its children
   step in once more behind their own rail so depth reads at a glance. */
.pl-sidebar__group--submenu { margin-top: 0; }
.pl-sidebar__group-label--submenu {
  padding: 0.4375rem 0.75rem 0.4375rem 0.5rem;
  /* Same left offset as the leaf rows it sits beside (see --nested above). */
  margin-left: 1px;
  border-left: 3px solid transparent;
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-regular, 400);
  color: rgba(255, 255, 255, 0.7);
  position: relative;
}
/* Branch rows keep their icon in the same 18px column as the leaf rows below. */
.pl-sidebar__group-label--submenu .pl-sidebar__group-icon {
  display: inline-block;
  font-size: 1rem;
  width: 18px;
  opacity: 0.78;
}
.pl-sidebar__group-label--submenu:hover .pl-sidebar__group-icon,
.pl-sidebar__group--submenu.has-active > .pl-sidebar__group-label--submenu .pl-sidebar__group-icon {
  opacity: 1;
}
/* Trail state: the branch holding the current page stays lit while collapsed. */
.pl-sidebar__group--submenu.has-active > .pl-sidebar__group-label--submenu {
  color: #fff;
  font-weight: var(--pl-fw-medium);
}
.pl-sidebar__items--submenu {
  margin-left: 1.25rem;
  padding-left: 0.25rem;
  border-left: 1px solid rgba(255, 255, 255, 0.08);
}
.pl-sidebar__items--submenu .pl-sidebar__item {
  padding-left: 0.4375rem;
  font-size: calc(var(--pl-fs-base) - 0.5px);
  color: rgba(255, 255, 255, 0.62);
}
.pl-sidebar__items--submenu .pl-sidebar__item > .bi {
  font-size: 0.9375rem;
  color: rgba(255, 255, 255, 0.55);
}

.pl-sidebar__items { display: flex; flex-direction: column; gap: 1px; }
.pl-sidebar__item {
  display: flex; align-items: center; gap: 0.625rem;
  padding: 0.4375rem 0.75rem 0.4375rem 0.875rem;
  border-radius: var(--pl-radius-sm);
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--pl-fs-md);
  font-weight: var(--pl-fw-medium);
  border-left: 3px solid transparent;
  margin-left: 1px;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
  position: relative;
  text-decoration: none;
}
.pl-sidebar__item:hover {
  /* Sky-tinted lift — a plain white/navy tint was invisible on the navy rail.
     (The rgba line is the fallback for a browser without color-mix.) */
  background: rgba(255, 255, 255, 0.07);
  background: color-mix(in srgb, var(--pl-sky-light) 14%, transparent);
  color: #fff;
}
.pl-sidebar__item .bi {
  font-size: 1.1rem;
  color: rgba(255, 255, 255, 0.72);
  flex-shrink: 0;
  width: 20px;
  text-align: center;
  transition: color var(--pl-dur-fast) var(--pl-ease);
}
.pl-sidebar__item:hover .bi { color: #fff; }
.pl-sidebar__item.is-active {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-left-color: var(--pl-coral);
  font-weight: var(--pl-fw-semibold);
}
.pl-sidebar__item.is-active .bi { color: #fff; }
.pl-sidebar__item:focus-visible {
  outline: 2px solid rgba(255, 255, 255, 0.3);
  outline-offset: -2px;
}
.pl-sidebar__item-label {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  transition: transform var(--pl-dur-base) var(--pl-ease);
}
/* Counts on the rail. The rail is navy in BOTH themes, so these are one
   on-dark treatment (a solid tone fill measured 2.2–2.6:1 here and failed AA;
   a translucent wash of the tone under the tone's light ink passes). A plain
   count is neutral; a tone is what makes one stand out. Tones are the H27
   status family — sage / coral / red — never amber. */
.pl-sidebar__badge {
  margin-left: auto;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.02em;
  line-height: 1.4;
  padding: 1px 6px; border-radius: var(--pl-radius-pill);
  min-width: 18px; text-align: center;
  flex-shrink: 0;
}
.pl-sidebar__badge--muted {
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.75);
}
.pl-sidebar__badge--success { background: color-mix(in srgb, var(--pl-sage) 24%, transparent);   color: var(--pl-sage-light); }
.pl-sidebar__badge--warning { background: color-mix(in srgb, var(--pl-coral) 22%, transparent);  color: var(--pl-coral-light); }
.pl-sidebar__badge--danger  { background: color-mix(in srgb, var(--pl-danger) 26%, transparent); color: color-mix(in srgb, var(--pl-danger) 55%, var(--pl-neutral-0)); }

.pl-sidebar__footer {
  margin-top: auto;
  padding: 0.75rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  display: flex; align-items: center; gap: 0.625rem;
  flex-shrink: 0;
  background: rgba(0, 0, 0, 0.12);
  color: rgba(255, 255, 255, 0.92);
}
.pl-sidebar__footer .pl-icon-btn {
  color: rgba(255, 255, 255, 0.7);
}
.pl-sidebar__footer .pl-icon-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}
.pl-sidebar__footer-meta {
  flex: 1 1 auto;
  min-width: 0;
  line-height: 1.25;
}
.pl-sidebar__footer-name {
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-semibold);
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pl-sidebar__footer-sub {
  font-size: var(--pl-fs-sm);
  color: rgba(255, 255, 255, 0.6);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── 07. Topbar ─────────────────────────────────────────────── */
.pl-topbar {
  position: sticky; top: 0; z-index: var(--pl-z-topbar);
  background: var(--pl-surface);
  border-bottom: 1px solid var(--pl-border);
  height: var(--pl-topbar-h);
  display: flex; align-items: center;
  padding: 0 1rem;
  gap: 0.75rem;
  /* No backdrop blur. Frosted-glass chrome is a 2020-21 idiom and the brand
     uses none of it — solid surface, hairline underneath. */
}
.pl-topbar__toggle {
  display: inline-flex;
  background: transparent; border: 0;
  width: 40px; height: 40px; border-radius: var(--pl-radius-control);
  color: var(--pl-text-muted); font-size: 1.3rem;
  align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0;
  transition: background var(--pl-dur-fast) var(--pl-ease), color var(--pl-dur-fast) var(--pl-ease), transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-topbar__toggle:hover {
  background: var(--pl-surface-alt);
  color: var(--pl-primary);
}
.pl-topbar__toggle:active { transform: scale(0.92); }
.pl-topbar__toggle:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}
@media (min-width: 769px) {
  /* Collapsed = compact ICON RAIL (mini sidebar), not fully hidden.
     Modern SaaS pattern (Linear / Vercel / Notion): every nav icon stays
     visible and clickable; labels appear as native tooltips on hover. */
  /* The class sits on <html> (set pre-paint by the base.html bootstrap) and is
     mirrored onto .pl-app; both selectors are kept so either carrier works. */
  .pl-app.is-sidebar-collapsed,
  .is-sidebar-collapsed .pl-app { grid-template-columns: var(--pl-sidebar-rail-w) 1fr; }
  .is-sidebar-collapsed .pl-sidebar { width: var(--pl-sidebar-rail-w); }

  /* Brand: swap the horizontal wordmark for the icon-only mark, centered */
  .is-sidebar-collapsed .pl-sidebar__brand { justify-content: center; padding: 0 0.5rem; gap: 0; }
  .is-sidebar-collapsed .pl-sidebar__brand-wordmark { display: none; }
  .is-sidebar-collapsed .pl-sidebar__brand-mark { display: block; }
  .is-sidebar-collapsed .pl-sidebar__brand-tier { display: none; }

  /* Section markers collapse to a hairline divider; group labels hide */
  .is-sidebar-collapsed .pl-sidebar__section-label {
    height: 1px; padding: 0; margin: 0.6rem 0.85rem;
    overflow: hidden; color: transparent;
    background: rgba(255, 255, 255, 0.1);
  }
  .is-sidebar-collapsed .pl-sidebar__section-label .bi { display: none; }
  .is-sidebar-collapsed .pl-sidebar__group-label { display: none; }

  /* Force every item visible even inside a previously-collapsed group */
  .is-sidebar-collapsed .pl-sidebar__group.is-collapsed .pl-sidebar__items { display: block; }

  /* Items: equal-sized square buttons, centered icon, no label */
  .is-sidebar-collapsed .pl-sidebar__items { padding: 0; }
  .is-sidebar-collapsed .pl-sidebar__item {
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    margin: 0.25rem auto;
    border-radius: var(--pl-radius-2xl);
    border-left: 0;
  }
  .is-sidebar-collapsed .pl-sidebar__item .bi { font-size: 1.15rem; width: auto; }
  .is-sidebar-collapsed .pl-sidebar__item-label { display: none; }
  .is-sidebar-collapsed .pl-sidebar__item:hover {
    background: rgba(255, 255, 255, 0.09);
  }
  .is-sidebar-collapsed .pl-sidebar__item.is-active {
    border-left: 0;
    background: rgba(255, 255, 255, 0.14);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  }

  /* Count badges shrink to a notification dot pinned to the icon corner */
  .is-sidebar-collapsed .pl-sidebar__badge {
    position: absolute; top: 6px; right: 6px;
    min-width: 9px; width: 9px; height: 9px; padding: 0;
    font-size: 0; line-height: 0; border-radius: 50%;
    box-shadow: 0 0 0 2px #14244f;
  }

  /* Nested groups flatten: hide sub-headers, drop the indent rail, and let
     every child's icon sit in the same centred column as a top-level row */
  .is-sidebar-collapsed .pl-sidebar__group-label--nested { display: none; }
  .is-sidebar-collapsed .pl-sidebar__items--nested {
    margin-left: 0; padding-left: 0; border-left: 0;
  }
  .is-sidebar-collapsed .pl-sidebar__items--nested .pl-sidebar__item {
    padding-left: 0;
  }
  .is-sidebar-collapsed .pl-sidebar__items--nested .pl-sidebar__item > .bi {
    display: inline-block;
    font-size: 1.15rem;
    width: auto;
  }

  /* Footer: avatar only, centered */
  .is-sidebar-collapsed .pl-sidebar__footer { justify-content: center; padding: 0.75rem 0; }
  .is-sidebar-collapsed .pl-sidebar__footer-meta,
  .is-sidebar-collapsed .pl-sidebar__footer .pl-icon-btn { display: none; }
}

/* ── Topbar breadcrumbs (replaces former .pl-search) ──────── */
.pl-topbar__crumbs {
  flex: 1 1 auto;
  min-width: 0;            /* allow children to truncate */
  overflow: hidden;
  display: flex;
  align-items: center;
}

.pl-topbar__crumbs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: 0.15rem;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;     /* Firefox */
  min-width: 0;
  max-width: 100%;
}
.pl-topbar__crumbs-list::-webkit-scrollbar { display: none; }

.pl-topbar__crumbs-item {
  display: inline-flex;
  align-items: center;
  gap: 0.15rem;
  flex-shrink: 0;
  min-width: 0;
}

.pl-topbar__crumb {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  height: 32px;
  padding: 0 0.65rem;
  border-radius: var(--pl-radius-pill);
  font-size: 0.82rem;
  font-weight: 500;
  color: var(--pl-text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
  max-width: 240px;
}

.pl-topbar__crumb-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.pl-topbar__crumb .bi {
  font-size: 0.95rem;
  flex-shrink: 0;
  opacity: 0.95;
}

.pl-topbar__crumb:hover,
.pl-topbar__crumb:focus-visible {
  background: var(--pl-primary-soft);
  color: var(--pl-primary-700);
  outline: none;
}
.pl-topbar__crumb:focus-visible {
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}

/* Tenant root chip — slightly stronger emphasis */
.pl-topbar__crumb--tenant {
  background: var(--pl-primary-soft);
  color: var(--pl-primary-700);
  font-weight: var(--pl-fw-semibold);
}
.pl-topbar__crumb--tenant:hover {
  background: var(--pl-primary-100);
  color: var(--pl-primary-800);
}
.pl-topbar__crumb--tenant .bi {
  color: var(--pl-primary-600);
}

/* Current page — strongest emphasis, no hover treatment */
.pl-topbar__crumb--current {
  color: var(--pl-text);
  font-weight: var(--pl-fw-semibold);
  cursor: default;
  background: transparent;
}
.pl-topbar__crumb--current:hover {
  background: transparent;
  color: var(--pl-text);
}
.pl-topbar__crumb--current .bi {
  color: var(--pl-primary-600);
}

.pl-topbar__crumbs-sep {
  color: var(--pl-text-subtle);
  font-size: 0.7rem;
  margin: 0 0.05rem;
  flex-shrink: 0;
}

.pl-topbar__actions {
  display: flex; align-items: center; gap: 0.375rem;
  flex-shrink: 0;
  margin-left: 0.5rem;
}

/* Search everything — the CRM command palette's launcher, in the topbar.
   Sits in the actions strip (not pinned over the page) so it is in the same
   place on a dashboard, a report and a record detail, and never lands on top of
   whatever buttons the page put in its top-right corner.

   Styled as a soft search FIELD rather than an icon button: it is the only
   control in this strip that takes typing, and reading as a field is what makes
   somebody click it without being told. Collapses to the bare magnifier below
   lg, where the strip is tight. */
.pl-search {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 4px 10px; border-radius: var(--pl-radius-pill);
  border: 1px solid var(--pl-border); background: var(--pl-surface, var(--bs-body-bg));
  color: var(--pl-text-muted, var(--bs-secondary-color));
  font-size: var(--pl-fs-sm); line-height: 1.4; text-decoration: none;
  transition: border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.pl-search:hover, .pl-search:focus-visible {
  border-color: var(--bs-primary); color: var(--bs-primary);
  box-shadow: 0 1px 6px rgb(13 27 62 / 10%); outline: none;
}
/* A11Y: the rule above cancels the outline and replaces it with a 10% shadow
   that is IDENTICAL to the hover state — keyboard focus was invisible on the
   topbar's search launcher. Restate the real ring after it. */
.pl-search:focus-visible {
  box-shadow: 0 0 0 3px var(--pl-primary-ring), 0 1px 6px rgb(13 27 62 / 10%);
}
.pl-search .bi { font-size: 0.9rem; }
.pl-search__kbd {
  padding: 0 0.32rem; border: 1px solid var(--pl-border); border-radius: 4px;
  background: var(--bs-tertiary-bg, transparent);
  font-family: inherit; font-size: var(--pl-fs-xs, 0.6875rem);
  color: inherit; opacity: 0.85;
}

/* Topbar action button — a labelled control in the actions strip, for work that
   belongs to no single page (currently: "Pull website leads", which sits right
   after the search box). Deliberately shaped like .pl-search — same pill, same
   border, same collapse-to-icon below lg — so the two read as one pair rather
   than as a field with a stray button glued on. It is a <button> inside a POST
   form, so it needs its own reset (buttons don't inherit font or background). */
.pl-topbtn {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 4px 10px; border-radius: var(--pl-radius-pill);
  border: 1px solid var(--pl-border); background: var(--pl-surface, var(--bs-body-bg));
  color: var(--pl-text-muted, var(--bs-secondary-color));
  font-family: inherit; font-size: var(--pl-fs-sm); line-height: 1.4;
  white-space: nowrap; cursor: pointer;
  transition: border-color .15s ease, color .15s ease, box-shadow .15s ease;
}
.pl-topbtn:hover, .pl-topbtn:focus-visible {
  border-color: var(--bs-primary); color: var(--bs-primary);
  box-shadow: 0 1px 6px rgb(13 27 62 / 10%); outline: none;
}
/* A11Y: same defect as .pl-search — focus was styled exactly like hover. */
.pl-topbtn:focus-visible {
  box-shadow: 0 0 0 3px var(--pl-primary-ring), 0 1px 6px rgb(13 27 62 / 10%);
}
.pl-topbtn .bi { font-size: 0.9rem; }

/* Pills */
.pl-pill {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 4px 10px; border-radius: var(--pl-radius-pill);
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  border: 1px solid var(--pl-border);
  background: var(--pl-surface);
  color: var(--pl-text);
  white-space: nowrap;
  line-height: 1.25;
  transition: background-color var(--pl-dur-fast) var(--pl-ease);
}
/* The dot's halo is the dot's own tone at 18% (DS-06, 2026-09-23). It used to
   be Tailwind green-600 / amber-600 / slate-400 rings around sage / coral /
   grey dots — two greens three pixels apart on every page's topbar. */
.pl-pill__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--pl-text-subtle);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-text-subtle) 18%, transparent);
}
.pl-pill--online  { color: var(--pl-success-text); background: var(--pl-success-soft); border-color: var(--pl-success-border); }
.pl-pill--online  .pl-pill__dot { background: var(--pl-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-success) 18%, transparent); animation: pl-pulse 2s ease-in-out infinite; }
.pl-pill--delayed { color: var(--pl-warning-text); background: var(--pl-warning-soft); border-color: var(--pl-warning-border); }
.pl-pill--delayed .pl-pill__dot { background: var(--pl-warning); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-warning) 18%, transparent); }
.pl-pill--offline { color: var(--pl-danger-text); background: var(--pl-danger-soft); border-color: var(--pl-danger-border); }
.pl-pill--offline .pl-pill__dot { background: var(--pl-danger); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-danger) 18%, transparent); }
/* A second dot inside one pill — the CRM → EHR lane beside the EHR → CRM
   verdict. Its own modifier, so the two directions keep their own colour
   even though the pill's background follows the pull. */
.pl-pill__sep { opacity: .55; margin: 0 2px; }
.pl-pill .pl-pill__dot--online  { background: var(--pl-success); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-success) 18%, transparent); animation: none; }
.pl-pill .pl-pill__dot--delayed { background: var(--pl-warning); box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-warning) 18%, transparent); animation: none; }
.pl-pill .pl-pill__dot--ghost   { background: var(--pl-text-subtle); box-shadow: none; animation: none; }
.pl-pill--tenant {
  background: var(--pl-primary-soft);
  color: var(--pl-primary-hover);
  border-color: var(--pl-primary-200);
}
.pl-pill--ghost {
  background: var(--pl-surface-alt);
  border-color: transparent;
  color: var(--pl-text-muted);
}

@keyframes pl-pulse {
  0%, 100% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--pl-success) 18%, transparent); }
  50%      { box-shadow: 0 0 0 5px color-mix(in srgb, var(--pl-success) 8%, transparent); }
}

/* Icon buttons */
.pl-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px;
  border-radius: var(--pl-radius-sm);
  background: transparent; border: 0; color: var(--pl-text);
  position: relative;
  cursor: pointer;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease),
              transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-icon-btn:hover { background: var(--pl-primary-tint); }
.pl-icon-btn:focus-visible { outline: 2px solid var(--pl-primary); outline-offset: 1px; }
.pl-icon-btn .bi { font-size: 1.05rem; }
.pl-icon-btn .pl-icon-btn__dot {
  position: absolute; top: 7px; right: 8px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--pl-danger);
  /* A ring in the topbar's own surface separates the dot from the glyph —
     as a box-shadow, so it never adds to the 8px box. */
  border: 0;
  box-shadow: 0 0 0 2px var(--pl-surface);
}

/* Avatar */
.pl-avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(135deg, var(--pl-primary-500), var(--pl-primary-700));
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  flex-shrink: 0;
  overflow: hidden;
}
.pl-avatar img { width: 100%; height: 100%; object-fit: cover; }
.pl-avatar--xs { width: 20px; height: 20px; font-size: 0.625rem; }
.pl-avatar--sm { width: 24px; height: 24px; font-size: 0.6875rem; }
.pl-avatar--lg { width: 40px; height: 40px; font-size: var(--pl-fs-base); }
.pl-avatar--xl { width: 56px; height: 56px; font-size: var(--pl-fs-lg); }

.pl-avatar-group {
  display: inline-flex;
  align-items: center;
}
.pl-avatar-group > .pl-avatar {
  border: 2px solid var(--pl-surface);
  margin-left: -8px;
}
.pl-avatar-group > .pl-avatar:first-child { margin-left: 0; }
.pl-avatar-group > .pl-avatar-group__more {
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pl-surface-alt);
  color: var(--pl-text-muted);
  border: 2px solid var(--pl-surface);
  margin-left: -8px;
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  border-radius: 50%;
  height: 32px; width: 32px;
}

/* Active-role chip — topbar + account menu. Tone classes use semantic token
   triplets (soft/text/border) that already auto-flip in dark mode. */
.pl-rolebadge {
  display: inline-flex; align-items: center; gap: 0.375rem;
  max-width: 14rem;
  padding: 0.25rem 0.625rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  line-height: 1.1;
  letter-spacing: 0.01em;
  white-space: nowrap;
  vertical-align: middle;
}
.pl-rolebadge .bi { font-size: 0.9em; flex-shrink: 0; }
.pl-rolebadge > span { overflow: hidden; text-overflow: ellipsis; }

.pl-rolebadge--exec       { color: var(--pl-purple-text);  background: var(--pl-purple-soft);  border-color: var(--pl-purple-border); }
.pl-rolebadge--sales      { color: var(--pl-info-text);    background: var(--pl-info-soft);    border-color: var(--pl-info-border); }
.pl-rolebadge--success    { color: var(--pl-success-text); background: var(--pl-success-soft); border-color: var(--pl-success-border); }
.pl-rolebadge--onboarding { color: var(--pl-warning-text); background: var(--pl-warning-soft); border-color: var(--pl-warning-border); }
.pl-rolebadge--marketing  { color: var(--pl-pink-text);    background: var(--pl-pink-soft);    border-color: var(--pl-pink-border); }
.pl-rolebadge--brand,
.pl-rolebadge--clinic     { color: var(--pl-accent);       background: var(--pl-primary-tint); border-color: var(--pl-primary-tint-hover); }
.pl-rolebadge--neutral    { color: var(--pl-text-muted);   background: var(--pl-surface-alt);  border-color: var(--pl-border); }

/* Dark mode: solid topbar + chip refinement (was glass — see the light rule) */
[data-theme="dark"] .pl-topbar {
  background: var(--pl-surface);
  border-bottom-color: var(--pl-border);
}
[data-theme="dark"] .pl-topbar__toggle:hover { background: var(--pl-surface-elevated); }
[data-theme="dark"] .pl-topbar__crumb:hover,
[data-theme="dark"] .pl-topbar__crumb:focus-visible {
  background: var(--pl-primary-tint);
  color: var(--pl-primary-200);
}
[data-theme="dark"] .pl-topbar__crumb--tenant {
  background: var(--pl-primary-tint);
  color: var(--pl-primary-200);
}
[data-theme="dark"] .pl-topbar__crumb--tenant:hover {
  background: var(--pl-primary-tint-hover);
  color: var(--pl-primary-100);
}
[data-theme="dark"] .pl-topbar__crumb--tenant .bi,
[data-theme="dark"] .pl-topbar__crumb--current .bi {
  color: var(--pl-primary-300);
}
[data-theme="dark"] .pl-topbar__crumb--current { color: var(--pl-text-strong); }
[data-theme="dark"] .pl-pill {
  background: var(--pl-surface-alt);
  border-color: var(--pl-border);
  color: var(--pl-text);
}
[data-theme="dark"] .pl-pill--tenant {
  background: var(--pl-primary-tint);
  color: var(--pl-primary-200);
  border-color: var(--pl-primary-tint-hover);
}
[data-theme="dark"] .pl-icon-btn:hover { background: var(--pl-surface-elevated); }

/* ── 08. Impersonation banner ───────────────────────────────── */
.pl-impersonate {
  background: var(--pl-warning-soft);
  border-bottom: 1px solid var(--pl-warning-border);
  color: var(--pl-warning-text);
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-medium);
  padding: 0.5rem 1rem;
  display: flex; align-items: center; gap: 0.75rem;
}
.pl-impersonate .bi { font-size: 1rem; }
.pl-impersonate form { margin-left: auto; }

/* ── 09. Content area & breadcrumbs ─────────────────────────── */
.pl-content {
  flex: 1 1 auto;
  padding: 1.25rem 1.5rem 3rem;
  min-width: 0;
  width: 100%;
}
.pl-content > .container-fluid { padding: 0; }

.pl-crumbs {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.25rem;
  font-size: var(--pl-fs-base);
  color: var(--pl-text-muted);
  margin-bottom: 0.75rem;
}
.pl-crumbs a {
  color: var(--pl-text-muted);
  padding: 2px 4px;
  border-radius: var(--pl-radius-xs);
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
}
.pl-crumbs a:hover { color: var(--pl-primary); background: var(--pl-primary-soft); }
.pl-crumbs__sep { color: var(--pl-text-subtle); margin: 0 0.125rem; font-size: 0.75rem; }
.pl-crumbs__current { color: var(--pl-text); font-weight: var(--pl-fw-semibold); padding: 2px 4px; }

/* ── 10. Page header ────────────────────────────────────────── */
.pl-page-header {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  margin-bottom: 1.25rem;
}
.pl-page-header__title {
  /* Matches .pacct-head__title so every module header reads identically. */
  margin: 0;
  font-size: var(--pl-fs-3xl);
  font-weight: var(--pl-fw-bold);
  letter-spacing: -0.011em;
  line-height: var(--pl-lh-tight);
}
.pl-page-header__icon {
  /* Flat navy plane on an 8px tile — the site's icon-tile treatment. Was a
     violet→navy gradient on an 18px tile under a 22px-blur coloured shadow;
     all three were off-system. The five tone variants below were five
     unrelated two-stop gradient recipes, now one flat-fill recipe. */
  width: var(--pl-tile-size); height: var(--pl-tile-size);
  border-radius: var(--pl-radius-tile);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pl-tile-gradient);
  color: var(--pl-on-tile);
  font-size: 1.6rem; flex-shrink: 0;
  box-shadow: var(--pl-tile-shadow);
}
.pl-page-header__icon.pl-stat__icon--success { background: var(--pl-success); color: #fff; box-shadow: none; }
.pl-page-header__icon.pl-stat__icon--warning { background: var(--pl-warning); color: #fff; box-shadow: none; }
.pl-page-header__icon.pl-stat__icon--danger  { background: var(--pl-danger);  color: #fff; box-shadow: none; }
.pl-page-header__icon.pl-stat__icon--info    { background: var(--pl-info);    color: #fff; box-shadow: none; }
.pl-page-header__subtitle {
  color: var(--pl-text-muted);
  font-size: var(--pl-fs-base);
  /* margin-bottom:0 because the subtitle is now a <p> (it is a sentence, not a
     generic box) and would otherwise inherit Bootstrap's 1rem paragraph gap,
     pushing the meta row away from the title it belongs to. */
  margin: 0.25rem 0 0;
  max-width: var(--pl-measure-lede);
  line-height: var(--pl-lh-snug);
}
.pl-page-header__meta {
  margin-top: 0.5rem;
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 0.375rem 0.875rem;
  font-size: var(--pl-fs-sm);
  color: var(--pl-text-muted);
}
.pl-page-header__meta-item { display: inline-flex; align-items: center; gap: 0.25rem; }
/* Optional tone on a meta item. Soft tint + the solid token as ink, per the
   house status language — and it turns the item into a real pill so the tint
   has an edge to sit inside. A tone is emphasis only: the label still says the
   word, so colour is never the sole carrier of the meaning. */
.pl-page-header__meta-item--success,
.pl-page-header__meta-item--warning,
.pl-page-header__meta-item--danger,
.pl-page-header__meta-item--info,
.pl-page-header__meta-item--muted {
  padding: 1px 8px;
  border-radius: var(--pl-radius-pill);
  font-weight: var(--pl-fw-semibold);
}
.pl-page-header__meta-item--success { background: var(--pl-success-tint); color: var(--pl-success-on-tint); }
.pl-page-header__meta-item--warning { background: var(--pl-warning-tint); color: var(--pl-warning-on-tint); }
.pl-page-header__meta-item--danger  { background: var(--pl-danger-tint);  color: var(--pl-danger-on-tint); }
.pl-page-header__meta-item--info    { background: var(--pl-info-tint);    color: var(--pl-info-on-tint); }
.pl-page-header__meta-item--muted   { background: var(--pl-neutral-tint); color: var(--pl-neutral-on-tint); }
.pl-page-header__actions {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
}
/* Header buttons — the .pacct action language: 10px radius, semibold, and a
   violet→navy gradient primary with a hover lift. */
.pl-page-header__actions .btn {
  border-radius: var(--pl-radius-control);
  font-weight: var(--pl-fw-semibold);
  transition: transform var(--pl-dur-fast) var(--pl-ease),
              box-shadow var(--pl-dur-fast) var(--pl-ease),
              filter var(--pl-dur-fast) var(--pl-ease);
}
.pl-page-header__actions .btn:active { transform: translateY(1px); }
.pl-page-header__actions .btn-primary {
  /* The site's signature CTA: flat coral, square-ish, no gradient, no glow.
     Uses coral-DARK rather than coral: white on #e8593a is 3.55:1, which fails
     AA at button type sizes — the site makes the same substitution in its own
     a11y block. Hover travels to navy, matching .h27-btn--fill's sliding fill.
     Coral is spent here and on the active tab underline only; that is what
     keeps it under the brand's <=10%-of-surface rule.
     DARK-MODE NOTE: .btn-primary sets --bs-btn-color from --pl-on-primary,
     which flips to near-black in dark. This button keeps its coral plane in
     both themes, so it pins white ink in both. */
  background: var(--pl-coral-dark);
  border: none;
  box-shadow: none;
  --bs-btn-color: #fff;
  --bs-btn-hover-color: #fff;
  --bs-btn-active-color: #fff;
  --bs-btn-disabled-color: #fff;
  color: #fff;
}
.pl-page-header__actions .btn-primary:hover {
  background: var(--pl-primary-900);
  transform: translateY(-1px);
  box-shadow: none;
}
.pl-page-header__actions .btn-primary:active { transform: translateY(0); }
/* A `method:"post"` action renders as a <form class="d-inline"> wrapping the
   button. Without this the form becomes a flex item of its own and the button
   inside it sits a hair off the baseline of its neighbouring links. */
.pl-page-header__actions form { display: inline-flex; margin: 0; }
/* The ghost variant is a text button; it should not carry the outline button's
   inherited padding jitter or a hover underline. */
.pl-page-header__actions .btn-link { padding-inline: 0.5rem; }
.pl-page-header__actions .btn-link:hover { color: var(--pl-text); }
/* The partial emits `<i class="bi bi-x"></i>{{ label }}` with no spacing class,
   so an action with an icon rendered as "⊞New account" with the glyph welded to
   the word. A gap on the button spaces icon from label without needing every
   call site to remember a utility class, and collapses to nothing when the
   button has only one child. */
.pl-page-header__actions .btn {
  display: inline-flex; align-items: center; gap: 0.35rem;
}

/* Header tabs — restyled from Bootstrap's underline tabs into the .pacct
   segmented pill control (tertiary well, floating active segment).
   The strip is wrapped in a named <nav> (these are links that navigate, not
   ARIA tabs controlling panels) — the wrapper is layout-transparent so the
   strip keeps shrink-wrapping to its content exactly as before. */
.pl-page-header__tabs-nav { display: block; max-width: 100%; }
.pl-page-header__tabs {
  display: inline-flex; align-self: flex-start; max-width: 100%;
  flex-wrap: wrap; gap: 4px;
  padding: 3px; margin-bottom: 1.25rem;
  background: var(--pl-surface-alt);
  border: 1px solid var(--pl-border);
  border-bottom: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 1px 2px rgba(13, 27, 62, 0.04);
  list-style: none;
}
.pl-page-header__tabs .nav-item { margin: 0; }
.pl-page-header__tabs .nav-link {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 14px;
  border: 0; border-radius: var(--pl-radius-control);
  font-size: var(--pl-fs-base); font-weight: var(--pl-fw-semibold);
  color: var(--pl-text-muted); white-space: nowrap;
  transition: color var(--pl-dur-fast) var(--pl-ease),
              background var(--pl-dur-fast) var(--pl-ease),
              box-shadow var(--pl-dur-fast) var(--pl-ease),
              transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-page-header__tabs .nav-link:hover { color: var(--pl-text); border-color: transparent; isolation: isolate; }
.pl-page-header__tabs .nav-link:active { transform: scale(.97); }
.pl-page-header__tabs .nav-link.active {
  background: var(--pl-surface);
  color: var(--pl-primary);
  border: 0;
  box-shadow: var(--pl-shadow-sm);
}
.pl-page-header__tabs .pl-tag {
  font-size: var(--pl-fs-xs); font-weight: var(--pl-fw-bold);
  padding: 1px 7px; border-radius: var(--pl-radius-pill);
  font-variant-numeric: tabular-nums;
}
.pl-page-header__tabs .nav-link.active .pl-tag {
  background: var(--pl-primary-soft); color: var(--pl-primary);
}

/* ── 11. Cards ──────────────────────────────────────────────── */
.card, .pl-card {
  background: var(--pl-surface);
  /* The site's card is a 6px plane held by a 1px INSET hairline and nothing
     else — no border, no drop shadow at rest. Carrying a border AND a shadow
     (as this did) reads as two borders' worth of weight and is the main
     reason the app looked heavier than the site at identical colours. */
  border: 0;
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 0 0 1px var(--pl-border);
  color: var(--pl-text);
}
.card .card-header, .pl-card__header {
  background: transparent;
  border-bottom: 1px solid var(--pl-border);
  font-weight: var(--pl-fw-semibold);
  padding: 0.875rem 1.25rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem;
  color: var(--pl-text);
}
.pl-card__title {
  font-size: var(--pl-fs-md);
  font-weight: var(--pl-fw-semibold);
  margin: 0;
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--pl-text);
}
.pl-card__title .bi { color: var(--pl-text-muted); }
.pl-card__body { padding: 1.25rem; }
.pl-card__footer {
  background: var(--pl-surface-alt);
  border-top: 1px solid var(--pl-border);
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 var(--pl-radius-card) var(--pl-radius-card);
  font-size: var(--pl-fs-base);
}

.pl-card--elevated { box-shadow: inset 0 0 0 1px var(--pl-border), var(--pl-shadow-md); }
.pl-card--ghost { background: transparent; box-shadow: none; }
.pl-card--gradient { background: var(--pl-surface-alt); }
.pl-card--hover {
  transition: transform var(--pl-dur-slow) var(--pl-ease),
              box-shadow var(--pl-dur-slow) var(--pl-ease);
}
.pl-card--hover:hover {
  /* The site's card lift: a real 6px rise with the hairline darkening into a
     soft, wide shadow. Was a 1px nudge under a 6px blur, which read as a
     rendering artefact rather than an affordance. */
  transform: translateY(-6px);
  box-shadow: inset 0 0 0 1px rgba(13, 27, 62, 0.16), 0 22px 54px rgba(13, 27, 62, 0.12);
}
@media (prefers-reduced-motion: reduce) {
  .pl-card--hover:hover { transform: none; }
}

/* Dark mode: real elevation steps for cards */
[data-theme="dark"] .card,
[data-theme="dark"] .pl-card {
  background: var(--pl-elevation-1);
  border-color: var(--pl-border);
}
[data-theme="dark"] .pl-card--elevated {
  background: var(--pl-elevation-2);
  border-color: var(--pl-border-strong);
}
[data-theme="dark"] .pl-card__footer {
  background: var(--pl-surface-sunken);
  border-top-color: var(--pl-border);
}
[data-theme="dark"] .pl-card--gradient {
  background: linear-gradient(180deg, var(--pl-primary-tint) 0%, transparent 60%), var(--pl-elevation-1);
}

/* ── 12. Tables ─────────────────────────────────────────────── */
.table {
  color: var(--pl-text);
  --bs-table-bg: transparent;
  --bs-table-color: var(--pl-text);
  --bs-table-hover-color: var(--pl-text);
  --bs-table-hover-bg: var(--pl-surface-alt);
  margin-bottom: 0;
}
.table > :not(caption) > * > * {
  border-bottom-color: var(--pl-border);
  padding: 0.75rem 1rem;
  background-color: transparent;
}
.table thead th {
  font-weight: var(--pl-fw-semibold);
  font-size: var(--pl-fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--pl-text-muted);
  border-bottom: 1px solid var(--pl-border);
  background: var(--pl-surface-alt);
  white-space: nowrap;
}
.table.table-light thead th { background: var(--pl-surface-alt); }
.table.table-hover tbody tr:hover > * { background-color: var(--pl-surface-alt); }
.pl-table thead th {
  position: sticky; top: 0;
  background: var(--pl-surface-alt);
  z-index: 1;
}
.pl-table--zebra tbody tr:nth-child(odd) { background: var(--pl-surface-alt); }
.pl-table--dense > :not(caption) > * > * { padding: 0.5rem 0.875rem; }
.pl-table tbody tr.is-expanded + tr.pl-table__expand {
  background: var(--pl-surface-alt);
}
.pl-table__expand > td {
  padding: 1rem 1.25rem;
  border-top: 0;
}

/* Dark mode: table bridges, zebra & borders */
[data-theme="dark"] .table {
  --bs-table-bg: transparent;
  --bs-table-color: var(--pl-text);
  --bs-table-hover-color: var(--pl-text);
  --bs-table-hover-bg: var(--pl-surface-elevated);
  --bs-table-striped-bg: var(--pl-surface-alt);
  --bs-table-striped-color: var(--pl-text);
  --bs-table-active-bg: var(--pl-surface-elevated);
  --bs-table-active-color: var(--pl-text);
  --bs-table-border-color: var(--pl-border);
  color: var(--pl-text);
}
[data-theme="dark"] .table > :not(caption) > * > * {
  border-bottom-color: var(--pl-border);
}
[data-theme="dark"] .table thead th,
[data-theme="dark"] .pl-table thead th {
  background: var(--pl-surface-alt);
  color: var(--pl-text-muted);
  border-bottom-color: var(--pl-border);
}
[data-theme="dark"] .table.table-hover tbody tr:hover > * { background-color: var(--pl-surface-elevated); }
[data-theme="dark"] .pl-table--zebra tbody tr:nth-child(odd) { background: rgba(255, 255, 255, 0.03); }
[data-theme="dark"] .pl-table tbody tr.is-expanded + tr.pl-table__expand { background: var(--pl-surface-elevated); }
[data-theme="dark"] .table-bordered,
[data-theme="dark"] .table-bordered > :not(caption) > * > * {
  border-color: var(--pl-border);
}

/* ── 13. Stat cards & KPI row ───────────────────────────────── */
.pl-stat {
  display: block;
  background: var(--pl-surface);
  /* The house card recipe (DS-05, 2026-09-23): a 6px plane held by a 1px
     INSET hairline, no border, no rest shadow — the same rule .pl-card uses
     four sections up. This carried an 8px radius, a border AND a shadow, so a
     stat row never matched the cards under it. */
  border: 0;
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 0 0 1px var(--pl-border);
  padding: 1rem 1.125rem;
  color: var(--pl-text);
  transition: transform var(--pl-dur-fast) var(--pl-ease),
              box-shadow var(--pl-dur-fast) var(--pl-ease);
  position: relative;
  overflow: hidden;
}
a.pl-stat:hover {
  text-decoration: none;
  transform: translateY(-2px);
  box-shadow: inset 0 0 0 1px var(--pl-border-strong), var(--pl-shadow-md);
}
a.pl-stat:focus-visible {
  outline: 2px solid var(--pl-primary);
  outline-offset: 2px;
  box-shadow: inset 0 0 0 1px var(--pl-border), 0 0 0 3px var(--pl-focus-ring);
}
.pl-stat__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem; margin-bottom: 0.375rem;
}
.pl-stat__label {
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--pl-text-muted);
}
.pl-stat__icon {
  width: 32px; height: 32px; border-radius: var(--pl-radius);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pl-primary-soft); color: var(--pl-primary);
  font-size: 0.95rem;
}
.pl-stat__icon--success { background: var(--pl-success-soft); color: var(--pl-success); }
.pl-stat__icon--warning { background: var(--pl-warning-soft); color: var(--pl-warning); }
.pl-stat__icon--danger  { background: var(--pl-danger-soft);  color: var(--pl-danger); }
.pl-stat__icon--info    { background: var(--pl-info-soft);    color: var(--pl-info); }
.pl-stat__value {
  font-size: var(--pl-fs-3xl);
  font-weight: var(--pl-fw-bold);
  line-height: var(--pl-lh-tight);
  color: var(--pl-text);
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.pl-stat__foot {
  margin-top: 0.5rem;
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem;
  min-height: 1.25rem;
}
.pl-stat__delta {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  font-variant-numeric: tabular-nums;
}
.pl-stat__delta--up   { color: var(--pl-success); }
.pl-stat__delta--down { color: var(--pl-danger); }
.pl-stat__delta--flat { color: var(--pl-text-muted); }
.pl-stat__delta-pill {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 1px 6px;
  border-radius: var(--pl-radius-pill);
  background: var(--pl-success-soft);
  color: var(--pl-success-text);
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
}
.pl-stat__delta-pill--down { background: var(--pl-danger-soft); color: var(--pl-danger-text); }
.pl-stat__delta-pill--flat { background: var(--pl-surface-alt); color: var(--pl-text-muted); }
.pl-stat__spark { color: var(--pl-primary); opacity: 0.85; }
.pl-stat__spark svg { display: block; }

.pl-kpi-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0.875rem;
  margin-bottom: 1.25rem;
}

/* KPI row density variants — pick based on how many stats you're showing. */
.pl-kpi-row--compact   { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
.pl-kpi-row--spacious  { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }

/* .pl-stat modifiers — let custom dashboard cards share the canonical
   pattern instead of inventing their own (.rep-kpi, .ss-stat, etc.). */
.pl-stat--no-icon .pl-stat__icon { display: none; }
.pl-stat--compact { padding: 0.75rem 0.875rem; }
.pl-stat--compact .pl-stat__value { font-size: var(--pl-fs-2xl); }
.pl-stat--simple {
  box-shadow: none;
  background: transparent;
}
.pl-stat--border-left {
  border-left: 3px solid var(--pl-primary);
  padding-left: 1rem;
}
.pl-stat--border-left.pl-stat--success { border-left-color: var(--pl-success); }
.pl-stat--border-left.pl-stat--warning { border-left-color: var(--pl-warning); }
.pl-stat--border-left.pl-stat--danger  { border-left-color: var(--pl-danger); }
.pl-stat--border-left.pl-stat--info    { border-left-color: var(--pl-info); }

/* Dashboard container — consistent page-level grid + gap for all dashboards. */
.pl-dashboard {
  display: grid;
  gap: 1.25rem;
}
.pl-dashboard__row {
  display: grid;
  gap: 1rem;
}
.pl-dashboard__row--2-col { grid-template-columns: 1fr; }
.pl-dashboard__row--3-col { grid-template-columns: 1fr; }
@media (min-width: 992px) {
  .pl-dashboard__row--2-col { grid-template-columns: 1fr 1fr; }
  .pl-dashboard__row--3-col { grid-template-columns: 1fr 1fr 1fr; }
  .pl-dashboard__row--main-aside { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
}

/* ── 14. Empty state ────────────────────────────────────────── */
.pl-empty {
  text-align: center;
  padding: 2.5rem 1.5rem;
  background: var(--pl-surface);
  border: 1px dashed var(--pl-border-strong);
  border-radius: var(--pl-radius-lg);
  color: var(--pl-text-muted);
}
.pl-empty__art {
  width: 96px; height: 96px;
  margin: 0 auto 1rem;
  display: flex; align-items: center; justify-content: center;
  color: var(--pl-primary);
  opacity: 0.85;
}
.pl-empty__icon {
  width: 56px; height: 56px; margin: 0 auto 1rem;
  border-radius: 50%;
  background: var(--pl-primary-soft);
  color: var(--pl-primary);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 1.5rem;
}
.pl-empty__title {
  color: var(--pl-text);
  font-weight: var(--pl-fw-semibold);
  font-size: var(--pl-fs-lg);
  margin-bottom: 0.375rem;
}
.pl-empty__body {
  max-width: 460px; margin: 0 auto 1rem;
  font-size: var(--pl-fs-base);
  color: var(--pl-text-muted);
}
.pl-empty__actions {
  display: inline-flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  justify-content: center;
}

/* An empty state in a full-bleed column is a 460px blob adrift in 1400px of
   nothing. --boxed caps the PANEL, not just its copy, so the whole thing reads
   as one deliberate object however wide the column is. */
.pl-empty--boxed { max-width: 560px; margin-inline: auto; }

/* --inline is the same content laid out as a single row: for a card body, a
   tab panel or a table's "no rows" cell, where a 2.5rem-padded panel with a
   96px illustration is out of scale with everything around it. */
.pl-empty--inline {
  display: flex; align-items: center; gap: 0.75rem;
  text-align: left;
  padding: 0.9rem 1rem;
}
.pl-empty--inline .pl-empty__icon,
.pl-empty--inline .pl-empty__art {
  width: 34px; height: 34px; margin: 0; flex: 0 0 auto; font-size: 1rem;
}
.pl-empty--inline .pl-empty__title { margin: 0; font-size: var(--pl-fs-base); }
.pl-empty--inline .pl-empty__body { margin: 0; max-width: none; }
.pl-empty--inline .pl-empty__actions { margin-left: auto; }

/* A FILTERED empty state is a different message from a never-had-data one: the
   records exist, the query hid them. Solid border and a warning wash say "this
   is a state you caused", where the dashed border says "nothing here yet". */
.pl-empty--filtered {
  border-style: solid;
  border-color: var(--pl-warning-border);
  background: linear-gradient(0deg, var(--pl-warning-tint), var(--pl-warning-tint)), var(--pl-surface);
}
.pl-empty--filtered .pl-empty__icon {
  background: var(--pl-warning-tint);
  color: var(--pl-warning-on-tint);
}

/* ── 15. Banners ────────────────────────────────────────────── */
.pl-banner {
  display: flex; align-items: flex-start; gap: 0.75rem;
  padding: 0.75rem 1rem;
  border-radius: var(--pl-radius);
  border: 1px solid var(--pl-border);
  background: var(--pl-surface);
  margin-bottom: 1rem;
  font-size: var(--pl-fs-base);
  position: relative;
}
.pl-banner__icon { flex: 0 0 auto; font-size: 1.1rem; margin-top: 1px; }
.pl-banner__body { flex: 1 1 auto; }
.pl-banner__title { font-weight: var(--pl-fw-semibold); color: inherit; }
.pl-banner__cta {
  display: inline-block;
  margin-top: 0.25rem;
  font-weight: var(--pl-fw-semibold);
  text-decoration: underline;
  color: inherit;
}
.pl-banner__close {
  background: transparent; border: 0; color: inherit; opacity: 0.6;
  font-size: 1rem; padding: 0 0.25rem; line-height: 1;
  cursor: pointer;
}
.pl-banner__close:hover { opacity: 1; }
.pl-banner--info    { background: var(--pl-info-soft);    border-color: var(--pl-info-border);    color: var(--pl-info-text); }
.pl-banner--success { background: var(--pl-success-soft); border-color: var(--pl-success-border); color: var(--pl-success-text); }
.pl-banner--warning { background: var(--pl-warning-soft); border-color: var(--pl-warning-border); color: var(--pl-warning-text); }
.pl-banner--danger  { background: var(--pl-danger-soft);  border-color: var(--pl-danger-border);  color: var(--pl-danger-text); }

/* ── 16. Dropdowns & notifications ──────────────────────────── */
.dropdown-menu {
  --bs-dropdown-bg: var(--pl-surface);
  --bs-dropdown-color: var(--pl-text);
  --bs-dropdown-link-color: var(--pl-text);
  --bs-dropdown-link-hover-color: var(--pl-text);
  --bs-dropdown-link-hover-bg: var(--pl-surface-alt);
  --bs-dropdown-link-active-bg: var(--pl-primary);
  --bs-dropdown-link-active-color: #fff;
  border-color: var(--pl-border);
  box-shadow: var(--pl-shadow-lg);
  border-radius: var(--pl-radius);
  padding: 0.375rem;
  font-size: var(--pl-fs-base);
}
.dropdown-item {
  border-radius: var(--pl-radius-sm);
  padding: 0.5rem 0.625rem;
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--pl-text);
}
.dropdown-item .bi { color: var(--pl-text-muted); font-size: 1rem; }
.dropdown-item:active { background: var(--pl-primary); color: #fff; }
.dropdown-item:active .bi { color: #fff; }
.dropdown-header {
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pl-text-subtle);
}
.dropdown-divider { border-color: var(--pl-border); margin: 0.25rem 0; }

.pl-notifs { width: 360px; }
.pl-notifs__item {
  display: flex; gap: 0.625rem;
  padding: 0.625rem; border-radius: var(--pl-radius-sm);
  color: var(--pl-text);
  text-decoration: none;
}
.pl-notifs__item:hover { background: var(--pl-surface-alt); color: var(--pl-text); }
.pl-notifs__item.is-unread { background: var(--pl-primary-soft); }
.pl-notifs__title { font-weight: var(--pl-fw-semibold); color: var(--pl-text); font-size: var(--pl-fs-base); }
.pl-notifs__body  { color: var(--pl-text-muted); font-size: var(--pl-fs-base); }
.pl-notifs__meta  { color: var(--pl-text-subtle); font-size: var(--pl-fs-sm); margin-top: 0.125rem; }
.pl-notifs__empty {
  padding: 1.5rem 1rem; text-align: center;
  color: var(--pl-text-muted); font-size: var(--pl-fs-base);
}
.pl-notifs__footer {
  border-top: 1px solid var(--pl-border);
  margin-top: 0.25rem;
  padding-top: 0.375rem;
  text-align: center;
}

/* Quick-create dropdown — "+" button in the topbar */
.pl-quick-create-menu {
  min-width: 240px;
}
.pl-quick-create-menu__item {
  position: relative;
  padding-right: 1.75rem;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              padding-left var(--pl-dur-fast) var(--pl-ease);
}
.pl-quick-create-menu__item:hover,
.pl-quick-create-menu__item:focus-visible {
  background: var(--pl-surface-alt);
}
.pl-quick-create-menu__item .bi:first-child {
  color: var(--pl-primary);
  font-size: 1.05rem;
  flex-shrink: 0;
}
.pl-quick-create-menu__label {
  flex-grow: 1;
  min-width: 0;
}
.pl-quick-create-menu__chev {
  position: absolute;
  right: 0.625rem;
  top: 50%;
  transform: translateY(-50%) translateX(-4px);
  color: var(--pl-text-subtle) !important;
  font-size: 0.85rem !important;
  opacity: 0;
  transition: opacity var(--pl-dur-fast) var(--pl-ease),
              transform var(--pl-dur-fast) var(--pl-ease);
}
.pl-quick-create-menu__item:hover .pl-quick-create-menu__chev,
.pl-quick-create-menu__item:focus-visible .pl-quick-create-menu__chev {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}
.pl-quick-create-menu__hint {
  padding: 0.25rem 0.75rem 0.375rem;
  font-size: var(--pl-fs-xs);
  color: var(--pl-text-subtle);
  text-align: center;
}
.pl-quick-create-menu__hint .pl-kbd { margin: 0 0.125rem; }

/* Make a pill feel clickable when rendered as an <a> */
a.pl-pill,
a.pl-pill--tenant {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
.pl-pill--tenant:hover,
.pl-pill--tenant:focus-visible {
  background: var(--pl-primary-100, var(--pl-primary-soft));
  border-color: var(--pl-primary-300, var(--pl-primary-200));
  color: var(--pl-primary-hover);
  text-decoration: none;
}
[data-theme="dark"] a.pl-pill--tenant { color: var(--pl-primary-200); }
[data-theme="dark"] .pl-pill--tenant:hover,
[data-theme="dark"] .pl-pill--tenant:focus-visible {
  background: var(--pl-primary-tint-hover);
  color: var(--pl-primary-100);
}

/* Dark mode: lifted dropdowns + visible hover */
[data-theme="dark"] .dropdown-menu {
  --bs-dropdown-bg: var(--pl-elevation-2);
  --bs-dropdown-color: var(--pl-text);
  --bs-dropdown-link-color: var(--pl-text);
  --bs-dropdown-link-hover-color: var(--pl-text-strong);
  --bs-dropdown-link-hover-bg: rgba(255, 255, 255, 0.06);
  --bs-dropdown-link-active-bg: var(--pl-primary);
  --bs-dropdown-link-active-color: var(--pl-on-primary);
  --bs-dropdown-border-color: var(--pl-border);
  background: var(--pl-elevation-2);
  border-color: var(--pl-border);
  box-shadow: var(--pl-shadow-xl);
}
[data-theme="dark"] .dropdown-item { color: var(--pl-text); }
[data-theme="dark"] .dropdown-item:hover,
[data-theme="dark"] .dropdown-item:focus { background: rgba(255, 255, 255, 0.06); color: var(--pl-text-strong); }
[data-theme="dark"] .dropdown-item:active,
[data-theme="dark"] .dropdown-item.active {
  background: var(--pl-primary);
  color: var(--pl-on-primary);
}
[data-theme="dark"] .dropdown-item:active .bi,
[data-theme="dark"] .dropdown-item.active .bi { color: var(--pl-on-primary); }
[data-theme="dark"] .dropdown-divider { border-color: var(--pl-border); }
[data-theme="dark"] .dropdown-header { color: var(--pl-text-subtle); }
[data-theme="dark"] .pl-notifs__item:hover { background: rgba(255, 255, 255, 0.06); }
[data-theme="dark"] .pl-notifs__item.is-unread { background: var(--pl-primary-tint); }

/* ── 17. Tabs ───────────────────────────────────────────────── */
.nav-tabs {
  border-bottom: 1px solid var(--pl-border);
  --bs-nav-tabs-link-active-bg: transparent;
}
.nav-tabs .nav-link {
  border: 0; color: var(--pl-text-muted);
  border-bottom: 2px solid transparent;
  font-weight: var(--pl-fw-medium);
  padding: 0.625rem 0.875rem;
  margin-bottom: -1px;
  transition: color var(--pl-dur-fast) var(--pl-ease),
              border-color var(--pl-dur-fast) var(--pl-ease);
  background: transparent;
}
.nav-tabs .nav-link:hover {
  color: var(--pl-text);
  border-color: transparent;
  isolation: isolate;
}
.nav-tabs .nav-link.active {
  color: var(--pl-primary);
  border-bottom-color: var(--pl-primary);
  background: transparent;
  font-weight: var(--pl-fw-semibold);
}

.pl-tabs {
  display: inline-flex;
  align-items: center;
  gap: 0;
  border-bottom: 1px solid var(--pl-border);
}
.pl-tabs .pl-tab {
  position: relative;
  padding: 0.625rem 0.875rem;
  color: var(--pl-text-muted);
  font-weight: var(--pl-fw-medium);
  font-size: var(--pl-fs-base);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--pl-dur-fast) var(--pl-ease);
  display: inline-flex; align-items: center; gap: 0.375rem;
}
.pl-tabs .pl-tab:hover { color: var(--pl-text); }
.pl-tabs .pl-tab.is-active {
  color: var(--pl-primary);
  border-bottom-color: var(--pl-primary);
  font-weight: var(--pl-fw-semibold);
}

/* The house style is a SEGMENTED control, not an underline — a tertiary well
   with a floating active segment, exactly as .pl-page-header__tabs and
   .pacct-tabs render. `.pl-tabs` itself stays an underline strip because
   several surfaces pair it with Bootstrap tab panes and expect that geometry;
   add `--segmented` to opt a strip into the 2027 look with no markup change. */
.pl-tabs--segmented {
  gap: 4px;
  padding: 3px;
  border-bottom: 0;
  background: var(--pl-surface-alt);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 1px 2px rgba(13, 27, 62, 0.04);
}
.pl-tabs--segmented .pl-tab {
  padding: 6px 14px;
  border-bottom: 0;
  margin-bottom: 0;
  border-radius: var(--pl-radius-control);
  font-weight: var(--pl-fw-semibold);
  transition: color var(--pl-dur-fast) var(--pl-ease),
              background var(--pl-dur-fast) var(--pl-ease),
              box-shadow var(--pl-dur-fast) var(--pl-ease);
}
.pl-tabs--segmented .pl-tab.is-active {
  background: var(--pl-surface);
  color: var(--pl-primary);
  border-bottom-color: transparent;
  box-shadow: var(--pl-shadow-sm);
}

/* ── 18. Tags & status chips ────────────────────────────────── */
.pl-tag {
  display: inline-flex; align-items: center; gap: 0.25rem;
  padding: 2px 8px;
  border-radius: var(--pl-radius-pill);
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  line-height: 1.4;
  background: var(--pl-surface-alt);
  color: var(--pl-text-muted);
  border: 1px solid transparent;
  white-space: nowrap;
}
.pl-tag .bi { font-size: 0.8em; }
.pl-tag--success { background: var(--pl-success-soft); color: var(--pl-success-text); }
.pl-tag--warning { background: var(--pl-warning-soft); color: var(--pl-warning-text); }
.pl-tag--danger  { background: var(--pl-danger-soft);  color: var(--pl-danger-text); }
.pl-tag--info    { background: var(--pl-info-soft);    color: var(--pl-info-text); }
.pl-tag--primary { background: var(--pl-primary-soft); color: var(--pl-primary-hover); }
.pl-tag--neutral { background: var(--pl-surface-alt);  color: var(--pl-text-muted); }
.pl-tag--outline {
  background: transparent;
  border-color: var(--pl-border-strong);
  color: var(--pl-text-muted);
}
.pl-tag--dot::before {
  content: "";
  width: 6px; height: 6px;
  border-radius: 50%;
  background: currentColor;
  display: inline-block;
}

/* ── 19. Segmented control ──────────────────────────────────── */
.pl-segmented {
  display: inline-flex;
  background: var(--pl-surface-alt);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius);
  padding: 2px;
  gap: 2px;
}
.pl-segmented__item {
  background: transparent;
  border: 0;
  padding: 4px 12px;
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-medium);
  color: var(--pl-text-muted);
  border-radius: var(--pl-radius-sm);
  cursor: pointer;
  display: inline-flex; align-items: center; gap: 0.25rem;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
  text-decoration: none;
  line-height: 1.4;
}
.pl-segmented__item:hover { color: var(--pl-text); }
.pl-segmented__item.is-active {
  background: var(--pl-surface);
  color: var(--pl-text);
  box-shadow: var(--pl-shadow-xs);
  font-weight: var(--pl-fw-semibold);
}

/* ── 20. Filter bar ─────────────────────────────────────────── */
.pl-filter-bar {
  display: flex; flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.625rem;
  padding: 0.625rem 0.75rem;
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius);
  margin-bottom: 1rem;
}
.pl-filter-chip {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 3px 10px;
  border: 1px dashed var(--pl-border-strong);
  border-radius: var(--pl-radius-pill);
  font-size: var(--pl-fs-sm);
  color: var(--pl-text-muted);
  background: transparent;
  cursor: pointer;
  transition: border-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease),
              background-color var(--pl-dur-fast) var(--pl-ease);
  text-decoration: none;
}
.pl-filter-chip:hover {
  border-color: var(--pl-primary);
  color: var(--pl-primary);
}
.pl-filter-chip.is-active {
  background: var(--pl-primary-soft);
  border-color: var(--pl-primary);
  border-style: solid;
  color: var(--pl-primary-hover);
  font-weight: var(--pl-fw-semibold);
}
.pl-filter-chip__close {
  margin-left: 2px;
  display: inline-flex;
  align-items: center;
  opacity: 0.6;
}
.pl-filter-chip__close:hover { opacity: 1; }
.pl-filter-bar__divider {
  width: 1px;
  align-self: stretch;
  background: var(--pl-border);
  margin: 0 0.125rem;
}

/* ── 21. Toolbar ────────────────────────────────────────────── */
.pl-toolbar {
  display: flex; flex-wrap: wrap;
  align-items: center; gap: 0.625rem;
  padding: 0.625rem 0.75rem;
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius);
  margin-bottom: 1rem;
}
/* The toolbar is ONE GET form whose controls must lay out as siblings of the
   non-form items (the view switcher, the create CTA), so the <form> element is
   display:contents. _partials/list_toolbar.html used to carry that as an inline
   `style="display: contents"` next to a `d-contents` class that Bootstrap does
   not ship — the class was inert and the inline style was doing all the work.
   Named here so the markup stays free of inline style. */
.pl-toolbar > [data-toolbar-form] { display: contents; }

.pl-toolbar__search {
  position: relative;
  flex: 1 1 240px;
  max-width: 360px;
  min-width: 200px;
}
.pl-toolbar__search input {
  width: 100%;
  height: 34px;
  padding: 0 0.625rem 0 2rem;
  background: var(--pl-bg);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-sm);
  font-size: var(--pl-fs-base);
  color: var(--pl-text);
}
.pl-toolbar__search input:focus {
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
  outline: none;
  background: var(--pl-surface);
}
.pl-toolbar__search .bi {
  position: absolute; left: 0.625rem; top: 50%;
  transform: translateY(-50%);
  color: var(--pl-text-subtle);
  pointer-events: none;
}
.pl-toolbar__group {
  display: inline-flex; align-items: center;
  gap: 0.375rem;
}
.pl-toolbar__divider {
  width: 1px;
  align-self: stretch;
  background: var(--pl-border);
  margin: 0 0.125rem;
}
.pl-toolbar__spacer { flex: 1 1 auto; }

/* Flush variant — the toolbar becomes a card's header bar (used inside
   .info-card.p-0): drop the standalone border/background/margin so it reads as
   one bar with a single divider under it, and align its padding to list rows. */
.pl-toolbar--flush {
  border: 0;
  border-bottom: 1px solid var(--pl-border);
  border-radius: 0;
  background: transparent;
  margin-bottom: 0;
  padding: 0.75rem 1rem;
}
/* Let the search take most of the row (reference layout: wide search, controls
   pushed to the right edge). */
.pl-toolbar__search--grow {
  flex: 1 1 320px;
  max-width: none;
}
[data-theme="dark"] .pl-toolbar--flush { border-bottom-color: rgba(255,255,255,0.08); }

/* ── 22. Section header ─────────────────────────────────────── */
.pl-section-header {
  display: flex; align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-bottom: 0.625rem;
  margin: 1.5rem 0 0.875rem;
  border-bottom: 1px solid var(--pl-border);
}
.pl-section-header__title {
  font-size: var(--pl-fs-md);
  font-weight: var(--pl-fw-semibold);
  margin: 0;
  display: flex; align-items: center; gap: 0.5rem;
  color: var(--pl-text);
}
.pl-section-header__title .bi { color: var(--pl-text-muted); }
.pl-section-header__sub {
  font-size: var(--pl-fs-sm);
  color: var(--pl-text-muted);
  margin-top: 0.125rem;
}
.pl-section-header--sticky {
  position: sticky;
  top: var(--pl-topbar-h);
  background: var(--pl-bg);
  z-index: 5;
  padding-top: 0.75rem;
}

/* ── 23. Progress & stepper ─────────────────────────────────── */
.pl-progress {
  background: var(--pl-surface-alt);
  border-radius: var(--pl-radius-pill);
  height: 6px;
  overflow: hidden;
  position: relative;
}
.pl-progress__bar {
  background: var(--pl-primary);
  height: 100%;
  transition: width var(--pl-dur-base) var(--pl-ease);
  border-radius: var(--pl-radius-pill);
}
.pl-progress--success .pl-progress__bar { background: var(--pl-success); }
.pl-progress--warning .pl-progress__bar { background: var(--pl-warning); }
.pl-progress--danger  .pl-progress__bar { background: var(--pl-danger); }
.pl-progress--sm { height: 4px; }
.pl-progress--lg { height: 10px; }

.pl-stepper {
  display: flex; align-items: center;
  gap: 0;
  padding: 0;
  list-style: none;
  margin: 0 0 1.25rem;
}
.pl-stepper__step {
  display: flex; align-items: center; gap: 0.5rem;
  flex: 1 1 0;
  min-width: 0;
  font-size: var(--pl-fs-base);
  color: var(--pl-text-muted);
}
.pl-stepper__step + .pl-stepper__step::before {
  content: "";
  flex: 1 1 auto;
  height: 1px;
  background: var(--pl-border);
  margin: 0 0.75rem;
}
.pl-stepper__circle {
  width: 24px; height: 24px;
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--pl-surface-alt);
  color: var(--pl-text-muted);
  border: 1px solid var(--pl-border);
  font-size: var(--pl-fs-sm);
  font-weight: var(--pl-fw-semibold);
  flex-shrink: 0;
}
.pl-stepper__step.is-active .pl-stepper__circle {
  background: var(--pl-primary);
  color: #fff;
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}
.pl-stepper__step.is-complete .pl-stepper__circle {
  background: var(--pl-success);
  color: #fff;
  border-color: var(--pl-success);
}
.pl-stepper__step.is-active { color: var(--pl-text); font-weight: var(--pl-fw-semibold); }
.pl-stepper__step.is-complete { color: var(--pl-text); }

/* Bootstrap Progress bridges */
.progress {
  --bs-progress-bg: var(--pl-surface-alt);
  --bs-progress-bar-bg: var(--pl-primary);
  --bs-progress-bar-color: var(--pl-on-primary);
}

/* Dark mode: progress + stepper polish */
[data-theme="dark"] .pl-progress { background: var(--pl-surface-alt); }
[data-theme="dark"] .progress {
  --bs-progress-bg: var(--pl-surface-alt);
  --bs-progress-bar-bg: var(--pl-primary);
  --bs-progress-bar-color: var(--pl-on-primary);
}
[data-theme="dark"] .pl-stepper__step.is-active .pl-stepper__circle {
  background: var(--pl-primary);
  color: var(--pl-on-primary);
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}
[data-theme="dark"] .pl-stepper__step.is-complete .pl-stepper__circle {
  background: var(--pl-success);
  color: var(--pl-on-success);
  border-color: var(--pl-success);
}
[data-theme="dark"] .pl-stepper__step + .pl-stepper__step::before { background: var(--pl-border); }

/* ── 24. Skeleton loader ────────────────────────────────────── */
.pl-skeleton {
  display: block;
  background: linear-gradient(
    90deg,
    var(--pl-skeleton-from) 0%,
    var(--pl-skeleton-via) 50%,
    var(--pl-skeleton-to) 100%
  );
  background-size: 200% 100%;
  animation: pl-skeleton-shimmer 1.4s ease-in-out infinite;
  border-radius: var(--pl-radius-sm);
  height: 12px;
  width: 100%;
}
.pl-skeleton--text { height: 0.875rem; margin: 0.25rem 0; }
.pl-skeleton--title { height: 1.25rem; width: 60%; margin: 0.5rem 0; }
.pl-skeleton--circle { border-radius: 50%; aspect-ratio: 1; }
.pl-skeleton--block { height: 100px; border-radius: var(--pl-radius); }

@keyframes pl-skeleton-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── 25. Keyboard shortcut ──────────────────────────────────── */
.pl-kbd {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 1.25rem;
  padding: 1px 5px;
  font-family: var(--pl-font-mono);
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  color: var(--pl-text-muted);
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-xs);
  box-shadow: 0 1px 0 var(--pl-border-strong);
  line-height: 1.25;
}

/* Dark mode: kbd uses elevated surface for legibility */
[data-theme="dark"] .pl-kbd {
  background: var(--pl-surface-alt);
  color: var(--pl-text);
  border-color: var(--pl-border-strong);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
}

/* ── 26. (retired) Command palette ──────────────────────────────
   The scaffold ⌘K palette (.pl-cmdk*, ~120 lines) was removed from the shell
   on 2026-09-23 — `_partials/command_palette.html` is gone and the topbar
   search is the quicksearch dialog (static/platform_crm/js/pcrm_quicksearch.js,
   .pqs-* classes, self-styled). No template or script references .pl-cmdk
   any more (core.tests.test_shell_chrome pins its absence). */

/* ── 27. Drawer / sheet ─────────────────────────────────────── */
.pl-drawer-backdrop {
  position: fixed; inset: 0;
  background: var(--pl-overlay);
  z-index: var(--pl-z-drawer);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--pl-dur-base) var(--pl-ease),
              visibility var(--pl-dur-base) var(--pl-ease);
}
.pl-drawer-backdrop.is-open { opacity: 1; visibility: visible; }
.pl-drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: min(480px, 100vw);
  background: var(--pl-surface);
  border-left: 1px solid var(--pl-border);
  z-index: calc(var(--pl-z-drawer) + 1);
  transform: translateX(100%);
  transition: transform var(--pl-dur-base) var(--pl-ease);
  display: flex; flex-direction: column;
  box-shadow: var(--pl-shadow-2xl);
}
.pl-drawer.is-open { transform: translateX(0); }
.pl-drawer--wide { width: min(720px, 100vw); }
.pl-drawer__header {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.5rem;
  padding: 0.875rem 1.25rem;
  border-bottom: 1px solid var(--pl-border);
  flex-shrink: 0;
}
.pl-drawer__title {
  margin: 0;
  font-size: var(--pl-fs-lg);
  font-weight: var(--pl-fw-semibold);
  color: var(--pl-text);
}
.pl-drawer__body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 1.25rem;
}
.pl-drawer__footer {
  display: flex; justify-content: flex-end; gap: 0.5rem;
  padding: 0.875rem 1.25rem;
  border-top: 1px solid var(--pl-border);
  background: var(--pl-surface-alt);
  flex-shrink: 0;
}

/* Dark mode: drawer — elevated surface, visible border, deeper shadow */
[data-theme="dark"] .pl-drawer-backdrop { background: var(--pl-overlay-strong); }
[data-theme="dark"] .pl-drawer {
  background: var(--pl-elevation-2);
  border-left: 1px solid var(--pl-border-strong);
  box-shadow: -20px 0 60px -10px rgba(0, 0, 0, 0.75);
}
[data-theme="dark"] .pl-drawer__header { border-bottom-color: var(--pl-border); }
[data-theme="dark"] .pl-drawer__footer {
  background: var(--pl-surface-sunken);
  border-top-color: var(--pl-border);
}

/* ── 28. Toast ──────────────────────────────────────────────── */
/* Top-right toast stack. Sits just below the 56px topbar so it never
   overlaps the topbar controls. Click-through except on toast bodies. */
.pl-toast-region {
  position: fixed;
  top: calc(56px + 0.75rem);
  right: 1rem;
  z-index: var(--pl-z-toast);
  display: flex; flex-direction: column;
  gap: 0.5rem;
  max-width: 380px;
  width: calc(100vw - 2rem);
  pointer-events: none;
}
@media (max-width: 768px) {
  .pl-toast-region { top: calc(56px + 0.5rem); right: 0.5rem; width: calc(100vw - 1rem); }
}
.pl-toast {
  pointer-events: auto;
  position: relative;
  display: flex; align-items: flex-start; gap: 0.625rem;
  background: var(--pl-surface);
  color: var(--pl-text);
  border: 1px solid var(--pl-border);
  border-left: 3px solid var(--pl-primary);
  border-radius: var(--pl-radius);
  padding: 0.75rem 0.875rem;
  box-shadow: var(--pl-shadow-lg);
  animation: pl-toast-slide var(--pl-dur-base) var(--pl-ease-spring);
  overflow: hidden;
}
.pl-toast.is-leaving {
  animation: pl-toast-out var(--pl-dur-base) var(--pl-ease) forwards;
}
@keyframes pl-toast-slide {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes pl-toast-out {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 0; transform: translateX(20px); }
}
.pl-toast__icon { flex-shrink: 0; font-size: 1.1rem; line-height: 1.2; color: var(--pl-primary); }
.pl-toast__body { flex: 1 1 auto; min-width: 0; }
.pl-toast__title { font-weight: var(--pl-fw-semibold); }
.pl-toast__msg { color: var(--pl-text-muted); font-size: var(--pl-fs-base); word-wrap: break-word; }
.pl-toast__close {
  background: transparent; border: 0;
  color: var(--pl-text-muted);
  font-size: 0.875rem; padding: 0 0.25rem; cursor: pointer;
  flex-shrink: 0;
  border-radius: var(--pl-radius-sm);
}
.pl-toast__close:hover { background: var(--pl-surface-sunken); color: var(--pl-text); }
.pl-toast__progress {
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  background: var(--pl-primary);
  width: 100%;
  transform-origin: left center;
  animation: pl-toast-progress linear forwards;
  opacity: 0.55;
}
@keyframes pl-toast-progress {
  from { transform: scaleX(1); }
  to   { transform: scaleX(0); }
}
.pl-toast:hover .pl-toast__progress { animation-play-state: paused; }

.pl-toast--success { border-left-color: var(--pl-success); }
.pl-toast--success .pl-toast__icon { color: var(--pl-success); }
.pl-toast--success .pl-toast__progress { background: var(--pl-success); }
.pl-toast--warning { border-left-color: var(--pl-warning); }
.pl-toast--warning .pl-toast__icon { color: var(--pl-warning); }
.pl-toast--warning .pl-toast__progress { background: var(--pl-warning); }
.pl-toast--danger  { border-left-color: var(--pl-danger);  }
.pl-toast--danger .pl-toast__icon  { color: var(--pl-danger); }
.pl-toast--danger .pl-toast__progress  { background: var(--pl-danger); }
.pl-toast--info    { border-left-color: var(--pl-info);    }
.pl-toast--info .pl-toast__icon    { color: var(--pl-info); }
.pl-toast--info .pl-toast__progress { background: var(--pl-info); }

/* Dark mode: toast — lifted surface with visible border */
[data-theme="dark"] .pl-toast {
  background: var(--pl-elevation-3);
  border-color: var(--pl-border-strong);
  color: var(--pl-text);
  box-shadow: var(--pl-shadow-xl);
}
[data-theme="dark"] .pl-toast__msg { color: var(--pl-text-muted); }
[data-theme="dark"] .pl-toast__close:hover { background: var(--pl-elevation-4, var(--pl-surface-sunken)); }

@media (prefers-reduced-motion: reduce) {
  .pl-toast { animation: none; }
  .pl-toast.is-leaving { animation: none; opacity: 0; }
  .pl-toast__progress { animation: none; display: none; }
}

/* ── 29. Timeline / activity feed ───────────────────────────── */
.pl-timeline {
  list-style: none;
  padding: 0;
  margin: 0;
  position: relative;
}
.pl-timeline::before {
  content: "";
  position: absolute;
  left: 17px;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--pl-border);
  border-radius: var(--pl-radius-pill);
}
.pl-timeline__item {
  position: relative;
  padding-left: 48px;
  padding-bottom: 1.25rem;
}
.pl-timeline__item:last-child { padding-bottom: 0; }
.pl-timeline__bullet {
  position: absolute;
  left: 0; top: 0;
  width: 36px; height: 36px;
  border-radius: 50%;
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--pl-text-muted);
  font-size: var(--pl-fs-base);
  z-index: 1;
}
.pl-timeline__item--success .pl-timeline__bullet { background: var(--pl-success-soft); border-color: var(--pl-success-border); color: var(--pl-success); }
.pl-timeline__item--warning .pl-timeline__bullet { background: var(--pl-warning-soft); border-color: var(--pl-warning-border); color: var(--pl-warning); }
.pl-timeline__item--danger  .pl-timeline__bullet { background: var(--pl-danger-soft);  border-color: var(--pl-danger-border);  color: var(--pl-danger); }
.pl-timeline__item--info    .pl-timeline__bullet { background: var(--pl-info-soft);    border-color: var(--pl-info-border);    color: var(--pl-info); }
.pl-timeline__item--primary .pl-timeline__bullet { background: var(--pl-primary-soft); border-color: var(--pl-primary-200);    color: var(--pl-primary); }
.pl-timeline__head {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: 0.375rem;
  font-size: var(--pl-fs-base);
}
.pl-timeline__actor { font-weight: var(--pl-fw-semibold); color: var(--pl-text); }
.pl-timeline__verb { color: var(--pl-text-muted); }
.pl-timeline__target { font-weight: var(--pl-fw-medium); color: var(--pl-text); }
.pl-timeline__meta {
  font-size: var(--pl-fs-sm);
  color: var(--pl-text-subtle);
  margin-top: 0.125rem;
}
.pl-timeline__body {
  margin-top: 0.375rem;
  font-size: var(--pl-fs-base);
  color: var(--pl-text-muted);
}

/* Back-compat for old activity feed name */
.activity-feed { list-style: none; padding: 0; }

/* ── 30. Forms ──────────────────────────────────────────────── */
.pl-form-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem 1.25rem;
}
.pl-form-grid > .span-2  { grid-column: span 2; }
.pl-form-grid > .span-3  { grid-column: span 3; }
.pl-form-grid > .span-4  { grid-column: span 4; }
.pl-form-grid > .span-6  { grid-column: span 6; }
.pl-form-grid > .span-8  { grid-column: span 8; }
.pl-form-grid > .span-12 { grid-column: span 12; }
@media (max-width: 768px) {
  .pl-form-grid > [class*="span-"] { grid-column: span 12; }
}
.pl-form-group {
  display: flex; flex-direction: column;
  gap: 0.375rem;
}
.pl-field-label {
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-medium);
  color: var(--pl-text);
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
}
.pl-field-label__required {
  color: var(--pl-danger);
}
.pl-field-help {
  font-size: var(--pl-fs-sm);
  color: var(--pl-text-muted);
}
.pl-field-error {
  font-size: var(--pl-fs-sm);
  color: var(--pl-danger);
  display: inline-flex; align-items: center; gap: 0.25rem;
}
.pl-fieldset {
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius);
  padding: 1rem 1.25rem 1.25rem;
  margin-bottom: 1rem;
}
.pl-fieldset > legend {
  width: auto;
  padding: 0 0.5rem;
  margin: 0 0 0 -0.5rem;
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-semibold);
  color: var(--pl-text);
  float: none;
}

/* Form check polish */
.form-check-input:checked {
  background-color: var(--pl-primary);
  border-color: var(--pl-primary);
}
.form-check-input:focus {
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}


/* Dark mode: form controls, check, switch, input-group */
[data-theme="dark"] .form-control,
[data-theme="dark"] .form-select {
  /* background-COLOR only — the `background` shorthand here was the real
     culprit: it ran AFTER the dark chevron rule above and reset the select's
     background-repeat back to `repeat`, tiling the SVG arrow. */
  background-color: var(--pl-input-bg);
  color: var(--pl-text);
  border-color: var(--pl-border);
}
[data-theme="dark"] .form-control:focus,
[data-theme="dark"] .form-select:focus {
  background-color: var(--pl-input-bg);
  color: var(--pl-text);
  border-color: var(--pl-primary);
  box-shadow: 0 0 0 3px var(--pl-primary-ring);
}
[data-theme="dark"] .form-control::placeholder { color: var(--pl-text-subtle); }
/* The native <option> list is painted by the OS from the select's own computed
   background, and --pl-input-bg is rgba(255,255,255,.03) in dark — translucent.
   It composites to near-white behind the popup while the option text stays
   --pl-text (#eef3f9), so every label rendered white-on-white and the list
   looked empty except the row under the cursor, which the OS repaints with its
   own highlight. The popup needs an OPAQUE ground; `color-scheme: dark` alone
   cannot supply it, because an explicit background on the select is what the
   popup follows. --pl-surface is opaque in both themes. optgroup is listed
   because it inherits nothing useful from the select. */
[data-theme="dark"] .form-select option,
[data-theme="dark"] .form-select optgroup,
[data-theme="dark"] select option,
[data-theme="dark"] select optgroup {
  background-color: var(--pl-surface);
  color: var(--pl-text);
}
[data-theme="dark"] .form-check-input {
  background-color: var(--pl-input-bg);
  border-color: var(--pl-border-strong);
}
[data-theme="dark"] .form-check-input:checked {
  background-color: var(--pl-primary);
  border-color: var(--pl-primary);
}
[data-theme="dark"] .form-switch .form-check-input {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%2394a3b8'/%3e%3c/svg%3e");
}
[data-theme="dark"] .form-switch .form-check-input:checked {
  background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='%23ffffff'/%3e%3c/svg%3e");
}
[data-theme="dark"] .input-group-text {
  background: var(--pl-surface-alt);
  color: var(--pl-text);
  border-color: var(--pl-border);
}
[data-theme="dark"] .form-control:disabled,
[data-theme="dark"] .form-select:disabled,
[data-theme="dark"] .form-check-input:disabled {
  background-color: var(--pl-surface-sunken);
  color: var(--pl-text-subtle);
  border-color: var(--pl-border);
}
[data-theme="dark"] .pl-fieldset { border-color: var(--pl-border); }

/* ── 32. Detail layout ──────────────────────────────────────── */
.pl-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 1.25rem;
}
@media (max-width: 992px) {
  .pl-detail { grid-template-columns: 1fr; }
}
.pl-detail__hero {
  display: flex; justify-content: space-between;
  align-items: flex-start;
  gap: 1rem; flex-wrap: wrap;
  padding: 1.25rem 1.5rem;
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-lg);
  margin-bottom: 1.25rem;
}
.pl-detail__title { display: flex; align-items: center; gap: 0.75rem; }
.pl-detail__avatar { flex-shrink: 0; }
.pl-detail__name {
  margin: 0;
  font-size: var(--pl-fs-2xl);
  font-weight: var(--pl-fw-bold);
}
.pl-detail__sub {
  color: var(--pl-text-muted);
  font-size: var(--pl-fs-base);
  margin-top: 0.125rem;
}
.pl-detail__actions { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.pl-detail__main { min-width: 0; }
.pl-detail__aside {
  position: sticky;
  top: calc(var(--pl-topbar-h) + 1rem);
  align-self: flex-start;
}

/* ── Detail hero — unified gradient hero used across detail pages ──
   Variants: --billing, --feature, --staff, --clinic, --success
   Anatomy:  .pl-hero
              ├ .pl-hero__main      (avatar + body)
              │   ├ .pl-hero__avatar
              │   └ .pl-hero__body  (eyebrow, title, sub, chips)
              └ .pl-hero__aside     (stat or actions) */
.pl-hero {
  position: relative;
  isolation: isolate;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  align-items: center;
  justify-content: space-between;
  padding: 1.4rem 1.6rem;
  margin-bottom: 1.25rem;
  /* The house card (DS-03, 2026-09-23): flat surface, 6px, inset hairline,
     no rest shadow — tokens only, so dark needs no twin. The base used to
     paint a Tailwind pastel gradient (#dbeafe → #e0e7ff → #fce7f3) under a
     drop shadow on a 16px radius; every one of its 17 call sites opted out
     with --plain/--bare, so the flat plane is now simply what a hero is. */
  border: 0;
  border-radius: var(--pl-radius-card);
  color: var(--pl-text);
  overflow: hidden;
  background: var(--pl-surface);
  box-shadow: inset 0 0 0 1px var(--pl-border);
}

.pl-hero__main {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex: 1 1 320px;
  min-width: 0;
}
.pl-hero__avatar {
  /* The house icon tile (same recipe as .pl-page-header__icon): flat navy
     plane on the 8px tile radius, white ink in both themes. Was a 16px
     frosted-glass disc with an inset highlight. */
  width: 68px;
  height: 68px;
  border-radius: var(--pl-radius-tile);
  background: var(--pl-tile-gradient);
  border: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--pl-on-tile);
  font-size: 1.65rem;
  font-weight: var(--pl-fw-bold);
  flex-shrink: 0;
  overflow: hidden;
  box-shadow: var(--pl-tile-shadow);
}
.pl-hero__avatar img {
  width: 100%; height: 100%; object-fit: cover;
}
.pl-hero__body { min-width: 0; flex: 1 1 auto; }
/* ── The eyebrow ────────────────────────────────────────────────────────
   The brand's most recognisable small element, and the app had only a washed
   out imitation of it (0.7rem / 600 / .08em / muted grey, no ticks — half the
   tracking, two weight steps light, wrong colour).
   The real recipe, measured off the site: 11px / 800 / .16em / uppercase /
   navy, with 11px coral corner brackets at top-left and bottom-right.
   `.pl-eyebrow` is the standalone class to reach for on any section header;
   `.pl-hero__eyebrow` inherits it so the ~26 existing hero call sites gain
   the treatment with no template change. */
.pl-eyebrow,
.pl-hero__eyebrow {
  position: relative;
  display: inline-block;
  width: max-content;
  max-width: 100%;
  padding: 6px 12px;
  margin-bottom: 0.5rem;
  font-size: 11px;
  font-weight: var(--pl-fw-extrabold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--pl-brand);
}
.pl-eyebrow::before, .pl-eyebrow::after,
.pl-hero__eyebrow::before, .pl-hero__eyebrow::after {
  content: "";
  position: absolute;
  width: 9px; height: 9px;
  border-style: solid;
  border-color: var(--pl-coral);
}
.pl-eyebrow::before, .pl-hero__eyebrow::before { top: 0; left: 0; border-width: 2px 0 0 2px; }
.pl-eyebrow::after,  .pl-hero__eyebrow::after  { bottom: 0; right: 0; border-width: 0 2px 2px 0; }
/* On a dark ground the ink and the ticks both step up to the light tints —
   navy on ink is invisible and coral on ink is muddy. */
[data-theme="dark"] .pl-eyebrow,
.pl-anon__pitch .pl-eyebrow { color: var(--pl-coral-light); }
[data-theme="dark"] .pl-eyebrow::before, [data-theme="dark"] .pl-eyebrow::after,
.pl-anon__pitch .pl-eyebrow::before, .pl-anon__pitch .pl-eyebrow::after {
  border-color: var(--pl-coral-light);
}
.pl-hero__title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: var(--pl-fw-extrabold);
  line-height: 1.2;
  letter-spacing: -0.012em;
  color: var(--pl-text);
}
.pl-hero__sub {
  margin-top: 0.4rem;
  font-size: 0.9rem;
  color: var(--pl-text-muted);
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}
.pl-hero__sub strong { font-weight: var(--pl-fw-bold); color: var(--pl-text); }
.pl-hero__code {
  font-family: var(--pl-font-mono);
  font-size: 0.78rem;
  padding: 0.1rem 0.4rem;
  border-radius: var(--pl-radius-card);
  background: var(--pl-surface-alt);
  border: 1px solid var(--pl-border);
  color: var(--pl-text);
}
.pl-hero__chips {
  display: flex;
  gap: 0.4rem;
  flex-wrap: wrap;
  margin-top: 0.75rem;
}
.pl-hero__pill,
.pl-hero__chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.7rem;
  border-radius: var(--pl-radius-pill);
  font-size: 0.74rem;
  font-weight: var(--pl-fw-semibold);
  background: var(--pl-surface-alt);
  border: 1px solid var(--pl-border);
  color: var(--pl-text);
  white-space: nowrap;
}
.pl-hero__chip .bi { font-size: 0.88em; opacity: 0.92; }

.pl-hero__aside {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  flex-shrink: 0;
  gap: 0.2rem;
}
.pl-hero__stat {
  font-size: 2rem;
  font-weight: var(--pl-fw-extrabold);
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--pl-text);
}
.pl-hero__stat small {
  font-size: 0.78rem;
  font-weight: var(--pl-fw-medium);
  color: var(--pl-text-muted);
  margin-left: 0.1rem;
}
.pl-hero__stat-sub {
  font-size: 0.78rem;
  color: var(--pl-text-muted);
}

.pl-hero__actions {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  align-items: center;
  flex-direction: row;
}
/* On a flat surface the house .btn bridges (§03) are the right buttons; the
   frosted-white glass buttons, the ink .btn-primary and the Tailwind red
   .btn-outline-danger that lived here were the pastel hero's own palette. */
.pl-hero__actions .btn,
.pl-hero .pl-hero__actions .btn {
  font-weight: var(--pl-fw-semibold);
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              border-color var(--pl-dur-fast) var(--pl-ease),
              transform var(--pl-dur-instant) var(--pl-ease);
}
.pl-hero__actions .btn:active { transform: translateY(1px); }

/* ── Hero surface ────────────────────────────────────────────────────────
   This was nine pastel gradient variants (billing / feature / staff / clinic
   / brand / tier / success / applied / neutral) in blue, violet, pink, teal,
   amber and emerald, each with its own avatar ink and its own dark-mode twin
   — roughly 40 hex literals, none of them in the brand.

   ALL NINE had zero call sites. Every one of the 17 templates that renders a
   .pl-hero reaches for `--plain` (16) or `--bare` (3), i.e. every page in the
   product was already opting OUT of the variant system. So the flat treatment
   is now simply what .pl-hero is, and the two flattening modifiers are kept as
   no-ops so none of those 19 call sites need editing.

   A hero identifies itself by its eyebrow and its icon, not by a hue. */
.pl-hero--plain,
.pl-hero--bare { background: var(--pl-surface); box-shadow: inset 0 0 0 1px var(--pl-border); }

/* Dark: nothing to do. The base rules above read only tokens (--pl-surface,
   --pl-border, --pl-text, --pl-tile-*), which the dark block already flips —
   the 60-line dark twin that stood here (white text, translucent chips, a
   second raised-plane rule) went with the gradient it was compensating for. */

@media (max-width: 720px) {
  .pl-hero { padding: 1.1rem 1.2rem; gap: 1rem; }
  .pl-hero__title { font-size: 1.25rem; }
  .pl-hero__avatar { width: 56px; height: 56px; font-size: 1.35rem; }
  .pl-hero__stat { font-size: 1.6rem; }
  .pl-hero__aside { align-items: flex-start; text-align: left; width: 100%; }
}

.pl-key-facts {
  background: var(--pl-surface);
  border: 1px solid var(--pl-border);
  border-radius: var(--pl-radius-lg);
  overflow: hidden;
}
.pl-key-facts__header {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--pl-border);
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--pl-text-muted);
}
.pl-key-facts__item {
  display: flex; align-items: flex-start;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.625rem 1rem;
  font-size: var(--pl-fs-base);
  border-bottom: 1px solid var(--pl-border);
}
.pl-key-facts__item:last-child { border-bottom: 0; }
.pl-key-facts__label {
  color: var(--pl-text-muted);
  font-size: var(--pl-fs-sm);
  flex-shrink: 0;
}
.pl-key-facts__value {
  color: var(--pl-text);
  font-weight: var(--pl-fw-medium);
  text-align: right;
  min-width: 0;
  word-wrap: break-word;
}

/* ── 33. Buttons polish ─────────────────────────────────────── */
.btn {
  /* The site's button is 4px and semibold-to-bold. Weight was `medium` (500),
     which made every action read as secondary. 600 is the dense-UI reading of
     the site's 700 — in-app buttons are much smaller than a marketing CTA. */
  --bs-btn-font-weight: var(--pl-fw-semibold);
  --bs-btn-border-radius: var(--pl-radius-control);
  font-size: var(--pl-fs-base);
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              border-color var(--pl-dur-fast) var(--pl-ease),
              box-shadow var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease),
              transform var(--pl-dur-fast) var(--pl-ease);
  display: inline-flex; align-items: center; gap: 0.375rem;
  justify-content: center;
}
.btn:active { transform: translateY(1px); }
.btn-sm { --bs-btn-padding-y: 0.25rem; --bs-btn-padding-x: 0.625rem; font-size: var(--pl-fs-sm); }
.btn-lg { --bs-btn-padding-y: 0.5rem;  --bs-btn-padding-x: 1rem;     font-size: var(--pl-fs-md); }
.btn-icon {
  width: 32px; height: 32px;
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}

.btn-soft-primary {
  background: var(--pl-primary-soft);
  color: var(--pl-primary-hover);
  border: 1px solid transparent;
}
.btn-soft-primary:hover {
  background: var(--pl-primary-100);
  color: var(--pl-primary-hover);
}
.btn-soft-success {
  background: var(--pl-success-soft);
  color: var(--pl-success-text);
  border: 1px solid transparent;
}
.btn-soft-warning {
  background: var(--pl-warning-soft);
  color: var(--pl-warning-text);
  border: 1px solid transparent;
}
.btn-soft-danger {
  background: var(--pl-danger-soft);
  color: var(--pl-danger-text);
  border: 1px solid transparent;
}
/* The soft success/warning/danger buttons had a hover in DARK only, so in light
   mode three of the four soft variants were inert under the cursor — the button
   looked disabled until you clicked it. A border on hover rather than a darker
   fill, so the ink keeps the contrast it was chosen for. */
.btn-soft-success:hover { background: var(--pl-success-soft); border-color: var(--pl-success-border); color: var(--pl-success-text); }
.btn-soft-warning:hover { background: var(--pl-warning-soft); border-color: var(--pl-warning-border); color: var(--pl-warning-text); }
.btn-soft-danger:hover  { background: var(--pl-danger-soft);  border-color: var(--pl-danger-border);  color: var(--pl-danger-text); }

/* Dark mode: soft buttons — visible hover bumps */
[data-theme="dark"] .btn-soft-primary {
  background: var(--pl-primary-tint);
  color: var(--pl-primary-on-tint);
}
[data-theme="dark"] .btn-soft-primary:hover {
  background: rgba(59, 134, 188, 0.28);
  color: var(--pl-primary-200);
}
[data-theme="dark"] .btn-soft-success {
  background: var(--pl-success-tint);
  color: var(--pl-success-on-tint);
}
[data-theme="dark"] .btn-soft-success:hover {
  background: color-mix(in srgb, var(--pl-success) 28%, transparent);
  color: var(--pl-success-on-tint);
}
[data-theme="dark"] .btn-soft-warning {
  background: var(--pl-warning-soft);
  color: var(--pl-warning-text);
}
[data-theme="dark"] .btn-soft-warning:hover {
  background: color-mix(in srgb, var(--pl-warning) 32%, transparent);
  color: var(--pl-warning-text);
}
[data-theme="dark"] .btn-soft-danger {
  background: var(--pl-danger-soft);
  color: var(--pl-danger-text);
}
[data-theme="dark"] .btn-soft-danger:hover {
  background: color-mix(in srgb, var(--pl-danger) 32%, transparent);
  color: var(--pl-danger-text);
}

/* ── 34. Anonymous (auth) shell ─────────────────────────────── */
.pl-anon {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /* Was indigo rgba(79,70,229) + violet rgba(124,58,237) — two hues that are
     not in the brand, on the shell behind every auth page. Now sky + coral,
     which is what the dark block below already did. */
  background:
    radial-gradient(1200px 600px at 10% -10%, rgba(59, 134, 188, 0.10), transparent 60%),
    radial-gradient(800px 400px at 110% 110%, rgba(232, 89, 58, 0.05), transparent 60%),
    var(--pl-bg);
}
.pl-anon__pitch {
  /* Two navies, matching the site's dark acts — was primary-700 (#17305c),
     which is a mid-navy the locked palette does not contain. */
  background: linear-gradient(135deg, var(--pl-brand) 0%, var(--pl-brand-void) 100%);
  color: #fff;
  padding: 3rem 2.5rem;
  display: flex; flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}
.pl-anon__pitch::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(600px 300px at 110% 0%, rgba(255, 255, 255, 0.12), transparent 60%),
    radial-gradient(400px 200px at 0% 110%, rgba(255, 255, 255, 0.08), transparent 60%);
  pointer-events: none;
}
.pl-anon__pitch-content { position: relative; z-index: 1; max-width: 480px; }
.pl-anon__brand {
  display: inline-flex; align-items: center; gap: 0.625rem;
  font-size: var(--pl-fs-lg);
  font-weight: var(--pl-fw-bold);
  color: #fff;
  text-decoration: none;
  letter-spacing: -0.01em;
}
.pl-anon__brand-mark {
  width: 36px; height: 36px;
  border-radius: var(--pl-radius-tile);
  background: rgba(255, 255, 255, 0.15);
  border: 1px solid rgba(255, 255, 255, 0.25);
  display: inline-flex; align-items: center; justify-content: center;
  backdrop-filter: blur(4px);
}
/* White cut of the client wordmark, sitting straight on the navy pitch panel. */
.pl-anon__brand-logo {
  height: 30px;
  width: auto;
  max-width: 260px;
  display: block;
  object-fit: contain;
  object-position: left center;
}
.pl-anon__hero {
  font-family: var(--pl-font-display);
  font-size: clamp(2rem, 2.6vw, 2.6rem);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: 0.005em;
  color: #fff;
  margin: 2.5rem 0 1rem;
}
.pl-anon__lead {
  font-size: var(--pl-fs-lg);
  color: rgba(255, 255, 255, 0.85);
  line-height: var(--pl-lh-snug);
  max-width: 44ch;
}
.pl-anon__features {
  list-style: none;
  padding: 0; margin: 2rem 0 0;
  display: grid;
  gap: 0.875rem;
  position: relative; z-index: 1;
}
.pl-anon__feature {
  display: flex; gap: 0.75rem; align-items: flex-start;
  font-size: var(--pl-fs-base);
  color: rgba(255, 255, 255, 0.92);
}
.pl-anon__feature-icon {
  width: 24px; height: 24px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  margin-top: 1px;
}
.pl-anon__footer {
  position: relative; z-index: 1;
  font-size: var(--pl-fs-sm);
  color: rgba(255, 255, 255, 0.6);
}

.pl-anon__form-wrap {
  display: flex; align-items: center;
  justify-content: center;
  padding: 2rem;
}
.pl-anon__card {
  width: 100%;
  max-width: 420px;
  background: var(--pl-surface);
  border-radius: var(--pl-radius-xl);
  padding: 2rem 2.25rem;
  box-shadow: var(--pl-shadow-lg);
  border: 1px solid var(--pl-border);
}
@media (max-width: 992px) {
  .pl-anon { grid-template-columns: 1fr; }
  .pl-anon__pitch { display: none; }
}

/* Dark mode: anon shell — brand-tinted background, lifted card, deeper pitch */
[data-theme="dark"] .pl-anon {
  background:
    radial-gradient(1200px 600px at 10% -10%, rgba(59, 134, 188, 0.12), transparent 60%),
    radial-gradient(800px 400px at 110% 110%, rgba(232, 89, 58, 0.06), transparent 60%),
    var(--pl-bg);
}
[data-theme="dark"] .pl-anon__pitch {
  background: linear-gradient(135deg, var(--pl-brand) 0%, var(--pl-brand-void) 100%);
}
[data-theme="dark"] .pl-anon__card {
  background: var(--pl-elevation-2);
  border-color: var(--pl-border-strong);
  box-shadow: var(--pl-shadow-xl);
}

/* ── 35. Mobile ─────────────────────────────────────────────── */
.pl-backdrop {
  display: none;
  position: fixed; inset: 0;
  background: var(--pl-overlay);
  z-index: var(--pl-z-backdrop);
}
.pl-backdrop.is-open { display: block; }

@media (max-width: 768px) {
  .pl-app { grid-template-columns: 1fr; }
  .pl-sidebar {
    position: fixed; top: 0; left: 0; bottom: 0;
    width: var(--pl-sidebar-w);
    transform: translateX(-100%);
    transition: transform var(--pl-dur-base) var(--pl-ease);
    box-shadow: var(--pl-shadow-lg);
  }
  .pl-sidebar.is-open { transform: translateX(0); }
  .pl-topbar__toggle { display: inline-flex; }
  .pl-pill--tenant { display: none; }
  .pl-content { padding: 1rem; }
  .pl-page-header { flex-direction: column; align-items: flex-start; }
  .pl-detail { grid-template-columns: 1fr; }

  /* Collapse the trail on tablet: keep Home + the LAST TWO crumbs (the page's
     parent and the page), hide everything between and mark the gap with "…".
     Was Home + current only, which lost the one crumb that says where the
     page lives. Group crumbs (rail sections, no page of their own) go first
     — they are the least load-bearing — and base.html's fitCrumbs() does the
     same overflow-driven pruning on wider screens. */
  .pl-topbar__crumbs-item:not(:first-child):not(:nth-last-child(-n + 2)) {
    display: none;
  }
  .pl-topbar__crumbs-item:nth-last-child(2):not(:nth-child(2))::before {
    content: "\2026";
    color: var(--pl-text-subtle);
    margin: 0 0.4rem;
    font-size: 0.85rem;
  }
}

/* ── Shell addenda ──────────────────────────────────────────────
   (2026-09-23, DS-04) This used to be a 180-line "Navigation modernization"
   layer that re-declared 22 §06/§07 selectors — a second sidebar active rule
   with a coral gradient, a glass topbar, hard-coded 200ms/150ms motion and a
   Tailwind-amber badge. Each of those is now folded into the ONE declaration
   its selector already had in §06/§07 (tokens only; the 3px coral active rail
   kept). What remains here is what was never a duplicate: the badge roll-up,
   the hover motion (gated on no-preference) and the compact-width topbar. */

/* A sub-menu row carries its children's count so a shut branch still shows it.
   Once the branch is open the child owns the badge again, so the parent's copy
   goes away and the same number is never on screen twice. */
.pl-sidebar__badge--rollup {
  margin-left: auto;
  margin-right: 0.35rem;
  flex-shrink: 0;
}
.pl-sidebar__group--submenu:not(.is-collapsed) > .pl-sidebar__group-label .pl-sidebar__badge--rollup,
.pl-sidebar__group--nested:not(.is-collapsed) > .pl-sidebar__group-label .pl-sidebar__badge--rollup {
  display: none;
}

/* ── Shell hooks (2026-09-23, handoff from the shell agent) ───────
   templates/base.html + _partials/topbar*.html shipped these with Bootstrap
   utilities only; this is the kit's treatment. Tokens only. Where the markup
   still carries an !important utility, the declaration is restated — noted
   inline so it can go when the utility does. */

/* Skip link — the first Tab on every page. Bootstrap's
   .visually-hidden-focusable does the hiding; on focus it is a navy pill
   pinned top-left OVER the rail and topbar (fixed, so no layout shift and it
   is in view whatever the scroll position). Navy in BOTH themes — it sits on
   the navy rail. */
.pl-skip.btn,
.pl-skip {
  /* `.pl-skip.btn` (0,2,0) outranks the `[data-theme="dark"] .btn-primary`
     bridge in §03, which would otherwise repaint the ink with --pl-on-primary
     (near-black on navy) in dark. The bare `.pl-skip` keeps the rule alive if
     the markup ever drops the Bootstrap button classes. */
  position: fixed;
  top: 0.5rem; left: 0.5rem;
  z-index: calc(var(--pl-z-sidebar) + 1);
  --bs-btn-bg: var(--pl-primary-900);
  --bs-btn-color: var(--pl-neutral-0);
  --bs-btn-border-color: var(--pl-primary-900);
  --bs-btn-hover-bg: var(--pl-primary-800);
  --bs-btn-hover-color: var(--pl-neutral-0);
  --bs-btn-hover-border-color: var(--pl-primary-800);
  --bs-btn-active-bg: var(--pl-primary-800);
  --bs-btn-active-color: var(--pl-neutral-0);
  --bs-btn-active-border-color: var(--pl-primary-800);
  padding: 0.45rem 0.9rem;
  border-radius: var(--pl-radius-pill);
  font-weight: var(--pl-fw-semibold);
  white-space: nowrap;
  box-shadow: var(--pl-shadow-lg);
}
.pl-skip:focus-visible {
  outline: 2px solid var(--pl-neutral-0);
  outline-offset: 2px;
  box-shadow: var(--pl-shadow-lg), 0 0 0 4px var(--pl-focus-ring);
}

/* Bell count — ONE coral pill overhanging the icon button's top-right
   corner, ringed in the topbar surface so it never touches the glyph.
   The markup still carries .badge.rounded-pill.text-bg-danger
   .position-absolute.top-0.end-0; .text-bg-danger is !important, hence the
   two !important restatements (drop with the utility). */
.pl-icon-btn .pl-icon-btn__count {
  position: absolute;
  top: 0; right: 0;
  transform: translate(28%, -28%);
  min-width: 18px; height: 18px;
  padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--pl-radius-pill);
  background-color: var(--pl-coral);
  color: var(--pl-on-primary);
  font-size: var(--pl-fs-xs);
  font-weight: var(--pl-fw-bold);
  line-height: 1;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--pl-surface);
  pointer-events: none;
}
[data-theme="dark"] .pl-icon-btn .pl-icon-btn__count { color: var(--pl-neutral-0); }

/* Group crumb — a section of the rail, not a page: muted, unlinked, no hover
   affordance. Hidden first when the strip is short (≤992px rule in §35 and
   fitCrumbs() above that); the last two crumbs always survive. */
.pl-topbar__crumb--group,
.pl-topbar__crumb--group:hover {
  color: var(--pl-text-subtle);
  font-weight: var(--pl-fw-regular);
  background: transparent;
  cursor: default;
}
@media (max-width: 991.98px) {
  .pl-topbar__crumbs-item--group:not(:nth-last-child(-n + 2)) { display: none; }
}

/* Account menu — and the product's ONE theme control inside it: a Bootstrap
   .btn-group in the markup, the .pl-seg recipe on screen (the strip and the
   selected state are the .pl-seg rules themselves, extended in §38; this rule
   only neutralises the .btn-outline-secondary skin and sizes the icon-only
   segments). */
.pl-usermenu { min-width: 240px; padding: 0.25rem; }
.pl-usermenu .dropdown-item { border-radius: var(--pl-radius-control); }
.pl-usermenu .btn-group > .btn[data-pl-theme-set] {
  --bs-btn-bg: transparent;
  --bs-btn-color: var(--pl-text-muted);
  --bs-btn-border-color: transparent;
  --bs-btn-hover-bg: color-mix(in srgb, var(--pl-surface) 60%, transparent);
  --bs-btn-hover-color: var(--pl-text);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-active-bg: var(--pl-surface);
  --bs-btn-active-color: var(--pl-text);
  --bs-btn-active-border-color: transparent;
  --bs-btn-focus-shadow-rgb: var(--bs-primary-rgb);
  margin-left: 0;
  width: 34px; height: 28px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: var(--pl-radius-control);
  font-size: var(--pl-fs-md);
}

/* Hover motion — the lifts only, gated on the reader NOT asking for reduced
   motion (§37 below neutralises them again for anyone who did). The
   transitions these ride on live in the base §06/§07 rules. */
@media (prefers-reduced-motion: no-preference) {
  .pl-sidebar__item:hover .pl-sidebar__item-label { transform: translateX(2px); }
  .pl-icon-btn:hover  { transform: scale(1.05); }
  .pl-icon-btn:active { transform: scale(0.97); }
  a.pl-pill--tenant:hover { transform: translateY(-1px); }
}

@media (max-width: 480px) {
  .pl-topbar { padding: 0 0.5rem; gap: 0.375rem; }
  .pl-content { padding: 0.75rem; }
  .pl-topbar__crumb { max-width: 140px; padding: 0 0.5rem; font-size: 0.78rem; }
  /* On phones the tenant chip text is hidden — keep just the icon to save space */
  .pl-topbar__crumb--tenant .pl-topbar__crumb-text { display: none; }
  .pl-topbar__crumb--tenant { padding: 0 0.45rem; }
}

/* ── 36. Print ──────────────────────────────────────────────── */
@media print {
  .pl-sidebar, .pl-topbar, .pl-impersonate, .pl-toast-region,
  .pl-drawer, .pl-drawer-backdrop, .pl-skip { display: none !important; }
  .pl-app { display: block; }
  .pl-content { padding: 0; }
  /* Paper is white whatever the theme: the neutral ramp does NOT flip in the
     dark block, so these tokens are the light values in both themes. */
  .pl-card, .card { break-inside: avoid; box-shadow: inset 0 0 0 1px var(--pl-neutral-300); }
  a { color: inherit; text-decoration: none; }
  body { background: var(--pl-neutral-0); color: var(--pl-neutral-900); }

  /* Force-light fallback: prevent dark-mode tokens from leaking into prints */
  [data-theme="dark"] {
    background: var(--pl-neutral-0) !important;
    color: var(--pl-neutral-900) !important;
  }
  [data-theme="dark"] body,
  [data-theme="dark"] .pl-content,
  [data-theme="dark"] .pl-card,
  [data-theme="dark"] .card {
    background: var(--pl-neutral-0) !important;
    color: var(--pl-neutral-900) !important;
    border-color: var(--pl-neutral-300) !important;
  }
}

/* ── 37. Reduced motion ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .pl-pill--online .pl-pill__dot { animation: none; }

  /* Zeroing the DURATION only makes the movement instant — it does not remove
     it, so the whole kit still jumps a pixel under the cursor for a reader who
     asked for no motion. Neutralise the hover/press lift itself. Listed by
     selector rather than as a blanket `transform: none`, because transform is
     load-bearing elsewhere (the drawer slides in on translateX, the caret
     rotates, .pl-toolbar__search .bi centres on translateY). */
  .pl-card--hover:hover,
  .pl-stat:hover, a.pl-stat:hover,
  .pl-kpi:hover, a.pl-kpi:hover,
  .pl-hero__actions .btn:active,
  .pl-page-header__actions .btn:hover,
  .pl-page-header__actions .btn:active,
  .pl-page-header__actions .btn-primary:hover,
  .pl-page-header__tabs .nav-link:active,
  a.pl-pill--tenant:hover,
  .pl-icon-btn:hover, .pl-icon-btn:active,
  .pl-sidebar__item:hover .pl-sidebar__item-label,
  .btn:active {
    transform: none;
  }
}

/* ── Forced-colors (Windows high-contrast) ──────────────────── */
@media (forced-colors: active) {
  *:focus-visible {
    outline: 2px solid CanvasText;
    outline-offset: 2px;
  }
  .pl-card, .dropdown-menu, .pl-drawer, .pl-toast {
    border: 1px solid CanvasText;
  }
}

/* ── 38. Kit primitives (2026-09-23, additive) ──────────────────
   Three house primitives for pages OUTSIDE the .pacct kit, mirroring the
   anatomy the acct kit already ships (acct/_styles.html) so a page can be
   consistent with Account 360 without importing that partial. Tokens only;
   nothing here restyles an existing class.

   .pl-empty--plain   the .pacct-empty look on the existing .pl-empty block:
                      no dashed box, centred column, 60px icon tile.
                      Anatomy: .pl-empty > .pl-empty__icon + .pl-empty__title
                      + .pl-empty__text (alias of __body / __hint) + .pl-empty__actions
   .pl-seg            segmented control: <nav class="pl-seg"> of
                      .pl-seg__item (a or button); current = .is-active or
                      [aria-current]. Keyboard focus via the global ring.
   .pl-kpis / .pl-kpi KPI tile row on the house card recipe:
                      .pl-kpi > .pl-kpi__label (+ .bi) | .pl-kpi__value
                      (.pl-kpi__value--sm) | .pl-kpi__hint; tones --ok / --warn
                      / --danger / --info; a.pl-kpi is clickable, .is-on = selected.
   ──────────────────────────────────────────────────────────────── */
.pl-empty--plain {
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
  padding: 48px 20px;
  background: transparent;
  border: 0;
  border-radius: 0;
}
.pl-empty--plain .pl-empty__icon {
  width: 60px; height: 60px; margin: 0 0 2px;
  border-radius: var(--pl-radius-tile);
  background: var(--pl-surface-alt);
  color: var(--pl-primary);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--pl-primary) 18%, transparent);
}
.pl-empty--plain .pl-empty__title,
.pl-empty--plain .pl-empty__body,
.pl-empty--plain .pl-empty__text,
.pl-empty--plain .pl-empty__hint { margin: 0; }
.pl-empty__text,
.pl-empty__hint {
  max-width: 460px; margin: 0 auto 1rem;
  font-size: var(--pl-fs-base);
  line-height: var(--pl-lh-base, 1.5);
  color: var(--pl-text-muted);
}
.pl-empty--plain .pl-empty__actions { margin-top: 4px; }

.pl-seg,
.pl-usermenu .btn-group:has(> [data-pl-theme-set]) {
  display: inline-flex; align-self: flex-start; max-width: 100%;
  gap: 4px; padding: 3px;
  flex-wrap: wrap;
  background: var(--pl-surface-alt);
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 0 0 1px var(--pl-border);
}
.pl-seg__item {
  display: inline-flex; align-items: center; gap: 0.375rem;
  padding: 5px 12px;
  border: 0; background: transparent;
  border-radius: var(--pl-radius-control);
  font-size: var(--pl-fs-base);
  font-weight: var(--pl-fw-medium);
  line-height: 1.4;
  color: var(--pl-text-muted);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--pl-dur-fast) var(--pl-ease),
              color var(--pl-dur-fast) var(--pl-ease);
}
.pl-seg__item:hover { color: var(--pl-text); background: color-mix(in srgb, var(--pl-surface) 60%, transparent); }
.pl-seg__item.is-active,
.pl-seg__item[aria-current],
.pl-usermenu .btn-group > .btn[data-pl-theme-set].active,
.pl-usermenu .btn-group > .btn[data-pl-theme-set][aria-pressed="true"] {
  background: var(--pl-surface);
  color: var(--pl-text);
  font-weight: var(--pl-fw-semibold);
  box-shadow: inset 0 0 0 1px var(--pl-border), var(--pl-shadow-xs);
}
.pl-seg__item:focus-visible { outline-offset: 0; }
.pl-seg__item .pl-tag { margin-left: 2px; }

.pl-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(212px, 1fr));
  gap: 12px;
}
.pl-kpi {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "label value" "hint value";
  align-items: center;
  column-gap: 12px; row-gap: 2px;
  padding: 11px 16px;
  overflow: hidden;
  background: var(--pl-surface);
  border: 0;
  border-radius: var(--pl-radius-card);
  box-shadow: inset 0 0 0 1px var(--pl-border);
  color: var(--pl-text);
  transition: transform var(--pl-dur-base) var(--pl-ease-out),
              box-shadow var(--pl-dur-base) var(--pl-ease-out);
}
.pl-kpi::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
  background: var(--pl-tile-gradient);
  opacity: 0;
  transition: opacity var(--pl-dur-fast) var(--pl-ease);
}
.pl-kpi:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1px var(--pl-border-strong), var(--pl-shadow-md); }
.pl-kpi:hover::before { opacity: 1; }
.pl-kpi__label {
  grid-area: label; align-self: end;
  display: flex; align-items: center; gap: 7px;
  font-size: var(--pl-fs-sm); font-weight: var(--pl-fw-semibold);
  letter-spacing: .05em; text-transform: uppercase;
  color: var(--pl-text-muted);
}
.pl-kpi__label .bi { color: var(--pl-primary); font-size: var(--pl-fs-md); }
.pl-kpi__value {
  grid-area: value; justify-self: end; align-self: center; text-align: right;
  font-size: var(--pl-fs-3xl); font-weight: var(--pl-fw-bold);
  letter-spacing: -.02em; line-height: var(--pl-lh-tight);
  color: var(--pl-text);
  font-variant-numeric: tabular-nums;
}
.pl-kpi__value--sm { font-size: var(--pl-fs-base); letter-spacing: normal; line-height: var(--pl-lh-snug, 1.3); }
.pl-kpi__hint { grid-area: hint; align-self: start; font-size: var(--pl-fs-sm); line-height: var(--pl-lh-snug, 1.3); color: var(--pl-text-muted); }
.pl-kpi--ok     .pl-kpi__label .bi { color: var(--pl-success); }
.pl-kpi--warn   .pl-kpi__label .bi { color: var(--pl-warning); }
.pl-kpi--danger .pl-kpi__label .bi { color: var(--pl-danger); }
.pl-kpi--info   .pl-kpi__label .bi { color: var(--pl-info); }
a.pl-kpi { text-decoration: none; color: inherit; }
a.pl-kpi:focus-visible { outline: 2px solid var(--pl-primary); outline-offset: 2px; box-shadow: inset 0 0 0 1px var(--pl-border), 0 0 0 3px var(--pl-focus-ring); }
.pl-kpi__go { grid-area: value; justify-self: end; align-self: end; font-size: .72rem; opacity: 0; transition: opacity var(--pl-dur-fast) var(--pl-ease); }
a.pl-kpi:hover .pl-kpi__go, a.pl-kpi:focus-visible .pl-kpi__go { opacity: .7; }
.pl-kpi.is-on { background: var(--pl-primary-tint); box-shadow: inset 0 0 0 1px var(--pl-primary); }
.pl-kpi.is-on::before { opacity: 1; }

/* ── Utilities ──────────────────────────────────────────────── */
.min-w-0 { min-width: 0; }
.pl-truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pl-hairline { border-bottom: 1px solid var(--pl-border-hairline); }
.pl-divider { height: 1px; background: var(--pl-border); margin: 1rem 0; }
.pl-mono { font-family: var(--pl-font-mono); }
