/* ============================================================
   LIBERTY OS — MODULE UI STANDARD  (module-ds.css)  v2.0
   Drop-in stylesheet for every /apps/<module>/ surface.

   CANONICAL COPY. Source: Claude Design project "Module UI Standard"
   (edf5c3f8-0b19-4868-9dc1-98d9bfb1d10c), imported 2026-08-20, plus two
   local additions: the DARK THEME block (the shell stamps data-theme into
   module iframes) and the self-hosted @font-face block (the design canvas used Google
   Fonts; modules must resolve type from their own ds/fonts/ under the
   strict CSP). Modules load a synced copy at web/ds/module-ds.css —
   run scripts/sync_module_ds.py after editing THIS file, never edit
   the copies.

   v2.0 (2026-08-28) ADOPTS THE LIBERTY INTERFACE PROTOCOL (design team,
   2026-08-27; Patrick's sign-off 2026-08-28):
   · THREE TYPE ROLES, no overlap — Raleway speaks (all language), Lato
     counts (all running data, tabular figures on), Prata announces (the
     page title plus AT MOST ONE hero figure per screen: .lds-hero-value).
     KPI values therefore moved from Prata to Lato in this version.
   · TYPE THE HEX: every colour below is on the protocol's palette sheet
     (2026 Branding Guide values) or an rgba() of one. The cool-tinted
     interface neutrals of v1 are gone.
   · COLOUR ROLES: the primary action is Liberty Blue (the gold-filled
     button is retired — rule 06 — .lds-btn--gold now renders as the
     primary); active tabs mark in Liberty Blue; Golden Yellow highlights
     on BLUE grounds only, so the gold-washed note and row-highlight
     styles moved to brand washes.
   · THE FLOOR: interactive controls are 44px minimum.

   RECORDED DEVIATIONS (Patrick, 2026-08-28 — named, not silent):
   1. Coloured data cells in reports stay (the protocol wanted retention
      counts on neutral surface); their fills use official status hexes.
   2. The signed-out landing keeps its near-black ground (protocol dark
      grounds are Liberty Blue shades).
   3. The DARK THEME below remains a full dark interface. Protocol rule 01
      allows only light panels on a dark ground; retiring the dark register
      is a product decision deferred to the brand escalation, not taken
      silently here.

   Adoption: load this file, delete your local token sheet, keep
   your layouts. Classes are prefixed lds-. The shell's density
   attribute (data-density="compact") is honored automatically.
   ============================================================ */

/* Self-hosted type. Fragment Mono ships no file on purpose: identifiers
   fall through --lds-mono to the system mono stack, which is the same
   register without another 100KB per module. Lato ships as latin-subset
   woff2 (~23KB/face) — it sets NUMBERS, and numbers are latin. */
