/* SessionHub Console — design tokens
   Following the brief exactly. Light mode is the design's primary surface;
   dark mode swaps to near-black + pale sage accent. */

@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=swap");

:root {
  /* TYPE */
  --font-sans: "Inter", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* SPACING (4px base, sticking to brief) */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px; --sp-4: 16px;
  --sp-5: 24px; --sp-6: 32px; --sp-7: 48px; --sp-8: 64px;

  /* RADIUS */
  --r-sm: 6px;
  --r-md: 10px;   /* secondary buttons, inputs */
  --r-lg: 14px;
  --r-xl: 16px;   /* cards */
  --r-pill: 999px;

  /* MOTION */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 140ms;
  --dur-base: 220ms;

  /* STATUS — same in both modes */
  --status-ok:   #10B981;
  --status-warn: #F59E0B;
  --status-err:  #EF4444;

  /* STATUS SURFACES — fg + soft/strong bg variants for chips, banners,
     row highlights, callouts. The flat --status-* above stays as the dot /
     accent color; these pairs are for filled surfaces. High-frequency
     ad-hoc usage across the codebase (audit 2026-05-15); promoted to tokens
     for the design-system cleanup approved by operator 2026-05-15. */
  --status-ok-fg:         #0E7C53;  /* = design getDashTokens okFg light (was #15803D) — mode-by-mode align 2026-06-21 */
  --status-ok-bg-soft:    #DCFCE7;
  --status-ok-bg-strong:  rgba(16,185,129,0.28);  /* design getDashTokens okBorder (was solid #A7F3D0) */
  --status-warn-fg:       #9A6520;  /* = design getDashTokens warnFg light (was #92400E) — mode-by-mode align 2026-06-21 */
  --status-warn-bg-soft:  #FEF3C7;
  --status-warn-bg-strong:rgba(245,158,11,0.30);  /* visible amber border (was #FFFBEB ≈ white) */
  --status-err-fg:        #B91C1C;  /* aligned to design gapFg (was #991B1B) — 2026-05-27 */
  --status-err-bg:        #FEF6F6;  /* design attention-strip fill (frame-accounts.jsx); light = dark in design but theme-flips here */
  --status-err-line:      #F6D9D9;  /* design attention-strip border (frame-accounts.jsx) */
  --status-err-bg-soft:   #FEF2F2;
  --status-err-bg-strong: rgba(239,68,68,0.28);  /* design getDashTokens badBorder (was solid #FECACA) */

  /* Accounts/Customers semantic accents (frame-accounts-kit.jsx acSem) — theme-aware
     so dark mode stays legible (operator color fix 2026-06-20). Dedicated vars
     because our --status-warn/err-fg deliberately flip to yellow/pink in dark,
     which is wrong for these money/quality accents. Light = design's deep shades. */
  --ac-commission:        #7E22CE;  /* purple — commission % / "You owe" */
  --ac-margin:            #0E7C53;  /* green  — wallet / margin markup */
  --ac-amber:             #B45309;  /* amber  — at-risk / low-ASR / abnormal ACD / fair MOS */
  --ac-red:               #B91C1C;  /* red    — overdue / low-balance / poor MOS */

  /* OVERRIDE / inheritance palette — the design's pale-sage "this level wins"
     accent used by the customer auth-rule editor (selected radio cards,
     overridden inherit rows, "✱ Override" pills). From getCustomerTokens:
     overrideBg #C7F0D6 / overrideFg #14532D (light). Distinct from --accent-soft
     so an override reads as a deliberate, calm green — not the primary accent. */
  --override-bg:      #C7F0D6;
  --override-bg-soft: rgba(199,240,214,0.40);
  --override-fg:      #14532D;
  --inherited-bg:     var(--bg-card-soft);

  /* VERDICT — call-quality palette for MOS / ASR scoring. The verdict
     tier escalates good → fair → poor → bad. Used in CDR rows, quality
     summary chips, and the simulator output card. */
  --verdict-good: #166534;   /* MOS 4.0+, ASR >50% */
  --verdict-fair: #92400E;   /* MOS 3.0-4.0, ASR 30-50% */
  --verdict-poor: #991B1B;   /* MOS <3.0, ASR <30% */
  --verdict-bad:  #7F1D1D;   /* dropped, unrouteable */

  /* TERMINAL / SESSION-REPLAY player — a recorded shell is semantically a
     DARK terminal in BOTH modes (it represents a literal asciinema-style
     recording, not a theme-able surface). So these live in :root and do NOT
     theme-flip — fixed dark in light AND dark mode. Values mirror the Claude
     Design "Session replay" artboard player exactly (Access Audit & Roles.dc.html
     artboard 02). Used by frame-cc-access-audit.jsx's CcReplay player. */
  --term-bg:       #1A1A1A;   /* terminal surface */
  --term-scrub-bg: #222222;   /* scrubber tray */
  --term-border:   #2A2A2A;   /* terminal + scrub border */
  --term-text:     #C4C4C4;   /* transcript text + progress fill */
  --term-dim:      #6E6E6E;   /* sys/$ lines, cursor */
  --term-ok:       #5CCB97;   /* read → arrow (allowed reads) */
  --term-bad:      #FCA5A5;   /* blocked write line */
  --term-note:     #9A9A9A;   /* block annotation, scrub timestamps */
  --term-track:    #3A3A3A;   /* scrubber track (unfilled) */
  --term-play-bg:  #F5F5F5;   /* round play button bg (fixed pale, not canvas) */
  --term-play-fg:  #1A1A1A;   /* play glyph */
  --term-marker:   #EF4444;   /* blocked-event marker on the timeline */
  /* CUSTOMER-PORTAL DEPICTION — a FIXED "warm-paper" palette used ONLY by the
     /cc-money dunning-ladder preview (frame-cc-money.jsx) to depict the
     customer's OWN separate portal surface. It is intentionally NOT the console
     theme: it shows the operator exactly what the customer will literally see,
     so it does NOT flip in dark mode (defined once in :root, no .sh-theme-dark
     override). Values come verbatim from the Claude Design "Money Billing &
     Dunning" AB2 customer-preview. See the frame's DESIGN DIVERGENCE note. */
  --portal-paper:   #FAFAF8;  /* warm paper body */
  --portal-chrome:  #ECEAE6;  /* window titlebar */
  --portal-line:    #DAD6CE;  /* titlebar bottom rule */
  --portal-border:  #D4D0C8;  /* secondary-button border */
  --portal-ink:     #1A1815;  /* primary ink / Pay-now bg */
  --portal-mute:    #6B6862;  /* body-mute text */
  --portal-label:   #8A8780;  /* window-title label grey */
  --portal-on-ink:  #FFFFFF;  /* text on the dark Pay-now button */
  --portal-warn-fg: #9A6520;  /* past-due icon (warm-paper warn) */
  --portal-ok-fg:   #0E7C53;  /* "calls still connecting" green */
  --portal-tl-red:   #F2655A; /* macOS traffic-light close */
  --portal-tl-amber: #F5BD4F; /* macOS traffic-light minimise */
  --portal-tl-green: #61C554; /* macOS traffic-light zoom */
}

