/* =========================================================
   Sarv CAI — Design System Stylesheet
   Shared by: Design System.html, Agent Management.html
   ========================================================= */

:root {
  /* ---------- Brand ---------- */
  --color-brand-50:  #EAF2FA;
  --color-brand-100: #D5E5F5;
  --color-brand-200: #ADCBEB;
  --color-brand-300: #84B0E0;
  --color-brand-400: #5B92D2;
  --color-brand-500: #3069B0;   /* primary */
  --color-brand-600: #275695;
  --color-brand-700: #1F457A;
  --color-brand-800: #163460;
  --color-brand-900: #0E2447;

  --color-accent-50:  #FEF1E6;
  --color-accent-100: #FCDDC2;
  --color-accent-200: #F9B988;
  --color-accent-300: #F4974E;
  --color-accent-400: #ED7C26;
  --color-accent-500: #E56910;  /* accent */
  --color-accent-600: #BF560C;
  --color-accent-700: #944209;
  --color-accent-800: #6B3007;
  --color-accent-900: #471F04;

  /* ---------- Neutral (slate) ---------- */
  --color-slate-50:  #F7F8FB;
  --color-slate-100: #F1F3F9;
  --color-slate-200: #E6E9F1;
  --color-slate-300: #D8DDE9;
  --color-slate-400: #B6BDD0;
  --color-slate-500: #8B94AC;
  --color-slate-600: #6B7691;
  --color-slate-700: #4A5572;
  --color-slate-800: #2A3450;
  --color-slate-900: #0B1530;

  /* ---------- Semantic ---------- */
  --color-success-50:  #E3F5EC;
  --color-success-500: #10936A;
  --color-success-700: #0A6D4F;

  --color-danger-50:  #FDECEC;
  --color-danger-500: #D94A4A;
  --color-danger-700: #A52C2C;

  --color-warning-50:  #FEF6E0;
  --color-warning-500: #D4A017;
  --color-warning-700: #8A6708;

  --color-info-50:  #E6F4F8;
  --color-info-500: #0891B2;
  --color-info-700: #0A607A;

  /* ---------- Surfaces (light theme aliases) ---------- */
  --bg:               var(--color-slate-50);
  --bg-elevated:      #F4F6FB;
  --surface:          #FFFFFF;
  --surface-2:        var(--color-slate-50);
  --border:           var(--color-slate-200);
  --border-strong:    var(--color-slate-300);
  --ink:              var(--color-slate-900);
  --ink-2:            var(--color-slate-800);
  --muted:            var(--color-slate-600);
  --muted-2:          var(--color-slate-500);

  --brand:        var(--color-brand-500);
  --brand-deep:   var(--color-brand-700);
  --brand-soft:   var(--color-brand-50);
  --brand-strong: var(--color-brand-600);

  --accent:       var(--color-accent-500);
  --accent-soft:  var(--color-accent-50);
  --accent-ink:   var(--color-accent-700);

  /* ---------- Typography ---------- */
  --font-sans: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --fs-xs:   11px;
  --fs-sm:   12px;
  --fs-base: 13px;
  --fs-md:   14px;
  --fs-lg:   16px;
  --fs-xl:   18px;
  --fs-2xl:  22px;
  --fs-3xl:  28px;
  --fs-4xl:  36px;

  --lh-tight: 1.2;
  --lh-snug:  1.35;
  --lh-base:  1.5;

  --tracking-tight: -0.02em;
  --tracking-base:  -0.005em;

  --fw-regular: 400;
  --fw-medium:  500;
  --fw-semi:    600;
  --fw-bold:    700;
  --fw-black:   800;

  /* ---------- Spacing (4px scale) ---------- */
  --space-0:  0;
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-7:  32px;
  --space-8:  40px;
  --space-9:  48px;
  --space-10: 64px;

  /* ---------- Radii ---------- */
  --r-sm:   6px;
  --r-md:   8px;
  --r-lg:   12px;
  --r-xl:   16px;
  --r-pill: 999px;

  /* ---------- Shadows ---------- */
  --shadow-xs:   0 1px 0 rgba(13, 22, 56, 0.04);
  --shadow-sm:   0 1px 2px rgba(13, 22, 56, 0.06), 0 1px 0 rgba(13, 22, 56, 0.04);
  --shadow-md:   0 6px 14px -8px rgba(13, 22, 56, 0.18), 0 1px 2px rgba(13, 22, 56, 0.04);
  --shadow-lg:   0 18px 40px -16px rgba(13, 22, 56, 0.28);
  --shadow-focus: 0 0 0 3px rgba(48, 105, 176, 0.20);
  --shadow-focus-danger: 0 0 0 3px rgba(217, 74, 74, 0.22);

  /* ---------- Motion ---------- */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --t-fast: 120ms;
  --t-base: 180ms;
  --t-slow: 280ms;

  /* ---------- Z-index scale ---------- */
  --z-nav:    50;
  --z-popover: 60;
  --z-modal:   70;
  --z-toast:   80;
}

/* Dark theme — opt-in by adding .dark to <body> or any ancestor */
.dark {
  --bg:            #0B0F1A;
  --bg-elevated:   #0F1422;
  --surface:       #131826;
  --surface-2:     #181E30;
  --border:        #232838;
  --border-strong: #2E3447;
  --ink:           #F7F8FB;
  --ink-2:         #D8DDE9;
  --muted:         #9AA3BC;
  --muted-2:       #6B7691;

  --brand:        #5B92D2;
  --brand-deep:   #84B0E0;
  --brand-soft:   rgba(91, 146, 210, 0.14);
  --brand-strong: #84B0E0;

  --accent:       #FF8533;
  --accent-soft:  rgba(255, 133, 51, 0.22);
  --accent-ink:   #FFCC9E;

  /* Raw scale tokens used inside gradients / borders need dark-flipped values too */
  --color-brand-50:  rgba(91, 146, 210, 0.12);
  --color-brand-100: rgba(91, 146, 210, 0.22);
  --color-brand-200: rgba(91, 146, 210, 0.32);
  --color-accent-50:  rgba(255, 133, 51, 0.18);
  --color-accent-100: rgba(255, 133, 51, 0.32);
  --color-accent-200: rgba(255, 133, 51, 0.45);
  --color-accent-300: #FFA866;
  --color-accent-400: #FF9650;
  --color-accent-500: #FF8533;
  --color-accent-600: #E56910;

  --color-success-50: rgba(16, 147, 106, 0.14);
  --color-success-500: #34C29A;
  --color-success-700: #6BE3BB;

  --color-danger-50: rgba(217, 74, 74, 0.14);
  --color-danger-500: #F37A7A;
  --color-danger-700: #FBB4B4;

  --color-warning-50: rgba(212, 160, 23, 0.14);
  --color-warning-500: #E8C254;
  --color-warning-700: #F4DD8C;

  --color-info-50: rgba(8, 145, 178, 0.14);
  --color-info-500: #38BDD1;
  --color-info-700: #7FDCEA;

  --color-slate-50:  #181E30;
  --color-slate-100: #1F2638;
  --color-slate-200: #232838;
  --color-slate-300: #2E3447;

  --shadow-xs:   0 1px 0 rgba(0,0,0,0.30);
  --shadow-sm:   0 1px 2px rgba(0,0,0,0.40);
  --shadow-md:   0 8px 20px -10px rgba(0,0,0,0.55);
  --shadow-lg:   0 22px 50px -18px rgba(0,0,0,0.65);
  --shadow-focus: 0 0 0 3px rgba(91, 146, 210, 0.28);
}

/* =========================================================
   Base
   ========================================================= */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--ink);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  letter-spacing: var(--tracking-base);
  -webkit-font-smoothing: antialiased;
}
a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }
code, kbd, pre { font-family: var(--font-mono); }

/* =========================================================
   Buttons
   ========================================================= */
.btn {
  /* Default height bumped from 36px to 38px so buttons line up with
     .input / .select / .input-group (all 38px) when they share a row —
     toolbars, page-header action groups, and form footers were getting
     a 2px height mismatch. Single source of truth: "field height = 38px"
     applies to every interactive form control, including buttons.
     btn-sm (30px) and btn-lg (44px) modifiers are unchanged. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: 38px;
  padding: 0 var(--space-4);
  border-radius: var(--r-md);
  border: 1px solid transparent;
  font-family: var(--font-sans);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  letter-spacing: var(--tracking-base);
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out),
              border-color var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out),
              box-shadow var(--t-fast) var(--ease-out);
  white-space: nowrap;
  user-select: none;
}
.btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-primary {
  background: var(--brand);
  color: #fff;
  box-shadow: 0 6px 14px -8px rgba(48, 105, 176, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.btn-primary:hover { background: var(--brand-strong); }

.btn-secondary {
  background: var(--surface);
  border-color: var(--border);
  color: var(--ink-2);
}
.btn-secondary:hover { border-color: var(--border-strong); background: var(--surface-2); }

.btn-ghost {
  background: transparent;
  color: var(--ink-2);
}
.btn-ghost:hover { background: var(--surface-2); }

.btn-accent {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 6px 14px -8px rgba(229, 105, 16, 0.55),
              inset 0 1px 0 rgba(255, 255, 255, 0.20);
}
.btn-accent:hover { background: var(--color-accent-600); }

.btn-danger {
  background: var(--color-danger-500);
  color: #fff;
}
.btn-danger:hover { background: var(--color-danger-700); }

/* Solid warning button — cautionary but non-destructive actions
   (e.g. reset password). Pairs with .banner.warning / .ico.warning. */
.btn-warning {
  background: var(--color-warning-500);
  color: #fff;
}
.btn-warning:hover { background: var(--color-warning-700); }

/* Tinted / soft action buttons — for row-level actions in tables/cards.
   Same height & typography as the standard btn, but uses a colored tint fill
   with same-family text color. Sits in the middle between ghost (no fill)
   and primary (full solid). */
.btn-tinted-brand {
  background: var(--brand-soft);
  color: var(--brand-deep);
  border-color: var(--color-brand-100);
}
.btn-tinted-brand:hover {
  background: var(--color-brand-100);
  border-color: var(--color-brand-200);
}
.btn-tinted-accent {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: var(--color-accent-100);
}
.btn-tinted-accent:hover {
  background: var(--color-accent-100);
  border-color: var(--color-accent-200);
}
.btn-tinted-success {
  background: var(--color-success-50);
  color: var(--color-success-700);
  border-color: rgba(16, 147, 106, 0.22);
}
.btn-tinted-success:hover {
  background: rgba(16, 147, 106, 0.14);
  border-color: rgba(16, 147, 106, 0.35);
}
.btn-tinted-danger {
  background: var(--color-danger-50);
  color: var(--color-danger-700);
  border-color: rgba(217, 74, 74, 0.22);
}
.btn-tinted-danger:hover {
  background: rgba(217, 74, 74, 0.12);
  border-color: rgba(217, 74, 74, 0.35);
}

.btn-sm { height: 30px; padding: 0 var(--space-3); font-size: var(--fs-sm); }
.btn-lg { height: 44px; padding: 0 var(--space-5); font-size: var(--fs-md); }

/* Icon-only button — width matches the .btn height (38px default) so
   the button renders as a perfect square. Sized variants match their
   respective heights. */
.btn-icon { width: 38px; padding: 0; }
.btn-icon.btn-sm { width: 30px; }
.btn-icon.btn-lg { width: 44px; }

/* =========================================================
   Form controls
   ========================================================= */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  color: var(--ink-2);
}
.hint  { font-size: var(--fs-sm); color: var(--muted); }
.error { font-size: var(--fs-sm); color: var(--color-danger-500); }

/* Live character counter shown under a capped textarea/input. `.is-limit`
   turns it red once the value reaches its max so the user sees why they
   can't type more (the field itself hard-stops via maxlength). */