@font-face { font-family: "Lato"; src: url("fonts/Lato-Regular.woff2") format("woff2"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Lato"; src: url("fonts/Lato-Bold.woff2") format("woff2"); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: "Prata"; src: url("fonts/Prata-Regular.ttf") format("truetype"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Raleway"; src: url("fonts/Raleway-Regular.ttf") format("truetype"); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: "Raleway"; src: url("fonts/Raleway-Italic.ttf") format("truetype"); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: "Raleway"; src: url("fonts/Raleway-Medium.ttf") format("truetype"); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: "Raleway"; src: url("fonts/Raleway-SemiBold.ttf") format("truetype"); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: "Raleway"; src: url("fonts/Raleway-Bold.ttf") format("truetype"); font-weight: 700; font-style: normal; font-display: swap; }

:root {
  /* --- CANVAS & SURFACES (protocol palette sheet: white ground, published
     Black tints for wells and rules; the v1 cool tint is retired) --- */
  --lds-canvas:       #FFFFFF;
  --lds-canvas-2:     #EBEBEB;
  --lds-surface:      #FFFFFF;
  --lds-surface-2:    #EBEBEB;
  --lds-surface-3:    #EBEBEB;
  --lds-line:         #DCDCDC;
  --lds-line-soft:    #EBEBEB;
  --lds-line-strong:  #8C8C8C;

  /* --- INK (the sheet's text column, verbatim) --- */
  --lds-ink:          #000000;
  --lds-ink-2:        #4D4D4D;
  --lds-ink-3:        #646464;
  --lds-ink-4:        #8C8C8C;   /* disabled / decorative only, never running text */

  /* --- BRAND (palette sheet, verbatim) --- */
  --lds-brand:        #004D85;   /* Liberty Blue */
  --lds-brand-hover:  #003A64;   /* the sheet's darker Liberty Blue shade */
  --lds-brand-2:      #337BB5;   /* Bell Blue */
  --lds-brand-3:      #5AB2E3;   /* Emphatic Blue — fills only, never text on white */
  --lds-brand-text:   #33719D;   /* text-safe accent blue, where Emphatic fails */
  --lds-brand-soft:   rgba(0, 77, 133, .07);
  --lds-gold:         #F19C38;   /* highlights on BLUE grounds only — never a control fill */
  --lds-gold-ink:     #784E1C;   /* the sheet's text-safe amber (7.23:1 on white) */
  --lds-gold-soft:    rgba(241, 156, 56, .14);

  /* --- STATUS (protocol: the three official values; text forms text-safe) --- */
  --lds-pos:          #1E7A1E;  --lds-pos-soft:  rgba(34, 139, 34, .10);
  --lds-caut:         #784E1C;  --lds-caut-soft: rgba(255, 216, 0, .20);
  --lds-crit:         #CE2029;  --lds-crit-soft: rgba(206, 32, 41, .09);

  /* --- CHART SERIES (order fixed: blues carry data, gold annotates, status
     colors appear only when the value IS the state). Declared HERE, in the
     light :root, never in a later block: a second :root after the dark theme
     ties on specificity and wins on order, which silently killed the dark
     block's lifted series colors (found 2026-09-01 reviewing the
     financial_reporting chart legends). --- */
  --lds-series-1: #004D85;
  --lds-series-2: #337BB5;
  --lds-series-3: #5AB2E3;
  --lds-series-4: #8FBBD9;   /* tint of Bell Blue — 4th series and "prior period" */
  --lds-series-5: #C6DCEA;   /* palest tint — context / remainder */
  --lds-grid: #EAEFF4;       /* hairline gridlines only, never boxed axes */

  /* --- TYPE (three roles, no overlap: Raleway speaks, Lato counts,
     Prata announces — see .lds-hero-value) --- */
  --lds-ui:           "Raleway", Arial, sans-serif;
  --lds-data:         "Lato", "Raleway", Arial, sans-serif;
  --lds-display:      "Prata", Georgia, serif;
  --lds-mono:         "Fragment Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* --- RADII (architectural, not friendly) --- */
  --lds-r1: 3px;  --lds-r2: 6px;  --lds-r3: 9px;  --lds-r4: 12px;

  /* --- DEPTH (hairlines do the work; shadow only where things float) --- */
  --lds-sh1: 0 1px 2px rgba(0, 0, 0, .05);
  --lds-sh2: 0 4px 12px rgba(0, 0, 0, .08);
  --lds-sh3: 0 14px 30px rgba(0, 0, 0, .14);
  --lds-focus: 0 0 0 3px rgba(90, 178, 227, .45);

  /* --- MOTION --- */
  --lds-ease: cubic-bezier(.22, 1, .36, 1);

  /* --- LAYOUT (shell geometry) --- */
  --lds-canvas-max: 1160px;
  --lds-pad: 26px 28px 44px;
  --lds-row-pad: 9px 12px;
  --lds-card-pad: 20px;
  --lds-gap: 14px;
}

[data-density="compact"] {
  --lds-row-pad: 5px 10px;
  --lds-card-pad: 14px;
  --lds-gap: 8px;
}

/* ============ DARK THEME ============
   The SHELL owns the toggle: it stamps data-theme="dark" onto each module
   iframe's <html> (same-origin), so a module never draws its own switch.
   Same hybrid contract in the dark register: cool night canvas, hairlines
   doing the depth work, blues carrying data. Brand-as-TEXT lightens for
   contrast; brand-as-FILL (buttons, KPI rules, bar fills) keeps a deep blue
   under white text - the component overrides below are that split. Local
   addition, not from the design project (2026-08-20). */
[data-theme="dark"] {
  --lds-canvas:       #101820;
  --lds-canvas-2:     #0C1218;
  --lds-surface:      #182430;
  --lds-surface-2:    #1C2A38;
  --lds-surface-3:    #223243;
  --lds-line:         #2C3E50;
  --lds-line-soft:    #263646;
  --lds-line-strong:  #3D5468;

  --lds-ink:          #E9EFF5;
  --lds-ink-2:        #B9C6D2;
  --lds-ink-3:        #8698A8;
  --lds-ink-4:        #5D6F80;

  --lds-brand:        #5FA8DC;   /* Liberty Blue, lifted for dark-ground text */
  --lds-brand-hover:  #7CBAE6;
  --lds-brand-2:      #6FB3E0;
  --lds-brand-3:      #8FC7EC;
  --lds-brand-soft:   #1B3A52;
  --lds-gold:         #F19C38;   /* gold reads on both grounds; still ONE action per screen */
  /* LIFTED for dark-ground text, same treatment brand/caut/pos get. The old #3D2900 was the
     light theme's dark-amber kept by mistake: dark ink over the amber wash over the dark
     canvas rendered unreadable mud (Patrick's 2026-08-31 statement screenshot - the Organic
     Growth row). */
  --lds-gold-ink:     #E8C25E;
  --lds-gold-soft:    rgba(241, 156, 56, .16);

  --lds-pos:          #4FB878;  --lds-pos-soft:  rgba(79, 184, 120, .14);
  --lds-caut:         #D9B23D;  --lds-caut-soft: rgba(217, 178, 61, .16);
  --lds-crit:         #E06B72;  --lds-crit-soft: rgba(224, 107, 114, .14);

  --lds-sh1: 0 1px 2px rgba(0, 0, 0, .35);
  --lds-sh2: 0 4px 12px rgba(0, 0, 0, .40);
  --lds-sh3: 0 14px 30px rgba(0, 0, 0, .55);
  --lds-focus: 0 0 0 3px rgba(111, 179, 224, .40);

  --lds-series-1: #5FA8DC;
  --lds-series-2: #7CBAE6;
  --lds-series-3: #9FCDEF;
  --lds-series-4: #3D6B8F;   /* prior period: the muted tint, still clearly the quieter series */
  --lds-series-5: #2A4A64;
  --lds-grid: #223243;
}
/* The page paints its own ground; without this a module body outside .lds-page
   would show the light default around a dark page. */
[data-theme="dark"] body { background: var(--lds-canvas); }
/* Brand-as-fill: solid controls keep a DEEP blue under white text - the lifted
   text-blue above would fail contrast as a background. */
[data-theme="dark"] .lds-btn { background: #155E92; }
[data-theme="dark"] .lds-btn:hover { background: #1B6FAE; }
[data-theme="dark"] .lds-btn--secondary { background: var(--lds-surface); color: var(--lds-brand); }
[data-theme="dark"] .lds-btn--secondary:hover { background: var(--lds-brand-soft); }
[data-theme="dark"] .lds-btn--ghost { background: transparent; color: var(--lds-ink-2); }
/* gold-as-button retired in v2 (rule 06): renders as the dark primary here too */
[data-theme="dark"] .lds-btn--gold { background: #155E92; color: #FFFFFF; border-color: transparent; }
[data-theme="dark"] .lds-btn--gold:hover { background: #1B6FAE; }
[data-theme="dark"] .lds-kpi { border-top-color: #155E92; }
[data-theme="dark"] .lds-bar-fill { background: #3D8BC4; }
[data-theme="dark"] .lds-bar-fill.alt { background: #5FA8DC; }

/* ============ PAGE FRAME ============ */
.lds-page {
  font-family: var(--lds-ui);
  font-size: 14px;
  line-height: 1.55;
  color: var(--lds-ink);
  background: var(--lds-canvas);
  min-height: 100%;
  -webkit-font-smoothing: antialiased;
  /* Lining figures, always. Raleway defaults to old-style numerals (the 9 descends, the 0
     sits at x-height), so a chip like 'last 90d' reads like 'god'. Inherited from the
     frame so every digit in a module sits on a common baseline. */
  font-feature-settings: 'lnum' 1;
  font-variant-numeric: lining-nums;
}
.lds-measure {
  max-width: var(--lds-canvas-max);
  margin: 0 auto;
  padding: var(--lds-pad);
}
/* SCROLLBARS FOLLOW THE THEME. The browser default paints a WHITE track, which on the dark
   ground renders as a bright strip across every wide table (Patrick's 2026-08-31 statement
   screenshot). scrollbar-color inherits, so the page sets it once; the ::-webkit rules cover
   engines that predate it. Tokens only - both themes resolve correctly. */
.lds-page { scrollbar-color: var(--lds-ink-3) var(--lds-surface-3); }
.lds-page *::-webkit-scrollbar { width: 10px; height: 10px; }
.lds-page *::-webkit-scrollbar-track { background: var(--lds-surface-3); }
.lds-page *::-webkit-scrollbar-thumb { background: var(--lds-ink-3); border-radius: 5px; }
.lds-page a { color: var(--lds-brand); text-decoration: none; }
/* An anchor dressed as a button keeps the button's ink. The rule above wins on
   specificity otherwise (class + type beats class), and a primary <a class="lds-btn">
   read brand-on-brand in light mode: a blue pill with invisible words (Producer
   Commissions' "Export to Excel", 2026-09-11). The variants keep their own ink. */
.lds-page a.lds-btn { color: #FFFFFF; }
.lds-page a.lds-btn--secondary { color: var(--lds-brand); }
.lds-page a.lds-btn--ghost { color: var(--lds-ink-2); }
.lds-page a.lds-btn--ghost:hover { color: var(--lds-ink); }
.lds-page a:hover { color: var(--lds-brand-2); text-decoration: underline; }
.lds-page :focus-visible { outline: none; box-shadow: var(--lds-focus); border-radius: var(--lds-r1); }

/* ============ MODULE HEADER ============
   The ONLY chrome a module draws. The shell bar above owns identity,
   nav and theme; dark module topbars are retired. One row: eyebrow +
   display title left, period/actions right. */
.lds-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
  flex-wrap: wrap;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--lds-line);
  margin-bottom: 22px;
}
.lds-eyebrow {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--lds-brand-2);
}
.lds-title {
  font-family: var(--lds-display);
  font-weight: 400;
  font-size: 30px;
  line-height: 1.2;
  color: var(--lds-brand);
  margin: 4px 0 2px;
  letter-spacing: -0.005em;
  text-wrap: balance;
}
.lds-sub { color: var(--lds-ink-3); font-size: 13px; margin: 0; max-width: 70ch; }
.lds-header-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ============ TOOLBAR / FILTER ROW ============ */
.lds-toolbar {
  display: flex;
  align-items: flex-end;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: var(--lds-gap);
}
.lds-filter { display: flex; flex-direction: column; gap: 4px; }
.lds-filter-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lds-ink-3);
}
.lds-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--lds-ink);
  background: var(--lds-surface);
  border: 1px solid var(--lds-line);
  border-radius: var(--lds-r2);
  padding: 9px 12px;
  min-width: 130px;
  min-height: 44px;   /* rule 08: dropdowns are controls */
  cursor: pointer;
  transition: border-color .15s var(--lds-ease);
}
.lds-trigger:hover { border-color: var(--lds-brand-2); }
.lds-trigger .caret { color: var(--lds-ink-4); font-size: 10px; }
.lds-trigger.is-set { border-color: var(--lds-brand-2); background: var(--lds-brand-soft); color: var(--lds-brand); }

/* ============ BUTTONS (protocol: primary is Liberty Blue, white text,
   44px tall, 6px radius — and there is ONE of it per screen) ============ */
.lds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  border-radius: var(--lds-r2);
  min-height: 44px;   /* the floor is not negotiable (rule 08) */
  padding: 10px 18px;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background .15s var(--lds-ease), border-color .15s var(--lds-ease), color .15s var(--lds-ease);
  background: var(--lds-brand);
  color: #FFFFFF;
}
.lds-btn:hover { background: var(--lds-brand-hover); }
.lds-btn--secondary { background: var(--lds-surface); color: var(--lds-brand); border-color: var(--lds-brand); }
.lds-btn--secondary:hover { background: var(--lds-brand-soft); }
.lds-btn--ghost { background: transparent; color: var(--lds-ink-2); border-color: transparent; }
.lds-btn--ghost:hover { background: var(--lds-surface-3); color: var(--lds-ink); }
/* RETIRED AS GOLD (protocol rule 06: Golden Yellow never fills a button). The class
   survives so module markup keeps working, but it renders as the Liberty Blue primary. */
.lds-btn--gold { background: var(--lds-brand); color: #FFFFFF; border-color: transparent; }
.lds-btn--gold:hover { background: var(--lds-brand-hover); }
.lds-btn[disabled] { opacity: .5; cursor: not-allowed; }

/* ============ INPUTS ============ */
.lds-input {
  font-family: inherit;
  font-size: 13.5px;
  color: var(--lds-ink);
  background: var(--lds-surface);
  border: 1px solid var(--lds-line);
  border-radius: var(--lds-r2);
  padding: 10px 12px;
  min-height: 44px;   /* rule 08 */
  transition: border-color .15s var(--lds-ease);
}
.lds-input::placeholder { color: var(--lds-ink-4); }
.lds-input:focus { outline: none; border-color: var(--lds-brand-2); box-shadow: var(--lds-focus); }

/* ============ SEGMENTED CONTROL ============ */
.lds-seg {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  background: var(--lds-surface-3);
  border: 1px solid var(--lds-line);
  border-radius: var(--lds-r2);
  padding: 3px;
}
.lds-seg button {
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--lds-ink-2);
  background: none;
  border: none;
  border-radius: var(--lds-r1);
  padding: 5px 14px;
  min-height: 36px;   /* 36 inside the 3px-padded rail = a 44px control (rule 08) */
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s var(--lds-ease), color .15s var(--lds-ease);
}
.lds-seg button:hover { color: var(--lds-brand); }
.lds-seg button.on { background: var(--lds-surface); color: var(--lds-brand); box-shadow: var(--lds-sh1); }

/* ============ TABS ============ */
.lds-tabs {
  display: flex;
  gap: 2px;
  border-bottom: 2px solid var(--lds-line);
  margin-bottom: var(--lds-gap);
  flex-wrap: wrap;
}
.lds-tab {
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  color: var(--lds-ink-3);
  background: none;
  border: none;
  border-bottom: 3px solid transparent;
  padding: 12px 14px;
  min-height: 44px;   /* rule 08 */
  margin-bottom: -2px;
  cursor: pointer;
  transition: color .15s var(--lds-ease);
}
.lds-tab:hover { color: var(--lds-brand); }
/* Active tabs are marked in Liberty Blue (rule 06); the gold underline is retired. */
.lds-tab.on { color: var(--lds-brand); border-bottom-color: var(--lds-brand); }

/* ============ CHIPS ============ */
.lds-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--lds-ink-2);
  background: var(--lds-surface);
  border: 1px solid var(--lds-line);
  border-radius: 999px;
  padding: 4px 14px;
  min-height: 44px;   /* rule 08: chips here are filter toggles, i.e. controls */
  cursor: pointer;
  transition: border-color .15s var(--lds-ease);
}
.lds-chip:hover { border-color: var(--lds-brand-2); }
.lds-chip.on { background: var(--lds-brand-soft); border-color: var(--lds-brand-2); color: var(--lds-brand); }
.lds-chip .x { color: var(--lds-ink-4); font-size: 13px; }