/* LIGHT (Ledgerix-inspired) */
.theme-light {
  --bg-canvas:  #F5F5F5;
  --bg-surface: #FFFFFF;
  --bg-raised:  #FFFFFF;
  --bg-card:    #FFFFFF;
  --bg-inset:   #F5F5F5;        /* design inset — was #FAFAFA */
  --bg-input:   #FFFFFF;
  --bg-chip:    #FFFFFF;        /* design chipBg — was #F5F5F5 */

  --fg-1: #0A0A0A;              /* primary */
  --fg-2: #404040;              /* secondary */
  --fg-mid: #525252;            /* between --fg-2 and --fg-3 (~150 ad-hoc hits) */
  --fg-3: #737373;              /* muted */
  --fg-4: #A3A3A3;              /* tertiary muted */
  --fg-5: #D4D4D4;              /* faintest tier — design fg5 (separators, off-dots) */
  --fg-on-accent: #FFFFFF;

  --line-0: #EBEBEB;            /* default border (most-used; 362 ad-hoc hits) */
  --line-1: #EBEBEB;            /* = design line / --line-0 (was #E5E5E5 — 1 step dark console-wide) */
  --line-2: #F5F5F5;            /* design lineSoft — was #EFEFEF */
  --line-3: #F0F0F0;

  --accent: #0A0A0A;            /* design accent — near-black, was #000000 */
  --accent-hover: #1A1A1A;
  --accent-soft: #FAFAFA;       /* design accentSoft — was #F0F0F0 */

  --spark: #D4D4D4;             /* sparkline gray */
  --spark-strong: #A3A3A3;

  /* Flow topology resting curve colour — design getDashTokens flowLine
     (#C4C4C4 light). ADDITIVE token (2026-06-17 cVerify P1): the dashboard
     flow frame previously mapped its resting bezier curves to var(--fg-1)
     (near-black), darkening every at-rest lane + the footer legend swatch.
     This grey matches the design exactly. Dark-mode value below. */
  --flow-line: #C4C4C4;

  --emphasis-bg: #0A0A0A;       /* inverted card */
  --emphasis-fg: #FFFFFF;

  --shadow-1: 0 1px 0 rgba(10,10,10,0.02), 0 1px 2px rgba(10,10,10,0.04);
  --shadow-2: 0 1px 0 rgba(10,10,10,0.02), 0 4px 12px rgba(10,10,10,0.06);

  /* Wave-2026-05-17 design-fidelity additions — granular tokens from
     /Users/mac/Desktop/sbc-redesign/project/thin-theme.js. Previously a
     handful of frame elements (most visibly the SHQuestionLauncher AI
     bar) used `var(--fg-1)` as background, which auto-inverts to WHITE
     in dark mode instead of staying dark. These tokens give those
     elements an explicit always-dark surface that's parallel to the
     auto-inverting fg/bg pair. */
  /* Delta pills — the "+12% vs prior 24h" chips on the dashboard etc.
     Design's `thin-theme.js` uses MINT (light) + SAGE-translucent (dark)
     greens for positive delta, and red-translucent for negative — NOT
     the emerald (#10B981 family) that --status-ok uses. These tokens
     stay theme-aware so the same chip class works in both modes. */
  --delta-pos-bg:      #C7F0D6;    /* design pillBg light — mint */
  --delta-pos-fg:      #14532D;    /* design pillFg light — deep forest green */
  --delta-neg-bg:      rgba(239,68,68,0.10);  /* design errBg light */
  --delta-neg-fg:      #B91C1C;    /* design errFg light */
  /* Wave-2026-05-18 (C-lite) — text color for the cron-health degraded
     banner. Warm brown on the amber pill (light), lighter amber in dark
     mode override below. Matches the dev-preview banner palette. */
  --cron-banner-fg:    #92400E;

  --bg-card-soft:      #FAFAFA;    /* panel inside card; cardSoft */
  --bg-ai:             #0A0A0A;    /* AI bar / question launcher bg */
  --bg-ai-pill:        #1F1F1F;    /* pill inside AI bar / launcher popover */
  --bg-ai-send:        #FFFFFF;    /* send button circle bg */
  --fg-ai-pill:        #D4D4D4;
  --fg-ai-send:        #0A0A0A;    /* arrow inside send circle */
  --bg-tooltip:        #FFFFFF;
  --line-tooltip:      #EBEBEB;
  --avatar-bg:         #0A0A0A;    /* INVERTED — dark on light bg */
  --avatar-fg:         #FFFFFF;
  --input-line:        #D4D4D4;
  --input-line-active: #0A0A0A;
  --line-soft:         #F5F5F5;
  --line-faint:        #F5F5F5;
  --bar-fg:            #0A0A0A;    /* chart bar/spark foreground */
  --bar-track:         #F5F5F5;
  --histo-bar:         #E5E5E5;    /* CDR distribution "answered" bar (design histo — visible on white, unlike --bar-track) */
  --grid-line:         #EBEBEB;
}