.char-counter {
  align-self: flex-end;
  font-size: var(--fs-xs);
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.char-counter.is-limit { color: var(--color-danger-500); font-weight: var(--fw-semi); }

/* Stacked fields inside a card section (e.g. the agent System prompt / First
   message / Idle prompt forms). Direct-child fields get clear separation so
   one field's hint doesn't crowd the next field's label, and those labels
   read as crisp field headings (full --ink). Scoped to direct children so
   side-by-side fields inside a .row keep their tight layout. */
.field-stack > .field + .field { margin-top: var(--space-4); }
.field-stack .field > .label { color: var(--ink); }

/* Auth pages (login / signup / forgot / reset) — comfier rhythm than the
   dense in-app forms: clear gaps between form rows, taller inputs, roomier
   card padding. Scoped to the AuthShell wrapper so app forms stay dense. */
[data-component="auth-shell"] .card-pad { padding: var(--space-7) var(--space-6); }
[data-component="auth-shell"] form > * + * { margin-top: var(--space-4); }
[data-component="auth-shell"] .input,
[data-component="auth-shell"] .select { height: 44px; }

.input,
.textarea,
.select {
  width: 100%;
  height: 38px;
  padding: 0 var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: var(--fs-base);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.input::placeholder, .textarea::placeholder { color: var(--muted-2); }
.input:hover, .textarea:hover, .select:hover { border-color: var(--border-strong); }
.input:focus, .textarea:focus, .select:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: var(--shadow-focus);
}
.input[aria-invalid="true"] {
  border-color: var(--color-danger-500);
}
.input[aria-invalid="true"]:focus { box-shadow: var(--shadow-focus-danger); }

/* Read-only value box — same footprint as .input but non-interactive and muted.
   Use on a <div> to show a saved field value without an editable control, so
   toggling between view and edit modes doesn't shift the layout. */
.input-readonly {
  display: flex;
  align-items: center;
  background: var(--surface-2);
  color: var(--ink-2, var(--muted));
  border-style: dashed;
  cursor: default;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.input-readonly:hover { border-color: var(--border); }

.textarea { height: auto; padding: var(--space-3); resize: vertical; min-height: 88px; line-height: var(--lh-snug); }

.input-group {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 0 var(--space-3);
  height: 38px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  color: var(--muted);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.input-group:focus-within {
  background: var(--surface);
  border-color: var(--brand);
  box-shadow: var(--shadow-focus);
}
.input-group input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  outline: none;
  font: inherit;
  color: var(--ink);
}

/* checkbox / radio / toggle */
.check, .radio {
  appearance: none;
  width: 16px; height: 16px;
  border: 1.5px solid var(--border-strong);
  background: var(--surface);
  cursor: pointer;
  display: inline-grid;
  place-items: center;
  transition: all var(--t-fast);
}
.check { border-radius: 4px; }
.radio { border-radius: 50%; }
.check:checked, .radio:checked { background: var(--brand); border-color: var(--brand); }
.check:checked::after {
  content: ""; width: 9px; height: 5px;
  border-left: 2px solid #fff; border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px);
}
.radio:checked::after {
  content: ""; width: 6px; height: 6px; border-radius: 50%; background: #fff;
}

.toggle {
  appearance: none;
  width: 32px; height: 18px;
  border-radius: 999px;
  background: var(--color-slate-300);
  position: relative;
  cursor: pointer;
  transition: background var(--t-fast);
}
.toggle::after {
  content: "";
  position: absolute; top: 2px; left: 2px;
  width: 14px; height: 14px;
  border-radius: 50%; background: #fff;
  transition: transform var(--t-fast) var(--ease-out);
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
}
.toggle:checked { background: var(--brand); }
.toggle:checked::after { transform: translateX(14px); }

/* =========================================================
   Badges / Status / Chips — three pill primitives that frequently
   appear in the same row (table cells, card meta).  They were
   originally specced with different paddings and font-sizes which
   made identical-shape pills render at 22/24/28px — visibly off.
   Unified at height: 24px (3px vertical padding + fs-xs + 1px
   border × 2) so they line up perfectly side-by-side.  Border
   radius still distinguishes them — .badge / .status are full
   pills, .chip is a soft rounded rect — keeping the semantic
   difference the demo intended.
   ========================================================= */
.badge {
  display: inline-flex; align-items: center; gap: var(--space-1);
  height: 24px;
  padding: 0 var(--space-2);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  background: var(--color-slate-100);
  color: var(--ink-2);
  border: 1px solid var(--border);
  white-space: nowrap;
  text-transform: capitalize;
}
.badge.brand   { background: var(--brand-soft);  color: var(--brand-deep);  border-color: var(--color-brand-100); }
.badge.accent  { background: var(--accent-soft); color: var(--accent-ink);  border-color: var(--color-accent-100); }
.badge.success { background: var(--color-success-50); color: var(--color-success-700); border-color: rgba(16,147,106,0.22); }
.badge.danger  { background: var(--color-danger-50);  color: var(--color-danger-700);  border-color: rgba(217,74,74,0.22); }
.badge.info    { background: var(--color-info-50);    color: var(--color-info-700);    border-color: rgba(8,145,178,0.22); }

.status {
  display: inline-flex; align-items: center; gap: 6px;
  height: 24px;
  padding: 0 10px 0 8px; border-radius: var(--r-pill);
  font-weight: var(--fw-bold); font-size: var(--fs-xs);
  background: var(--color-success-50); color: var(--color-success-700);
  border: 1px solid rgba(16,147,106,0.22);
  white-space: nowrap;
}
.status .pulse {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--color-success-500);
  box-shadow: 0 0 0 3px rgba(16,147,106,0.18);
}
.status.paused { background: var(--color-warning-50);  color: var(--color-warning-700);  border-color: rgba(212,160,23,0.30); }
.status.paused .pulse { background: var(--color-warning-500); box-shadow: 0 0 0 3px rgba(212,160,23,0.22); }
.status.draft  { background: var(--color-slate-100); color: var(--ink-2); border-color: var(--border); }
.status.draft  .pulse { background: var(--muted-2);  box-shadow: 0 0 0 3px rgba(139,148,172,0.20); }
.status.error  { background: var(--color-danger-50); color: var(--color-danger-700); border-color: rgba(217,74,74,0.22); }
.status.error  .pulse { background: var(--color-danger-500); box-shadow: 0 0 0 3px rgba(217,74,74,0.18); }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  height: 24px;
  padding: 0 8px; border-radius: var(--r-sm);
  font-weight: var(--fw-semi); font-size: var(--fs-xs);
  background: var(--brand-soft); color: var(--brand-deep);
  border: 1px solid var(--color-brand-100);
  white-space: nowrap;
}
.chip svg { flex-shrink: 0; }
/* Make <button class="chip"> render identical to <span class="chip">.
   Without these resets the browser's user-agent <button> styles leak
   through (smaller line-height, different font-family) and the chip
   renders shorter than the span variants beside it. */
button.chip, button.badge, button.status {
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
  text-align: left;
}
.chip.accent { background: var(--accent-soft); color: var(--accent-ink); border-color: var(--color-accent-100); }
.chip.grey   { background: var(--color-slate-100); color: var(--muted); border-color: var(--border); }

/* =========================================================
   Surfaces
   ========================================================= */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.card-pad { padding: var(--space-5); }
.card-divider {
  height: 1px;
  background: var(--border);
}

/* =========================================================
   Tables
   ========================================================= */
.table-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
table.ds { width: 100%; border-collapse: separate; border-spacing: 0; }
table.ds thead th {
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  color: var(--muted);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 10px var(--space-4);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.ds tbody td {
  padding: var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  font-size: var(--fs-base);
  color: var(--ink-2);
}
table.ds tbody tr:last-child td { border-bottom: 0; }
table.ds tbody tr:hover td { background: var(--surface-2); }
/* Row state tints — used by Orgs & Users (suspended = light red,
   reseller = light blue). Kept on hover so the state stays legible. */
table.ds tbody tr.row-danger td { background: var(--color-danger-50); }
table.ds tbody tr.row-danger:hover td { background: var(--color-danger-50); }
table.ds tbody tr.row-info td { background: var(--color-brand-50); }
table.ds tbody tr.row-info:hover td { background: var(--color-brand-100); }

/* =========================================================
   Tabs / Filter pills
   ========================================================= */
.filter-tabs {
  display: inline-flex; gap: 4px;
  padding: 3px;
  background: var(--surface-2);
  border-radius: var(--r-md);
  border: 1px solid var(--border);
}
.filter-tabs button {
  border: 0; background: transparent; cursor: pointer;
  padding: 6px var(--space-3);
  border-radius: var(--r-sm);
  font: var(--fw-semi) var(--fs-sm) var(--font-sans);
  color: var(--muted);
}
.filter-tabs button.active {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-xs);
}

.tabs-underline {
  display: flex; gap: var(--space-5);
  border-bottom: 1px solid var(--border);
}
.tabs-underline button {
  border: 0; background: transparent; cursor: pointer;
  padding: var(--space-3) 0;
  font: var(--fw-semi) var(--fs-base) var(--font-sans);
  color: var(--muted);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.tabs-underline button.active { color: var(--ink); border-color: var(--brand); }

/* =========================================================
   Avatars
   ========================================================= */
.avatar {
  display: inline-grid; place-items: center;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--color-brand-500), var(--color-brand-300));
  color: #fff;
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  letter-spacing: 0.02em;
}
.avatar-square {
  border-radius: var(--r-md);
}
.avatar-sm { width: 24px; height: 24px; font-size: 10px; }
.avatar-lg { width: 40px; height: 40px; font-size: var(--fs-base); }

/* =========================================================
   Toast / Banner
   ========================================================= */
.banner {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  background: var(--surface);
  font-size: var(--fs-base);
  color: var(--ink-2);
}
.banner.info    { background: var(--color-info-50);    border-color: rgba(8,145,178,0.20);    color: var(--color-info-700); }
.banner.success { background: var(--color-success-50); border-color: rgba(16,147,106,0.20);   color: var(--color-success-700); }
.banner.warning { background: var(--color-warning-50); border-color: rgba(212,160,23,0.28);   color: var(--color-warning-700); }
.banner.danger  { background: var(--color-danger-50);  border-color: rgba(217,74,74,0.22);    color: var(--color-danger-700); }
.banner svg { flex-shrink: 0; margin-top: 1px; }

/* =========================================================
   Pill nav (icon + label) — used in agent editor pages
   ========================================================= */
.pill-nav {
  display: inline-flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  background: var(--surface);
  padding: 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-pill);
}
.pill-nav button {
  display: inline-flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 16px;
  border: 0; background: transparent;
  border-radius: var(--r-pill);
  font: var(--fw-semi) var(--fs-base) var(--font-sans);
  color: var(--ink-2);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
  white-space: nowrap;
}
.pill-nav button:hover { background: var(--surface-2); }
.pill-nav button.active {
  background: var(--brand);
  color: #fff;
  box-shadow: 0 4px 12px -4px rgba(48,105,176,.45);
}
.pill-nav button svg { width: 15px; height: 15px; flex-shrink: 0; }
.pill-nav .count {
  background: rgba(255,255,255,.22);
  color: inherit;
  font-size: 11px;
  font-weight: var(--fw-bold);
  padding: 1px 6px;
  border-radius: var(--r-pill);
  margin-left: 2px;
}
.pill-nav button:not(.active) .count {
  background: var(--brand-soft);
  color: var(--brand);
}

/* Compact pill-nav — slimmer height + smaller font/icons + tighter padding.
   Used when the pill-nav has to live inside a narrow sidebar (e.g. the
   Widget Editor settings pane). Keeps the same active-state color contrast
   as the default variant — only spacing changes. */
.pill-nav.compact { padding: 4px; }
.pill-nav.compact button {
  height: 30px;
  padding: 0 10px;
  font-size: var(--fs-sm);
  gap: 6px;
}
.pill-nav.compact button svg { width: 13px; height: 13px; }

/* =========================================================
   Section icon block — 44x44 (default) tinted square that introduces
   a card body or modal header. Tone follows the brand soft / accent
   soft / status palettes already defined in the design system.
   ========================================================= */
.section-ico {
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--brand-soft);
  color: var(--brand);
}
.section-ico.sm { width: 36px; height: 36px; }
.section-ico.lg { width: 56px; height: 56px; }
.section-ico.accent  { background: var(--accent-soft);         color: var(--accent-ink); }
.section-ico.success { background: var(--color-success-50);    color: var(--color-success-700); }
.section-ico.danger  { background: var(--color-danger-50);     color: var(--color-danger-500); }
.section-ico.warning { background: var(--color-warning-50);    color: var(--color-warning-700); }
.section-ico.info    { background: var(--color-info-50);       color: var(--color-info-700); }

/* Required-field marker — the red asterisk after a .label. */
.required { color: var(--color-danger-500); margin-left: 2px; }

/* =========================================================
   Gradient tone palette — deterministic gradients lifted directly from
   the design-system HTML demo (#avatars + #choice-cards examples use
   these exact hex pairs as inline style="background:linear-gradient(...)"
   on .avatar.avatar-square and .choice-card .ico). Pulling them into
   named classes lets pages reference the same palette deterministically
   by name hash (utils/avatarGradient.js → g1..g6) instead of inlining
   gradient strings in JSX. Works on any element — .avatar, .ico,
   .choice-card .ico — because the selector is just the tone class.
   Declared after .choice-card .ico so it wins specificity ties. */