/* ============ CARD ============ */
.lds-card {
  background: var(--lds-surface);
  border: 1px solid var(--lds-line);
  border-radius: var(--lds-r3);
  padding: var(--lds-card-pad);
  box-shadow: var(--lds-sh1);
}
.lds-card-h {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}
.lds-card-title { font-size: 14px; font-weight: 700; color: var(--lds-brand); margin: 0; }
.lds-tag {
  font-size: 11px;
  font-weight: 600;
  color: var(--lds-ink-3);
  background: var(--lds-surface-3);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
}

/* ============ KPI ============ */
.lds-kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--lds-gap);
  margin-bottom: var(--lds-gap);
}
.lds-kpi {
  background: var(--lds-surface);
  border: 1px solid var(--lds-line);
  border-top: 3px solid var(--lds-brand);
  border-radius: var(--lds-r3);
  padding: 14px 16px 12px;
}
.lds-kpi-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--lds-brand-2);
}
.lds-kpi-value {
  /* Lato counts (rule 02). v1 set every KPI in Prata — five display-serif figures
     and no hero is exactly the hierarchy failure rule 03 names. The ONE hero on a
     screen opts in via .lds-hero-value below. */
  font-family: var(--lds-data);
  font-weight: 700;
  font-size: 26px;
  line-height: 1.15;
  color: var(--lds-ink);
  margin: 5px 0 2px;
  font-variant-numeric: tabular-nums lining-nums;
}
/* PRATA GETS ONE NUMBER PER SCREEN (rule 03): the page's single most important
   figure — a grand total, or the number the page exists to deliver. If two of
   these render on one screen, one of them is wrong. */