/* DARK — "Thin · lighter dark palette" per the 2026-05-17 design canvas
   update. Lighter base (#1C1C1C) than the previous near-black (#0A0A0A) so
   surfaces have more separation; accent flips to WHITE (was pale sage) as
   the Thin variant's signature. Emphasis card returns to a neutral raised
   tone instead of the sage-cream from the previous direction.

   Selector list: applies BOTH when an element directly has `.theme-dark`
   (legacy / explicit usage) AND when the user toggles dark mode via the
   topbar (which sets `body.sh-theme-dark` — this matches `.theme-light`
   roots without forcing edits across 80+ frame files).

   `html.sh-theme-dark` (bare) added 2026-05-27 — ROOT FIX for washed-out dark
   mode: the redesign layout (sessionhub_redesign.html.erb) AND dev-preview.html
   set `sh-theme-dark` on <html> with NO `.theme-light` wrapper in the body, so
   `html.sh-theme-dark .theme-light` never matched → only the hardcoded body bg
   went dark while every --fg, --bg-card, --line var stayed undefined (dim,
   low-contrast text). Matching `html.sh-theme-dark` directly applies the dark
   vars on the <html> root and lets them cascade. Safe: pages that DO have a
   `.theme-light` wrapper still get the more-specific override; light mode
   (no sh-theme-dark) is untouched. */