.g1 { background: linear-gradient(135deg, #7c3aed, #c084fc) !important; color: #fff !important; }
.g2 { background: linear-gradient(135deg, #0891b2, #22d3ee) !important; color: #fff !important; }
.g3 { background: linear-gradient(135deg, #10936A, #34C29A) !important; color: #fff !important; }
.g4 { background: linear-gradient(135deg, #D94A4A, #F37A7A) !important; color: #fff !important; }
.g5 { background: linear-gradient(135deg, #3069B0, #5B92D2) !important; color: #fff !important; }
.g6 { background: linear-gradient(135deg, #E56910, #F4974E) !important; color: #fff !important; }

/* =========================================================
   Position picker — 3x3 grid for choosing widget docking corners.
   ========================================================= */
.position-picker {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  aspect-ratio: 3 / 2;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: 8px;
}
.position-picker button {
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--muted);
  border-radius: var(--r-sm);
  cursor: pointer;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4px;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.position-picker button:hover { border-color: var(--border-strong); }
.position-picker button.selected {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

/* (Removed invented .toggle-row + .section-caption — the design-system HTML
   demo (Selection controls section, #inputs) renders toggle rows as a plain
   <label class="row" style="gap: 8px;"> with no border/padding, and group
   captions use the existing .label class. Stay close to the demo.) */

/* =========================================================
   Choice card — voice/plan/phone-number/template
   ========================================================= */
/* =========================================================
   Option card — a selectable radio/checkbox row for "pick one
   mode" choices (reset-password method, export format, plan…).
   Wrap a <label> around it so the whole card is the click
   target; drive the .selected modifier from React state to give
   the chosen card a brand border + soft fill. Radio/check sits
   top-left, title (+ optional chip) and hint stack on the right.
   The .opt-extra slot holds a revealed input when selected.
   ========================================================= */
.opt-card {
  display: flex; align-items: flex-start; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.opt-card:hover { border-color: var(--border-strong); }
.opt-card.selected { border-color: var(--brand); background: var(--brand-soft); }
.opt-card.selected:focus-within { box-shadow: var(--shadow-focus); }
.opt-card > .radio,
.opt-card > .check { margin-top: 2px; flex-shrink: 0; }
.opt-card .opt-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.opt-card .opt-title {
  display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
  font-weight: var(--fw-semi); color: var(--ink); font-size: var(--fs-base);
}
.opt-card .opt-extra { margin-top: var(--space-2); }

.choice-card {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.choice-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.choice-card.selected { border-color: var(--brand); box-shadow: var(--shadow-focus); }
.choice-card .ico {
  width: 38px; height: 38px;
  border-radius: 50%;
  display: grid; place-items: center;
  flex-shrink: 0;
  color: #fff;
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  background: linear-gradient(135deg, var(--color-brand-500), var(--color-brand-300));
}
.choice-card .body {
  /* min-width:0 lets flex children shrink below their intrinsic content
     width so the ellipsis below can actually clip — without it the body
     would stretch the whole .choice-card and push the .action button
     off-screen. */
  flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2;
  overflow: hidden;
}
.choice-card .name {
  font-weight: var(--fw-bold); color: var(--ink); font-size: var(--fs-md);
  /* Single-line truncation — voice display names like "Australian Male
     Voice - Dave" or "Charlie - Deep, Confident, Energetic" must not wrap,
     because then card heights become uneven and the name overlaps the
     .action button on the right. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}
.choice-card .meta {
  font-size: var(--fs-xs); color: var(--muted); margin-top: 2px;
  /* Same truncation rule — meta carries the voice_code (12+ chars of
     mono) and a locale tag. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  min-width: 0;
}

/* =========================================================
   Tooltip card — rich hover popover with key/value rows.
   Pure CSS reveal on parent .tt-host:hover, gated by a 1s dwell
   delay (see the :hover rule). Used by the voice grid to show
   language / provider / model / accent / age / category on hover
   without leaving the page.
   ========================================================= */
.tt-host { position: relative; }
.tt-card {
  /* Positioned ABOVE the host element; arrow points down. */
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  min-width: 240px;
  max-width: 320px;
  background: var(--ink);
  color: #fff;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  text-align: left;
  z-index: var(--z-popover);
  pointer-events: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--t-fast), transform var(--t-fast), visibility 0s linear var(--t-fast);
  box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}
/* Reveal only after the pointer dwells on the host for 1s (the delay lives
   on this :hover state, so it applies to showing only). Leaving falls back to
   the base .tt-card transition above, which has no delay — so the card hides
   instantly. If the pointer leaves before 1s the reveal never fires.
   Hover-only on purpose: :focus-within would pin the card open after a click
   on an inner control (e.g. the play button) until a click elsewhere blurs it. */
.tt-host:hover > .tt-card {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  transition: opacity var(--t-fast) 1s, transform var(--t-fast) 1s, visibility 0s linear 1s;
}
.tt-card::after {
  /* Caret pointing down at the host. */
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--ink);
}
.tt-card .tt-title {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  color: #fff;
  margin-bottom: var(--space-2);
  white-space: normal;
  word-break: break-word;
}
.tt-card .tt-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-3);
  padding: 3px 0;
  font-size: var(--fs-xs);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.tt-card .tt-row:first-of-type { border-top: 0; padding-top: 6px; }
.tt-card .tt-row > .k { color: rgba(255, 255, 255, 0.55); flex-shrink: 0; }
.tt-card .tt-row > .v { color: #fff; font-weight: var(--fw-semi); text-align: right; word-break: break-all; }
.tt-card .tt-row > .v.mono { font-family: var(--font-mono); }
.tt-card .tt-desc {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.75);
  font-size: var(--fs-xs);
  line-height: 1.5;
}

/* =========================================================
   Info tip — small single-line/paragraph hover tooltip for a
   help (?) glyph. Unlike .tt-card (which is an absolute child
   of its host), the bubble here is portaled to <body> and
   positioned with `position: fixed` by JS (see cai-ui InfoTip),
   so it escapes any `overflow: hidden` ancestor — e.g. the
   `.table-card` that clips a row-level tooltip. The host is just
   the trigger glyph; all positioning lives on .info-tip-pop.
   ========================================================= */
/* Thin progress bar — background-job / upload progress. */
.progress-track {
  width: 100%; height: 6px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  overflow: hidden;
}
.progress-fill {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--color-accent-600), var(--color-accent-400));
  transition: width var(--t-base, 240ms) ease;
}

/* KB create page — main builder column + sticky right rail (AI providers +
   summary). Collapses to a single column on narrow viewports. */
.kb-create-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: var(--space-3);
  align-items: start;
}
@media (max-width: 1024px) {
  .kb-create-grid { grid-template-columns: 1fr; }
}

/* =========================================================
   Header notification bell + dropdown. The bell pulses while
   background (scheduler) jobs run; the panel lists notifications
   and active jobs with a download for completed exports.
   ========================================================= */
.nb-pulse { animation: nb-pulse 1.6s ease-in-out infinite; border-radius: var(--r-md); }
@keyframes nb-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(48, 105, 176, 0.5); }
  50%      { box-shadow: 0 0 0 4px rgba(48, 105, 176, 0); }
}
.nb-dot { position: absolute; top: 2px; right: 2px; width: 8px; height: 8px; border-radius: 50%; background: var(--brand); }
.nb-badge {
  position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px; padding: 0 4px;
  display: grid; place-items: center; border-radius: 999px;
  background: var(--color-danger-500); color: #fff; font-size: 10px; font-weight: var(--fw-bold); line-height: 1;
}
.nb-panel {
  position: absolute; top: calc(100% + 8px); right: 0;
  width: 360px; max-height: 480px; display: flex; flex-direction: column;
  padding: 0; overflow: hidden; z-index: var(--z-popover);
}
.nb-head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--border); background: var(--surface-2); }
.nb-body { overflow-y: auto; max-height: 420px; }
.nb-section { border-bottom: 1px solid var(--border); }
.nb-section-label { display: flex; align-items: center; gap: 6px; padding: var(--space-2) var(--space-4); font-size: var(--fs-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.nb-job { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-2) var(--space-4); }
.nb-job-link { cursor: pointer; border: 0; background: transparent; width: 100%; text-align: left; }
.nb-job-link:hover { background: var(--surface-2); }
.nb-foot { border-top: 1px solid var(--border); padding: var(--space-2) var(--space-4); text-align: center; background: var(--surface-2); }
.nb-item { display: flex; align-items: flex-start; gap: var(--space-3); width: 100%; text-align: left; padding: var(--space-3) var(--space-4); border: 0; border-bottom: 1px solid var(--border); background: transparent; cursor: pointer; }
.nb-item:hover { background: var(--surface-2); }
.nb-item.unread { background: var(--brand-soft); }
.nb-item-ico { width: 28px; height: 28px; flex-shrink: 0; border-radius: 8px; display: grid; place-items: center; background: var(--surface-2); color: var(--muted); }
.nb-unread-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex-shrink: 0; margin-top: 6px; }

.info-tip-host {
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  cursor: help;
  line-height: 0;
}
.info-tip-host:hover,
.info-tip-host:focus-visible { color: var(--ink); outline: none; }
.info-tip-pop {
  /* JS sets fixed top/left at the trigger's top-centre; we shift up
     by our own height + a gap and centre horizontally so the bubble
     sits just above the glyph with a downward caret. */
  transform: translate(-50%, calc(-100% - 8px));
  max-width: 280px;
  background: var(--ink);
  color: #fff;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--r-md);
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  line-height: var(--lh-snug);
  text-align: left;
  white-space: normal;
  z-index: var(--z-toast);
  pointer-events: none;
  box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}
.info-tip-pop::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: var(--ink);
}
/* Flip variant — when the trigger is too near the viewport top, JS adds
   .below so the bubble drops under the glyph with an upward caret. */
.info-tip-pop.below {
  transform: translate(-50%, 8px);
}
.info-tip-pop.below::after {
  top: auto;
  bottom: 100%;
  border-top-color: transparent;
  border-bottom-color: var(--ink);
}

/* Auto-fill grid wrapper for a .choice-card collection. Used by the
   Voices playground tab and any future picker that needs a responsive
   grid of choice-card rows (plans, integrations, templates).  Replaces
   inline `display: grid; grid-template-columns: repeat(auto-fill,
   minmax(220px, 1fr))` style attributes scattered across pages. */
.choice-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: var(--space-2);
}
.choice-card .action {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
  cursor: pointer;
}
.choice-card .action:hover { color: var(--brand); border-color: var(--brand); background: var(--brand-soft); }

/* =========================================================
   Stepper — horizontal progress indicator for multi-step
   wizards (e.g. the agent-creation flow). Render one
   .stepper-step per step (numbered/checked dot + label) with a
   .stepper-line connector between them. Drive .active (current)
   and .done (completed) from React state. The connector aligns
   to the dot's vertical centre (margin-top = half the 32px dot)
   so labels can hang below without dragging the line down.
   ========================================================= */
.stepper { display: flex; align-items: flex-start; }
.stepper-step {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-2); flex-shrink: 0;
}
.stepper-dot {
  width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--muted);
  font-weight: var(--fw-semi); font-size: var(--fs-sm);
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.stepper-step.active .stepper-dot {
  background: var(--brand); border-color: var(--brand); color: #fff;
  box-shadow: var(--shadow-focus);
}
.stepper-step.done .stepper-dot {
  background: var(--brand-soft); border-color: var(--brand); color: var(--brand-deep);
}
.stepper-label {
  font-size: var(--fs-xs); font-weight: var(--fw-semi);
  color: var(--muted); white-space: nowrap;
}
.stepper-step.active .stepper-label { color: var(--ink); }
.stepper-step.done .stepper-label { color: var(--brand-deep); }
.stepper-line {
  flex: 1; min-width: 24px; height: 2px;
  margin-top: 15px; /* (32px dot − 2px line) / 2 → centres on the dot */
  background: var(--border); border-radius: 1px;
  transition: background var(--t-fast);
}
.stepper-line.filled { background: var(--brand); }

/* =========================================================
   Pick card — a selectable option card with a wrapping title +
   description and a check badge. Unlike .choice-card (which
   truncates name/meta to one line for dense voice grids), this
   lets multi-line descriptions wrap, so it suits category /
   industry / task pickers. Lay them out in a .choice-card-grid.
   Render as a <button>; drive .selected from React state.
   ========================================================= */
.pick-card {
  position: relative;
  display: flex; flex-direction: column; gap: 4px;
  width: 100%; text-align: left;
  padding: var(--space-3) var(--space-4);
  padding-right: var(--space-7); /* clearance for the check badge */
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast), box-shadow var(--t-fast);
}
.pick-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.pick-card.selected { border-color: var(--brand); background: var(--brand-soft); box-shadow: var(--shadow-focus); }
.pick-card .pick-title { font-weight: var(--fw-semi); color: var(--ink); font-size: var(--fs-base); }
.pick-card .pick-desc { font-size: var(--fs-xs); color: var(--muted); line-height: var(--lh-snug); }
.pick-card .pick-check {
  position: absolute; top: var(--space-3); right: var(--space-3);
  width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand); color: #fff;
  opacity: 0; transform: scale(0.6);
  transition: opacity var(--t-fast), transform var(--t-fast);
}
.pick-card.selected .pick-check { opacity: 1; transform: scale(1); }

/* =========================================================
   Channel cards — the v2 Channels page grid. A WebRTC card shows a
   mock chat-launcher thumbnail tinted with the channel's brand colour
   (set --ch-color inline); a phone card shows a country-flag number
   plate. Shared chrome: title + status, a meta row (agent / mode), a
   stat row and an actions footer.
   ========================================================= */
.ch-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--space-3);
}
.ch-card {
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.ch-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }

/* WebRTC launcher-mock thumbnail. */
.ch-thumb {
  position: relative;
  height: 120px;
  background: radial-gradient(circle at 50% 38%,
    color-mix(in srgb, var(--ch-color, var(--brand)) 16%, var(--surface-2)),
    var(--surface-2));
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.ch-thumb::before { /* faux website dotted backdrop */
  content: "";
  position: absolute; inset: 0;
  background-image: radial-gradient(var(--border-strong) 1px, transparent 1px);
  background-size: 16px 16px;
  opacity: 0.35;
}
.ch-launcher { /* the mock chat-launcher bubble */
  position: absolute; bottom: 16px; right: 16px;
  width: 50px; height: 50px;
  border-radius: 50%;
  display: grid; place-items: center;
  color: #fff;
  background: var(--ch-color, var(--brand));
  box-shadow: 0 8px 20px -6px color-mix(in srgb, var(--ch-color, var(--brand)) 65%, transparent);
}
.ch-thumb.pos-bl .ch-launcher { right: auto; left: 16px; }
.ch-thumb.pos-bc .ch-launcher { right: auto; left: 50%; transform: translateX(-50%); }
.ch-bubble { /* faux collapsed-message pill */
  position: absolute; bottom: 26px; right: 78px;
  max-width: 55%;
  padding: 6px 10px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-size: var(--fs-xs); color: var(--ink-2);
  box-shadow: var(--shadow-sm);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ch-thumb.pos-bl .ch-bubble { right: auto; left: 78px; }
.ch-thumb.pos-bc .ch-bubble { display: none; }

/* Phone / DID number-plate thumbnail. */
.ch-plate {
  height: 120px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 4px;
  background: linear-gradient(135deg, var(--color-slate-100), var(--surface-2));
  border-bottom: 1px solid var(--border);
}
.ch-plate .ch-flag { font-size: 26px; line-height: 1; }
.ch-plate .ch-num {
  font-family: var(--font-mono); font-size: var(--fs-md); font-weight: var(--fw-bold);
  color: var(--ink); letter-spacing: 0.04em;
}
.ch-plate .ch-sub { font-size: var(--fs-xs); color: var(--muted); }

/* Card body + footer. */
.ch-body { padding: var(--space-3) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); flex: 1; }
.ch-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); }
.ch-title { font-weight: var(--fw-bold); color: var(--ink); font-size: var(--fs-md); min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ch-meta { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; }
.ch-stats { display: flex; gap: var(--space-5); margin-top: auto; padding-top: var(--space-2); border-top: 1px solid var(--border); }
.ch-stat { display: flex; flex-direction: column; line-height: 1.2; }
.ch-stat .v { font-size: var(--fs-md); font-weight: var(--fw-bold); color: var(--ink); }
.ch-stat .k { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.ch-actions { display: flex; align-items: center; gap: var(--space-1); padding: var(--space-2) var(--space-3); border-top: 1px solid var(--border); background: var(--surface-2); }
.ch-actions .spacer { flex: 1; }

/* =========================================================
   Chat bubble — call transcripts
   ========================================================= */
.chat-row {
  display: flex; gap: var(--space-3);
  align-items: flex-start;
  margin-bottom: var(--space-4);
}
.chat-row.user { flex-direction: row-reverse; }
.chat-row .who {
  width: 32px; height: 32px;
  border-radius: var(--r-md);
  background: var(--brand-soft);
  color: var(--brand);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.chat-row.user .who { background: var(--color-success-50); color: var(--color-success-500); }
.chat-row .body { display: flex; flex-direction: column; gap: 6px; max-width: 70%; min-width: 0; }
.chat-row.user .body { align-items: flex-end; }
.chat-row .meta {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-xs); color: var(--muted);
}
.chat-row .meta .who-name { font-weight: var(--fw-bold); color: var(--ink); font-size: var(--fs-sm); }
.chat-row .bubble {
  padding: 10px var(--space-3);
  border-radius: var(--r-md);
  background: var(--brand-soft);
  color: var(--ink);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  border: 1px solid var(--color-brand-100);
}
.chat-row.user .bubble {
  background: var(--color-success-50);
  border-color: rgba(16,147,106,.18);
}

/* =========================================================
   Side drawer — slide-over for viewing one record in the
   context of its list (Call Details). Scrim dims the page;
   the drawer pins to the right. 60% wide on desktop, full
   width on mobile. Header → 4-up stat grid → tabs → body.
   ========================================================= */
.drawer-scrim {
  position: fixed; inset: 0; z-index: var(--z-modal);
  background: rgba(11, 21, 48, 0.32);
  backdrop-filter: blur(1px);
  display: flex; justify-content: flex-end;
}
.drawer {
  width: 60%; max-width: 760px; height: 100%;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
}
.drawer-head {
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; gap: var(--space-3);
}
.drawer-head .icon {
  width: 38px; height: 38px; border-radius: 10px;
  background: var(--brand-soft); color: var(--brand);
  display: grid; place-items: center; flex-shrink: 0;
}
.drawer-head .titles { flex: 1; min-width: 0; line-height: 1.2; }
.drawer-head .titles .t { font-weight: var(--fw-bold); color: var(--ink); font-size: var(--fs-md); }
.drawer-head .titles .sub {
  font-size: var(--fs-xs); color: var(--muted);
  text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
}
.drawer-stats {
  padding: var(--space-5);
  display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.drawer-stats .k { font-size: var(--fs-xs); font-weight: var(--fw-bold); text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.drawer-stats .v { margin-top: 6px; font-weight: var(--fw-bold); font-size: var(--fs-lg); color: var(--ink); }
.drawer-tabs { padding: var(--space-4) var(--space-5) 0; }
.drawer-body { padding: var(--space-5); flex: 1; min-height: 0; overflow-y: auto; }
@media (max-width: 640px) {
  .drawer { width: 100%; max-width: none; }
}

/* =========================================================
   Activity item — billing recent activity, audit log
   ========================================================= */
.activity-list {
  display: flex; flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
}
.activity-item {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  border-left: 3px solid transparent;
}
.activity-item:last-child { border-bottom: 0; }
.activity-item.debit  { border-left-color: var(--color-danger-500); }
.activity-item.credit { border-left-color: var(--color-success-500); }
.activity-item .ico {
  width: 32px; height: 32px;
  border-radius: var(--r-md);
  background: var(--color-danger-50);
  color: var(--color-danger-500);
  display: grid; place-items: center;
  flex-shrink: 0;
}
.activity-item.credit .ico { background: var(--color-success-50); color: var(--color-success-500); }
.activity-item .text { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.activity-item .label { font-weight: var(--fw-semi); color: var(--ink-2); font-size: var(--fs-base); }
.activity-item .when  { color: var(--muted); font-size: var(--fs-sm); margin-top: 2px; }
.activity-item .amount {
  font-family: var(--font-mono);
  font-weight: var(--fw-bold);
  font-size: var(--fs-md);
  white-space: nowrap;
}
.activity-item.debit  .amount { color: var(--color-danger-500); }
.activity-item.credit .amount { color: var(--color-success-500); }

/* =========================================================
   Empty state
   ========================================================= */
.empty {
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: var(--space-9) var(--space-6);
  color: var(--muted);
}
.empty .art {
  width: 96px; height: 96px;
  border-radius: 50%;
  background: var(--surface-2);
  display: grid; place-items: center;
  color: var(--muted-2);
  margin-bottom: var(--space-4);
  border: 1px solid var(--border);
}
.empty h4 { margin: 0 0 6px; color: var(--ink); font-size: var(--fs-md); font-weight: var(--fw-bold); }
.empty p  { margin: 0 0 var(--space-4); max-width: 320px; font-size: var(--fs-base); }

/* =========================================================
   Pipeline stage card — call pipeline / flow visualization
   ========================================================= */
.pipeline {
  display: flex; align-items: center; gap: 0;
  flex-wrap: nowrap;
  overflow-x: auto;
  padding: var(--space-5);
}
/* Centered variant — collapses to flex-start when the content overflows so the
   row remains scrollable. Used on the Agent Overview call-pipeline animation
   where we want the row hugging the centre of the wide card. */
.pipeline.is-centered { justify-content: center; }
.pipeline-stage {
  display: flex; align-items: center; gap: var(--space-3);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--space-3) var(--space-4);
  min-width: 140px;
  flex-shrink: 0;
  position: relative;
}
.pipeline-stage.brand   { border-color: var(--color-brand-200); background: linear-gradient(180deg, var(--surface), var(--color-brand-50)); }
.pipeline-stage.accent  { border-color: var(--color-accent-200); background: linear-gradient(180deg, var(--surface), var(--color-accent-50)); }
.pipeline-stage.success { border-color: rgba(16,147,106,.30); background: linear-gradient(180deg, var(--surface), var(--color-success-50)); }
.pipeline-stage.info    { border-color: rgba(8,145,178,.30); background: linear-gradient(180deg, var(--surface), var(--color-info-50)); }
.pipeline-stage .ico {
  width: 40px; height: 40px;
  border-radius: 10px;
  display: grid; place-items: center;
  color: #fff;
  flex-shrink: 0;
  background: linear-gradient(135deg, var(--color-brand-600), var(--color-brand-400));
}
.pipeline-stage.accent .ico  { background: linear-gradient(135deg, var(--color-accent-600), var(--color-accent-400)); }
.pipeline-stage.success .ico { background: linear-gradient(135deg, var(--color-success-700), var(--color-success-500)); }
.pipeline-stage.info .ico    { background: linear-gradient(135deg, #0A607A, var(--color-info-500)); }
.pipeline-stage .text { display: flex; flex-direction: column; line-height: 1.2; }
.pipeline-stage .title { font-weight: var(--fw-bold); color: var(--ink); font-size: var(--fs-md); }
.pipeline-stage .sub   { color: var(--muted); font-size: var(--fs-xs); margin-top: 2px; }
.pipeline-stage .dot {
  position: absolute; top: 8px; right: 8px;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--color-success-500);
  box-shadow: 0 0 0 3px var(--color-success-50);
}
.pipeline-arrow {
  display: grid; place-items: center;
  height: 64px; width: 28px;
  flex-shrink: 0;
  color: var(--muted-2);
}
.pipeline-arrow svg { width: 100%; height: 16px; }
.pipeline-endpoint {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--brand-soft);
  color: var(--brand);
  border: 1px dashed var(--color-brand-200);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* Pipeline header — eyebrow + description block above the flow. Used at the top
   of an agent overview pipeline. The icon block reuses the brand-soft tone. */
.pipeline-header {
  display: flex; align-items: center; gap: var(--space-3);
  margin-bottom: var(--space-4);
}
.pipeline-header .ico {
  width: 32px; height: 32px;
  border-radius: 9px;
  display: grid; place-items: center;
  background: var(--brand-soft);
  color: var(--brand);
  flex-shrink: 0;
}
.pipeline-header .eyebrow {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-black);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
}
.pipeline-header .desc {
  display: block;
  font-size: var(--fs-sm);
  color: var(--muted);
}

/* Pipeline stage — interactive + animation states. The .is-active state is the
   walkthrough highlight that pulses on a single stage at a time; .is-dimmed is
   the "not yet reached" state during playback; .is-emphasis enlarges the brain
   stage. All states reuse design-system tokens — no inline styles needed. */
.pipeline-stage.is-clickable { cursor: pointer; transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease; }
.pipeline-stage.is-clickable:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px -10px rgba(15, 23, 42, 0.18);
}
.pipeline-stage.is-active {
  transform: translateY(-3px) scale(1.04);
  box-shadow: 0 0 0 3px rgba(48,105,176,.18), 0 14px 28px -10px rgba(48,105,176,.35);
  border-color: var(--color-brand-400);
  z-index: 4;
  animation: ds-pipeline-pulse 1.4s ease-in-out infinite;
}
.pipeline-stage.is-active.accent  { box-shadow: 0 0 0 3px rgba(229,105,16,.18), 0 14px 28px -10px rgba(229,105,16,.35); border-color: var(--color-accent-400); }
.pipeline-stage.is-active.success { box-shadow: 0 0 0 3px rgba(16,147,106,.18), 0 14px 28px -10px rgba(16,147,106,.35); border-color: var(--color-success-500); }
.pipeline-stage.is-active.info    { box-shadow: 0 0 0 3px rgba(8,145,178,.18), 0 14px 28px -10px rgba(8,145,178,.35); border-color: var(--color-info-500); }
.pipeline-stage.is-dimmed {
  opacity: 0.42;
  filter: saturate(0.65);
  transition: opacity 0.3s ease, filter 0.3s ease;
}
.pipeline-stage.is-emphasis {
  min-width: 180px;
  padding: var(--space-4) var(--space-4);
}
.pipeline-stage.is-emphasis .ico { width: 48px; height: 48px; border-radius: 12px; }
.pipeline-stage.is-emphasis .title { font-size: var(--fs-lg); }
@keyframes ds-pipeline-pulse {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.12); }
}

/* Endpoint active state — same pulse, plus a halo */
.pipeline-endpoint.is-active {
  transform: scale(1.12);
  box-shadow: 0 0 0 5px rgba(48,105,176,.18), 0 8px 18px -6px rgba(48,105,176,.45);
  animation: ds-pipeline-pulse 1.4s ease-in-out infinite;
}
.pipeline-endpoint.is-dimmed { opacity: 0.42; }

/* Flowing-dashes animation on the arrows. The svg <line> must have
   stroke-dasharray="3 3" for the offset to read as motion. */
.pipeline-arrow svg line { animation: ds-pipeline-flow 1.4s linear infinite; }
@keyframes ds-pipeline-flow { to { stroke-dashoffset: -12; } }

/* "Brain reaches for" caption pill — sits between the main flow row and the
   capability cluster below it. Uses brand-soft to read as connected to the
   Brain stage above. */
.pipeline-caption {
  display: flex;
  justify-content: center;
  margin: var(--space-3) 0 0;
}
.pipeline-caption span {
  font-size: var(--fs-xs);
  font-weight: var(--fw-black);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  padding: 5px 14px;
  background: var(--brand-soft);
  border: 1px solid var(--color-brand-200);
  border-radius: 999px;
}

/* Capability tree — three cards centered under the Brain stage, with an SVG
   manifold (trunk + horizontal bar + three drops) above them. Replaces the
   inline flex/justify-content layout the page used to ship with. */
.pipeline-tree {
  position: relative;
  max-width: 600px;
  margin: var(--space-3) auto 0;
  padding-top: 48px;            /* room for the SVG manifold */
}
.pipeline-tree__svg {
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 48px;
  width: 100%;
  pointer-events: none;
}
.pipeline-tree__line {
  fill: none;
  stroke: var(--color-brand-400);
  stroke-width: 1.5;
  stroke-dasharray: 2 3;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  animation: ds-pipeline-flow 2s linear infinite;
}
.pipeline-tree__row {
  display: flex;
  justify-content: space-between;
  align-items: stretch;
  gap: var(--space-3);
}
.pipeline-tree__row > * { flex: 1; min-width: 0; }
@media (max-width: 900px) {
  .pipeline-tree { padding-top: var(--space-2); }
  .pipeline-tree__svg { display: none; }
  .pipeline-tree__row { flex-direction: column; gap: var(--space-2); }
}

/* =========================================================
   Anatomy timeline — vertical dotted line + cards + toggles
   ========================================================= */
.anatomy { position: relative; padding-left: 56px; }
.anatomy::before {
  content: "";
  position: absolute;
  left: 19px; top: 18px; bottom: 18px;
  border-left: 1.5px dashed var(--border-strong);
}
.anatomy-step { position: relative; margin-bottom: var(--space-5); }
.anatomy-step:last-child { margin-bottom: 0; }
.anatomy-step .marker {
  position: absolute;
  left: -56px; top: 0;
  width: 40px; height: 40px;
  border-radius: 10px;
  display: grid; place-items: center;
  color: #fff;
  background: linear-gradient(135deg, var(--color-brand-600), var(--color-brand-400));
  box-shadow: 0 4px 10px -4px rgba(48,105,176,.45);
}
.anatomy-step.accent .marker  { background: linear-gradient(135deg, var(--color-accent-600), var(--color-accent-400)); box-shadow: 0 4px 10px -4px rgba(229,105,16,.45); }
.anatomy-step.success .marker { background: linear-gradient(135deg, var(--color-success-700), var(--color-success-500)); box-shadow: 0 4px 10px -4px rgba(16,147,106,.40); }
.anatomy-step.warning .marker { background: linear-gradient(135deg, #B07908, var(--color-warning-500)); box-shadow: 0 4px 10px -4px rgba(212,160,23,.40); }
.anatomy-step .panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--space-4);
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.anatomy-step .panel .title { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.anatomy-step .panel .title h5 { margin: 0; font-size: var(--fs-md); color: var(--ink); font-weight: var(--fw-bold); }
/* The whole panel acts as a click target when a phase is expandable. */
.anatomy-step .panel.is-clickable { cursor: pointer; transition: border-color var(--t-fast), box-shadow var(--t-fast); }
.anatomy-step .panel.is-clickable:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
/* Endpoint steps mark the start/end of a flow (e.g. "User asks" / "Answer
   grounded") — a muted, dashed, fill-less marker + plain inline label, so
   they read as events rather than active phases. */
.anatomy-step.endpoint .marker {
  background: var(--surface-2);
  border: 1.5px dashed var(--border-strong);
  color: var(--muted);
  box-shadow: none;
}
.anatomy-step .endpoint-label {
  display: flex; align-items: center; min-height: 40px;
  font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
/* A phase's header (.panel) and its detail (.phase-body) read as ONE card so
   fields are clearly grouped under their step instead of floating below it:
   the panel drops its bottom edge + radius and each phase-body continues the
   card (a top border divides header from body / body from body), with the
   last body closing it off with a rounded bottom. Steps that are panel-only
   (e.g. call-log timeline) keep their standalone card — :not(:last-child)
   only fires when a phase-body follows. */
.anatomy-step .panel:not(:last-child) {
  border-bottom: 0;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.anatomy-step .phase-body {
  margin-top: 0;
  padding: var(--space-3) var(--space-4) var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: 0;
}
.anatomy-step .phase-body:last-child {
  border-bottom: 1px solid var(--border);
  border-bottom-left-radius: var(--r-lg);
  border-bottom-right-radius: var(--r-lg);
}
/* Field labels inside a journey step read as crisp field headings (full --ink),
   matching the highlighted labels in .field-stack form sections. */
.anatomy-step .phase-body .label { color: var(--ink); }

/* =========================================================
   Audio recording — two-channel track view (caller + agent)
   ========================================================= */
.waveform {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--space-4);
  display: flex; flex-direction: column; gap: var(--space-3);
}
.waveform-bars {
  display: flex; align-items: center; gap: 2px;
  height: 56px;
}
.waveform-bars span {
  flex: 1;
  background: var(--brand);
  border-radius: 1px;
  opacity: 0.35;
}
.waveform-bars span.peak { opacity: 1; background: var(--color-success-500); }

.audio-player {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}
.audio-player .a-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  gap: var(--space-3);
  flex-wrap: wrap;
}
.audio-player .a-meta {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-sm); color: var(--muted);
  font-family: var(--font-mono);
}
.audio-player .a-meta strong { color: var(--ink); font-family: var(--font-sans); }

.track-stack {
  display: flex; flex-direction: column;
  position: relative;
}
.track {
  display: grid;
  grid-template-columns: 132px 1fr 60px;
  align-items: stretch;
  border-bottom: 1px solid var(--border);
  min-height: 80px;
}
.track:last-of-type { border-bottom: 0; }
.track .t-info {
  display: flex; align-items: center; gap: var(--space-3);
  padding: 0 var(--space-3);
  background: var(--surface-2);
  border-right: 1px solid var(--border);
}
.track .t-info .who {
  width: 30px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  flex-shrink: 0;
  background: var(--brand-soft); color: var(--brand);
}
.track.caller .t-info .who {
  background: var(--color-success-50);
  color: var(--color-success-500);
}
.track .t-info .who-label {
  display: flex; flex-direction: column; line-height: 1.15;
  min-width: 0;
}
.track .t-info .who-name {
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  color: var(--ink);
}
.track .t-info .who-role {
  font-size: 10px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: var(--fw-bold);
}

.track .t-canvas {
  position: relative;
  background: var(--surface);
  overflow: hidden;
  cursor: pointer;
}
.track .t-canvas::before {
  /* center baseline */
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px; background: var(--border);
}
.track .t-bars {
  display: flex; align-items: center; gap: 1.5px;
  height: 100%;
  padding: 4px 8px;
  position: relative;
}
.track .t-bars span {
  flex: 1;
  background: var(--brand);
  border-radius: 1px;
  min-width: 1px;
  opacity: 0.85;
  transform-origin: center;
  align-self: center;
}
.track.caller .t-bars span { background: var(--color-success-500); }
.track .t-bars span.silent { opacity: 0.18; }

.track .t-ctl {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 0 var(--space-2);
  border-left: 1px solid var(--border);
  background: var(--surface-2);
}
.track .t-btn {
  width: 26px; height: 26px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  display: grid; place-items: center;
}
.track .t-btn:hover { background: var(--surface); border-color: var(--border); color: var(--ink); }
.track .t-btn.active { background: var(--brand); color: #fff; border-color: var(--brand); }
.track .t-btn.muted { color: var(--color-danger-500); }

/* Playhead — drawn across both tracks */
.playhead {
  position: absolute;
  top: 0; bottom: 0;
  width: 1.5px;
  background: var(--accent);
  z-index: 2;
  pointer-events: none;
}
.playhead::before {
  content: "";
  position: absolute;
  top: -4px; left: -4px;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(229,105,16,0.20);
}

/* Time ruler */
.t-ruler {
  display: grid;
  grid-template-columns: 132px 1fr 60px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}
.t-ruler .ruler-pad { background: transparent; }
.t-ruler .ruler {
  display: flex; justify-content: space-between;
  padding: 4px 8px;
  position: relative;
}
.t-ruler .ruler::before,
.t-ruler .ruler::after { content: ""; }

.audio-player .transport {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}
.audio-player .play-btn {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--brand);
  color: #fff;
  border: 0;
  cursor: pointer;
  display: grid; place-items: center;
  box-shadow: 0 6px 14px -6px rgba(48,105,176,0.55);
  flex-shrink: 0;
}
.audio-player .play-btn:hover { background: var(--brand-strong); }
.audio-player .time {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--ink-2);
  white-space: nowrap;
}
.audio-player .time .now { color: var(--ink); font-weight: var(--fw-bold); }
.audio-player .scrub {
  flex: 1;
  height: 4px;
  border-radius: 999px;
  background: var(--border);
  position: relative;
  cursor: pointer;
  min-width: 80px;
}
.audio-player .scrub-fill {
  position: absolute;
  left: 0; top: 0; bottom: 0;
  background: var(--brand);
  border-radius: 999px;
}
.audio-player .speed {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  padding: 4px 10px;
  border-radius: var(--r-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  color: var(--ink-2);
  cursor: pointer;
}

/* =========================================================
   Icon grid (design system showcase)
   ========================================================= */
.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: var(--space-3);
  margin-bottom: var(--space-5);
}
.icon-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--space-4) var(--space-3);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  text-align: center;
  color: var(--ink-2);
  transition: border-color var(--t-fast), background var(--t-fast);
  cursor: default;
}
.icon-card:hover { border-color: var(--brand); background: var(--brand-soft); }
.icon-card .icon-frame {
  width: 56px; height: 56px;
  display: grid; place-items: center;
  background: var(--surface-2);
  border-radius: var(--r-md);
  color: var(--ink);
}
.dark .icon-card .icon-frame { color: var(--ink-2); }
.icon-card .icon-name {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--ink);
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.icon-card .icon-file {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-family: var(--font-mono);
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* =========================================================
   Dropdown menu — anchored to a trigger button
   ========================================================= */
.ds-dropdown {
  position: relative;
  display: inline-block;
}
.ds-dropdown-trigger {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink-2);
  font: 600 13px var(--font-sans);
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.ds-dropdown-trigger:hover { background: var(--surface-2); border-color: var(--border-strong); }
.ds-dropdown-trigger.open {
  background: var(--surface);
  border-color: var(--brand);
  box-shadow: var(--shadow-focus);
}
.ds-dropdown-trigger .chev { color: var(--muted); transition: transform var(--t-fast); }
.ds-dropdown-trigger.open .chev { transform: rotate(180deg); }

.ds-dropdown-menu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  min-width: 220px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  z-index: var(--z-popover);
  display: none;
}
.ds-dropdown-menu.open { display: block; }
.ds-dropdown-menu.right { left: auto; right: 0; }