.lds-hero-value {
  font-family: var(--lds-display);
  font-weight: 400;
  font-size: 34px;
  line-height: 1.12;
  color: var(--lds-ink);
  margin: 5px 0 2px;
  font-variant-numeric: tabular-nums lining-nums;
}
/* Utility for any running number outside a component: Lato, tabular. */
.lds-num { font-family: var(--lds-data); font-variant-numeric: tabular-nums lining-nums; }
.lds-kpi-sub { font-size: 12px; color: var(--lds-ink-3); }
.lds-kpi-sub, .lds-kpi-sub * { font-variant-numeric: tabular-nums lining-nums; }
.lds-delta { font-family: var(--lds-data); font-weight: 700; font-variant-numeric: tabular-nums lining-nums; }
.lds-delta.up { color: var(--lds-pos); }
.lds-delta.down { color: var(--lds-crit); }

/* ============ TABLE ============ */
/* color:inherit is QUIRKS-MODE armour: a module page served without a doctype renders in
   quirks mode, where tables do not inherit color - every unclassed cell computes black
   regardless of theme (found live in dark mode, 2026-08-29). Stated explicitly so the
   sheet survives the next fragment page. */
.lds-table { width: 100%; border-collapse: collapse; font-size: 13px; color: inherit; }
.lds-table th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--lds-ink-3);
  padding: var(--lds-row-pad);
  border-bottom: 2px solid var(--lds-line);
  white-space: nowrap;
}
.lds-table td { padding: var(--lds-row-pad); border-bottom: 1px solid var(--lds-line-soft); vertical-align: top; }
.lds-table tbody tr { transition: background .12s var(--lds-ease); }
.lds-table tbody tr:hover { background: var(--lds-surface-2); }
.lds-table .num { text-align: right; font-family: var(--lds-data); font-variant-numeric: tabular-nums lining-nums; white-space: nowrap; }
.lds-table .key { font-weight: 700; color: var(--lds-brand); }
.lds-table .mono { font-family: var(--lds-mono); font-size: 11.5px; color: var(--lds-ink-2); }
.lds-table .meta { font-size: 11.5px; color: var(--lds-ink-3); }
/* Row highlight in a brand wash — Golden Yellow never sits on white (rule 06). */
.lds-table tr.hl td { background: var(--lds-brand-soft); }