.theme-dark,
html.sh-theme-dark,
html.sh-theme-dark .theme-light {
  --bg-canvas:  #1C1C1C;
  --bg-surface: #242424;
  --bg-raised:  #2A2A2A;
  --bg-card:    #2A2A2A;
  --bg-inset:   #333333;
  --bg-input:   #2A2A2A;
  --bg-chip:    #2A2A2A;        /* design chipBg dark — was #333333 */

  --fg-1: #F5F5F5;
  --fg-2: #C4C4C4;
  --fg-mid: #B5B5B5;            /* dark equivalent (between --fg-2 and --fg-3) */
  --fg-3: #9A9A9A;
  --fg-4: #6E6E6E;
  --fg-5: #525252;             /* faintest tier — design fg5 dark */
  --fg-on-accent: #1C1C1C;

  --line-0: #3A3A3A;            /* dark equivalent of default border */
  --line-1: #3A3A3A;
  --line-2: #303030;
  --line-3: #2A2A2A;

  --accent: #F5F5F5;            /* white — Thin signature on dark */
  --accent-hover: #FFFFFF;
  --accent-soft: rgba(245,245,245,0.08);

  --spark: #3A3A3A;
  --spark-strong: #5C5C5C;

  /* Flow topology resting curve colour (dark) — design getDashTokens flowLine
     dark = #5C5C5C. ADDITIVE token (2026-06-17 cVerify P1). */
  --flow-line: #5C5C5C;

  --emphasis-bg: #333333;       /* neutral raised card (was sage cream) */
  --emphasis-fg: #F5F5F5;

  --shadow-1: none;
  --shadow-2: 0 4px 16px rgba(0,0,0,0.4);

  /* Wave-2026-05-17 design-fidelity additions — granular dark tokens
     matched 1:1 with thin-theme.js. These do NOT auto-invert with the
     standard fg/bg pair; they stay dark in dark mode (the design's
     intent for the AI bar etc.) and dark in light mode (always-dark
     surfaces). The "send button circle" stays light in both modes
     because the design intent is a contrasting send affordance. */
  /* Delta pills — design uses SAGE (not emerald) for positive in dark.
     `rgba(181,214,133,0.18)` = sage with 18% alpha so it sits gently
     on the dark canvas; pillFg is #C4DF9A (light sage) for the text. */
  --delta-pos-bg:      rgba(181,214,133,0.18);  /* design pillBg dark */
  --delta-pos-fg:      #C4DF9A;                 /* design pillFg dark */
  --delta-neg-bg:      rgba(239,68,68,0.18);    /* design errBg dark */
  --delta-neg-fg:      #FCA5A5;                 /* design errFg dark */
  --cron-banner-fg:    #FCD34D;                 /* light amber in dark mode */

  --bg-card-soft:      #262626;    /* cardSoft — panel inside card */
  --bg-ai:             #2A2A2A;    /* aiBar — design says #2A2A2A in dark, NOT #F5F5F5 (var(--fg-1)) */
  --bg-ai-pill:        #333333;    /* aiPill — slightly raised pill on AI bar */
  --bg-ai-send:        #F5F5F5;    /* aiSendBg — stays light (contrast affordance) */
  --fg-ai-pill:        #C4C4C4;
  --fg-ai-send:        #1C1C1C;    /* aiSendFg — dark arrow on the light send circle */
  --bg-tooltip:        #333333;
  --line-tooltip:      #404040;
  --avatar-bg:         #F5F5F5;    /* INVERTED — light on dark bg */
  --avatar-fg:         #1C1C1C;
  --input-line:        #404040;
  --input-line-active: #F5F5F5;
  --line-soft:         #303030;
  --line-faint:        #262626;
  --bar-fg:            #F5F5F5;    /* chart bar/spark foreground in dark */
  --bar-track:         #3A3A3A;
  --histo-bar:         #3A3A3A;    /* CDR distribution "answered" bar (design histo, dark) */
  --grid-line:         #303030;

  /* Status surfaces — re-tuned for dark backgrounds so soft-bg variants
     remain visible against #1C1C1C without losing contrast on text. */
  --status-ok-fg:         #5CCB97;  /* = design getDashTokens okFg DARK — re-aligned to regenerated dark artboards (Messaging Omnichannel) 2026-06-27 (was #5EE3B0) */
  --status-ok-bg-soft:    rgba(16,185,129,0.14);
  --status-ok-bg-strong:  rgba(16,185,129,0.32);  /* design dark okBorder (was 0.22) */
  --status-warn-fg:       #E8B765;  /* = design getDashTokens warnFg DARK — re-aligned to regenerated dark artboards (Messaging Omnichannel) 2026-06-27 (was #E6B25E) */
  --status-warn-bg-soft:  rgba(245,158,11,0.14);
  --status-warn-bg-strong:rgba(245,158,11,0.34);  /* design dark warnBorder (was 0.22) */
  --status-err-fg:        #FCA5A5;
  --status-err-bg:        rgba(239,68,68,0.08);  /* design attention-strip fill (dark) */
  --status-err-line:      rgba(239,68,68,0.25);  /* design attention-strip border (dark) */
  --status-err-bg-soft:   rgba(239,68,68,0.14);
  --status-err-bg-strong: rgba(239,68,68,0.36);  /* design dark badBorder (was 0.22) */

  /* Accounts/Customers semantic accents — dark tints (acSem dark; operator fix 2026-06-20) */
  --ac-commission:        #D8B4FE;  /* purple (dark) */
  --ac-margin:            #6EE7B7;  /* green  (dark) */
  --ac-amber:             #FBBF24;  /* amber  (dark) */
  --ac-red:               #FCA5A5;  /* red    (dark) */

  /* Override / inheritance palette (dark) — design getCustomerTokens dark:
     overrideBg rgba(181,214,133,.14) / overrideFg #C4DF9A. */
  --override-bg:      rgba(181,214,133,0.22);
  --override-bg-soft: rgba(181,214,133,0.14);
  --override-fg:      #C4DF9A;
  --inherited-bg:     var(--bg-card-soft);

  /* Verdict palette — call-quality scoring also needs dark-mode readjustment
     for legibility on dark surfaces. */
  --verdict-good: #6EE7B7;
  --verdict-fair: #FCD34D;
  --verdict-poor: #FCA5A5;
  --verdict-bad:  #F87171;
}