.ds-dropdown-header {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding: 8px 10px 4px;
}
.ds-dropdown-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: var(--r-sm);
  font-size: 13px;
  color: var(--ink-2);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--t-fast);
}
.ds-dropdown-item:hover { background: var(--surface-2); color: var(--ink); }
.ds-dropdown-item.selected { background: var(--brand-soft); color: var(--brand-deep); }
.ds-dropdown-item.danger { color: var(--color-danger-500); }
.ds-dropdown-item.danger:hover { background: var(--color-danger-50); }
.ds-dropdown-item .item-icon { color: var(--muted); flex-shrink: 0; }
.ds-dropdown-item.selected .item-icon { color: var(--brand); }
.ds-dropdown-item .item-check {
  margin-left: auto;
  color: var(--brand);
  opacity: 0;
  transition: opacity var(--t-fast);
}
.ds-dropdown-item.selected .item-check { opacity: 1; }
.ds-dropdown-item .item-kbd {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--muted);
  background: var(--surface-2);
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--border);
}
.ds-dropdown-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 0;
}

/* =========================================================
   Chart container
   ========================================================= */
.ds-chart {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
}
.ds-chart-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-4);
  gap: var(--space-3);
  flex-wrap: wrap;
}
.ds-chart-head h4 {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  color: var(--ink);
}
.ds-chart-head .h-sub {
  font-size: var(--fs-sm);
  color: var(--muted);
  margin-top: 2px;
}
.ds-chart-head .h-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.2;
}
.ds-chart-head .h-value {
  font-size: var(--fs-2xl);
  font-weight: var(--fw-black);
  color: var(--ink);
  letter-spacing: var(--tracking-tight);
  font-feature-settings: "tnum";
}
.ds-chart-head .h-delta {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  color: var(--color-success-700);
}
.ds-chart-head .h-delta.down { color: var(--color-danger-500); }
.ds-chart svg { display: block; width: 100%; height: auto; }
.ds-chart .axis-text { font: 600 10px var(--font-mono); fill: var(--muted); }
.ds-chart .grid-line { stroke: var(--border); stroke-dasharray: 3 3; }
.ds-chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-4);
  margin-top: var(--space-4);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}
.ds-chart-legend > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-sm);
  color: var(--muted);
  font-weight: var(--fw-semi);
}
.ds-chart-legend > span::before {
  content: "";
  width: 10px; height: 10px;
  border-radius: 2px;
  background: var(--lg-color, var(--brand));
}
.ds-chart-legend .strong { color: var(--ink); }

/* =========================================================
   Funnel — horizontal step bars showing conversion through ordered stages.
   Each step shrinks proportionally to its count. Used on Reports → Overview
   to show initiated → answered → completed → resolved.
   ========================================================= */
.funnel {
  display: flex; flex-direction: column;
  gap: var(--space-2);
}
.funnel-step {
  display: grid;
  grid-template-columns: 110px 1fr 80px;
  align-items: center;
  gap: var(--space-3);
  font-size: var(--fs-sm);
}
.funnel-step .label {
  color: var(--ink);
  font-weight: var(--fw-semi);
}
.funnel-step .bar {
  position: relative;
  height: 22px;
  background: var(--surface-2);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.funnel-step .bar-fill {
  position: absolute; top: 0; bottom: 0; left: 0;
  width: calc(var(--w, 0) * 100%);
  background: linear-gradient(90deg, var(--brand) 0%, var(--color-brand-400) 100%);
  border-radius: var(--r-sm);
  transition: width 0.5s ease;
}
.funnel-step .value {
  font-family: var(--font-mono);
  color: var(--ink);
  font-weight: var(--fw-bold);
  text-align: right;
  font-feature-settings: "tnum";
}
.funnel-step.success .bar-fill { background: linear-gradient(90deg, var(--color-success-500) 0%, var(--color-success-700) 100%); }
.funnel-step.accent  .bar-fill { background: linear-gradient(90deg, var(--accent) 0%, var(--color-accent-400) 100%); }
.funnel-step .pct {
  font-size: var(--fs-xs);
  color: var(--muted);
  font-family: var(--font-mono);
}

/* Chart-overlay markers — small circles dropped on top of a line chart at
   specific data points. Used to mark thumbs-up / thumbs-down events on the
   call-volume timeline so positive vs negative feedback is visible at a
   glance. Each marker uses cx/cy in the SVG viewBox; tone classes below set
   the fill + halo. */
.ds-chart .chart-marker {
  stroke: var(--surface);
  stroke-width: 1.5;
  fill: var(--muted-2);
}
.ds-chart .chart-marker.up   { fill: var(--color-success-500); }
.ds-chart .chart-marker.down { fill: var(--color-danger-500); }
.ds-chart .chart-marker.halo {
  opacity: 0.18;
  stroke: none;
}
.ds-chart .chart-marker.halo.up   { fill: var(--color-success-500); }
.ds-chart .chart-marker.halo.down { fill: var(--color-danger-500); }

/* =========================================================
   Calendar / Date picker
   ========================================================= */
.ds-calendar {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--space-4);
  width: 308px;
  box-shadow: var(--shadow-md);
}
.cal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-3);
}
.cal-head .cal-title {
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  color: var(--ink);
  letter-spacing: var(--tracking-tight);
}
.cal-head .cal-nav {
  display: flex;
  gap: 2px;
}
.cal-head .cal-nav button {
  width: 28px; height: 28px;
  border: 0;
  background: transparent;
  border-radius: var(--r-sm);
  color: var(--muted);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.cal-head .cal-nav button:hover { background: var(--surface-2); color: var(--ink); }

.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
}
.cal-grid .cal-dow {
  font-size: 11px;
  font-weight: var(--fw-bold);
  color: var(--muted);
  text-align: center;
  padding: 6px 0;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.cal-day {
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  font-size: 13px;
  color: var(--ink-2);
  border-radius: var(--r-sm);
  cursor: pointer;
  background: transparent;
  border: 0;
  font-family: var(--font-sans);
  font-weight: var(--fw-medium);
  transition: background var(--t-fast), color var(--t-fast);
  position: relative;
}
.cal-day:hover:not(:disabled):not(.range-start):not(.range-end):not(.selected) {
  background: var(--surface-2);
  color: var(--ink);
}
.cal-day.outside { color: var(--muted-2); opacity: 0.5; }
.cal-day:disabled { color: var(--muted-2); opacity: 0.35; cursor: not-allowed; }
.cal-day.today { font-weight: var(--fw-bold); color: var(--brand); }
.cal-day.today::after {
  content: "";
  position: absolute;
  bottom: 4px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--brand);
}
.cal-day.selected,
.cal-day.range-start,
.cal-day.range-end {
  background: var(--brand);
  color: #fff;
  font-weight: var(--fw-bold);
}
.cal-day.selected.today::after,
.cal-day.range-start.today::after,
.cal-day.range-end.today::after { background: #fff; }
.cal-day.in-range {
  background: var(--brand-soft);
  color: var(--brand-deep);
  border-radius: 0;
}
.cal-day.range-start { border-radius: var(--r-sm) 0 0 var(--r-sm); }
.cal-day.range-end { border-radius: 0 var(--r-sm) var(--r-sm) 0; }

.cal-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
  gap: var(--space-2);
}