/* ============ BADGES (always icon/text + color, never color alone) ============ */
.lds-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 700;
  border-radius: var(--lds-r1);
  padding: 2px 8px;
  white-space: nowrap;
}
.lds-badge--pos  { background: var(--lds-pos-soft);  color: var(--lds-pos); }
.lds-badge--caut { background: var(--lds-caut-soft); color: var(--lds-caut); }
.lds-badge--crit { background: var(--lds-crit-soft); color: var(--lds-crit); }
.lds-badge--brand { background: var(--lds-brand-soft); color: var(--lds-brand); }
.lds-badge--neutral { background: var(--lds-surface-3); color: var(--lds-ink-2); }

/* ============ BAR ROWS (ranked lists, breakdowns, retention splits) ============ */
.lds-bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 1fr) 2fr 110px;
  align-items: center;
  gap: 12px;
  padding: var(--lds-row-pad);
}
.lds-bar-row + .lds-bar-row { border-top: 1px solid var(--lds-line-soft); }
.lds-bar-name { font-size: 13px; font-weight: 600; color: var(--lds-ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lds-bar-track { height: 12px; border-radius: var(--lds-r1); background: var(--lds-surface-3); overflow: hidden; display: flex; }
.lds-bar-fill { height: 100%; background: var(--lds-brand-2); border-radius: var(--lds-r1); }
.lds-bar-fill.alt { background: var(--lds-brand-3); }
.lds-bar-fill.pos { background: var(--lds-pos); }
.lds-bar-fill.crit { background: var(--lds-crit); }
.lds-bar-val { text-align: right; font-family: var(--lds-data); font-size: 13px; font-weight: 700; color: var(--lds-ink); font-variant-numeric: tabular-nums lining-nums; }
.lds-bar-val .pct { display: block; font-size: 11px; font-weight: 500; color: var(--lds-ink-3); }

/* ============ LOADING (2026-08-28: every dashboard shows this instead of a blank
   measure while its first payload is in flight; remove it on first render) ============ */
.lds-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 70px 20px;
  color: var(--lds-ink-3);
  font-size: 13px;
}
.lds-spinner {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 3px solid var(--lds-line);
  border-top-color: var(--lds-brand);
  animation: lds-spin .8s linear infinite;
}
/* `display: flex` above is an AUTHOR rule, so it beats the user-agent's `[hidden] { display:
   none }` - meaning `el.hidden = true` did NOTHING to this class and the Pipeline's spinner
   stayed on screen forever over a fully rendered page (Patrick, 2026-08-31). Dashboards that
   remove() the node never noticed. This restores the hidden attribute's meaning for pages
   that show the loader more than once and so cannot remove it. */
.lds-loading[hidden] { display: none; }
@keyframes lds-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .lds-spinner { animation: none; }
}
/* The overlay form sits over the measure's placeholder skeleton until first render. */
.lds-measure { position: relative; }
.lds-loading--overlay {
  position: absolute;
  inset: 0;
  z-index: 5;
  background: var(--lds-canvas);
  justify-content: flex-start;
  padding-top: 140px;
}