/* ====== TYPE STYLES ======
   Numbers are tabular; eyebrows are uppercase + tracked. */
.t-hero {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: 96px;
  line-height: 0.95;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
}
.t-hero-mobile {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: 64px;
  line-height: 0.95;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
}
.t-page {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 32px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--fg-1);
}
.t-section {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 20px;
  letter-spacing: -0.01em;
  color: var(--fg-1);
}
.t-eyebrow {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.t-body {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-1);
}
.t-body-mute {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 14px;
  line-height: 1.5;
  color: var(--fg-3);
}
.t-num-card {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: 48px;
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
}
.t-num-md {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 24px;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  color: var(--fg-1);
}
.t-mono {
  font-family: var(--font-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  color: var(--fg-2);
}

.tab-num { font-variant-numeric: tabular-nums; }

/* ====== ROOT FRAME WRAPPER ====== */
.frame {
  font-family: var(--font-sans);
  background: var(--bg-canvas);
  color: var(--fg-1);
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ====== COMMON COMPONENTS ====== */
.card {
  background: var(--bg-card);
  border: 1px solid var(--line-1);
  border-radius: var(--r-xl);
  padding: var(--sp-5);
}
.card-emphasis {
  background: var(--emphasis-bg);
  color: var(--emphasis-fg);
  border-radius: var(--r-xl);
  padding: var(--sp-5);
}
.card-emphasis * { color: inherit; }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out);
  white-space: nowrap;
  user-select: none;
}
.btn-primary {
  background: var(--accent);
  color: var(--fg-on-accent);
  padding: 10px 18px;
  border-radius: var(--r-pill);
}
.btn-primary:hover { background: var(--accent-hover); }
.btn-secondary {
  background: var(--bg-surface);
  color: var(--fg-1);
  border-color: var(--line-1);
  padding: 9px 14px;
  border-radius: var(--r-md);
}
.btn-secondary:hover { background: var(--bg-inset); }
.btn-ghost {
  background: transparent;
  color: var(--fg-2);
  padding: 8px 12px;
  border-radius: var(--r-md);
}
.btn-ghost:hover { background: var(--bg-inset); color: var(--fg-1); }