/* =========================================================
   Date range picker
   ========================================================= */
.ds-daterange {
  display: flex;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  max-width: 860px;
}
.ds-daterange .presets {
  width: 200px;
  flex-shrink: 0;
  border-right: 1px solid var(--border);
  background: var(--surface);
  padding: var(--space-2);
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.ds-daterange .presets .preset-h {
  font-size: 12px;
  font-weight: var(--fw-bold);
  color: var(--muted);
  padding: 8px 10px 6px;
  text-transform: none;
  letter-spacing: 0;
}
.ds-daterange .presets button {
  text-align: left;
  padding: 8px 10px;
  border: 0;
  background: transparent;
  border-radius: var(--r-sm);
  font: 500 13px var(--font-sans);
  color: var(--ink-2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  position: relative;
}
.ds-daterange .presets button:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.ds-daterange .presets button.active {
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-weight: var(--fw-semi);
}
.ds-daterange .presets button.active::after {
  content: "";
  width: 14px; height: 14px;
  background: var(--brand);
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12 10 17 20 7'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><polyline points='5 12 10 17 20 7'/></svg>");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  flex-shrink: 0;
}
.ds-daterange .presets-divider {
  height: 1px;
  background: var(--border);
  margin: 4px 6px;
}
.ds-daterange .cals {
  display: flex;
  padding: var(--space-3);
  gap: var(--space-3);
}
.ds-daterange .ds-calendar {
  border: 0;
  box-shadow: none;
  padding: var(--space-2);
}

.daterange-input {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  color: var(--ink);
  font: 13px var(--font-sans);
  cursor: pointer;
  white-space: nowrap;
}
.daterange-input:hover { border-color: var(--border-strong); }
.daterange-input .sep { color: var(--muted); }
.daterange-input .value { font-weight: var(--fw-semi); }

/* =========================================================
   Mini stat card — for dense KPI strips below a hero chart/map
   ========================================================= */
.stat-mini {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  padding: var(--space-3) var(--space-4);
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.stat-mini .sm-label {
  font-size: 11px;
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.stat-mini .sm-value {
  font-size: 28px;
  font-weight: var(--fw-black);
  letter-spacing: var(--tracking-tight);
  line-height: 1;
  color: var(--ink);
  font-feature-settings: "tnum";
}
.stat-mini.brand   .sm-value { color: var(--brand); }
.stat-mini.accent  .sm-value { color: var(--accent); }
.stat-mini.success .sm-value { color: var(--color-success-500); }
.stat-mini.danger  .sm-value { color: var(--color-danger-500); }
.stat-mini.info    .sm-value { color: var(--color-info-500); }
.stat-mini.purple  .sm-value { color: #6F5BD6; }
.stat-mini .sm-sub {
  font-size: 11.5px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 6px;
}
.stat-mini .sm-sub .thumb-up { color: var(--color-success-500); }
.stat-mini .sm-sub .thumb-down { color: var(--color-danger-500); }

/* =========================================================
   Geographic map — stylized world map + pulsing markers
   ========================================================= */
.ds-map {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  aspect-ratio: 2 / 1;
  width: 100%;
  min-height: 0;
}
.ds-map .map-bg {
  /* Match the Dashboard's WorldMap: flat landmass in a single neutral grey
     (the React map fills its geographies with #dee2e8). Instead of tinting a
     background image with a filter — which reads slightly blue/washed and
     never matches the live map — we MASK the world-map silhouette and paint
     it with a solid colour, so the continents are exactly the Dashboard grey
     and stay crisp at any size. */
  position: absolute;
  inset: 0;
  background-color: #dee2e8;
  -webkit-mask: url("icons/world-map.svg") center / contain no-repeat;
          mask: url("icons/world-map.svg") center / contain no-repeat;
  /* The SVG paths are opaque black on transparent — alpha-mask them so the
     continents show the fill colour (luminance mode would hide them). */
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
}
.dark .ds-map .map-bg { background-color: #2b3344; }

.map-marker {
  /* Match the Dashboard's WorldMap markers: a small solid centre dot wrapped
     in two soft translucent halos (the React map stacks three <circle>s:
     a faint outer halo, a mid inner glow, and a tiny solid core). No hard
     ring, no inline label — just a soft glow sized to the location. */
  position: absolute;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: rgba(48,105,176,0.9);
  transform: translate(-50%, -50%);
  z-index: 2;
  box-shadow:
    0 0 0 6px rgba(48,105,176,0.32),
    0 0 0 15px rgba(48,105,176,0.12);
}
.map-marker .marker-label {
  position: absolute;
  top: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-sans);
  font-weight: var(--fw-bold);
  font-size: 11px;
  color: var(--ink);
  background: var(--surface);
  padding: 3px 8px;
  border-radius: 4px;
  border: 1px solid var(--border);
  white-space: nowrap;
  box-shadow: var(--shadow-sm);
}
.map-marker.accent  { background: rgba(229,105,16,0.9);  box-shadow: 0 0 0 6px rgba(229,105,16,0.30), 0 0 0 15px rgba(229,105,16,0.11); }
.map-marker.success { background: rgba(16,147,106,0.9);  box-shadow: 0 0 0 6px rgba(16,147,106,0.30), 0 0 0 15px rgba(16,147,106,0.11); }

.map-overlay {
  /* Glass-card style — matches the legacy Dashboard overlays
     (react-ui/src/pages/Dashboard:473 / :501). Translucent surface with
     blurred backdrop so the world map shows through, plus tighter
     10px/14px padding so the inline KPI row and 70px chart sit snug. */
  position: absolute;
  background: rgba(255, 255, 255, 0.75);
  border: 1px solid rgba(255, 255, 255, 0.5);
  border-radius: var(--r-md);
  padding: 10px 14px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06), 0 0 0 1px rgba(255, 255, 255, 0.5) inset;
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  z-index: 3;
  min-width: 180px;
}
.dark .map-overlay {
  background: rgba(20, 24, 38, 0.65);
  border-color: rgba(255, 255, 255, 0.08);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.04) inset;
}
.map-overlay.top-right { top: 16px; right: 16px; }
.map-overlay.top-left { top: 16px; left: 16px; }
.map-overlay.bottom-left { bottom: 16px; left: 16px; }
.map-overlay.bottom-right { bottom: 16px; right: 16px; }
.map-overlay .ovl-h {
  font-size: 10px;
  font-weight: var(--fw-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 8px;
}
.map-overlay .ovl-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
  gap: var(--space-3);
  font-size: 13px;
}
.map-overlay .ovl-row:last-child { border-bottom: 0; padding-bottom: 0; }
.map-overlay .ovl-row .city { font-weight: var(--fw-semi); color: var(--ink); }
.map-overlay .ovl-row .count { font-family: var(--font-mono); font-weight: var(--fw-bold); color: var(--brand); }

/* Date control row (matches the dashboard hero) */
.ds-date-row {
  position: absolute;
  top: 16px; left: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  z-index: 3;
}

/* =========================================================
   Helpers
   ========================================================= */
.muted { color: var(--muted); }
.mono { font-family: var(--font-mono); }
/* Single-line ellipsis — clip overflowing text to one line. The consumer sets
   a max-width inline (the constraint is per-instance / layout-dependent) and
   pairs it with a title attribute so the full value stays available on hover. */
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: bottom; max-width: 100%; }
.row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
.stack { display: flex; flex-direction: column; gap: var(--space-3); }
.stack-2 { display: flex; flex-direction: column; gap: var(--space-2); }
.row-tight { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }

/* Search-input width preset — used on list-page toolbars so search inputs share
   a consistent 240px floor that doesn't crowd adjacent controls. Pages just write
   <div class="input-group input-search"> instead of inline minWidth. */
.input-search { min-width: 240px; }

/* =========================================================
   Markdown editor — split view (textarea + rendered prose) with a popout
   to full-screen. Used on every prompt textarea on the Agent Detail page so
   the user can author rich prompts and see exactly how they render.
   ========================================================= */

/* Generic flex spacer — drop a `<span class="spacer" />` between flex items to
   push everything after it to the far end of the row. Replaces ad-hoc
   `margin-left: auto` overrides. */
.spacer { flex: 1 1 auto; min-width: 0; }

/* =========================================================
   Sparkline — inline mini-chart for table cells / KPI cards.
   Pure CSS — the React component just emits N <span class="sparkline-bar">
   with a `--h` custom property (0..1 normalized height). No SVG needed.
   ========================================================= */
.sparkline {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 28px;
  min-width: 80px;
  padding: 2px 0;
}
.sparkline.lg { height: 48px; min-width: 140px; }
.sparkline.sm { height: 18px; min-width: 60px; gap: 1px; }
.sparkline-bar {
  flex: 1;
  min-width: 3px;
  height: calc(2px + (100% - 2px) * var(--h, 0));
  background: var(--color-brand-400);
  border-radius: 2px 2px 0 0;
  transition: background 0.15s ease;
}
.sparkline-bar.is-today { background: var(--brand); }
.sparkline-bar.is-empty { background: var(--border); }
.sparkline.accent .sparkline-bar { background: var(--color-accent-400); }
.sparkline.accent .sparkline-bar.is-today { background: var(--accent); }
.sparkline.success .sparkline-bar { background: var(--color-success-500); }
.sparkline.muted   .sparkline-bar { background: var(--muted-2); opacity: 0.55; }

/* =========================================================
   Delta chip — small up/down trend pill next to a number.
   Use with .delta.up (green), .delta.down (red), .delta.flat (grey).
   ========================================================= */
.delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  padding: 1px 6px;
  border-radius: 999px;
  font-feature-settings: "tnum";
  line-height: 1.4;
}
.delta.up   { background: var(--color-success-50); color: var(--color-success-700); }
.delta.down { background: var(--color-danger-50);  color: var(--color-danger-700); }
.delta.flat { background: var(--surface-2);        color: var(--muted); }

/* =========================================================
   Health dot — circular indicator for "is this agent healthy".
   Sized 10px; pair with a status pill for label. Tones:
     .good     green — has channels, traffic, success > 60%
     .warning  amber — issue (low success, no channels, etc.)
     .quiet    blue  — no calls in window but otherwise OK
     .inactive grey  — agent is_active === false
   ========================================================= */
.health-dot {
  display: inline-block;
  width: 10px; height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 0 3px transparent;
  vertical-align: middle;
}
.health-dot.good     { background: var(--color-success-500); box-shadow: 0 0 0 3px rgba(16,147,106,.18); }
.health-dot.warning  { background: var(--color-warning-500); box-shadow: 0 0 0 3px rgba(212,160,23,.22); }
.health-dot.quiet    { background: var(--color-info-500);    box-shadow: 0 0 0 3px rgba(8,145,178,.18); }
.health-dot.inactive { background: var(--muted-2);           box-shadow: 0 0 0 3px rgba(139,148,172,.20); }

/* Toolbar above the editor — view-mode toggle + popout button. */
.md-toolbar {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: 6px;
}
.md-toolbar .pill-nav { margin: 0; }

/* Collapsed prompt — a compact read-only preview shown until the user opts
   in to editing (MarkdownTextarea `collapsible`). A 2-line clamp of the
   current text on the left, an Edit button on the right. Keeps long-prompt
   pages calm: nothing is expanded until you click Edit. */
.md-collapsed {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}
.md-collapsed__text {
  flex: 1; min-width: 0;
  font-size: var(--fs-sm); color: var(--ink-2);
  line-height: var(--lh-snug);
  white-space: pre-wrap;
  cursor: pointer;
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2;
  -webkit-box-orient: vertical; overflow: hidden;
}
.md-collapsed__text.is-empty { color: var(--muted); font-style: italic; }
.md-collapsed .btn { flex-shrink: 0; }

/* Editor surface — wraps either the textarea, the preview, or both. */
.md-editor {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface);
  overflow: hidden;
}
.md-editor .textarea { border: 0; border-radius: 0; }
.md-editor.is-split { display: grid; grid-template-columns: 1fr 1fr; }
.md-editor.is-split .md-pane + .md-pane { border-left: 1px solid var(--border); }
.md-editor .md-pane { min-height: 0; display: flex; flex-direction: column; }
.md-editor .md-pane .textarea { flex: 1; min-height: 140px; }
.md-editor .md-pane.md-pane--preview {
  background: var(--surface-2);
  overflow: auto;
  max-height: 480px;
  padding: var(--space-4);
}

/* Rendered-markdown typography. Subset of GitHub flavoured markdown — headings,
   paragraphs, lists, code, blockquote, table. All colours from tokens. */