/* ============ NOTES & EMPTY STATES ============
   Brand wash, not gold: Golden Yellow never sits on white (rule 06). */
.lds-note {
  background: var(--lds-brand-soft);
  border: 1px solid var(--lds-brand-2);
  border-left-width: 4px;
  border-radius: var(--lds-r2);
  padding: 11px 14px;
  font-size: 13px;
  color: var(--lds-ink-2);
}
.lds-note b { color: var(--lds-ink); }
.lds-empty { padding: 22px 20px; color: var(--lds-ink-3); font-size: 13px; font-style: italic; }

/* ============ CHARTS ============
   Series tokens live in the two theme blocks up top (light :root + dark
   override) — a :root block HERE would come after the dark theme and win the
   cascade tie, reverting dark charts to light-series colors. */
.lds-legend { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; font-size: 11.5px; font-weight: 600; color: var(--lds-ink-2); }
.lds-legend .sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.lds-cols { display: flex; align-items: flex-end; gap: 8px; height: 140px; border-bottom: 2px solid var(--lds-line); padding: 0 4px; }
.lds-col { flex: 1; background: var(--lds-series-1); border-radius: var(--lds-r1) var(--lds-r1) 0 0; min-height: 3px; }
.lds-col.prior { background: var(--lds-series-4); }
.lds-col-labels { display: flex; gap: 8px; padding: 6px 4px 0; }
.lds-col-label { flex: 1; text-align: center; font-size: 10.5px; font-weight: 600; color: var(--lds-ink-3); }
.lds-chart-val { font-family: var(--lds-data); font-size: 11px; font-weight: 700; color: var(--lds-ink-2); text-align: center; font-variant-numeric: tabular-nums lining-nums; }
.lds-stack { display: flex; height: 16px; border-radius: var(--lds-r1); overflow: hidden; }
.lds-stack > i { display: block; height: 100%; }

/* ============ FOOTER NOTES (methodology, sources) ============ */
.lds-foot {
  margin-top: 28px;
  padding-top: 16px;
  border-top: 1px solid var(--lds-line);
  color: var(--lds-ink-3);
  font-size: 12px;
  line-height: 1.65;
}
.lds-foot b { color: var(--lds-ink-2); }
.lds-foot code {
  font-family: var(--lds-mono);
  font-size: 11px;
  background: var(--lds-surface-3);
  border-radius: var(--lds-r1);
  padding: 1px 5px;
}