/* Pill segmented control */
.seg {
  display: inline-flex;
  background: var(--bg-chip);
  border-radius: var(--r-pill);
  padding: 3px;
  gap: 2px;
}
.theme-light .seg { background: #ECECEC; }
.seg-item {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 13px;
  padding: 6px 14px;
  border-radius: var(--r-pill);
  cursor: pointer;
  color: var(--fg-3);
  border: none;
  background: transparent;
  transition: all var(--dur-fast) var(--ease-out);
}
.seg-item.active {
  background: var(--accent);
  color: var(--fg-on-accent);
}
.theme-light .seg-item.active { background: #0A0A0A; color: #FFF; }
.seg-item:not(.active):hover { color: var(--fg-1); }

/* Inputs */
.input {
  font-family: var(--font-sans);
  font-size: 14px;
  background: var(--bg-input);
  color: var(--fg-1);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  padding: 10px 14px;
  outline: none;
  transition: border-color var(--dur-fast) var(--ease-out);
  width: 100%;
}
.input:focus { border-color: var(--accent); }
.input::placeholder { color: var(--fg-4); }

/* Tabs (underline style)
 *
 * Wave 56 — horizontal scroll for medium widths (tab strip no longer
 * silently cuts off when there are >8 tabs on an 1100px window), and a
 * mobile breakpoint <768px that hides the tab row in favor of a
 * <select>-based picker (`.tabs-picker`, rendered inline by the page).
 */
.tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--line-1);
  overflow-x: auto;
  flex-wrap: nowrap;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.tabs::-webkit-scrollbar { height: 4px; }
.tabs::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 2px; }
.tab {
  font-family: var(--font-sans);
  font-weight: 500;
  font-size: 14px;
  padding: 14px 0;
  margin-right: 28px;
  color: var(--fg-3);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--dur-fast) var(--ease-out);
  white-space: nowrap;
  flex-shrink: 0;
}
.tab.active { color: var(--fg-1); border-bottom-color: var(--accent); }
.tab:hover { color: var(--fg-1); }