.md-prose { color: var(--ink); font-size: var(--fs-base); line-height: var(--lh-base); }
.md-prose > *:first-child { margin-top: 0; }
.md-prose > *:last-child  { margin-bottom: 0; }
.md-prose h1, .md-prose h2, .md-prose h3, .md-prose h4 {
  color: var(--ink); font-weight: var(--fw-bold); margin: 1em 0 0.4em;
}
.md-prose h1 { font-size: 1.4em; }
.md-prose h2 { font-size: 1.2em; }
.md-prose h3 { font-size: 1.1em; }
.md-prose h4 { font-size: 1em; }
.md-prose p, .md-prose ul, .md-prose ol { margin: 0 0 0.7em; }
.md-prose ul, .md-prose ol { padding-left: 1.4em; }
.md-prose li { margin: 0.15em 0; }
.md-prose a { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }
.md-prose code {
  font-family: var(--font-mono); font-size: 0.9em;
  background: var(--surface-3, rgba(48,105,176,0.08));
  padding: 1px 5px; border-radius: 4px;
}
.md-prose pre {
  background: var(--surface-3, rgba(48,105,176,0.05));
  border: 1px solid var(--border);
  padding: var(--space-3);
  border-radius: var(--r-sm);
  overflow-x: auto;
}
.md-prose pre code { background: transparent; padding: 0; }
.md-prose blockquote {
  margin: 0 0 0.7em;
  padding: 0.2em 0.9em;
  border-left: 3px solid var(--color-brand-200);
  color: var(--muted);
  background: var(--brand-soft);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
.md-prose table {
  width: 100%; border-collapse: collapse; margin: 0.5em 0 0.9em;
  font-size: var(--fs-sm);
}
.md-prose th, .md-prose td {
  border: 1px solid var(--border);
  padding: 6px 8px; text-align: left;
}
.md-prose th { background: var(--surface-2); font-weight: var(--fw-bold); }
.md-prose hr { border: 0; border-top: 1px solid var(--border); margin: 1em 0; }
.md-prose .md-empty { color: var(--muted); font-style: italic; }

/* Full-screen popout — full-viewport modal with toolbar + grid pane(s). */
.md-modal-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 23, 42, 0.55);
  display: flex; align-items: stretch; justify-content: stretch;
  z-index: 60;
  padding: var(--space-5);
}
.md-modal {
  flex: 1;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  display: flex; flex-direction: column;
  overflow: hidden;
  box-shadow: 0 24px 64px -16px rgba(15, 23, 42, 0.4);
}
.md-modal__head {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
}
.md-modal__head .title { font-weight: var(--fw-bold); color: var(--ink); }
.md-modal__body { flex: 1; min-height: 0; display: flex; }
.md-modal__body .md-editor {
  flex: 1; border: 0; border-radius: 0;
  display: flex; flex-direction: column;
}
.md-modal__body .md-editor.is-split { display: grid; }
.md-modal__body .md-pane .textarea { min-height: 100%; resize: none; }
.md-modal__body .md-pane.md-pane--preview { max-height: none; }

/* =========================================================
   Agent test panel — true two-column layout. The agent settings
   slide left (their flex column shrinks) and the test panel sits
   beside them as a real flex child, not an overlay. So the user
   can edit settings on the left while watching effects on the right.
   ========================================================= */

/* Layout wrapper inside the page — flex row hosting the main column
   and the test panel. The main column stacks the header + tabs + tab body
   vertically; the panel takes a fixed width on the right. */
.agent-detail-layout {
  display: flex;
  gap: var(--space-3);
  flex: 1; min-height: 0;
  align-items: stretch;
}
.agent-detail-main {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column;
  gap: var(--space-3);
}

.agent-test-panel {
  flex: 0 0 clamp(360px, 25vw, 480px);
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: 0 4px 16px -8px rgba(15, 23, 42, 0.12);
  display: flex; flex-direction: column;
  overflow: hidden;
  position: sticky;
  /* Pin the panel exactly to the visible viewport area below the 68px topbar.
     Using `height` (not max-height) so the iframe body always fills whatever
     vertical room exists, regardless of how tall the surrounding page is.
     The `var(--space-4)` subtraction leaves a 16px breathing gap at the
     bottom so the action bar (Reload / Embed code / Open) has room and is
     never clipped by the viewport edge. */
  top: calc(68px + var(--space-2));
  height: calc(100vh - 68px - var(--space-4));
  min-height: 0;
}
.agent-test-panel__head {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.agent-test-panel__head .ico {
  width: 32px; height: 32px;
  border-radius: 9px;
  display: grid; place-items: center;
  background: var(--brand-soft);
  color: var(--brand);
  flex-shrink: 0;
}
.agent-test-panel__body {
  flex: 1; min-height: 0;
  background: var(--surface-2);
  overflow: hidden;
  display: flex;
}
.agent-test-panel__iframe {
  flex: 1;
  width: 100%;
  border: 0;
  background: transparent;
}
.agent-test-panel__actions {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-3);
  border-top: 1px solid var(--border);
  flex-wrap: wrap;
}

/* Below tablet, stack: main on top, panel below (or full-screen overlay
   via a backdrop — for now we just stack and let the user scroll). */
@media (max-width: 1100px) {
  .agent-detail-layout { flex-direction: column; }
  .agent-test-panel {
    flex: 0 0 auto;
    width: 100%;
    position: relative;
    top: auto;
    max-height: 70vh;
  }
}
.text-right { text-align: right; }
.text-danger  { color: var(--color-danger-700); }
.text-warning { color: var(--color-warning-700); }
.text-success { color: var(--color-success-700); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }

/* "Link"-style button — looks like a bold text link, no chrome. Used wherever a
   table cell name or chip needs to navigate/edit without the visual weight of a
   real button. Preserves cursor, inherits font, supports hover underline. */
.btn-link {
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  font: inherit;
  cursor: pointer;
  color: var(--ink);
  text-align: left;
  font-weight: var(--fw-bold);
}
.btn-link:hover { color: var(--brand); text-decoration: underline; text-underline-offset: 2px; }

/* KPI strip — equal-width auto-fit grid used at the top of list pages. Picks the
   column count from `data-cols` (defaults to 4). Pages just write
   <div class="kpi-strip" data-cols="5"> instead of inline grid-template. */
.kpi-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-3);
}
.kpi-strip[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
.kpi-strip[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
.kpi-strip[data-cols="5"] { grid-template-columns: repeat(5, 1fr); }
.kpi-strip[data-cols="6"] { grid-template-columns: repeat(6, 1fr); }
@media (max-width: 900px) { .kpi-strip { grid-template-columns: repeat(2, 1fr); } }

/* Dense KPI strip — used when 5–6 tiles need to fit in one row and the
   default ~28px value font would overflow. Halves the vertical padding
   and shrinks the value font so the tiles read more like a compact
   metrics ribbon than a full hero. */
.kpi-strip.is-dense .stat-mini { padding: var(--space-2) var(--space-3); gap: 4px; }
.kpi-strip.is-dense .stat-mini .sm-value { font-size: 22px; }
.kpi-strip.is-dense .stat-mini .sm-label { font-size: 10px; }
.kpi-strip.is-dense .stat-mini .sm-sub   { font-size: 10.5px; }

/* Safety net: a KPI strip with 5+ tiles that doesn't declare an explicit
   data-cols still stays on ONE row (equal-width columns) instead of
   wrapping after the default 4. data-cols strips keep their fixed layout. */
.kpi-strip:not([data-cols]):has(> :nth-child(5)) {
  grid-template-columns: none;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
}
@media (max-width: 900px) {
  .kpi-strip:not([data-cols]):has(> :nth-child(5)) {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, 1fr);
  }
}

/* =========================================================
   Spinner — loading indicator (used with lucide Loader2 etc.)
   ========================================================= */
@keyframes ds-spin { to { transform: rotate(360deg); } }
.spin { animation: ds-spin 0.8s linear infinite; }

/* =========================================================
   Legend dot — colored swatch + label + optional value.
   Used in chart legends and inside map overlays.
   Pass color via the `--swatch` CSS variable inline.
   ========================================================= */
.legend-dot {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
}
.legend-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--swatch, var(--brand));
  display: inline-block;
}
.legend-dot strong { color: var(--ink); }

/* =========================================================
   Stat-mini overlay — denser mini-stat block used INSIDE a
   .map-overlay panel. Smaller typography than .stat-mini.
   ========================================================= */
.stat-mini-overlay {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.stat-mini-overlay .sm-label {
  font-size: 9px;
  color: var(--muted-2);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.stat-mini-overlay .sm-value {
  font-size: 20px;
  font-weight: var(--fw-bold);
  color: var(--ink);
  line-height: 1.1;
  font-feature-settings: "tnum";
}
.stat-mini-overlay.brand .sm-value { color: var(--brand); }

/* =========================================================
   .ds-map modifiers
   ========================================================= */
.ds-map.fixed {
  /* Mirrors the legacy Dashboard hero (react-ui/src/pages/Dashboard:415)
     so the world map gets the same breathing room it always had:
     60vh in the middle, clamped between 350px and 500px. */
  aspect-ratio: auto;
  height: 60vh;
  min-height: 350px;
  max-height: 500px;
  flex-shrink: 0;
}

/* =========================================================
   Page layouts
   ========================================================= */
/* Generic page wrapper — used by list pages (Agents, Channels, Users…) where
   content scrolls naturally if it exceeds the viewport. */
.page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3);
}

/* Dashboard variant — locks to viewport, no outer scroll. Used by the
   one-screen Dashboard hero+stats+chart layout. */
.dashboard-page {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3);
  /* Fit exactly within the viewport: 100vh − topbar(48) − lp-page padding(20).
     The lp-page padding was halved to 10px per side, so the deduction here is
     20 (was 40) — total 68. `height` (not min-height) caps growth and
     overflow:hidden prevents the outer scrollbar when content tries to push
     past the cap. */
  height: calc(100vh - 68px);
  overflow: hidden;
}
.dashboard-stats-grid {
  display: grid;
  gap: var(--space-2);
  grid-template-columns: repeat(7, minmax(0, 1fr));
  flex-shrink: 0;
}
@media (max-width: 900px) {
  .dashboard-stats-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 540px) {
  .dashboard-stats-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.dashboard-call-source {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0; /* allows flex child to shrink below its content size */
  gap: 8px;
}
.dashboard-chart-canvas {
  position: relative;
  flex: 1;
  min-height: 0;
}
.dashboard-overlay-chart {
  /* Match legacy overlay chart height (70px in
     react-ui/src/pages/Dashboard:523) so the visitors / conversations
     curves have a bit more vertical headroom inside the glass card. */
  height: 70px;
}

/* =========================================================
   MODALS & DRAWERS
   Pattern lifted verbatim from the Design System HTML demo
   (#modals section): rgba(11,21,48,0.5) backdrop holding a
   .card with optional .modal-head / .modal-body / .modal-foot.
   ========================================================= */
.modal-backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  background: rgba(11, 21, 48, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-4);
}
.modal-dialog {
  width: 100%;
  max-width: 480px;
  max-height: calc(100vh - var(--space-6));
  display: flex;
  flex-direction: column;
  overflow: hidden; /* lets inner body scroll independently */
  box-shadow: var(--shadow-lg);
}
.modal-dialog.modal-sm { max-width: 380px; }
.modal-dialog.modal-md { max-width: 560px; }
.modal-dialog.modal-lg { max-width: 720px; }
.modal-head {
  padding: var(--space-5);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  border-bottom: 1px solid var(--border);
}
.modal-head .ico {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex-shrink: 0;
  background: var(--brand-soft);
  color: var(--brand);
}
.modal-head .ico.danger  { background: var(--color-danger-50);  color: var(--color-danger-500); }
.modal-head .ico.success { background: var(--color-success-50); color: var(--color-success-500); }
.modal-head .ico.warning { background: var(--color-warning-50); color: var(--color-warning-700); }
.modal-head .text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.modal-head .text h4 { margin: 0; font-size: var(--fs-md); color: var(--ink); font-weight: var(--fw-bold); }
.modal-head .text p  { margin: 0; color: var(--muted); font-size: var(--fs-base); }
.modal-head .close {
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  background: transparent;
  border: 0;
  color: var(--muted);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.modal-head .close:hover { background: var(--surface-2); color: var(--ink); }
.modal-body {
  padding: var(--space-5);
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}
.modal-foot {
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  padding: var(--space-3) var(--space-5);
  display: flex;
  justify-content: flex-end;
  gap: var(--space-2);
}
/* When a <form> wraps the body + foot, let its children participate directly
   in the dialog's flex column so .modal-body can scroll (flex:1 + overflow)
   and the footer stays pinned. Without this the form's block box swallows the
   flex sizing and tall content (e.g. the Roles permission picker) clips. */
.modal-dialog > form { display: contents; }

/* =========================================================
   CODE BLOCK
   Snippet panel used by embed code, API token responses,
   webhook payload previews, etc. Mac-window dots optional.
   ========================================================= */
.code-block {
  position: relative;
  background: var(--ink);
  color: #d1d5db;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  padding: var(--space-4) var(--space-4) var(--space-4);
  border-radius: var(--r-md);
  border: 1px solid var(--border-strong);
  overflow-x: auto;
  white-space: pre;
  word-break: break-all;
}
.code-block.has-dots { padding-top: calc(var(--space-4) + 18px); }
.code-block .dots {
  position: absolute;
  top: 10px;
  left: 16px;
  display: flex;
  gap: 6px;
}
.code-block .dots span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
}
.code-block .dots span:nth-child(1) { background: var(--color-danger-500); }
.code-block .dots span:nth-child(2) { background: var(--color-warning-500); }
.code-block .dots span:nth-child(3) { background: var(--color-success-500); }
.code-block .copy-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background: rgba(255, 255, 255, 0.10);
  color: #fff;
  border: 0;
  padding: 4px 10px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs);
  font-family: var(--font-sans);
  font-weight: var(--fw-semi);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.code-block .copy-btn:hover { background: rgba(255, 255, 255, 0.18); }
.code-block code {
  background: transparent;
  color: inherit;
  font-family: inherit;
  font-size: inherit;
  padding: 0;
}
/* Soft-wrap variant — for prose payloads (LLM prompts / model output) where
   horizontal scrolling hurts readability. Keeps the mono log look but wraps. */
.code-block.wrap { white-space: pre-wrap; word-break: break-word; }

/* TTS highlight — inline <mark>-style tint marking the span of transcript text
   a TTS chunk synthesised, so call-detail transcripts show which words were
   spoken and whether they were served from cache. Green = cache hit, amber =
   cache miss. The element's title attribute carries per-chunk metadata. */