/* Mobile tab picker (Wave 56). A page that renders BOTH `.tabs` (the
 * horizontal strip) and `.tabs-picker` (a styled <select>) lets the CSS
 * pick which one shows based on viewport. Default: picker hidden, strip
 * shown. <768px: picker shown, strip hidden. */
.tabs-picker {
  display: none;
  width: 100%;
  padding: 12px 14px;
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--fg-1);
  background: var(--bg-surface);
  border: 1px solid var(--line-1);
  border-radius: var(--r-md);
  outline: none;
}
.tabs-picker:focus { border-color: var(--accent); }
@media (max-width: 768px) {
  .tabs { display: none; }
  .tabs-picker { display: block; }
}

/* Status dot */
.dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}
.dot-ok   { background: var(--status-ok); }
.dot-warn { background: var(--status-warn); }
.dot-err  { background: var(--status-err); }
.dot-mute { background: var(--fg-4); }

/* Status indicator (dot + label) */
.status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  font-weight: 500;
  color: var(--fg-2);
}

/* Pill chip (positive / negative change) — design palette:
   pos: MINT (#C7F0D6 light) / SAGE-translucent (rgba(181,214,133,0.18) dark)
   neg: RED-translucent in both modes (0.10 alpha light, 0.18 alpha dark)
   These were previously emerald-based (#10B981) which is more teal/cyan;
   design uses warmer sage/forest green instead. Driven by --delta-pos-* /
   --delta-neg-* tokens so a single chip class works in both modes. */
.chip-delta {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: var(--delta-pos-bg);
  color: var(--delta-pos-fg);
}
.chip-delta.neg { background: var(--delta-neg-bg); color: var(--delta-neg-fg); }

/* Chip neutral */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: var(--r-pill);
  background: var(--bg-chip);
  color: var(--fg-2);
  border: 1px solid var(--line-1);
}
.theme-light .chip { border-color: var(--line-1); }

/* Tables */
.tbl { width: 100%; border-collapse: collapse; font-size: 14px; }
.tbl th {
  text-align: left;
  font-weight: 500;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fg-3);
  padding: 12px 0;
  border-bottom: 1px solid var(--line-1);
}
.tbl td {
  padding: 16px 0;
  border-bottom: 1px solid var(--line-2);
  color: var(--fg-1);
  font-variant-numeric: tabular-nums;
}
.tbl tr:last-child td { border-bottom: none; }
/* Wave 2026-05-19 (Issue-carrierPageBugs): scope hover to clickable rows
   only. The bare `.tbl tr:hover` was a false affordance on (a) empty-
   state rows ("No carriers configured…"), (b) read-only data tables
   (translations, account-detail, etc.). Now hover only fires on rows
   that opt in via `data-clickable="true"`. Components that already
   wire inline onMouseEnter/onMouseLeave for hover continue to work; the
   CSS rule below is the primary path for SHListPage-style row navigation. */
.tbl tr[data-clickable="true"]:hover td { background: var(--bg-inset); }

/* Sparkline svg sizing default */
.spark-bg { color: var(--spark); }

/* Connection map node */
.flow-card {
  background: var(--bg-card);
  border: 1px solid var(--line-1);
  border-radius: 14px;
  padding: 14px 16px;
  min-width: 168px;
  position: relative;
}
.flow-card.broken {
  border-style: dashed;
  border-color: var(--status-err);
}

/* Subtle scrollbar hide */
.frame *::-webkit-scrollbar { display: none; }
.frame * { scrollbar-width: none; }

/* ====== HORIZONTAL OVERFLOW GUARD ======
   Belt-and-suspenders for the tooltip-overflow bug. If any frame's
   inner element ever extends past the viewport's right edge (a
   too-wide tooltip, an unflexed table, a runaway absolute-positioned
   popover), browsers add horizontal scroll on body → operator sees
   a white edge (in light) or canvas edge (in dark) when scrolling.
   Clipping at html keeps everything contained without changing the
   layout's intrinsic width. */
html, html body { overflow-x: hidden; }

/* ====== HTML/BODY BG (cascade-independent) ======
   The CSS-var cascade for `--bg-canvas` is rooted in `.theme-light`
   (and its dark-override `html.sh-theme-dark .theme-light`). That
   means the var is set INSIDE each frame's root div — html and body
   themselves have NO `--bg-canvas`, so `body { background: var(--bg-canvas) }`
   in a page layout resolves to UNDEFINED → browser default (white).
   Symptom: any horizontal scroll past the frame's right edge reveals
   the white body bg in dark mode (operator-spotted 2026-05-17).
   Fix: paint html with a fixed hex per theme so any uncovered area
   matches the canvas color. Body inherits via the same selector.
   The fixed values mirror tokens.css's --bg-canvas in each mode. */
html,
html body { background: #F5F5F5; }
html.sh-theme-dark,
html.sh-theme-dark body { background: #1C1C1C; }

/* ====== MOBILE THIN-TEXT (LIGHT MODE) ======
   Per the 2026-05-17 design canvas update — "05 · Mobile dashboard" and
   "06 · Mobile customer detail" both use lighter type weights at mobile
   widths than their desktop equivalents. The mobile artboards (390×844)
   intentionally drop hero/page weights from 800/600 → 300/200 to keep
   the small surface feeling airy rather than crowded.

   Breakpoint matches sh-topnav.css's mobile mode (<768px). Affects ALL
   pages, not just dashboard, so a customer/carrier/etc. detail page on
   a phone gets the same thinner-text treatment automatically. */
@media (max-width: 768px) {
  .t-hero        { font-weight: 200; letter-spacing: -0.03em; font-size: 64px; }
  .t-hero-mobile { font-weight: 200; letter-spacing: -0.03em; }
  .t-page        { font-weight: 300; font-size: 28px; }
  .t-section     { font-weight: 500; font-size: 18px; }
  .t-num-card    { font-weight: 300; font-size: 40px; }
  .t-num-md      { font-weight: 400; font-size: 22px; }
}

/* ====== TOPNAV THEME-TOGGLE BUTTON ======
   Sun/moon icon next to the bell. Same chrome as `sh-topnav-icon-btn`
   so it inherits the topbar's hover + sizing automatically; pair with
   the toggle script in frame-shared.jsx that flips body.sh-theme-dark
   + persists to localStorage('sh-theme'). */
.sh-theme-toggle {
  /* hover/visual state inherited from sh-topnav-icon-btn — only add
     a subtle transition for the icon swap so the change feels smooth
     rather than abrupt. */
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out);
}
.sh-theme-toggle .sh-theme-icon-light,
.sh-theme-toggle .sh-theme-icon-dark { display: none; }
/* In light mode: show the MOON (click → switch to dark). */
html:not(.sh-theme-dark) .sh-theme-toggle .sh-theme-icon-dark { display: inline-flex; }
/* In dark mode: show the SUN (click → switch back to light). */
html.sh-theme-dark .sh-theme-toggle .sh-theme-icon-light { display: inline-flex; }

/* Smooth the cross-mode visual transition on the page chrome itself so
   the toggle feels intentional rather than a hard flash. Limit to
   background/color so layout reflow + sparkline animations are
   unaffected. */
body, .frame, .card, .card-emphasis, .btn, .input, .chip, .flow-card {
  transition: background-color var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out);
}