.tts-hl {
  background: var(--color-success-50);
  color: var(--color-success-700);
  border-radius: var(--r-sm);
  padding: 0 2px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
.tts-hl.miss { background: var(--color-warning-50); color: var(--color-warning-700); }

/* =========================================================
   Language designer — enable-languages grid, detection-method
   cards, and the per-string translation editor used by the
   widget editor's Language tab.

   Each card paints itself in a per-language accent fed through
   one inline custom property: `--lg-color`. That's the only
   per-instance value (like the chart legend dot) — the class
   derives every tint/ring from it via color-mix, so a single
   rule colours English blue, Hindi amber, Tamil teal, … with
   no bespoke per-card CSS.
   ========================================================= */
.lang-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: var(--space-3);
}
.lang-card {
  --lg-color: var(--brand);
  position: relative;
  display: flex; flex-direction: column; align-items: center;
  gap: var(--space-2);
  padding: var(--space-5) var(--space-3) var(--space-4);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.lang-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.lang-card.is-on {
  border-color: var(--lg-color);
  background: color-mix(in srgb, var(--lg-color) 5%, var(--surface));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lg-color) 14%, transparent);
}
.lang-card .lang-badge {
  width: 44px; height: 44px; border-radius: var(--r-lg);
  display: grid; place-items: center;
  font-size: 20px; font-weight: var(--fw-bold);
  color: var(--lg-color);
  background: color-mix(in srgb, var(--lg-color) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--lg-color) 18%, transparent);
  transition: background var(--t-fast);
}
.lang-card.is-on .lang-badge { background: color-mix(in srgb, var(--lg-color) 16%, transparent); }
.lang-card .lang-name {
  font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--muted);
  transition: color var(--t-fast);
}
.lang-card.is-on .lang-name { color: var(--lg-color); }
/* Persistent corner badges — enabled check (right) + default star (left). */
.lang-card .lang-check,
.detect-card .pick-check {
  position: absolute; top: var(--space-2); right: var(--space-2);
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--lg-color); color: #fff; font-size: 10px;
}
.detect-card .pick-check { width: 16px; height: 16px; top: 6px; right: 6px; }
.lang-card .lang-star {
  position: absolute; top: var(--space-2); left: var(--space-2);
  color: var(--color-warning-500);
}
/* Hover overlay — Enable/Disable + Set-default actions sit on a frosted
   sheet that fades in over the card body. */
.lang-card .lang-actions {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2);
  padding: var(--space-2);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast);
}
.lang-card:hover .lang-actions,
.lang-card:focus-within .lang-actions { opacity: 1; pointer-events: auto; }

/* Detection-method picker — smaller stat-style tiles. */
.detect-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-2);
}
.detect-card {
  --lg-color: var(--brand);
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-1);
  padding: var(--space-3) var(--space-2);
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-md);
  cursor: pointer;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.detect-card:hover { border-color: var(--border-strong); }
.detect-card.is-on {
  border-color: var(--lg-color);
  background: color-mix(in srgb, var(--lg-color) 6%, var(--surface));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--lg-color) 12%, transparent);
}
.detect-card .detect-ico { display: flex; color: var(--muted); }
.detect-card.is-on .detect-ico { color: var(--lg-color); }
.detect-card .detect-name { font-size: var(--fs-xs); font-weight: var(--fw-semi); color: var(--ink-2); }
.detect-card.is-on .detect-name { color: var(--lg-color); }
.detect-card .detect-desc { font-size: 9px; color: var(--muted); line-height: 1.3; }

/* Per-string editor — collapsible sections of English → translation rows. */
.str-section {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
}
.str-section-head {
  display: flex; align-items: center; gap: var(--space-2);
  width: 100%; padding: var(--space-3);
  background: var(--surface);
  border: 0; cursor: pointer; text-align: left; font: inherit;
  transition: background var(--t-fast);
}
.str-section-head:hover { background: var(--surface-2); }
.str-section-head .str-section-ico {
  --lg-color: var(--brand);
  width: 22px; height: 22px; border-radius: var(--r-sm);
  display: grid; place-items: center; flex-shrink: 0;
  color: var(--lg-color);
  background: color-mix(in srgb, var(--lg-color) 12%, transparent);
}
.str-section-head .str-section-name { flex: 1; min-width: 0; font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--ink); }
.str-section-head .str-section-count { font-size: var(--fs-xs); color: var(--muted); }
.str-section-body { background: var(--surface); }
.str-row {
  --lg-color: var(--brand);
  padding: var(--space-2) var(--space-3);
  border-top: 1px solid var(--border);
}
.str-row.is-on { background: color-mix(in srgb, var(--lg-color) 4%, transparent); }
.str-row .str-row-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  margin-bottom: var(--space-1);
}
.str-row .str-row-label {
  display: flex; align-items: center; gap: var(--space-1);
  font-size: var(--fs-xs); font-weight: var(--fw-semi); color: var(--muted);
}
.str-row.is-on .str-row-label { color: var(--lg-color); }
.str-row .str-grid {
  display: grid; grid-template-columns: 1fr 20px 1fr; gap: var(--space-2);
  align-items: center;
}
.str-row .str-en {
  display: flex; align-items: center; min-height: 36px;
  padding: var(--space-2);
  font-size: var(--fs-sm); font-style: italic; color: var(--ink-2);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-sm);
}
.str-row .str-arrow { display: grid; place-items: center; color: var(--muted-2); }

/* =========================================================
   Avatar designer — the widget editor's Avatar tab. An
   enable card, a picker grid of avatar styles (icon, name,
   description, supported-mode pill, Use/Edit hover overlay)
   and a per-engine editor: an icon rail on the left, a panel
   on the right built from segmented controls, selectable
   chips, a gradient slider, accent swatches and an inline
   hex color field. All tints derive from --brand (or a
   per-instance --sw-color on swatches) — no bespoke hex.
   ========================================================= */
/* Enable-avatar card — toggle + label, brand-tinted when on. */
.av-enable {
  display: flex; align-items: center; gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--border); border-radius: var(--r-md);
  background: var(--surface);
  transition: border-color var(--t-fast), background var(--t-fast);
}
.av-enable.is-on {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 6%, var(--surface));
}
.av-enable .av-enable-body { flex: 1; min-width: 0; }
.av-enable .av-enable-title { font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--ink); }
.av-enable .av-enable-sub { font-size: var(--fs-xs); color: var(--muted); margin-top: 1px; }

/* Avatar picker grid. */
.avatar-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--space-3);
}
.avatar-card {
  position: relative;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: var(--space-2);
  padding: var(--space-4) var(--space-2) var(--space-3);
  min-height: 120px;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), background var(--t-fast);
}
.avatar-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.avatar-card.is-on {
  border-color: var(--brand);
  background: color-mix(in srgb, var(--brand) 5%, var(--surface));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 14%, transparent);
}
.avatar-card .av-ico { width: 48px; height: 48px; display: grid; place-items: center; font-size: 32px; }
.avatar-card .av-ico svg { display: block; }
.avatar-card .av-name { font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--ink-2); }
.avatar-card.is-on .av-name { color: var(--brand-deep); }
.avatar-card .av-desc { font-size: 10px; line-height: 1.3; color: var(--muted); }
.avatar-card .av-mode {
  font-size: 9px; font-weight: var(--fw-semi); letter-spacing: .02em;
  padding: 3px 8px; border-radius: 999px; white-space: nowrap;
}
.avatar-card .av-mode.all {
  color: var(--color-success-700);
  background: color-mix(in srgb, var(--color-success-500) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-success-500) 30%, transparent);
}
.avatar-card .av-mode.chat {
  color: var(--color-warning-700);
  background: color-mix(in srgb, var(--color-warning-500) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-warning-500) 32%, transparent);
}
.avatar-card .av-check {
  position: absolute; top: var(--space-2); right: var(--space-2); z-index: 2;
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--brand); color: #fff;
  box-shadow: 0 2px 6px color-mix(in srgb, var(--brand) 40%, transparent);
}
.avatar-card .av-actions {
  position: absolute; inset: 0; z-index: 3;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--space-2); padding: var(--space-2);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast);
}
.avatar-card:hover .av-actions,
.avatar-card:focus-within .av-actions { opacity: 1; pointer-events: auto; }

/* Editor shell — "Customize X" head, icon rail + content panel. */
.av-editor-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r-md);
}
.av-editor-head .av-editor-title {
  display: flex; align-items: center; gap: var(--space-2);
  font-size: var(--fs-sm); font-weight: var(--fw-semi); color: var(--ink-2);
}
.av-editor { display: flex; gap: 0; min-height: 200px; }
.av-rail {
  display: flex; flex-direction: column; gap: 2px;
  padding: 4px; flex-shrink: 0;
  background: var(--surface-2); border-radius: var(--r-lg);
}
.av-rail-btn {
  width: 40px; height: 40px; border-radius: 9px;
  display: grid; place-items: center;
  background: transparent; border: 0; cursor: pointer;
  color: var(--muted); transition: background var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.av-rail-btn:hover:not(.is-on) { background: color-mix(in srgb, var(--surface) 55%, transparent); color: var(--ink-2); }
.av-rail-btn.is-on { background: var(--surface); color: var(--brand); box-shadow: var(--shadow-sm); }
.av-panel { flex: 1; min-width: 0; padding: 4px 0 4px var(--space-4); }
.av-panel-head {
  display: flex; align-items: center; gap: var(--space-2);
  margin-bottom: var(--space-3); padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm); font-weight: var(--fw-bold); color: var(--ink);
}
.av-panel-head::before {
  content: ""; width: 4px; height: 14px; border-radius: 2px;
  background: linear-gradient(180deg, var(--brand), var(--brand-deep));
}

/* Editor fields + tiny uppercase labels. */
.av-field + .av-field { margin-top: var(--space-3); }
.av-field-label {
  display: block; font-size: 10px; font-weight: var(--fw-semi);
  color: var(--muted); margin-bottom: var(--space-2);
  text-transform: uppercase; letter-spacing: .06em;
}

/* Segmented control (≤4 options). */
.seg {
  display: flex; gap: 2px; padding: 3px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-md);
}
.seg-btn {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  white-space: nowrap;
  padding: var(--space-2) var(--space-3);
  font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semi);
  color: var(--muted); background: transparent; border: 0; border-radius: var(--r-sm);
  cursor: pointer; transition: background var(--t-fast), color var(--t-fast), box-shadow var(--t-fast);
}
.seg-btn svg { flex-shrink: 0; }
.seg-btn:hover:not(.is-on) { color: var(--ink-2); }
.seg-btn.is-on { background: var(--surface); color: var(--brand-deep); box-shadow: var(--shadow-sm); }

/* Selectable chips (5+ options, accessories). */
.opt-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.opt-chip {
  padding: 5px 14px; font: inherit; font-size: var(--fs-xs); font-weight: var(--fw-semi);
  color: var(--ink-2); background: var(--surface);
  border: 1px solid var(--border); border-radius: 999px;
  cursor: pointer; white-space: nowrap; transition: background var(--t-fast), border-color var(--t-fast), box-shadow var(--t-fast);
}
.opt-chip:hover:not(.is-on) { background: var(--surface-2); }
.opt-chip.is-on {
  color: var(--brand-deep); background: var(--brand-soft); border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 12%, transparent);
}

/* Gradient range slider with value pill. The fill width comes from an
   inline --av-range-pct (the only per-instance value). */
.av-slider-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-2); }
.av-slider-val {
  font-size: var(--fs-xs); font-weight: var(--fw-bold); color: var(--brand-deep);
  background: var(--brand-soft); padding: 1px 8px; border-radius: 999px;
  min-width: 20px; text-align: center;
}
.av-range {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 6px; border-radius: 3px; cursor: pointer;
  background-color: var(--color-slate-200);
  background-image: linear-gradient(90deg, var(--brand), var(--brand-deep));
  background-repeat: no-repeat;
  background-size: var(--av-range-pct, 50%) 100%;
}
.av-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--brand); box-shadow: var(--shadow-sm); cursor: pointer;
}
.av-range::-moz-range-thumb {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--surface); border: 2px solid var(--brand); box-shadow: var(--shadow-sm); cursor: pointer;
}
.av-range::-moz-range-track { background: transparent; }

/* Accent swatch circles — colour fed via inline --sw-color. */
.swatch-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); }
.swatch {
  --sw-color: var(--brand);
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--sw-color); border: 2px solid transparent; padding: 0;
  cursor: pointer; box-shadow: 0 1px 3px rgba(0,0,0,.12);
  transition: transform var(--t-fast), box-shadow var(--t-fast), width var(--t-fast), height var(--t-fast);
}
.swatch:hover:not(.is-on) { transform: scale(1.1); }
.swatch.is-on { width: 32px; height: 32px; border-color: var(--surface); box-shadow: 0 0 0 2px var(--sw-color); }
.swatch.custom {
  position: relative; display: grid; place-items: center;
  background: var(--surface-2); border: 2px dashed var(--border-strong); color: var(--muted);
}
.swatch.custom input[type="color"] {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; border: 0; padding: 0; cursor: pointer;
}

/* Inline hex colour field — native picker + mono hex toggle. */
.color-field {
  display: inline-flex; align-items: center; gap: var(--space-2);
  padding: 4px 10px 4px 4px; border-radius: var(--r-md);
  border: 1px solid var(--border); background: var(--surface-2);
}
.color-field input[type="color"] {
  width: 30px; height: 30px; border: 0; border-radius: var(--r-sm);
  background: none; padding: 0; cursor: pointer; flex-shrink: 0;
}
.color-field .cf-hex {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  color: var(--muted); background: transparent; border: 0; cursor: pointer;
}
.color-field input.cf-hex {
  width: 72px; border: 1.5px solid var(--brand); border-radius: var(--r-sm);
  padding: 3px 6px; color: var(--ink-2); background: var(--surface); cursor: text;
}
