/* ============================================================
   Bot Dynamics AI — Workspace · "APPLE" theme  (Pass 2)
   ------------------------------------------------------------
   THE SINGLE SOURCE OF TRUTH for the client portal's theme.
   Loaded AFTER app.css (so it is the winning layer); app.css
   provides only structural defaults. DUAL-THEME: refined Apple
   neutral palettes for light AND dark, Apple-system-blue accent,
   SF-system font stack, one coherent type scale, frosted-glass
   surfaces. Gated on html[data-theme="light"|"dark"] (set by the
   ThemeManager). Every surface/glass/hover value is tokenised so
   the toggle truly switches. Markup + JS untouched.

   (Replaces the former Linear theme + retires Pass-1's .ap-dash
   specificity hack and the bd-visual-fix inline block — both
   folded in here so there is no second layer fighting this one.)
   ============================================================ */

/* ---- 1a. SHARED TOKENS (theme-independent) ---- */
:root {
  /* Apple system-blue accent — overridden per-theme below (light/dark) */
  --brand:        #0071e3;
  --brand-hover:  #0077ed;

  /* SF-system font stack (no web font needed — uses the OS San Francisco /
     Segoe / Roboto). --font-display + --font-sans share it; numerals render
     in SF too (KPI values no longer use a monospace face). */
  --font-system:  -apple-system, BlinkMacSystemFont, 'SF Pro Text',
                  'SF Pro Display', 'Segoe UI', Roboto, system-ui, sans-serif;
  --font-sans:    var(--font-system);
  --font-display: var(--font-system);
  --font-mono:    'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Type scale — one coherent Apple-clean ramp */
  --fs-display: 30px;   /* hero greeting, big KPI value */
  --fs-title:   24px;
  --fs-heading: 19px;   /* section / card heads */
  --fs-subhead: 16px;
  --fs-body:    14px;
  --fs-label:   12px;   /* KPI label, table head */
  --fs-meta:    12px;
  --fs-caption: 12px;   /* was 11.5px - half-pixel sizes are an "AI CSS" tell */
  --tracking-tight: -0.022em;

  /* Integer type-scale tokens (design-audit §1.2): one ramp the inline blocks
     and any new markup snap to, so no more 9.5/10.5/11.5/12.5/13.5 one-offs. */
  --fs-2xs: 11px; --fs-xs: 12px; --fs-sm: 13px; --fs-base: 14px;
  --fs-md: 16px; --fs-lg: 18px; --fs-xl: 20px; --fs-2xl: 24px; --fs-3xl: 30px;

  /* One icon-size scale (design-audit §1.4): map the ~10 raw SVG sizes onto 3. */
  --icon-sm: 16px; --icon-md: 20px; --icon-lg: 24px;

  /* Apple radii (slightly softer, continuous-corner feel). NOTE: these
     intentionally override the app.css radius tokens - app.linear.css is the
     winning theme layer, so these 6/10/14/18 values ARE the canonical scale.
     Use the var(), never a raw 8/12/16px, to stay aligned with it (a raw 8px
     is off-by-2 from --radius-md and a raw 12/16 from --radius-lg/xl). */
  --radius-sm: 6px; --radius-md: 10px; --radius-lg: 14px; --radius-xl: 18px;

  /* Aliases for tokens app.css references but never defines — resolve to
     whichever theme is active (var() is evaluated at use time). */
  --bg-card:      var(--bg-elevated);
  --text:         var(--text-primary);
  --text-muted:   var(--text-secondary);
  --border-color: var(--border);
  --brand-strong: var(--brand);

  /* a11y AA: white-text button fill. --brand #0A84FF is only 3.6:1 under
     white; these are theme-independent (white-on-fill) so they live here in
     the base :root and cover BOTH themes. Fill 5.51:1, hover 6.4:1.
     (Regression fix: they were mistakenly scoped to the dark block only,
     which left every light-theme .btn-primary transparent/invisible.) */
  --brand-btn:      #0067cc;
  --brand-btn-hover:#005bbf;
}

/* ---- 1b. DARK palette (Apple neutral) ---- */
html[data-theme="dark"] {
  color-scheme: dark;   /* native <select> option popups, date pickers, scrollbars match the dark theme */
  --bg-page:       #0a0a0b;
  --bg-elevated:   #1c1c1e;
  --bg-subtle:     #242426;
  --bg-hover:      #2c2c2e;

  --text-primary:   #f5f5f7;
  --text-secondary: #a1a1a6;
  --text-tertiary:  #8e8e93; /* a11y AA: was #6e6e73 (3.36:1 on #1c1c1e); now 5.22:1 */
  --text-inverse:   #1d1d1f;

  --border:        rgba(255,255,255,0.12);
  --border-strong: rgba(255,255,255,0.20);

  /* Apple system blue (dark) */
  --brand:      #0A84FF;
  --brand-hover:#409CFF;
  --brand-soft: rgba(10,132,255,0.18);
  --brand-text: #409CFF;

  /* Apple system colours (dark variants) */
  --success: #30d158;  --success-soft: rgba(48,209,88,0.16);
  --warning: #ff9f0a;  --warning-soft: rgba(255,159,10,0.16);
  --danger:  #ff453a;  --danger-soft:  rgba(255,69,58,0.16);

  --shadow-glow: 0 0 0 3px rgba(10,132,255,0.40);

  /* surfaces / chrome */
  --glass-bar:      rgba(20,20,22,0.66);
  --glass-bg:       rgba(28,28,30,0.62);
  --glass-border:   rgba(255,255,255,0.10);
  --glass-blur:     saturate(180%) blur(20px);
  --surface-1:      rgba(255,255,255,0.04);
  --surface-2:      rgba(255,255,255,0.07);
  --hover:          rgba(255,255,255,0.06);
  --highlight:      rgba(255,255,255,0.06);
  --input-bg:       rgba(255,255,255,0.03);
  --scrollbar:      #38383a;
  --scrollbar-hover:#48484a;
  --aurora-1: rgba(10,132,255,0.06);
  --aurora-2: rgba(10,132,255,0.04);

  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.30);
  --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.35), 0 1px 2px -1px rgb(0 0 0 / 0.35);
  --shadow-md: 0 8px 24px -8px rgb(0 0 0 / 0.50), 0 2px 6px -2px rgb(0 0 0 / 0.40);
  --shadow-lg: 0 24px 60px -16px rgb(0 0 0 / 0.60), 0 8px 18px -8px rgb(0 0 0 / 0.45);
}

/* ---- 1c. LIGHT palette (Apple neutral) ---- */
html[data-theme="light"] {
  color-scheme: light;   /* native <select> option popups, date pickers, scrollbars match the light theme */
  --bg-page:       #f5f5f7;
  --bg-elevated:   #ffffff;
  --bg-subtle:     #ececee;
  --bg-hover:      #ededf0;

  --text-primary:   #1d1d1f;
  --text-secondary: #6e6e73;
  --text-tertiary:  #737379; /* a11y AA: was #86868b (3.62:1 on #fff); now 4.71:1, stays below secondary 5.07 */
  --text-inverse:   #ffffff;

  --border:        rgba(0,0,0,0.10);
  --border-strong: rgba(0,0,0,0.16);

  /* Apple system blue (light) */
  --brand:      #0071e3;
  --brand-hover:#0077ed;
  --brand-soft: rgba(0,113,227,0.10);
  --brand-text: #0066cc;          /* link blue, a touch darker for AA on white */

  /* Apple system colours (on-white variants for contrast) */
  --success: #248a3d;  --success-soft: rgba(36,138,61,0.12);
  --warning: #b25000;  --warning-soft: rgba(178,80,0,0.10);
  --danger:  #d70015;  --danger-soft:  rgba(215,0,21,0.09);

  --shadow-glow: 0 0 0 3px rgba(0,113,227,0.28);

  /* surfaces / chrome */
  --glass-bar:      rgba(255,255,255,0.72);
  --glass-bg:       rgba(255,255,255,0.72);
  --glass-border:   rgba(0,0,0,0.08);
  --glass-blur:     saturate(180%) blur(20px);
  --surface-1:      rgba(0,0,0,0.025);
  --surface-2:      rgba(0,0,0,0.05);
  --hover:          rgba(0,0,0,0.04);
  --highlight:      rgba(0,0,0,0.03);
  --input-bg:       #ffffff;
  --scrollbar:      #c7c7cc;
  --scrollbar-hover:#aeaeb2;
  --aurora-1: rgba(0,113,227,0.05);
  --aurora-2: rgba(0,113,227,0.03);

  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.06);
  --shadow-md: 0 8px 24px -8px rgb(0 0 0 / 0.12), 0 2px 6px -2px rgb(0 0 0 / 0.08);
  --shadow-lg: 0 24px 60px -16px rgb(0 0 0 / 0.16), 0 8px 18px -8px rgb(0 0 0 / 0.10);
}

/* ---- 2. BASE / ATMOSPHERE ---- */
html, body {
  background: var(--bg-page);
  color: var(--text-primary);
  font-family: var(--font-sans);
  -webkit-font-smoothing: antialiased;
  letter-spacing: -0.005em;
}
/* Very faint Apple-blue wash behind everything (near-flat; tokens are low-alpha) */
body {
  background:
    radial-gradient(1200px 620px at 15% -10%, var(--aurora-1), transparent 60%),
    radial-gradient(1000px 600px at 100% 0%, var(--aurora-2), transparent 55%),
    var(--bg-page);
  background-attachment: fixed;
}

::selection { background: rgba(0,113,227,0.28); color: #fff; }

/* Thin scrollbars */
* { scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 8px; border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-hover); background-clip: padding-box; }

:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 5px; }

a, .btn-link { color: var(--brand-text); }
a:hover { color: var(--brand-text); text-decoration: underline; }

/* ---- 3. TYPOGRAPHY — Apple-clean: SF system, tight display tracking,
   sentence-case labels (no shouty uppercase), SF numerals (not mono) ---- */
h1, h2, h3, .login-heading, .modal-title, .card-head, .page-title {
  font-family: var(--font-display);
  letter-spacing: var(--tracking-tight);
  font-weight: 600;
}
.badge, .nav-tag, .op-tab-count, .stat-card .label, .stat-card > .label,
.table thead th, .card-head .sub, .login-foot, .kpi-grid .label {
  font-family: var(--font-sans);
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-label);
  font-weight: 590;
}
.stat-card .value, .an-kpi .value, .kpi-grid .value, .op-bd-balance-amt {
  font-family: var(--font-system);   /* SF numerals, not JetBrains Mono */
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  font-weight: 600;
}

/* ---- 4. COMPONENT POLISH ---- */

/* Brand bar — translucent glass */
html[data-theme] .brand-bar, .brand-bar {
  background: var(--glass-bar);
  border-bottom: 1px solid var(--border);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
}
.brand-bar-dot { background: var(--brand) !important; box-shadow: 0 0 12px rgba(0,113,227,0.8); }

/* Login atmosphere — indigo aurora over the page surface */
html[data-theme] .login-screen {
  background:
    radial-gradient(circle at 0% 0%, var(--aurora-1), transparent 42%),
    radial-gradient(circle at 100% 100%, var(--aurora-2), transparent 45%),
    linear-gradient(135deg, var(--bg-page) 0%, var(--bg-elevated) 100%);
}
html[data-theme] .modal-backdrop { background: rgba(5,6,9,0.6); backdrop-filter: blur(4px); }

/* Buttons */
.btn {
  border-radius: var(--radius-md);
  transition: transform 80ms ease, background var(--transition), border-color var(--transition);
}
.btn:active { transform: translateY(0.5px); }
.btn-primary {
  background: var(--brand);
  color: #fff;
  font-weight: 600;
  border: 1px solid var(--brand);
  box-shadow: 0 1px 0 0 rgba(255,255,255,0.10) inset, 0 8px 22px -10px rgba(0,113,227,0.40);
}
.btn-primary:hover { background: var(--brand-hover); border-color: var(--brand-hover); }
.btn-secondary, .btn-ghost {
  background: var(--surface-1);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
}
.btn-secondary:hover, .btn-ghost:hover { background: var(--surface-2); border-color: var(--border-strong); }
.btn-danger { background: var(--danger); color: #fff; border: 1px solid var(--danger); }

/* Cards / panels — surface w/ hairline + faint top highlight */
.card, .stat-card, .login-card, .modal {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  position: relative;
}
/* Apple cards are flat — retire the Linear faint top-highlight line */
.card::before, .stat-card::before, .login-card::before { display: none; }
.card, .stat-card, .login-card { box-shadow: var(--shadow-sm); }
.stat-card { transition: box-shadow var(--transition-slow), transform var(--transition-slow), border-color var(--transition); }
.stat-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-1px); }

/* Inputs */
input, select, textarea, .login-field input {
  background: var(--input-bg);
  border: 1px solid var(--border-strong);
  color: var(--text-primary);
  border-radius: var(--radius-md);
}
input::placeholder, textarea::placeholder { color: var(--text-tertiary); }
input:focus, select:focus, textarea:focus { border-color: var(--brand); box-shadow: var(--shadow-glow); outline: none; }

/* Badges */
.badge { background: var(--surface-1); border: 1px solid var(--border-strong); color: var(--text-secondary); border-radius: var(--radius-sm); }
.badge-success { color: var(--success); border-color: rgba(76,183,130,0.45); background: var(--success-soft); }
.badge-warning { color: var(--warning); border-color: rgba(242,153,74,0.45); background: var(--warning-soft); }
.badge-danger  { color: var(--danger);  border-color: rgba(235,87,87,0.45);  background: var(--danger-soft); }
.badge-brand   { color: var(--brand-text); border-color: rgba(0,113,227,0.45); background: var(--brand-soft); }

/* Sidebar + nav */
.sidebar { background: var(--glass-bar); border-right: 1px solid var(--border); }
.nav-item { color: var(--text-secondary); border-radius: var(--radius-md); position: relative; }
.nav-item:hover { background: var(--hover); color: var(--text-primary); }
.nav-item.active { background: var(--brand-soft); color: var(--brand-text); }
.nav-item.active::before {
  content: ""; position: absolute; left: 0; top: 18%; bottom: 18%; width: 3px;
  background: var(--brand); border-radius: 0 3px 3px 0;
}
.nav-item.active .nav-icon { color: var(--brand-text); }

/* Tables */
.table { border-color: var(--border); }
.table thead th { color: var(--text-tertiary); border-bottom: 1px solid var(--border-strong); background: var(--surface-1); }
.table tbody tr { border-bottom: 1px solid var(--border); }
.table tbody tr:hover { background: var(--hover); }

/* Modal + backdrop */
.modal-backdrop { background: rgba(5,6,9,0.6); backdrop-filter: blur(4px); }
.modal { box-shadow: var(--shadow-lg); }

/* Toasts */
.toast { background: var(--bg-elevated); border: 1px solid var(--border-strong); box-shadow: var(--shadow-lg); }

/* Small hardcoded chips */
.avatar-source.voice { background: var(--warning-soft); color: var(--warning); }
.avatar-source.api   { background: var(--surface-1);  color: var(--text-secondary); }
.kb-doc-icon.kb-fmt-pdf  { background: var(--danger-soft);  color: var(--danger); }
.kb-doc-icon.kb-fmt-json { background: var(--warning-soft); color: var(--warning); }

/* Progress / meter fills → Apple-blue gradient */
.op-bd-progress-fill, .progress-fill, .meter-fill {
  background: linear-gradient(90deg, #0071e3, #0A84FF) !important;
}

@media (prefers-reduced-motion: reduce) { .btn:active { transform: none; } }

/* Contact identifier (phone/handle) */
.conv-cell-contact, .conv-contact { font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
/* The cell holds separate name + identifier spans; stack them (inline they
   render run-together: "Ahmed Yousif971569780904"). */
.conv-cell-contact { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; }
.conv-contact strong, .pill.conv-contact strong { color: var(--brand-text); }

/* ============================================================
   5. STRUCTURAL REDESIGN — new layout (Linear)
   Full-width labelled sidebar → slim ICON RAIL that expands on
   hover. Desktop-only (min-width:901px) so the mobile drawer is
   untouched. All .nav-item[data-route] JS hooks preserved.
   ============================================================ */
@media (min-width: 901px) {
  :root, html[data-theme] { --sidebar-w: 76px; }

  .app-shell { grid-template-columns: 76px 1fr; }

  .sidebar {
    position: fixed;
    top: var(--brandbar-h, 60px);
    left: 0;
    width: 76px;
    height: calc(100vh - var(--brandbar-h, 60px));
    padding: 18px 14px;
    background: var(--glass-bar);
    backdrop-filter: saturate(140%) blur(14px);
    -webkit-backdrop-filter: saturate(140%) blur(14px);
    border-right: 1px solid var(--border);
    overflow: hidden;
    z-index: 60;
    transition: width 180ms cubic-bezier(.4,0,.2,1), box-shadow 180ms ease, border-color 180ms ease;
  }
  .sidebar:hover {
    width: 252px;
    box-shadow: var(--shadow-lg);
    border-right-color: var(--border-strong);
  }

  .sidebar-nav { gap: 4px; }

  .nav-item {
    gap: 14px;
    padding: 11px 12px;
    border-radius: 10px;
    white-space: nowrap;
    overflow: hidden;
  }
  .nav-icon { width: 21px; height: 21px; }
  .nav-label, .nav-tag {
    opacity: 0;
    transform: translateX(-4px);
    transition: opacity 130ms ease, transform 180ms cubic-bezier(.4,0,.2,1);
  }
  .sidebar:hover .nav-label, .sidebar:hover .nav-tag { opacity: 1; transform: none; }

  .nav-item.is-active { background: var(--brand-soft); color: var(--brand-text); font-weight: 600; }
  .nav-item.is-active .nav-icon { color: var(--brand-text); }
  .nav-item.is-active::after {
    content: ""; position: absolute; left: -14px; top: 22%; bottom: 22%;
    width: 3px; background: var(--brand); border-radius: 0 3px 3px 0;
  }

  .sidebar-foot { opacity: 0; transition: opacity 130ms ease; padding-left: 12px; }
  .sidebar:hover .sidebar-foot { opacity: 1; }

  .main {
    max-width: 1120px;
    padding: 44px 60px 96px;
  }

  .page > h1:first-child, .page-title, .page-head h1, h1.page-title {
    font-size: clamp(26px, 2.6vw, 34px);
    letter-spacing: -0.03em;
    font-weight: 600;
    margin-bottom: 4px;
  }

  .card, .stat-card {
    border-radius: 12px;
    background: linear-gradient(180deg, var(--highlight), transparent 40%), var(--bg-elevated);
    transition: border-color 160ms ease, transform 160ms ease;
  }
  .card:hover, .stat-card:hover { transform: translateY(-1px); border-color: var(--border-strong); }

  .brand-bar { backdrop-filter: saturate(150%) blur(16px); }
}

/* ============================================================
   6. COLOR CORRECTIONS (post-audit) — theme-aware via tokens
   ============================================================ */
.kb-status.is-completed { color: var(--success); }
.kb-status.is-error     { color: var(--danger);  }
.kb-status.is-indexing  { color: var(--warning); }

.avatar-source.whatsapp                                  { background: var(--success-soft); color: var(--success); }
.avatar-source.telegram, .kb-doc-icon.kb-fmt-url,
.kb-doc-icon.kb-fmt-gdoc                                 { background: rgba(86,163,255,0.14);  color: #2f7fd6; }
.avatar-source.ig                                        { background: rgba(236,72,153,0.14);  color: #c026a0; }
.avatar-source.widget                                    { background: var(--brand-soft);      color: var(--brand-text); }
.kb-doc-icon.kb-fmt-csv, .kb-doc-icon.kb-fmt-xlsx        { background: var(--success-soft);    color: var(--success); }

/* ============================================================
   7. DEEP-VIEW CONTRAST PASS (post-audit) — theme-aware via tokens
   ============================================================ */
.delta-up, .channel-status.is-connected, .wa-badge-connected,
.wa-reg-pill[data-status="connected"] .wa-reg-pill-label,
.wa-phone-badge[data-status="connected"], .wa-cloud-substate[data-status="connected"],
.meta-result-badge.is-connected, .bl-status-pill.s-active, .bl-amount-pos,
.bl-type-badge.t-topup, .bl-inv-status.s-paid { color: var(--success); }

.delta-down.is-warn, .channel-status.is-coming-soon, .wa-badge-pending,
.wa-reg-pill[data-status="offline"] .wa-reg-pill-label,
.wa-phone-badge[data-status="offline"], .wa-cloud-substate[data-status="offline"],
.tg-badge-pending, .ig-badge-pending, .mg-badge-pending, .tg-pending-card,
.voice-speaker.is-caller, .meta-warnings, .bl-status-pill.s-past_due,
.bl-inv-status.s-open, .impersonation-banner, .impersonation-banner .ib-return { color: var(--warning); }

.delta-down, .xlink-card-error, .meta-result-badge.is-failed,
.bl-status-pill.s-suspended, .bl-lapse-title, .bl-lapse-sub,
.bl-lapse-mini, .bl-lapse-mini-close { color: var(--danger); }

.tg-badge-connected { color: #2f7fd6; }
.ig-badge-connected { color: #c026a0; }
.mg-badge-connected { color: #2f6fe0; }

.settings-warning { background: var(--warning-soft); border-color: rgba(242,153,74,0.40); color: var(--warning); }
.avatar-source.messenger { background: rgba(24,119,242,0.16); color: #2f6fe0; }
.bl-type-badge.t-refund  { background: var(--bg-subtle); color: var(--text-secondary); }
.bl-lapse { background: linear-gradient(135deg, var(--danger-soft) 0%, var(--bg-elevated) 100%); }

.oc-item.is-done .oc-dot { background: var(--success); border-color: var(--success); }
.xlink-checkmark { background: var(--success); }
.bl-progress-fill { background: linear-gradient(90deg, var(--success), #6fd6a3); }

/* ============================================================
   8. CHANNEL APP LOGOS — settings + channels page
   Swap the single-letter chips for the real brand app icons.
   Theme-independent. Scoped to .channel-icon.
   ============================================================ */
.channel-icon.avatar-source.whatsapp,
.channel-icon.avatar-source.telegram,
.channel-icon.avatar-source.ig,
.channel-icon.avatar-source.messenger,
.channel-icon.avatar-source.widget,
.channel-icon.avatar-source.voice,
.channel-icon.avatar-source.api {
  color: transparent !important;
  text-indent: -9999px;
  /* ALL !important: the dark-only rule html[data-theme="dark"] .avatar-source.messenger
     uses a `background:` shorthand that out-specifies us and resets size/position →
     in dark the messenger logo rendered natural-size + top-left (shifted/"moving"). */
  background-color: transparent !important;
  background-repeat: no-repeat !important;
  background-position: center !important;
  background-size: cover !important;
  border: none !important;
  box-shadow: none !important;
}
.channel-icon.avatar-source.whatsapp  { background-image: url("/logos/ch-whatsapp.svg?v=2") !important; }
.channel-icon.avatar-source.telegram  { background-image: url("/logos/ch-telegram.svg?v=2") !important; }
.channel-icon.avatar-source.ig        { background-image: url("/logos/ch-instagram.svg?v=2") !important; }
.channel-icon.avatar-source.messenger { background-image: url("/logos/ch-messenger.svg?v=2") !important; }
.channel-icon.avatar-source.widget    { background-image: url("/logos/ch-widget.svg?v=2") !important; }
.channel-icon.avatar-source.voice     { background-image: url("/logos/ch-voice.svg?v=2") !important; }
.channel-icon.avatar-source.api       { background-image: url("/logos/ch-api.svg?v=2") !important; }

/* ============================================================
   9. THEME-AWARE conversation-list channel chips
   The telegram/ig/messenger avatar chips (NOT the settings logos —
   those are covered by §8) had one fixed brand colour that read a
   bit low-contrast in light mode. Give each a per-theme text colour:
   darker/saturated on light, lighter on dark. (whatsapp/widget/voice/
   api already use theme tokens.) Backgrounds stay translucent (OK both).
   ============================================================ */
html[data-theme="light"] .avatar-source.telegram  { color: #1d6fd6; }
html[data-theme="light"] .avatar-source.ig         { color: #b81d8f; }
html[data-theme="light"] .avatar-source.messenger  { color: #1565d8; }
html[data-theme="dark"]  .avatar-source.telegram   { color: #7ab8ff; }
html[data-theme="dark"]  .avatar-source.ig          { color: #f0abfc; }
html[data-theme="dark"]  .avatar-source.messenger   { color: #93c5fd; }

/* ============================================================
   10. FROSTED GLASS (Apple) — applied where it reads over content
   ------------------------------------------------------------
   Solid fallback first (opaque surface), blur layered only where
   backdrop-filter is supported. NOT blanket — only the slide-over
   detail panel, dropdown menus, and the already-glass brand-bar /
   sidebar rail. var()-driven so both themes switch correctly.
   ============================================================ */

/* Reusable utility (foundation for future surfaces) */
.ap-glass { background: var(--bg-elevated); border: 1px solid var(--glass-border); }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ap-glass {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}

/* Slide-over detail panel (Conversations + Contacts reference page) —
   frosted so the list behind it shows through. Solid fallback. */
.detail-panel { background: var(--bg-elevated); }      /* fallback */
.detail-head  { background: transparent; }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .detail-panel {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}
.detail-backdrop { background: rgb(0 0 0 / 0.18); }

/* Dropdown / command menus — frosted over the page */
.dropdown-menu, .cmdk-wrap {
  background: var(--bg-elevated);                       /* fallback */
  border: 1px solid var(--glass-border);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .dropdown-menu, .cmdk-wrap {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}

/* ============================================================
   11. RETIRED bd-visual-fix — relocated verbatim from the
   app.html inline <style id="bd-visual-fix"> block so the theme
   has ONE source (no inline layer). Covers: voice/conversations
   outcome pills, contacts list + history panel, #voiceDrawer
   under-nav fix, notifications, client insights, the UNIFIED
   PILL SPEC, and insights takeaway/axis labels. Behaviour
   unchanged — same cascade position (last-loaded file).
   ============================================================ */
    /* --- Voice/Conversations outcome pill (B1: centered text, even sizing) --- */
    .vcr-outcome {
      display: inline-flex; align-items: center; justify-content: center;
      padding: 3px 10px; border-radius: 999px;
      font-size: 11px; font-weight: 600; line-height: 1;
      vertical-align: middle; white-space: nowrap;
    }
    /* a11y AA: light-theme pill text darkened to >=4.5:1 over the tinted pill bg
       (was completed 3.24 / transferred 4.30 / abandoned 4.38; now 4.72 / 5.58 / 6.19) */
    .vcr-outcome[data-outcome="completed"]   { background: rgba(16,185,129,.16); color: #047857; }
    .vcr-outcome[data-outcome="transferred"] { background: rgba(59,130,246,.16); color: #1d4ed8; }
    .vcr-outcome[data-outcome="abandoned"]   { background: rgba(245,158,11,.18); color: #92400e; }
    html[data-theme="dark"] .vcr-outcome[data-outcome="completed"]   { color: #34d399; }
    html[data-theme="dark"] .vcr-outcome[data-outcome="transferred"] { color: #60a5fa; }
    html[data-theme="dark"] .vcr-outcome[data-outcome="abandoned"]   { color: #fbbf24; }

    /* --- Contacts list (B2 contrast, B4 icons/layout, B5 even rows) --- */
    .bd-contacts-card {
      background: var(--bg-elevated, #fff);
      border: 1px solid var(--border, #e2e8f0);
      border-radius: 14px; overflow: hidden;
      box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04));
    }
    .bd-contact-row {
      display: grid; grid-template-columns: 38px minmax(0,1fr) auto;
      gap: 12px; align-items: center;
      padding: 11px 16px;
      border-bottom: 1px solid var(--border, #e2e8f0);
      cursor: pointer; transition: background .12s ease;
    }
    .bd-contact-row:last-child { border-bottom: none; }
    .bd-contact-row:hover { background: var(--bg-hover, #f7f8fa); }
    .bd-contact-av {
      width: 38px; height: 38px; border-radius: 50%;
      display: flex; align-items: center; justify-content: center;
      flex-shrink: 0; color: #fff;
    }
    .bd-contact-av svg { width: 19px; height: 19px; display: block; }
    .bd-contact-av.ch-voice    { background: linear-gradient(135deg, var(--brand), var(--brand-hover)); }
    .bd-contact-av.ch-whatsapp { background: #25D366; }
    .bd-contact-av.ch-other    { background: linear-gradient(135deg,#64748b,#94a3b8); }
    .bd-contact-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
    .bd-contact-name {
      font-size: 14px; font-weight: 600; line-height: 1.25;
      color: var(--text-primary, #0f172a);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .bd-contact-sub {
      font-size: 12.5px; line-height: 1.2;
      color: var(--text-secondary, #475569);
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .bd-contact-time {
      font-size: 12px; color: var(--text-tertiary, #94a3b8);
      white-space: nowrap; text-align: right;
    }
    .bd-contacts-empty {
      padding: 30px 18px; text-align: center;
      color: var(--text-tertiary, #94a3b8); font-size: 13px;
    }
    /* History slide-panel list (same theme-aware contrast) */
    .bd-hist-meta { font-size: 12px; color: var(--text-tertiary, #94a3b8); margin-bottom: 10px; }
    .bd-hist-item {
      display: block; width: 100%; text-align: left;
      border: 1px solid var(--border, #e2e8f0); border-radius: 10px;
      padding: 11px 13px; margin-bottom: 9px;
      background: var(--bg-elevated, #fff); color: var(--text-primary, #0f172a);
    }
    .bd-hist-item.is-link { cursor: pointer; }
    .bd-hist-item.is-link:hover { background: var(--bg-hover, #f7f8fa); }
    .bd-hist-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
    .bd-hist-title { font-size: 13px; font-weight: 600; color: var(--text-primary, #0f172a); }
    .bd-hist-when { font-size: 12px; color: var(--text-tertiary, #94a3b8); white-space: nowrap; }
    .bd-hist-sub { font-size: 12px; color: var(--text-secondary, #475569); margin-top: 3px;
                   overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* 2b — Voice page call drawer (#voiceDrawer): app.css ships it as
       `position:fixed; inset:0; z-index:50`, so it sat UNDER the z-100 brand
       bar (inset:0 → top:0) and its header/close were hidden behind the nav.
       Mirror the shared .detail-panel pattern: start the drawer BELOW the
       brand bar and lift it above the bar. The inner backdrop/panel are
       absolute within this wrapper, so they inherit the offset automatically.
       (conversations/contacts already use .detail-panel, which is correct.) */
    #voiceDrawer.voice-drawer { inset: var(--brandbar-h, 64px) 0 0 0; z-index: 170; }

    /* 2a — Voice "Recent Calls" identity cell: name primary, number secondary
       (matches the Contacts row). Number-only when no name is known yet. */
    .vcr-who { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
    .vcr-name { font-weight: 600; color: var(--text-primary, #0f172a);
                overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .vcr-num { font-size: 11.5px; color: var(--text-secondary, #475569);
               overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

    /* ============================================================
       VOICE PAGE (redesign) — phone bar, stat row, calls table, detail
       drawer. Theme-token driven (one --brand accent, converged radii +
       shadows), matching the rest of the client portal. Owner order: the
       Voice Settings card was removed (operator-managed, not client-facing).
       ============================================================ */
    .vp-phone-bar {
      display: flex; align-items: center; justify-content: space-between;
      gap: 16px; flex-wrap: wrap;
      padding: 16px 18px;
      background: var(--bg-elevated, #fff);
      border: 1px solid var(--border, #e2e8f0);
      border-radius: var(--radius-lg, 14px);
      box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04));
    }
    .vp-phone-info { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
    .vp-phone-label { font-size: 12px; font-weight: 600; color: var(--text-secondary, #475569);
                      text-transform: uppercase; letter-spacing: .04em; }
    .vp-phone-number {
      font-size: 22px; font-weight: 700; letter-spacing: .01em;
      font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, monospace;
      color: var(--brand, #0071e3);
    }
    .vp-copy-btn {
      display: inline-flex; align-items: center; gap: 7px;
      background: var(--bg-hover, #f7f8fa);
      border: 1px solid var(--border, #e2e8f0);
      border-radius: var(--radius-md, 10px);
      padding: 8px 13px; font-size: 13px; font-weight: 600;
      color: var(--text-primary, #0f172a); cursor: pointer;
      transition: background .12s ease, border-color .12s ease;
    }
    .vp-copy-btn:hover { background: var(--bg-elevated, #fff); border-color: var(--brand, #0071e3); }
    .vp-copy-btn svg { width: 15px; height: 15px; }

    /* Stat row */
    .vp-stats {
      display: grid;
      grid-template-columns: repeat(6, minmax(0, 1fr));
      gap: 12px;
    }
    @media (max-width: 900px) { .vp-stats { grid-template-columns: repeat(3, minmax(0,1fr)); } }
    @media (max-width: 520px) { .vp-stats { grid-template-columns: repeat(2, minmax(0,1fr)); } }
    .vp-stat {
      display: flex; flex-direction: column; gap: 4px;
      padding: 14px 16px;
      background: var(--bg-elevated, #fff);
      border: 1px solid var(--border, #e2e8f0);
      border-radius: var(--radius-lg, 14px);
      box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04));
    }
    .vp-stat-value {
      font-size: 24px; font-weight: 700; line-height: 1.05;
      color: var(--text-primary, #0f172a); font-variant-numeric: tabular-nums;
    }
    .vp-stat-label { font-size: 12px; color: var(--text-secondary, #475569); line-height: 1.3; }

    /* Calls table card */
    .vp-calls-card {
      background: var(--bg-elevated, #fff);
      border: 1px solid var(--border, #e2e8f0);
      border-radius: var(--radius-lg, 14px);
      box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04));
      overflow: hidden;
    }
    .vp-calls-head {
      display: flex; align-items: center; justify-content: space-between;
      padding: 15px 18px; border-bottom: 1px solid var(--border, #e2e8f0);
    }
    .vp-calls-head h2 { margin: 0; font-size: 14px; font-weight: 600; color: var(--text-primary, #0f172a); }
    .vp-table-wrap { overflow-x: auto; min-width: 0; }
    .vp-table { width: 100%; border-collapse: collapse; font-size: 13px; }
    .vp-table thead th {
      text-align: left; padding: 10px 18px;
      font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em;
      color: var(--text-tertiary, #94a3b8);
      border-bottom: 1px solid var(--border, #e2e8f0);
      white-space: nowrap;
    }
    .vp-table tbody td {
      padding: 12px 18px; border-bottom: 1px solid var(--border, #e2e8f0);
      color: var(--text-primary, #0f172a); vertical-align: middle;
    }
    .vp-table tbody tr:last-child td { border-bottom: none; }
    .vp-row { cursor: pointer; transition: background .12s ease; }
    .vp-row:hover { background: var(--bg-hover, #f7f8fa); }
    .vp-row:focus-visible { outline: 2px solid var(--brand, #0071e3); outline-offset: -2px; }
    .vp-col-when, .vp-col-dur { color: var(--text-secondary, #475569); white-space: nowrap; font-variant-numeric: tabular-nums; }
    .vp-col-dur { text-align: right; }
    .vp-col-media { text-align: center; width: 64px; }
    .vp-outcome-cell { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    .vp-xfer { font-size: 11.5px; color: var(--text-secondary, #475569); }
    .vp-media-icon { display: inline-flex; color: var(--text-tertiary, #94a3b8); }
    .vp-media-icon svg { width: 17px; height: 17px; }
    .vp-row:hover .vp-media-icon { color: var(--brand, #0071e3); }
    .vp-calls-empty { padding: 36px 24px; text-align: center; color: var(--text-secondary, #475569); font-size: 13.5px; }
    .vp-calls-empty[hidden] { display: none; }
    .vp-calls-empty p { margin: 0; max-width: 460px; margin-inline: auto; line-height: 1.5; }
    .vp-table[hidden] { display: none; }

    /* Detail drawer body sections */
    .vp-detail-section { margin-bottom: 18px; }
    .vp-detail-section:last-child { margin-bottom: 0; }
    .vp-detail-h {
      margin: 0 0 8px; font-size: 11.5px; font-weight: 600;
      text-transform: uppercase; letter-spacing: .03em;
      color: var(--text-tertiary, #94a3b8);
    }
    .vp-detail-summary { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--text-primary, #0f172a); }
    .vp-audio { width: 100%; }
    .vp-consent {
      font-size: 12px; padding: 7px 11px; border-radius: var(--radius-md, 10px);
      margin-bottom: 16px;
    }
    .vp-consent-on  { background: var(--success-soft, rgba(16,185,129,.12)); color: var(--success, #248a3d); }
    .vp-consent-off { background: var(--bg-hover, #f7f8fa); color: var(--text-secondary, #475569); }

    /* --- Notifications (#1) — theme-aware, matches the settings cards --- */
    .notif-grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1.3fr);
                  gap: 18px; align-items: start; }
    @media (max-width: 900px) { .notif-grid { grid-template-columns: 1fr; } }
    .notif-card-h { font-size: 14px; font-weight: 600; margin: 0 0 14px;
                    color: var(--text-primary, #0f172a); }
    .notif-field { margin-bottom: 18px; }
    .notif-field-label { display: block; font-size: 12px; font-weight: 600;
                         color: var(--text-secondary, #475569); margin-bottom: 7px; }
    .notif-email-readonly { font-size: 13.5px; color: var(--text-primary, #0f172a);
                            padding: 9px 12px; border-radius: 9px;
                            background: var(--bg-hover, #f7f8fa);
                            border: 1px solid var(--border, #e2e8f0); }
    .notif-hint, .notif-muted { font-size: 11.5px; color: var(--text-tertiary, #94a3b8); }
    .notif-hint { display: block; margin-top: 5px; }
    .notif-toggle-row { display: flex; align-items: center; justify-content: space-between;
                        padding: 9px 0; border-bottom: 1px solid var(--border, #e2e8f0);
                        font-weight: 600; /* label weight; the toggle text inherits */ }
    .notif-toggle-row:last-child { border-bottom: none; }
    .notif-toggle-label { font-size: 13.5px; color: var(--text-primary, #0f172a); }
    .notif-toggle-row input[type="checkbox"] { width: 17px; height: 17px; cursor: pointer; accent-color: var(--brand); }
    .notif-recipients { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 9px; }
    .notif-chip { display: inline-flex; align-items: center; gap: 6px;
                  font-size: 12.5px; color: var(--text-primary, #0f172a);
                  background: var(--bg-hover, #f7f8fa);
                  border: 1px solid var(--border, #e2e8f0);
                  border-radius: 999px; padding: 4px 6px 4px 11px; }
    .notif-chip-x { border: none; background: none; cursor: pointer; font-size: 15px;
                    line-height: 1; color: var(--text-tertiary, #94a3b8); padding: 0 2px; }
    .notif-chip-x:hover { color: var(--danger, #ef4444); }
    .notif-add-row { display: flex; gap: 8px; }
    .notif-add-row .input { flex: 1; min-width: 0; }
    .notif-card { display: flex; align-items: flex-start; gap: 12px;
                  padding: 13px 14px; border-radius: 11px;
                  border: 1px solid var(--border, #e2e8f0);
                  background: var(--bg-elevated, #fff); margin-bottom: 9px; }
    .notif-card.is-unread { border-left: 3px solid var(--brand); background: var(--bg-hover, #f7f8fa); }
    .notif-card-main { min-width: 0; flex: 1; }
    .notif-card-head { display: flex; justify-content: space-between; gap: 10px; align-items: baseline; }
    .notif-card-title { font-size: 13.5px; font-weight: 600; color: var(--text-primary, #0f172a); }
    .notif-card-when { font-size: 11.5px; color: var(--text-tertiary, #94a3b8); white-space: nowrap; }
    .notif-card-body { font-size: 12.5px; color: var(--text-secondary, #475569); margin-top: 4px; }
    .notif-card-caller { font-size: 12.5px; color: var(--text-primary, #0f172a); margin-top: 6px; font-weight: 500; }
    .notif-read-btn { border: 1px solid var(--border, #e2e8f0); background: var(--bg-elevated,#fff);
                      color: var(--text-secondary, #475569); font-size: 11.5px; border-radius: 8px;
                      padding: 5px 9px; cursor: pointer; white-space: nowrap; }
    .notif-read-btn:hover { background: var(--bg-hover, #f7f8fa); }

    /* --- Client Insights — theme-aware, customer-friendly --- */
    .ins-block { margin-bottom: 28px; }
    .ins-h { font-size: 15px; font-weight: 600; color: var(--text-primary, #0f172a); margin: 0 0 14px; }
    .ins-h3 { font-size: 13px; font-weight: 600; color: var(--text-primary, #0f172a); margin: 0 0 8px; }
    .ins-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; }
    .ins-card { padding: 16px 18px; border: 1px solid var(--border, #e2e8f0); border-radius: 14px;
                background: var(--bg-elevated, #fff); box-shadow: var(--shadow-xs, 0 1px 2px rgba(0,0,0,.04)); }
    .ins-card-v { font-size: 22px; font-weight: 700; color: var(--text-primary, #0f172a); line-height: 1.1; }
    .ins-card-l { font-size: 13px; font-weight: 600; color: var(--text-secondary, #475569); margin-top: 6px; }
    .ins-card-s { font-size: 11.5px; color: var(--text-tertiary, #94a3b8); margin-top: 3px; }
    .ins-two { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
    @media (max-width: 820px) { .ins-two { grid-template-columns: 1fr; } }
    .ins-note { font-size: 12px; color: var(--text-tertiary, #94a3b8); margin: 0 0 10px; }
    .ins-table { width: 100%; border-collapse: collapse; font-size: 13px; }
    .ins-table th, .ins-table td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--border, #e2e8f0); }
    .ins-table th:last-child, .ins-table td:last-child { text-align: right; white-space: nowrap; }
    .ins-table th { font-size: 11.5px; font-weight: 600; color: var(--text-secondary, #475569); }
    .ins-table td { color: var(--text-primary, #0f172a); }
    .ins-muted { color: var(--text-tertiary, #94a3b8); }
    /* Trend */
    .ins-trend { display: flex; align-items: flex-end; gap: 22px; flex-wrap: wrap; }
    .ins-trend-now { display: flex; flex-direction: column; }
    .ins-trend-n { font-size: 30px; font-weight: 800; color: var(--text-primary, #0f172a); line-height: 1; }
    .ins-trend-l { font-size: 12.5px; color: var(--text-secondary, #475569); margin-top: 5px; }
    .ins-trend-dir { display: flex; flex-direction: column; font-size: 13.5px; font-weight: 600; padding-bottom: 2px; }
    .ins-trend-dir.ins-up { color: var(--success, #10b981); }
    .ins-trend-dir.ins-down { color: var(--danger, #ef4444); }
    .ins-trend-dir.ins-flat { color: var(--text-tertiary, #94a3b8); }
    .ins-trend-prev { font-size: 11.5px; font-weight: 400; color: var(--text-tertiary, #94a3b8); margin-top: 3px; }
    /* Sparkline */
    .ins-spark-wrap { margin-top: 16px; }
    .ins-spark { display: flex; align-items: flex-end; gap: 2px; height: 46px; }
    .ins-spark-bar { flex: 1; min-width: 2px; background: var(--brand, #6366f1); border-radius: 2px 2px 0 0; opacity: .8; }
    .ins-spark-cap { font-size: 11px; color: var(--text-tertiary, #94a3b8); margin-top: 5px; }
    /* Busiest hours */
    .ins-tz { font-size: 11.5px; font-weight: 400; color: var(--text-tertiary, #94a3b8); }
    .ins-hours { display: flex; align-items: flex-end; gap: 3px; height: 110px; }
    .ins-hour { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
    .ins-hour-bar { width: 100%; background: var(--brand, #6366f1); border-radius: 3px 3px 0 0; opacity: .55; min-height: 2px; }
    .ins-hour-bar.is-peak { opacity: 1; background: linear-gradient(180deg, var(--brand), var(--brand-hover)); }
    .ins-hour-x { font-size: 9.5px; color: var(--text-tertiary, #94a3b8); margin-top: 4px; white-space: nowrap; height: 12px; }

    /* === UNIFIED PILL SPEC === one box shape for every status/badge/chip pill
       across the client app (they varied page-to-page: padding 1px-10px,
       font 10-13px, radius 8-999px). This unifies SIZE/PADDING/SHAPE only —
       per-state COLORS are set elsewhere and untouched. Pill-local font-size
       (not a body/heading change; the global type pass is deferred). Applied
       from this override layer because app.js/app.html is the change scope. */
    .vcr-outcome, .vcr-status, .badge, .delta, .chip, .pill, .conv-count,
    .latency-chip, .nav-tag, .notif-chip, .kb-status, .channel-status,
    .wa-badge, .wa-phone-badge, .bl-status-pill {
      padding: 4px 11px !important;
      font-size: 11.5px !important;
      line-height: 1.4 !important;
      border-radius: 999px !important;
      height: auto !important;
      min-height: 0 !important;
      display: inline-flex !important;
      align-items: center !important;
      justify-content: center !important;
      vertical-align: middle;
      box-sizing: border-box;
    }
    /* notif-chip keeps a little less right padding for its × remove button */
    .notif-chip { padding-right: 6px !important; gap: 6px; }

    /* Insights: data-driven takeaway line (the readable, computed insight that
       replaces the removed decorative captions) + chart axis labels. */
    .ins-takeaway { font-size: 13.5px; color: var(--text-primary, #0f172a);
                    font-weight: 500; margin: 0 0 14px; line-height: 1.45; }
    .ins-axis { font-size: 11px; color: var(--text-tertiary, #94a3b8); margin-top: 6px; }
    .ins-axis-y { font-size: 11px; color: var(--text-tertiary, #94a3b8); margin-bottom: 4px; }

    /* === Insights v2 — period selector, channel bars, heatmap, chips,
       sentiment trend, knowledge-gap list, empty states. Theme-aware (uses the
       shared tokens); plain-language, no money anywhere. === */
    .ins-empty { font-size: 13px; color: var(--text-secondary, #475569);
                 background: var(--bg-elevated, #fff); border: 1px dashed var(--border, #e2e8f0);
                 border-radius: 12px; padding: 16px 18px; line-height: 1.5; }

    /* Period selector */
    .ins-period { display: flex; gap: 8px; margin: 0 0 22px; flex-wrap: wrap; }
    .ins-period-btn { font-size: 12.5px; font-weight: 600; color: var(--text-secondary, #475569);
                      background: var(--bg-elevated, #fff); border: 1px solid var(--border, #e2e8f0);
                      border-radius: 999px; padding: 6px 14px; cursor: pointer;
                      transition: background .15s, border-color .15s, color .15s; }
    .ins-period-btn:hover { background: var(--hover, #f7f8fa); }
    .ins-period-btn.is-active { background: var(--brand, #0071e3); border-color: var(--brand, #0071e3);
                                color: #fff; }

    /* Channel comparison bars */
    .ins-chan { display: flex; flex-direction: column; gap: 12px; }
    .ins-chan-row { display: grid; grid-template-columns: 130px 1fr auto; align-items: center; gap: 12px; }
    .ins-chan-name { font-size: 13px; font-weight: 600; color: var(--text-primary, #0f172a); }
    .ins-chan-track { height: 12px; background: var(--hover, #f1f5f9); border-radius: 999px; overflow: hidden; }
    .ins-chan-fill { height: 100%; background: var(--brand, #0071e3); border-radius: 999px; min-width: 2px; }
    .ins-chan-n { font-size: 12.5px; font-weight: 600; color: var(--text-primary, #0f172a); white-space: nowrap; }
    .ins-chan-speed { font-size: 11px; font-weight: 400; color: var(--text-tertiary, #94a3b8); margin-left: 6px; }
    @media (max-width: 560px) { .ins-chan-row { grid-template-columns: 96px 1fr auto; gap: 8px; } }

    /* Busy-times heatmap (7 rows x 24 cols, plus a label column + header row) */
    .ins-hm-scroll { overflow-x: auto; padding-bottom: 4px; }
    .ins-hm { display: grid; grid-template-columns: 34px repeat(24, 1fr);
              gap: 3px; min-width: 520px; align-items: center; }
    .ins-hm-corner { }
    .ins-hm-col { font-size: 9.5px; color: var(--text-tertiary, #94a3b8); text-align: center; height: 14px; }
    .ins-hm-row { font-size: 10.5px; color: var(--text-secondary, #475569); font-weight: 600; }
    .ins-hm-cell { width: 100%; aspect-ratio: 1 / 1; border-radius: 3px; background: var(--hover, #f1f5f9); }
    .ins-hm-l0 { background: var(--hover, #eef2f6); }
    .ins-hm-l1 { background: color-mix(in srgb, var(--brand, #0071e3) 22%, transparent); }
    .ins-hm-l2 { background: color-mix(in srgb, var(--brand, #0071e3) 44%, transparent); }
    .ins-hm-l3 { background: color-mix(in srgb, var(--brand, #0071e3) 70%, transparent); }
    .ins-hm-l4 { background: var(--brand, #0071e3); }
    .ins-hm-legend { display: flex; align-items: center; gap: 5px; margin-top: 12px;
                     font-size: 11px; color: var(--text-tertiary, #94a3b8); }
    .ins-hm-legend .ins-hm-cell { width: 14px; height: 14px; aspect-ratio: auto; }

    /* Topic chips */
    .ins-chips { display: flex; flex-wrap: wrap; gap: 9px; }
    .ins-chip { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; font-weight: 500;
                color: var(--text-primary, #0f172a); background: var(--bg-elevated, #fff);
                border: 1px solid var(--border, #e2e8f0); border-radius: 999px; padding: 6px 12px; }
    .ins-chip.is-big { background: var(--brand-soft, rgba(0,113,227,0.10)); border-color: transparent;
                       font-weight: 600; }
    .ins-chip-n { font-size: 11px; font-weight: 700; color: var(--text-secondary, #475569);
                  background: var(--hover, #f1f5f9); border-radius: 999px; padding: 1px 7px; }

    /* Sentiment trend (baseline split: positive up, negative down) */
    .ins-sent { display: flex; align-items: stretch; gap: 3px; height: 96px;
                border-top: 1px solid var(--border, #e2e8f0); border-bottom: 1px solid var(--border, #e2e8f0);
                position: relative; }
    .ins-sent::before { content: ""; position: absolute; left: 0; right: 0; top: 50%;
                        border-top: 1px dashed var(--border, #e2e8f0); }
    .ins-sent-col { flex: 1; min-width: 3px; display: flex; flex-direction: column; height: 100%;
                    justify-content: center; }
    .ins-sent-bar { width: 100%; border-radius: 2px; }
    .ins-sent-bar.is-pos { background: var(--success, #30d158); }
    .ins-sent-bar.is-neg { background: var(--danger, #ff453a); }
    .ins-sent-axis { display: flex; justify-content: space-between; margin-top: 6px;
                     font-size: 10.5px; color: var(--text-tertiary, #94a3b8); }

    /* Knowledge-gap list */
    .ins-gaps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
    .ins-gap { display: flex; align-items: center; justify-content: space-between; gap: 12px;
               background: var(--bg-elevated, #fff); border: 1px solid var(--border, #e2e8f0);
               border-radius: 12px; padding: 12px 14px; }
    .ins-gap-q { font-size: 13px; color: var(--text-primary, #0f172a); line-height: 1.4; }
    .ins-gap-n { font-size: 11.5px; font-weight: 600; color: var(--text-tertiary, #94a3b8); white-space: nowrap; }
    .ins-gap-hint { font-size: 12px; color: var(--text-tertiary, #94a3b8); margin: 12px 0 0; line-height: 1.5; }

/* ============================================================
   12. DASHBOARD — per-page Apple polish (Pass 3)
   ------------------------------------------------------------
   Scoped to [data-page="dashboard"] so ONLY the landing page gets
   the roomy treatment; every other page keeps the shared component
   styles. APPLIES the locked Pass-2 tokens (accent / SF type scale /
   radii / shadows) with proper Apple spacing + hierarchy — no token
   value is redefined here.
   ============================================================ */

/* Hero — large clean SF greeting with generous room below */
[data-page="dashboard"] .hero {
  margin: 4px 0 36px;
  align-items: center;
}
[data-page="dashboard"] .hero-text h1 {
  font-size: clamp(30px, 3vw, 40px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--text-primary);
}

/* KPI grid — roomy, equal-height cards, steady gap */
[data-page="dashboard"] .kpi-grid {
  gap: 20px;
  margin-bottom: 48px;
}
[data-page="dashboard"] .stat-card {
  display: flex;
  flex-direction: column;
  min-width: 0;              /* let KPI cards shrink inside the grid on mobile */
  padding: 24px 24px 22px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: var(--bg-elevated);          /* flat Apple card (no gradient) */
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-slow),
              transform var(--transition-slow),
              border-color var(--transition);
}
[data-page="dashboard"] .stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}
/* Label quiet (sentence case, secondary); value prominent (SF tabular) */
[data-page="dashboard"] .stat-card .label {
  margin: 0 0 10px;
  font-size: var(--fs-label);
  font-weight: 590;
  letter-spacing: 0;
  text-transform: none;
  color: var(--text-secondary);
}
[data-page="dashboard"] .stat-card .value-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0;
}
[data-page="dashboard"] .stat-card .value {
  font-size: clamp(30px, 2.4vw, 36px);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
/* The delta chip sits quietly beside the number */
[data-page="dashboard"] .stat-card .delta { font-size: var(--fs-caption); }
/* Card 1 keeps its sparkline; the other three carry an EMPTY spark-wrap —
   collapse it so they aren't padded by a reserved 32px gap. Grid stretch
   keeps all four equal height. */
[data-page="dashboard"] .stat-card .spark-wrap { margin-top: 18px; }
[data-page="dashboard"] .stat-card .spark-wrap:empty { display: none; }

/* Section rhythm — clear heading, comfortable separation */
[data-page="dashboard"] .section { margin-top: 8px; }
[data-page="dashboard"] .section-head { margin-bottom: 16px; }
[data-page="dashboard"] .section-head h2 {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
}

/* Recent activity — clean roomy card, comfortable rows */
[data-page="dashboard"] .activity-list {
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
[data-page="dashboard"] .activity-row {
  padding: 16px 20px;
  gap: 16px;
  align-items: center;
  transition: background var(--transition);
}
[data-page="dashboard"] .activity-preview {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-primary);
}
[data-page="dashboard"] .activity-sub,
[data-page="dashboard"] .activity-time {
  font-size: var(--fs-caption);
  color: var(--text-tertiary);
}

/* Onboarding checklist (shown only for brand-new tenants) — give it room */
[data-page="dashboard"] .onboarding-checklist { margin-bottom: 40px; }

/* ============================================================
   13–21. PER-PAGE APPLE POLISH (Pass 4 — final)
   ------------------------------------------------------------
   Each block is [data-page="…"]-scoped (header components are
   shared only by in-scope pages — Conversations/Contacts use
   .conv-head, Dashboard uses .hero, so none leak there). Applies
   the LOCKED tokens with the Dashboard bar: roomy spacing, SF
   type hierarchy, refined cards (radius-lg + soft shadow +
   hairline + gentle hover), accent restraint. No token redefined.
   Glass only on the voice slide-over (reads over content), with
   an @supports solid fallback.
   ============================================================ */

/* ---- 13. SHARED PAGE HEADER (in-scope pages only) ---- */
.settings-head, .an-head, .kb-head { margin-bottom: 28px; }
.settings-head-text h1, .an-head-text h1, .kb-head-text h1 {
  font-size: clamp(24px, 2.4vw, 32px);
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.1;
  color: var(--text-primary);
}
.an-head-text p, .kb-head-text p {
  font-size: var(--fs-subhead);
  color: var(--text-secondary);
  margin-top: 4px;
}

/* ---- 14. ANALYTICS ---- */
[data-page="analytics"] .an-filters { margin-bottom: 24px; }
[data-page="analytics"] .an-kpi-strip { gap: 16px; margin-bottom: 32px; }
[data-page="analytics"] .an-kpi {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-slow), transform var(--transition-slow), border-color var(--transition);
}
[data-page="analytics"] .an-kpi:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}
[data-page="analytics"] .an-kpi .label {     /* quiet sentence-case label */
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-label);
  font-weight: 590;
  color: var(--text-secondary);
}
[data-page="analytics"] .an-kpi .value { font-weight: 600; }
[data-page="analytics"] .an-chart-grid,
[data-page="analytics"] .an-bottom-grid { gap: 20px; }
[data-page="analytics"] .an-chart-grid { margin-bottom: 20px; }
[data-page="analytics"] .chart-card {
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-slow), border-color var(--transition);
}
[data-page="analytics"] .chart-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }
[data-page="analytics"] .chart-title {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin-bottom: 16px;
}

/* ---- 15. BILLING ---- */
[data-page="billing"] .billing-top-grid { gap: 20px; margin-bottom: 20px; }
[data-page="billing"] .billing-card {
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-slow), transform var(--transition-slow), border-color var(--transition);
}
[data-page="billing"] .billing-top-grid .billing-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
  border-color: var(--border-strong);
}
[data-page="billing"] .billing-section { margin-top: 20px; }
[data-page="billing"] .bl-card-title {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}
[data-page="billing"] .bl-credit-amount {
  font-size: clamp(28px, 2.4vw, 34px);
  font-weight: 600;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
[data-page="billing"] .bl-table th {
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-label);
  font-weight: 590;
  color: var(--text-tertiary);
  padding: 10px 12px;
}
[data-page="billing"] .bl-table td { padding: 12px; border-bottom: 1px solid var(--border); }
[data-page="billing"] .bl-table tbody tr:hover td { background: var(--hover); }

/* ---- 16. VOICE ----
   The page body (phone bar, stat row, calls table) is themed inline in §11
   under the VOICE PAGE block (.vp-*). Only the transcript slide-over rules
   live here. */
[data-page="voice"] .voice-drawer-head h3 {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}
/* Voice transcript slide-over — frosted over the voice page (solid fallback) */
[data-page="voice"] .voice-drawer-panel { background: var(--bg-elevated); }
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  [data-page="voice"] .voice-drawer-panel {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}

/* ---- 17. INSIGHTS (ins-* already themed in §11 — rhythm pass) ---- */
[data-page="insights"] .ins-block { margin-bottom: 32px; }
[data-page="insights"] .ins-h {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
  margin-bottom: 16px;
}
[data-page="insights"] .ins-card {
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
[data-page="insights"] .ins-card-v { font-weight: 600; letter-spacing: -0.02em; }
[data-page="insights"] .ins-cards { gap: 16px; }

/* ---- 18. CHANNELS (re-mounted settings channels card + warning banner) ---- */
[data-page="channels"] .settings-card { box-shadow: var(--shadow-sm); }
[data-page="channels"] .settings-grid { gap: 20px; }
[data-page="channels"] .channel-row { transition: background var(--transition); }
[data-page="channels"] .settings-warning {
  border-radius: var(--radius-md);
  padding: 14px 16px;
}

/* ---- 19. SETTINGS ---- */
[data-page="settings"] .settings-grid { gap: 20px; }
[data-page="settings"] .settings-card {
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-slow), border-color var(--transition);
}
[data-page="settings"] .settings-card:hover { box-shadow: var(--shadow-md); border-color: var(--border-strong); }
[data-page="settings"] .settings-card h3 {     /* quiet sentence-case section label */
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--fs-heading);
  font-weight: 600;
  color: var(--text-primary);
}

/* ---- 20. KNOWLEDGE BASE ---- */
[data-page="knowledge-base"] .kb-layout { gap: 20px; }
[data-page="knowledge-base"] .kb-upload-card,
[data-page="knowledge-base"] .kb-docs-card { box-shadow: var(--shadow-sm); }
[data-page="knowledge-base"] .kb-card-title {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}
[data-page="knowledge-base"] .kb-doc-row {
  padding: 14px 16px;
  border-bottom: 1px solid var(--border);
  transition: background var(--transition);
}
[data-page="knowledge-base"] .kb-doc-row:hover { background: var(--hover); }
[data-page="knowledge-base"] .kb-doc-name { font-weight: 500; color: var(--text-primary); }
[data-page="knowledge-base"] .kb-doc-sub,
[data-page="knowledge-base"] .kb-doc-size { font-size: var(--fs-caption); color: var(--text-tertiary); }

/* ---- 21. NOTIFICATIONS (notif-* already themed in §11 — rhythm pass) ---- */
[data-page="notifications"] .notif-grid { gap: 20px; }
[data-page="notifications"] .settings-card { box-shadow: var(--shadow-sm); }
[data-page="notifications"] .notif-card-h {
  font-size: var(--fs-heading);
  font-weight: 600;
  letter-spacing: var(--tracking-tight);
}


/* =====================================================================
   RESTYLE PASS — appended (client). Everything ABOVE is the original
   overlay, untouched. Inherits design-system.md. CSS-only, additive.
   ===================================================================== */
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/hanken-grotesk-latin-ext-400.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/hanken-grotesk-latin-400.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/hanken-grotesk-latin-ext-500.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/hanken-grotesk-latin-500.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/hanken-grotesk-latin-ext-600.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/hanken-grotesk-latin-600.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/hanken-grotesk-latin-ext-700.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/hanken-grotesk-latin-700.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:800;font-display:swap;src:url(fonts/hanken-grotesk-latin-ext-800.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'Hanken Grotesk';font-style:normal;font-weight:800;font-display:swap;src:url(fonts/hanken-grotesk-latin-800.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/jetbrains-mono-latin-ext-400.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/jetbrains-mono-latin-400.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/jetbrains-mono-latin-ext-500.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/jetbrains-mono-latin-500.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/jetbrains-mono-latin-ext-600.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/jetbrains-mono-latin-600.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/jetbrains-mono-latin-ext-700.woff2) format('woff2');unicode-range:U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/jetbrains-mono-latin-700.woff2) format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Noto Sans';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/noto-sans-cyrillic-400.woff2) format('woff2');unicode-range:U+0400-04FF, U+2116;}
@font-face{font-family:'Noto Sans';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/noto-sans-cyrillic-500.woff2) format('woff2');unicode-range:U+0400-04FF, U+2116;}
@font-face{font-family:'Noto Sans';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/noto-sans-cyrillic-600.woff2) format('woff2');unicode-range:U+0400-04FF, U+2116;}
@font-face{font-family:'Noto Sans';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/noto-sans-cyrillic-700.woff2) format('woff2');unicode-range:U+0400-04FF, U+2116;}
@font-face{font-family:'Noto Sans Georgian';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/noto-sans-georgian-400.woff2) format('woff2');unicode-range:U+0589, U+10A0-10FF, U+1C90-1CBF;}
@font-face{font-family:'Noto Sans Georgian';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/noto-sans-georgian-500.woff2) format('woff2');unicode-range:U+0589, U+10A0-10FF, U+1C90-1CBF;}
@font-face{font-family:'Noto Sans Georgian';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/noto-sans-georgian-600.woff2) format('woff2');unicode-range:U+0589, U+10A0-10FF, U+1C90-1CBF;}
@font-face{font-family:'Noto Sans Georgian';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/noto-sans-georgian-700.woff2) format('woff2');unicode-range:U+0589, U+10A0-10FF, U+1C90-1CBF;}
@font-face{font-family:'Noto Sans Arabic';font-style:normal;font-weight:400;font-display:swap;src:url(fonts/noto-sans-arabic-400.woff2) format('woff2');unicode-range:U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;}
@font-face{font-family:'Noto Sans Arabic';font-style:normal;font-weight:500;font-display:swap;src:url(fonts/noto-sans-arabic-500.woff2) format('woff2');unicode-range:U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;}
@font-face{font-family:'Noto Sans Arabic';font-style:normal;font-weight:600;font-display:swap;src:url(fonts/noto-sans-arabic-600.woff2) format('woff2');unicode-range:U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;}
@font-face{font-family:'Noto Sans Arabic';font-style:normal;font-weight:700;font-display:swap;src:url(fonts/noto-sans-arabic-700.woff2) format('woff2');unicode-range:U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF;}

/* ============================================================
   RESTYLE PASS · TOKEN CONTRACT (client)  — appended, additive.
   Inherits design-system.md verbatim. The Apple light/dark
   palette already lives above in app.linear.css; here we (a) bind
   the self-hosted multilingual font stack, (b) add the density /
   control / channel / leading tokens the restyle rules use.
   Existing variable NAMES are preserved; nothing above is removed.
   ============================================================ */
:root{
  /* self-hosted, multilingual (Latin Hanken · RU/KA/AR Noto · code JBM) */
  --font-system:'Hanken Grotesk','Noto Sans','Noto Sans Georgian','Noto Sans Arabic',system-ui,-apple-system,'Segoe UI',sans-serif;
  --font-sans:var(--font-system);
  --font-display:var(--font-system);
  --font-mono:'JetBrains Mono',ui-monospace,'SF Mono',Menlo,monospace;

  /* large KPI numerals — on the scale, not magic numbers */
  --fs-kpi:32px; --fs-kpi-sm:22px;

  /* per-script leading (KA/AR get more; bound to [lang] the app already sets) */
  --lh-tight:1.3; --lh-body:1.5; --lh-relaxed:1.6;

  /* data density — one spec for every table (design-system.md §4) */
  --row-h:40px; --row-h-compact:34px;
  --cell-pad-y:9px; --cell-pad-x:12px;

  /* dedicated control tokens (skill: don't reuse surface tokens for controls) */
  --ctrl-bg:var(--input-bg); --ctrl-border:var(--border-strong);
  --focus-ring:0 0 0 2px var(--bg-page),0 0 0 4px var(--brand);

  /* channel identity — one source (today re-declared ~3x) */
  --ch-whatsapp:#25D366; --ch-telegram:#229ED9; --ch-instagram:#E1306C;
  --ch-messenger:#0084FF; --ch-voice:#8b5cf6; --ch-widget:var(--brand);
}
:lang(ka),:lang(ar){ --lh-tight:1.45; --lh-body:1.62; }
/* ============================================================
   RESTYLE PASS · PARTIAL 10 — CLIENT APP SHELL + SHARED PRIMITIVES
   ============================================================
   Targets:  app-shell, sidebar / nav, brandbar, buttons, inputs,
             badges/pills/chips, cards, modals, detail-panel,
             dropdown-menu, toasts, avatars, skeletons, focus ring,
             RTL base layer.
   Contract: additive only, tokens only (no raw hex/px for themed
             values), one accent (--brand), no JS/HTML/existing-CSS edits.
   Load order: app.css → app.linear.css → 00-app-tokens.css → THIS
   ============================================================ */

/* ============================================================
   § GLOBAL — focus ring (one, visible, AA per design-system.md §6)
   ============================================================ */

/* Canonical 2px brand ring — already in app.linear.css:191 but
   we re-assert to ensure it wins over any UA reset.              */
:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: 5px;
}

/* ============================================================
   § BASE — body / html canonical font + smoothing
   ============================================================ */

html, body {
  font-family: var(--font-sans);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
:lang(ka), :lang(ar) {
  --lh-tight: 1.45;
  --lh-body:  1.62;
}

/* ============================================================
   § APP SHELL — layout wrapper
   ============================================================ */

/* Shell sits below the sticky brandbar; grid already defined in
   app.css. We ensure bg-page is the canvas and no extra seam
   shows between sidebar and main.                               */
.app-shell {
  background: var(--bg-page);
  min-height: calc(100vh - var(--brandbar-h, 64px));
}

/* ============================================================
   § BRANDBAR — glass top-chrome
   ============================================================ */

/* Design: same-hue translucent glass; border separates cleanly. */
.brand-bar {
  background: var(--glass-bar);
  border-bottom: 1px solid var(--border);
  backdrop-filter: saturate(140%) blur(12px);
  -webkit-backdrop-filter: saturate(140%) blur(12px);
}

/* Brand dot: brand color + faint aura (signature touch) */
.brand-bar-dot {
  background: var(--brand);
  box-shadow: 0 0 0 4px var(--brand-soft);
}

/* Workspace type badge in brand bar — slightly smaller */
.brand-bar-workspace .badge {
  font-size: var(--fs-2xs, 11px);
  letter-spacing: 0.04em;
}

/* ============================================================
   § SIDEBAR — nav rail (icon-only, expands on hover)
   ============================================================ */

/* Sidebar uses same-hue glass as the canvas — NOT a different
   surface. A hairline border does the structural work.          */
.sidebar {
  background: var(--glass-bar);
  border-right: 1px solid var(--border);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
}

/* Nav group labels — micro uppercase mono labels */
.nav-group-label {
  font-size: var(--fs-2xs, 11px);
  font-family: var(--font-mono);
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  padding: 0 var(--space-3, 12px);
  margin-bottom: 2px;
}

/* Nav items — all states */
.nav-item {
  display: flex;
  align-items: center;
  gap: var(--space-3, 12px);
  padding: 9px 12px;
  border-radius: var(--radius-md, 10px);
  font-size: var(--fs-body, 14px);
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: none;
  cursor: pointer;
  transition:
    background var(--transition, 150ms),
    color var(--transition, 150ms);
  white-space: nowrap;
  overflow: hidden;
  position: relative;
  width: 100%;
  text-align: start;
}

.nav-item:hover {
  background: var(--hover, rgba(0,0,0,.04));
  color: var(--text-primary);
}

/* Active: brand-soft fill + left accent bar (2px brand) */
.nav-item.is-active {
  background: var(--brand-soft);
  color: var(--brand-text, var(--brand));
  font-weight: 600;
}
.nav-item.is-active .nav-icon {
  color: var(--brand-text, var(--brand));
}
/* Left accent bar — only on desktop expanded rail */
@media (min-width: 901px) {
  .nav-item.is-active::after {
    content: "";
    position: absolute;
    inset-inline-start: -14px;   /* logical: respects RTL */
    top: 22%; bottom: 22%;
    width: 3px;
    background: var(--brand);
    border-radius: 0 3px 3px 0;
  }
  [dir="rtl"] .nav-item.is-active::after {
    border-radius: 3px 0 0 3px;
  }
}

.nav-item:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* Disabled nav */
.nav-item.is-disabled {
  color: var(--text-tertiary);
  cursor: not-allowed;
}
.nav-item.is-disabled:hover { background: transparent; }

/* Nav icon — size + color reset */
.nav-icon {
  width: 20px; height: 20px;
  flex-shrink: 0;
  color: var(--text-tertiary);
  transition: color var(--transition, 150ms);
}
.nav-item:hover .nav-icon { color: var(--text-secondary); }

/* Sidebar footer — thin divider + muted meta */
.sidebar-foot {
  border-top: 1px solid var(--border);
  padding-top: var(--space-3, 12px);
  font-size: var(--fs-2xs, 11px);
  color: var(--text-tertiary);
  padding-inline-start: 12px;   /* logical property */
}

/* ============================================================
   § BUTTONS — height 32 (sm 28), weight 600, radius --radius-md
   ============================================================ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2, 8px);
  height: 32px;
  padding: 0 14px;
  font-family: var(--font-sans);
  font-size: var(--fs-body, 14px);
  font-weight: 600;
  line-height: 1;
  border-radius: var(--radius-md, 10px);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  transition:
    background var(--transition, 150ms),
    border-color var(--transition, 150ms),
    box-shadow var(--transition, 150ms),
    transform 80ms ease;
}
.btn:active      { transform: translateY(0.5px); }
.btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
}

/* -- btn-primary: brand fill --  */
.btn-primary {
  background: var(--brand-btn, #0067cc);
  color: #fff;
  border-color: var(--brand-btn, #0067cc);
  /* Subtle inset highlight (Apple-style top gloss) */
  box-shadow:
    0 1px 0 0 rgba(255,255,255,.10) inset,
    0 8px 22px -10px rgba(0,113,227,.40);
}
.btn-primary:hover { background: var(--brand-btn-hover, #005bbf); border-color: var(--brand-btn-hover, #005bbf); }

/* form-error is display:flex, which beats the UA [hidden]{display:none} at
   cascade time — without this guard every pre-error .form-error paints its
   ::before red dot while "hidden" (11 call sites: login, pwd, contacts,
   channel creds, bookings). */
.form-error[hidden] { display: none; }

/* -- btn-secondary: bg-elevated + strong border --  */
.btn-secondary {
  background: var(--bg-elevated);
  color: var(--text-primary);
  border-color: var(--border-strong);
  box-shadow: var(--shadow-xs, 0 1px 2px 0 rgb(0 0 0/.05));
}
.btn-secondary:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
}

/* -- btn-ghost: transparent + text-secondary --  */
.btn-ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
}
.btn-ghost:hover {
  background: var(--surface-1, rgba(0,0,0,.025));
  border-color: var(--border);
  color: var(--text-primary);
}

/* -- btn-danger: danger fill --  */
.btn-danger {
  background: var(--danger);
  color: #fff;
  border-color: var(--danger);
}
.btn-danger:hover {
  filter: brightness(0.92);
}

/* -- btn-sm: height 28, smaller padding --  */
.btn-sm {
  height: 28px !important;   /* override app.css padding-only .btn-sm */
  padding: 0 11px !important;
  font-size: var(--fs-sm, 13px);
}

/* -- btn-icon: square, icon only.
   app.css sets 36×36; proof spec = 32 for consistency with btn height.
   Keep 32 here so it aligns on the same row as regular buttons.        */
.btn-icon {
  width: 32px; height: 32px;
  padding: 0;
}
.btn-icon svg { width: var(--icon-md, 18px); height: var(--icon-md, 18px); }

/* -- btn-block: full width --  */
.btn-block { width: 100%; }

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .btn:active { transform: none; }
}

/* ============================================================
   § INPUTS — ctrl-bg + 1px border + radius-md
   ============================================================ */

/* Base .input element (class used on <input>, <select> via JS) */
.input {
  width: 100%;
  height: 34px;
  padding: 0 11px;
  font-family: var(--font-sans);
  font-size: var(--fs-body, 14px);
  color: var(--text-primary);
  background: var(--ctrl-bg, var(--input-bg));
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  transition:
    border-color var(--transition, 150ms),
    box-shadow var(--transition, 150ms);
  -webkit-appearance: none;
  appearance: none;
}
.input::placeholder    { color: var(--text-tertiary); }
.input:hover           { border-color: var(--border-strong); }
.input:focus,
.input:focus-visible   {
  border-color: var(--brand);
  box-shadow: var(--shadow-glow, 0 0 0 3px rgba(0,113,227,.28));
  outline: none;
}
.input.has-error       { border-color: var(--danger); }
.input.has-error:focus { box-shadow: 0 0 0 3px rgba(215,0,21,.16); }
.input.input-sm        { height: 28px; font-size: var(--fs-sm, 13px); padding: 0 9px; }
.input.input-mono,
.input-mono            { font-family: var(--font-mono); letter-spacing: 0; }

/* Native <input>/<select>/<textarea> (non-class form elements) */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]),
select,
textarea {
  background: var(--ctrl-bg, var(--input-bg));
  border: 1px solid var(--border);
  border-radius: var(--radius-md, 10px);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-body, 14px);
  transition: border-color var(--transition, 150ms), box-shadow var(--transition, 150ms);
}
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"])::placeholder,
textarea::placeholder { color: var(--text-tertiary); }
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="color"]):focus,
select:focus,
textarea:focus {
  border-color: var(--brand);
  box-shadow: var(--shadow-glow, 0 0 0 3px rgba(0,113,227,.28));
  outline: none;
}

/* Native <select> option popup — force a solid, theme-matched surface so the
   OS popup never renders our light --text-primary on a system-default white
   background (the "text and background are the same colour" bug in Settings).
   color-scheme on the theme roots fixes most engines; this covers the ones
   that style the option list directly (e.g. Chromium on Windows). */
select option,
select optgroup {
  background-color: var(--bg-elevated);
  color: var(--text-primary);
}

/* Textarea: no horizontal resize; uses lh-body */
textarea {
  line-height: var(--lh-body, 1.5);
  resize: vertical;
}

/* .label  */
.label {
  display: block;
  font-size: var(--fs-label, 12px);
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: 5px;
  line-height: var(--lh-tight, 1.3);
}

/* ============================================================
   § BADGES / PILLS / CHIPS
   ============================================================ */

/* .badge — fs-2xs, radius-full, semantic soft-bg + solid text
   (base neutral; variants override bg+color)                   */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  font-size: var(--fs-2xs, 11px);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-radius: var(--radius-full, 9999px);
  line-height: 1;
  background: var(--surface-1, rgba(0,0,0,.025));
  color: var(--text-secondary);
  border: 1px solid var(--border-strong);
  white-space: nowrap;
}
.badge-brand   { background: var(--brand-soft);   color: var(--brand-text, var(--brand));  border-color: rgba(0,113,227,.30); }
.badge-success { background: var(--success-soft); color: var(--success);                   border-color: rgba(36,138,61,.30); }
.badge-warning { background: var(--warning-soft); color: var(--warning);                   border-color: rgba(178,80,0,.30); }
.badge-danger  { background: var(--danger-soft);  color: var(--danger);                    border-color: rgba(215,0,21,.25); }

/* Dark theme badge border-color adjustments for semantic clarity */
html[data-theme="dark"] .badge-success { border-color: rgba(48,209,88,.28); }
html[data-theme="dark"] .badge-warning { border-color: rgba(255,159,10,.28); }
html[data-theme="dark"] .badge-danger  { border-color: rgba(255,69,58,.28); }
html[data-theme="dark"] .badge-brand   { border-color: rgba(10,132,255,.30); }

/* .pill — used in detail-panel, conversation pills (softer than badge) */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  font-size: var(--fs-2xs, 11px);
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--surface-1, rgba(0,0,0,.025));
  border-radius: var(--radius-full, 9999px);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.pill strong {
  font-weight: 600;
  color: var(--text-primary);
}

/* .chip — filter / segmented control chips */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  font-size: var(--fs-label, 12px);
  font-weight: 500;
  color: var(--text-secondary);
  background: var(--surface-1, rgba(0,0,0,.025));
  border: 1px solid var(--border);
  border-radius: var(--radius-full, 9999px);
  cursor: pointer;
  white-space: nowrap;
  transition:
    background var(--transition, 150ms),
    border-color var(--transition, 150ms),
    color var(--transition, 150ms);
  user-select: none;
}
.chip:hover {
  background: var(--bg-hover);
  border-color: var(--border-strong);
  color: var(--text-primary);
}
.chip.is-active {
  background: var(--brand-soft);
  border-color: var(--brand);
  color: var(--brand-text, var(--brand));
  font-weight: 600;
}
.chip:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ============================================================
   § CARDS — bg-elevated + 1px border + shadow-sm + radius-lg
   ============================================================ */

.card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-sm);
  position: relative;
}
/* Disable the old gradient highlight trick on linear (Apple = flat) */
.card::before { display: none; }

.card-body { padding: var(--space-5, 20px) var(--space-6, 24px); }

.card-head {
  padding: var(--space-4, 16px) var(--space-6, 24px);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3, 12px);
}
.card-head h3 {
  font-size: var(--fs-body, 14px);
  font-weight: 600;
  margin: 0;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight, -0.022em);
}

/* Hover lift — very subtle (density 7 = restrained elevation) */
.card:hover {
  border-color: var(--border-strong);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  transition:
    border-color var(--transition, 150ms),
    transform var(--transition, 150ms),
    box-shadow var(--transition, 150ms);
}

/* Stat card — KPI surface */
.stat-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-sm);
  padding: var(--space-6, 24px);
  position: relative;
  overflow: hidden;
  transition:
    box-shadow var(--transition, 150ms),
    border-color var(--transition, 150ms),
    transform var(--transition, 150ms);
}
.stat-card::before { display: none; }  /* retire gradient highlight */
.stat-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}

/* KPI labels — small, mono-ish uppercase (design-system §4) */
.stat-card .label {
  font-size: var(--fs-label, 12px);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 var(--space-3, 12px);
}
/* KPI value — large, tabular */
.stat-card .value {
  font-size: var(--fs-kpi);
  font-weight: 700;
  line-height: 1.1;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight, -0.022em);
  font-variant-numeric: tabular-nums;
}
.stat-card .sub {
  font-size: var(--fs-label, 12px);
  color: var(--text-tertiary);
  margin-top: 2px;
}

/* Chart card — frame only; canvas NOT styled */
.chart-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

/* ============================================================
   § OVERLAYS — modals, detail-panel, dropdown, toast
   ============================================================ */

/* Modal backdrop */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(5, 6, 9, 0.60);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: var(--space-8, 32px) var(--space-4, 16px) var(--space-4, 16px);
  z-index: 200;
}
.modal-backdrop[hidden] { display: none; }

/* Modal panel */
.modal {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg, 14px);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - var(--space-8, 32px) * 2);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.modal.modal-sm { max-width: 420px; }
.modal.modal-md { max-width: 520px; }

.modal-head {
  flex: none;
  padding: var(--space-5, 20px) var(--space-6, 24px) var(--space-4, 16px);
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3, 12px);
}
.modal-head h3 {
  font-size: var(--fs-subhead, 16px);
  font-weight: 600;
  color: var(--text-primary);
  margin: 0;
  letter-spacing: var(--tracking-tight, -0.022em);
}

.modal-body {
  flex: 1 1 auto;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--space-5, 20px) var(--space-6, 24px);
}

.modal-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-2, 8px);
  padding: var(--space-4, 16px) var(--space-6, 24px);
  border-top: 1px solid var(--border);
  flex: none;
}

/* Detail panel (slide-over) */
.detail-panel {
  background: var(--bg-elevated);
  border-inline-start: 1px solid var(--border);   /* logical: flips in RTL */
  box-shadow: var(--shadow-lg);
}
/* Frosted glass enhancement where supported */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .detail-panel {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}
.detail-head  { background: transparent; }

/* Dropdown menu */
.dropdown-menu {
  background: var(--bg-elevated);
  border: 1px solid var(--glass-border, var(--border));
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow-md);
  padding: var(--space-1, 4px);
}
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .dropdown-menu {
    background: var(--glass-bg);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
  }
}

.dropdown-item {
  display: flex;
  align-items: center;
  gap: var(--space-3, 12px);
  padding: 8px 12px;
  font-size: var(--fs-sm, 13px);
  color: var(--text-primary);
  border-radius: var(--radius-sm, 6px);
  cursor: pointer;
  width: 100%;
  text-align: start;
  background: transparent;
  border: none;
  transition: background var(--transition, 150ms);
}
.dropdown-item:hover      { background: var(--hover, rgba(0,0,0,.04)); }
.dropdown-item.danger     { color: var(--danger); }
.dropdown-item.danger:hover { background: var(--danger-soft); }
.dropdown-item:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: var(--radius-sm, 6px); }

/* Toast */
.toast {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3, 12px);
  padding: 12px 14px;
  background: var(--bg-elevated);
  border: 1px solid var(--border-strong);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius-md, 10px);
  box-shadow: var(--shadow-lg);
  font-size: var(--fs-sm, 13px);
  color: var(--text-primary);
  max-width: 360px;
}
.toast.success { border-left-color: var(--success); }
.toast.error   { border-left-color: var(--danger); }
.toast.info    { border-left-color: var(--brand); }
.toast .toast-icon { flex-shrink: 0; width: 18px; height: 18px; margin-top: 1px; }
.toast.success .toast-icon { color: var(--success); }
.toast.error   .toast-icon { color: var(--danger); }
.toast.info    .toast-icon { color: var(--brand); }

/* ============================================================
   § AVATARS — .avatar + .avatar-source channel chips
   ============================================================ */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--radius-full, 9999px);
  background: var(--brand);
  color: #fff;
  font-size: var(--fs-sm, 13px);
  font-weight: 600;
  line-height: 1;
  flex-shrink: 0;
  user-select: none;
  border: none;
  cursor: default;
}
.avatar-lg { width: 40px; height: 40px; font-size: var(--fs-md, 16px); }

/* Channel source chips — mapped to --ch-* tokens */
/* Base: brand soft */
.avatar-source {
  background: var(--brand-soft);
  color: var(--brand-text, var(--brand));
}
/* Per-channel color using token-based backgrounds */
.avatar-source.whatsapp  { background: var(--success-soft);            color: var(--success); }
.avatar-source.telegram  { background: rgba(34, 158, 217, 0.14);       color: var(--ch-telegram, #229ED9); }
.avatar-source.ig,
.avatar-source.instagram { background: rgba(225, 48, 108, 0.13);       color: var(--ch-instagram, #E1306C); }
.avatar-source.messenger { background: rgba(0, 132, 255, 0.13);        color: var(--ch-messenger, #0084FF); }
.avatar-source.voice     { background: rgba(139,92,246,.15);             color: var(--ch-voice); }
.avatar-source.widget    { background: var(--brand-soft);              color: var(--brand-text, var(--brand)); }
.avatar-source.api       { background: var(--surface-1, rgba(0,0,0,.025)); color: var(--text-secondary); }

/* Theme-aware channel text contrast (higher saturation on light, softer on dark) */
html[data-theme="light"] .avatar-source.telegram  { color: #1d6fd6; }
html[data-theme="light"] .avatar-source.ig,
html[data-theme="light"] .avatar-source.instagram { color: #b81d8f; }
html[data-theme="light"] .avatar-source.messenger { color: #1565d8; }
html[data-theme="dark"]  .avatar-source.telegram  { color: #7ab8ff; }
html[data-theme="dark"]  .avatar-source.ig,
html[data-theme="dark"]  .avatar-source.instagram { color: #f0abfc; }
html[data-theme="dark"]  .avatar-source.messenger { color: #93c5fd; }

/* ============================================================
   § SKELETONS — shimmer loading placeholders
   ============================================================ */

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

.skeleton {
  background: linear-gradient(
    90deg,
    var(--bg-subtle) 0%,
    var(--bg-hover)  45%,
    var(--bg-subtle) 100%
  );
  background-size: 200% 100%;
  animation: bd-shimmer 1.6s ease-in-out infinite;
  border-radius: var(--radius-sm, 6px);
  display: inline-block;
}
.skeleton-line       { height: 12px; width: 100%; }
.skeleton-line.sm    { height: 10px; }
.skeleton-line.lg    { height: 18px; }
.skeleton-avatar     { width: 32px; height: 32px; border-radius: var(--radius-full, 9999px); }

/* Skeleton reduced-motion: static low-opacity instead of shimmer */
@media (prefers-reduced-motion: reduce) {
  .skeleton { animation: none; opacity: 0.5; }
}

/* ============================================================
   § RTL BASE LAYER — dir="rtl" (Arabic)
   Additive only; no markup changes. Uses logical properties.
   App already sets dir="rtl" on <html> for AR.
   ============================================================ */

/* Sidebar moves to the right */
[dir="rtl"] .sidebar {
  border-inline-start: none;
  border-inline-end: 1px solid var(--border);
  inset-inline-start: auto;
  inset-inline-end: 0;
}

[dir="rtl"] .app-shell {
  grid-template-areas: "main sidebar";
}

/* Nav items — text aligns to RTL */
[dir="rtl"] .nav-item {
  text-align: end;
}

/* Chevrons/back arrows in nav — mirror */
[dir="rtl"] .nav-arrow,
[dir="rtl"] .back-arrow {
  transform: scaleX(-1);
}

/* Sidebar footer indent flips */
[dir="rtl"] .sidebar-foot {
  padding-inline-start: 0;
  padding-inline-end: 12px;
}

/* Detail panel slides in from the left in RTL */
[dir="rtl"] .detail-panel {
  right: auto;
  left: 0;
  border-left: none;
  border-right: 1px solid var(--border);
  transform: translateX(-100%);
}
[dir="rtl"] .detail-panel.is-open {
  transform: translateX(0);
}

/* Dropdown menu opens to the left in RTL */
[dir="rtl"] .dropdown-menu {
  right: auto;
  left: 0;
}

/* Toast container: bottom-left in RTL */
[dir="rtl"] .toast-container {
  right: auto;
  left: var(--space-6, 24px);
}

/* Inline logical properties — padding/margin use the start/end model
   throughout, so most flip automatically. Explicit LTR leftovers: */
[dir="rtl"] .modal-actions {
  justify-content: flex-start;   /* mirror action row */
}
/* ============================================================
   RESTYLE PASS · PARTIAL 30 — Forms / Inbox / Conversation / Boards
   Client portal (app.) surfaces only.
   Reads: 00-app-tokens.css → app.css → app.linear.css → THIS.
   Rule: tokens only, additive, no raw hex/px for themed values.
   DO NOT redefine .btn*, .input*, .badge*, .card, .modal*.
   ============================================================ */

/* ----
   1. UNIFIED FIELD WRAPPER
   Reconciles .login-field, .wa-field, .bd-camp-field, .bd-auto-field,
   .bk-form-row children (label+control), .settings-field label side.
   Visual spec only — layout comes from app.css / each inline block.
   ---- */

/* label: consistent secondary weight, label size, bottom gap */
.login-field > label,
.login-field > .label,
.wa-field > .label,
.bd-camp-field > label,
.bd-auto-field > span,
.bd-auto-msg-row > label,
.bk-form-row > div > label {
  display: block;
  font-size: var(--fs-label);
  font-weight: 500;
  color: var(--text-secondary);
  margin-bottom: var(--space-2);
  line-height: var(--lh-tight);
}

/* Login is the one form where the field label is the row's main text -
   Username / Password read as proper labels. */
.login-field > .label { font-weight: 600; }

/* help / hint text below the control */
.wa-help,
.bd-camp-hint,
.bk-svc-hint,
.bd-auto-hint {
  font-size: var(--fs-label);
  color: var(--text-tertiary);
  line-height: var(--lh-body);
  margin-top: var(--space-1);
}

/* field spacing */
.login-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: 0;         /* gap comes from the parent form */
}

.wa-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.bd-camp-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}

.bd-auto-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}

/* .bk-form-row is already a 2-col grid; children keep flex-col structure */
.bk-form-row > div {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

/* inputs inside field wrappers — inset feel (slightly darker than surface) */
.login-field .input,
.wa-field .input,
.bd-camp-field .input,
.bd-camp-field select,
.bd-camp-field textarea,
.bd-auto-field input[type="text"],
.bd-auto-field select,
.bd-auto-msg-row textarea,
.bk-form-row .input,
.bk-form-row textarea {
  background: var(--input-bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  transition: border-color 150ms, box-shadow 150ms;
}

.login-field .input:focus-visible,
.wa-field .input:focus-visible,
.bd-camp-field .input:focus-visible,
.bd-camp-field select:focus-visible,
.bd-camp-field textarea:focus-visible,
.bd-auto-field input[type="text"]:focus-visible,
.bd-auto-field select:focus-visible,
.bd-auto-msg-row textarea:focus-visible,
.bk-form-row .input:focus-visible,
.bk-form-row textarea:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-color: var(--brand);
}

/* --- settings-field rows (key / val display pairs in settings-card) --- */
.settings-field {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--cell-pad-y) 0;
  border-bottom: 1px solid var(--border);
  gap: var(--space-4);
}

.settings-field:last-child { border-bottom: none; }

.settings-field .key {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

.settings-field .val {
  font-size: var(--fs-body);
  color: var(--text-primary);
  text-align: end;
  word-break: break-word;
  max-width: 60%;
}

.settings-field .val.mono {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  letter-spacing: 0.02em;
}

/* --- settings-card (the card wrapper) --- */
.settings-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-sm);
}

.settings-card > h3 {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-family: var(--font-mono);
  margin: 0 0 var(--space-4) 0;
}

/* ----
   2. CHANNELS — .channel-row + .chcard-* (grid-card variant)
   ---- */

/* Channels page: card grid */
[data-page="channels"] #channels-body .channel-row {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  transition: border-color 150ms, box-shadow 150ms;
}

[data-page="channels"] #channels-body .channel-row:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

/* Connected state — subtle brand tint left bar */
[data-page="channels"] #channels-body .channel-row:has(.wa-badge-connected),
[data-page="channels"] #channels-body .channel-row:has(.tg-badge-connected),
[data-page="channels"] #channels-body .channel-row:has(.ig-badge-connected),
[data-page="channels"] #channels-body .channel-row:has(.mg-badge-connected),
[data-page="channels"] #channels-body .channel-row:has(.channel-status.is-connected) {
  border-color: var(--brand-soft);
  box-shadow: inset 3px 0 0 var(--brand), var(--shadow-sm);
}

/* chcard sub-elements */
[data-page="channels"] #channels-body .chcard-top {
  padding: var(--space-5) var(--space-5) var(--space-3);
}

[data-page="channels"] #channels-body .chcard-body {
  padding: 0 var(--space-5) var(--space-3);
}

[data-page="channels"] #channels-body .chcard-pitch {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

[data-page="channels"] #channels-body .chcard-id-value {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  color: var(--text-primary);
}

[data-page="channels"] #channels-body .chcard-id-sub {
  font-size: var(--fs-label);
  color: var(--text-secondary);
}

[data-page="channels"] #channels-body .chcard-foot {
  padding: var(--space-3) var(--space-5) var(--space-4);
  border-top: 1px solid var(--border);
  background: var(--bg-subtle);
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}

/* Muted state for disabled channels (IG/MG) */
[data-page="channels"] #channels-body .channel-row[data-channel="instagram"],
[data-page="channels"] #channels-body .channel-row[data-channel="messenger"] {
  opacity: 0.55;
  pointer-events: none;
}

/* Settings page: inline row list */
[data-page="settings"] #settings-body .channel-row {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-4);
  margin-bottom: var(--space-3);
  transition: background 150ms;
}

[data-page="settings"] #settings-body .channel-row:last-child {
  margin-bottom: 0;
}

/* ----
   3. AI TOGGLE (.bd-ai-toggle)
   ---- */

.bd-ai-toggle {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) 0;
  cursor: pointer;
  user-select: none;
}

.bd-ai-toggle input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.bd-ai-toggle-name {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--text-primary);
  line-height: var(--lh-tight);
}

/* Track */
.bd-ai-toggle-mark {
  flex: 0 0 30px;
  width: 30px;
  height: 17px;
  border-radius: var(--radius-full);
  background: var(--border-strong);
  position: relative;
  transition: background 150ms;
}

/* Thumb */
.bd-ai-toggle-mark::after {
  content: "";
  position: absolute;
  top: 2px;
  inset-inline-start: 2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--text-inverse, #fff);
  box-shadow: var(--shadow-xs);
  transition: transform 150ms;
}

.bd-ai-toggle input:checked + .bd-ai-toggle-mark {
  background: var(--brand);
}

.bd-ai-toggle input:checked + .bd-ai-toggle-mark::after {
  transform: translateX(13px);
}

.bd-ai-toggle:has(input:disabled) {
  cursor: not-allowed;
  opacity: 0.55;
}

/* State label */
.bd-ai-toggle-state {
  font-size: var(--fs-2xs);
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* AI badge chips on inbox rows — map to semantic tokens */
.bd-inbox-aibadge {
  display: inline-block;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 2px 7px;
  border-radius: var(--radius-full);
  line-height: 1.5;
}

.bd-inbox-aibadge.is-active {
  background: var(--success-soft);
  color: var(--success);
}

.bd-inbox-aibadge.is-paused {
  background: var(--warning-soft);
  color: var(--warning);
}

.bd-inbox-aibadge.is-off {
  background: var(--bg-subtle);
  color: var(--text-secondary);
}

/* ----
   4. INBOX LIST (.bd-inbox-layout / .bd-inbox-list / .bd-inbox-row)
   ---- */

.bd-inbox-layout {
  display: grid;
  grid-template-columns: 360px minmax(0, 1fr);
  gap: var(--space-4);
  align-items: stretch;
}

@media (max-width: 900px) {
  .bd-inbox-layout { grid-template-columns: 1fr; }
}

/* Contact list panel */
.bd-inbox-list {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

/* Individual contact row */
.bd-inbox-row {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 100ms;
}

.bd-inbox-row:last-child { border-bottom: none; }

.bd-inbox-row:hover {
  background: var(--bg-hover);
}

.bd-inbox-row.is-active {
  background: var(--brand-soft);
  box-shadow: inset 2px 0 0 0 var(--brand);
}

/* Name line */
.bd-inbox-row-name {
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}

.bd-inbox-row.is-unread .bd-inbox-row-name {
  font-weight: 700;
}

/* Timestamp */
.bd-inbox-row-time {
  font-size: var(--fs-2xs);
  color: var(--text-tertiary);
  flex: none;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

/* Preview snippet */
.bd-inbox-row-preview {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: 2px;
  line-height: var(--lh-tight);
}

.bd-inbox-row.is-unread .bd-inbox-row-preview {
  color: var(--text-primary);
  font-weight: 500;
}

/* Unread dot */
.bd-inbox-unread-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand);
  margin-top: 5px;
}

/* Topic chips on rows */
.bd-inbox-topic-chip {
  display: inline-block;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 2px 6px;
  border-radius: var(--radius-full);
  background: var(--brand-soft);
  color: var(--brand-text);
  line-height: 1.5;
}

/* Channel badge icon on row */
.bd-inbox-chbadge {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: var(--radius-md);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

/* ----
   5. CONVERSATION PANE (.bd-inbox-pane / .bd-inbox-thread)
   ---- */

.bd-inbox-pane {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

/* Thread header */
.bd-inbox-thread-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-4) var(--space-5);
  border-bottom: 1px solid var(--border);
  background: var(--bg-subtle);
  flex-shrink: 0;
}

.bd-inbox-thread-name {
  font-size: var(--fs-body);
  font-weight: 650;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bd-inbox-thread-sub {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Paused note banner */
.bd-inbox-paused-note {
  padding: var(--space-2) var(--space-4);
  font-size: var(--fs-label);
  background: var(--warning-soft);
  color: var(--warning);
  border-bottom: 1px solid var(--border);
  line-height: var(--lh-body);
}

.bd-inbox-paused-note.is-channel-off {
  background: var(--bg-subtle);
  color: var(--text-secondary);
}

/* Messages scroll area */
.bd-inbox-messages {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* ----
   6. CHAT BUBBLES (.bd-inbox-msg)
   Surface tokens: inbound = bg-subtle, outbound = brand-soft (design-system §8)
   RTL: logical properties mirror sides automatically.
   ---- */

.bd-inbox-msg {
  max-width: 70%;
  display: flex;
  flex-direction: column;
}

.bd-inbox-msg.is-in {
  align-self: flex-start;
  align-items: flex-start;
}

.bd-inbox-msg.is-out {
  align-self: flex-end;
  align-items: flex-end;
}

/* RTL: inbound on the right, outbound on the left */
[dir="rtl"] .bd-inbox-msg.is-in { align-self: flex-end; align-items: flex-end; }
[dir="rtl"] .bd-inbox-msg.is-out { align-self: flex-start; align-items: flex-start; }

.bd-inbox-msg-bubble {
  padding: 10px 14px;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  border-radius: var(--radius-lg);
  word-break: break-word;
}

/* Inbound (customer) — surface-level bg */
.bd-inbox-msg.is-in .bd-inbox-msg-bubble {
  background: var(--bg-subtle);
  color: var(--text-primary);
  border-end-start-radius: 4px;    /* logical: corners "point" to sender */
}

/* Outbound (staff/agent) — brand tint */
.bd-inbox-msg.is-out .bd-inbox-msg-bubble {
  background: var(--brand-soft);
  color: var(--text-primary);
  border-end-end-radius: 4px;
}

/* Agent (AI auto-reply) — success tint, distinct from staff */
.bd-inbox-msg.is-agent .bd-inbox-msg-bubble {
  background: var(--success-soft);
  color: var(--text-primary);
  border-end-start-radius: 4px;
}

.bd-inbox-msg-bubble p {
  margin: 0 0 6px;
}

.bd-inbox-msg-bubble p:last-child {
  margin-bottom: 0;
}

.bd-inbox-msg-meta {
  font-size: var(--fs-2xs);
  color: var(--text-tertiary);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

/* ----
   7. REPLY BOX + TEXTAREA
   ---- */

.bd-inbox-replybox {
  display: flex;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border);
  background: var(--bg-elevated);
  flex-shrink: 0;
}

.bd-inbox-textarea {
  flex: 1;
  resize: none;
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  background: var(--input-bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  padding: 8px var(--space-3);
  line-height: var(--lh-body);
  transition: border-color 150ms, box-shadow 150ms;
}

.bd-inbox-textarea:focus {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-color: var(--brand);
}

.bd-inbox-textarea::placeholder {
  color: var(--text-tertiary);
}

/* ----
   8. ASSIGN SELECT
   ---- */

.bd-inbox-assign-select {
  height: 30px;
  padding: 2px var(--space-2);
  font-size: var(--fs-label);
  background: var(--input-bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-family: var(--font-sans);
  cursor: pointer;
}

.bd-inbox-assign-select:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

.bd-inbox-assignee {
  display: inline-block;
  margin-top: 4px;
  margin-inline-start: 6px;
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--brand-text);
}

.bd-inbox-assignee.is-unassigned {
  background: var(--bg-subtle);
  color: var(--text-secondary);
  padding: 2px 7px;
  border-radius: var(--radius-full);
}

/* ----
   9. INBOX NOTES (.bd-inbox2-notes) + CANNED REPLIES (.bd-inbox2-canned-list)
   ---- */

.bd-inbox2-notes {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  background: var(--bg-elevated);
}

.bd-inbox2-internal-tag {
  display: inline-block;
  font-size: var(--fs-2xs);
  font-weight: 700;
  padding: 2px 7px;
  border-radius: var(--radius-full);
  background: var(--warning-soft);
  color: var(--warning);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.bd-inbox2-note {
  background: var(--warning-soft);
  border: 1px dashed var(--warning);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-3);
  opacity: 0.85;
}

.bd-inbox2-note-meta {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.bd-inbox2-note-body {
  font-size: var(--fs-sm);
  color: var(--text-primary);
  line-height: var(--lh-body);
  margin-top: 3px;
}

/* Canned replies list */
.bd-inbox2-canned-list {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
}

.bd-inbox2-canned-row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  padding: 9px var(--space-3);
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 100ms;
}

.bd-inbox2-canned-row:last-child { border-bottom: none; }

.bd-inbox2-canned-row:hover {
  background: var(--bg-hover);
}

.bd-inbox2-canned-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bd-inbox2-canned-body {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ----
   10. CONVERSATION DRAWER (#conv-panel / .detail-panel interior)
   Only touching the interior — structure/positioning handled by app.css.
   ---- */

.detail-panel {
  background: var(--bg-elevated);
  border-inline-start: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
}

.detail-head {
  background: var(--bg-subtle);
  border-bottom: 1px solid var(--border);
  padding: var(--space-5) var(--space-6) var(--space-4);
}

.detail-head-title {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-family: var(--font-mono);
}

.detail-head-id {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  color: var(--text-tertiary);
  /* Phone/ID header: force LTR + isolate so a space-grouped number like
     "+995 514 07 77 66" can never be bidi-reordered into "66 77 07 514 995+". */
  direction: ltr;
  unicode-bidi: isolate;
  text-align: left;
}

/* Pills in drawer header */
.detail-head-pills .pill {
  font-size: var(--fs-2xs);
  font-weight: 500;
  padding: 3px 10px;
  border-radius: var(--radius-full);
  background: var(--bg-subtle);
  color: var(--text-secondary);
}

.detail-head-pills .pill strong {
  font-weight: 600;
  color: var(--text-primary);
}

/* Detail body sections */
.detail-body {
  padding: var(--space-5) var(--space-6);
}

/* section sub-heads inside drawer */
.detail-section-head {
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-family: var(--font-mono);
  margin-bottom: var(--space-2);
}

/* Sentiment / risk chips (semantic colors) */
.sentiment-chip,
.risk-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  line-height: 1.5;
}

/* positive / negative / neutral sentiment variants */
.sentiment-chip.positive  { background: var(--success-soft); color: var(--success); }
.sentiment-chip.negative  { background: var(--danger-soft);  color: var(--danger); }
.sentiment-chip.neutral   { background: var(--bg-subtle);    color: var(--text-secondary); }

/* risk chips */
.risk-chip.high    { background: var(--danger-soft);  color: var(--danger); }
.risk-chip.medium  { background: var(--warning-soft); color: var(--warning); }
.risk-chip.low     { background: var(--success-soft); color: var(--success); }

/* ----
   11. BOOKINGS — .bk-card / .bk-pill / .bk-stats
   ---- */

/* Stat summary bar */
.bk-stats { display: flex; gap: var(--space-3); margin: var(--space-2) 0 var(--space-4); flex-wrap: wrap; }

.bk-stat {
  flex: 1;
  min-width: 120px;
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  box-shadow: var(--shadow-xs);
}

.bk-stat .n {
  font-size: var(--fs-kpi-sm);
  font-weight: 800;
  line-height: 1;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
}

.bk-stat .l {
  font-size: var(--fs-label);
  color: var(--text-tertiary);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-family: var(--font-mono);
  margin-top: 5px;
}

/* Semantic tint for KPI numbers */
.bk-stat.pending .n   { color: var(--warning); }
.bk-stat.confirmed .n { color: var(--success); }

/* Booking card */
.bk-card {
  display: flex;
  gap: var(--space-4);
  align-items: stretch;
  padding: 13px var(--space-4);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  margin-bottom: var(--space-3);
  transition: border-color 150ms, box-shadow 150ms;
}

.bk-card:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-md);
}

.bk-card.is-cancelled { opacity: 0.6; }

/* Date column */
.bk-date {
  flex-shrink: 0;
  width: 60px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: var(--bg-subtle);
  border-radius: var(--radius-sm);
  padding: var(--space-2) 0;
  text-align: center;
}

.bk-date .mon {
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-tertiary);
}

.bk-date .day {
  font-size: var(--fs-kpi-sm);
  font-weight: 800;
  line-height: 1.05;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

.bk-date .tm {
  font-size: var(--fs-2xs);
  font-weight: 600;
  color: var(--text-secondary);
  margin-top: 3px;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

/* Body */
.bk-title {
  font-size: var(--fs-body);
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.bk-meta {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

.bk-meta b {
  color: var(--text-primary);
  font-weight: 600;
}

.bk-party { color: var(--text-tertiary); }

.bk-notes {
  font-size: var(--fs-label);
  color: var(--text-tertiary);
  font-style: italic;
  margin-top: 3px;
}

/* Body fills the middle of the card; enriched info row sits under the meta. */
.bk-body { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }
.bk-info { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 8px; }
.bk-chip { display: inline-flex; flex-direction: column; line-height: 1.25; }
.bk-chip .k { font-size: var(--fs-2xs); text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); font-weight: 700; }
.bk-chip .v { font-size: var(--fs-sm); color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.bk-summary { font-size: var(--fs-sm); color: var(--text-secondary); line-height: var(--lh-body); margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

/* Status pills — ONE semantic set (design-system §1.3, replaces per-feature dupes) */
.bk-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  font-size: var(--fs-2xs);
  font-weight: 600;
  line-height: 1.5;
}

.bk-pill .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.bk-pill.requested  { background: var(--warning-soft); color: var(--warning); }
.bk-pill.confirmed  { background: var(--success-soft); color: var(--success); }
.bk-pill.cancelled  { background: var(--danger-soft);  color: var(--danger); }
.bk-pill.completed  { background: var(--brand-soft);   color: var(--brand-text); }
/* checked_in / no_show (Task 10 calendar popover statuses; the Bookings list
   never showed these two so the set above never needed them). checked_in
   gets a neutral tint - .completed already owns brand-soft, so reusing it
   here would make the two statuses indistinguishable. no_show mirrors the
   hollow/dashed idiom #calendar-root already uses for the same status
   (app.linear.css section 16) instead of a fourth solid color. */
.bk-pill.checked_in { background: var(--bg-subtle); color: var(--text-secondary); }
.bk-pill.no_show    { background: transparent; border: 1px dashed var(--danger); color: var(--danger); }

/* ----
   12. CAMPAIGNS — .bd-camp-* boards
   ---- */

.bd-camp-row {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  transition: background 100ms;
}

.bd-camp-row:last-child { border-bottom: none; }

.bd-camp-row:hover { background: var(--bg-hover); }

.bd-camp-name {
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--text-primary);
}

.bd-camp-meta {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  margin-top: 4px;
  line-height: var(--lh-body);
}

/* Campaign status badges — unified semantic set */
.bd-camp-badge {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  line-height: 1.5;
}

.bd-camp-badge.q   { background: var(--warning-soft); color: var(--warning); }    /* queued/pending */
.bd-camp-badge.s   { background: var(--brand-soft);   color: var(--brand-text); } /* sending */
.bd-camp-badge.ok  { background: var(--success-soft); color: var(--success); }    /* done */
.bd-camp-badge.err { background: var(--danger-soft);  color: var(--danger); }     /* error */
.bd-camp-badge.off { background: var(--bg-subtle);    color: var(--text-secondary); opacity: 0.8; }

/* Campaign preview block */
.bd-camp-preview {
  font-size: var(--fs-sm);
  padding: 9px var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  color: var(--text-secondary);
  margin-top: var(--space-2);
}

/* ----
   13. AUTOMATION — .bd-auto-* boards
   ---- */

.bd-auto-seq-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  gap: var(--space-3);
}

.bd-auto-seq-item:last-child { border-bottom: none; }

.bd-auto-seq-meta {
  font-size: var(--fs-label);
  color: var(--text-secondary);
  margin-top: 2px;
  line-height: var(--lh-body);
}

/* Automation status badges — unified semantic set */
.bd-auto-badge {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-2xs);
  font-weight: 600;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  line-height: 1.5;
}

.bd-auto-badge.on  { background: var(--success-soft); color: var(--success); }
.bd-auto-badge.off { background: var(--bg-subtle);    color: var(--text-secondary); opacity: 0.8; }

.bd-auto-code {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  color: var(--text-secondary);
  letter-spacing: 0.02em;
}

.bd-auto-secret-reveal {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--bg-subtle);
  border: 1px solid var(--border);
}

.bd-auto-note {
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--warning-soft);
  border: 1px solid var(--border);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

/* ----
   14. FOCUS + TRANSITIONS (all interactive inbox/board elements)
   ---- */

.bd-inbox-row:focus-visible,
.bd-inbox2-canned-row:focus-visible,
.bk-card:focus-visible,
.bd-camp-row:focus-visible,
.bd-auto-seq-item:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
  border-radius: var(--radius-md);
}

/* ----
   15. RTL MIRRORING (logical properties already used above where new rules
   were written; legacy selectors that used physical left/right need explicit
   [dir="rtl"] overrides so we don't touch markup or JS)
   ---- */

/* Inbox row selected bar flips side */
[dir="rtl"] .bd-inbox-row.is-active {
  box-shadow: inset -2px 0 0 0 var(--brand);
}

/* Connected channel bar flips side */
[dir="rtl"] [data-page="channels"] #channels-body .channel-row:has(.wa-badge-connected),
[dir="rtl"] [data-page="channels"] #channels-body .channel-row:has(.tg-badge-connected),
[dir="rtl"] [data-page="channels"] #channels-body .channel-row:has(.ig-badge-connected),
[dir="rtl"] [data-page="channels"] #channels-body .channel-row:has(.mg-badge-connected),
[dir="rtl"] [data-page="channels"] #channels-body .channel-row:has(.channel-status.is-connected) {
  box-shadow: inset -3px 0 0 var(--brand), var(--shadow-sm);
}

/* detail-panel slides from left in RTL */
[dir="rtl"] .detail-panel {
  right: auto;
  left: 0;
  border-inline-start: none;
  border-inline-end: 1px solid var(--border);
  transform: translateX(-100%);
}

[dir="rtl"] .detail-panel.is-open { transform: translateX(0); }
/* ============================================================
   RESTYLE PASS — 20-tables.css
   ONE density spec for every table on both surfaces.
   design-system.md §4 / proof.css dense-table block.

   Additive only. Targets existing selectors; no markup changes.
   Badge/dot/button content inside cells is left to their owners.
   ============================================================ */

/* ─────────────────────────────────────────────────────────────
   SHARED RESET (both surfaces use border-collapse tables)
   ─────────────────────────────────────────────────────────────*/
.table,
.conv-table,
.ins-table,
.bd-inbox-team-table,
.op-billing-table,
.op-kb-table,
.op-users-table,
.op-cost-table,
.op-costs-top-table,
.op-bd-mini-table,
.op-kv {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-body);   /* 14px — single size floor for all tables */
  font-family: var(--font-sans);
}

/* ─────────────────────────────────────────────────────────────
   HEADER — --bg-subtle bg, --text-secondary, --fs-label (12px),
   1px --border-strong bottom, sticky where the table scrolls.
   ─────────────────────────────────────────────────────────────*/
.table thead th,
.conv-table thead th,
.ins-table thead th,
.bd-inbox-team-table thead th,
.op-billing-table thead th,
.op-kb-table thead th,
.op-users-table thead th,
.op-cost-table thead th,
.op-costs-top-table thead th,
.op-bd-mini-table thead th,
.op-kv thead th {
  height: var(--row-h);                    /* 40px */
  padding: 0 var(--cell-pad-x);           /* 0 12px (y via height) */
  background: var(--bg-subtle);
  color: var(--text-secondary);
  font-size: var(--fs-label);             /* 12px */
  font-weight: 600;
  font-family: var(--font-sans);
  text-align: start;
  white-space: nowrap;
  border-bottom: 1px solid var(--border-strong);
  position: sticky;
  top: 0;
  z-index: 1;
  /* kill existing uppercase/letter-spacing variations */
  text-transform: none;
  letter-spacing: 0;
}

/* ─────────────────────────────────────────────────────────────
   ROWS — 40px height, 1px --border bottom
   ─────────────────────────────────────────────────────────────*/
.table tbody td,
.conv-table tbody td,
.ins-table tbody td,
.bd-inbox-team-table tbody td,
.op-billing-table tbody td,
.op-kb-table tbody td,
.op-users-table tbody td,
.op-cost-table tbody td,
.op-costs-top-table tbody td,
.op-bd-mini-table tbody td,
.op-kv tbody td,
.op-kv td {
  height: var(--row-h);                    /* 40px */
  padding: 0 var(--cell-pad-x);           /* 0 12px */
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  font-size: var(--fs-body);
}

/* op-kv th is a row-header column (not a thead th — keep styling it correctly) */
.op-kv th {
  height: var(--row-h);
  padding: 0 var(--cell-pad-x);
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--text-secondary);
  text-align: start;
  background: transparent;
  white-space: nowrap;
  /* Reset sticky from thead rule above */
  position: static;
  top: auto;
}

/* ─────────────────────────────────────────────────────────────
   LAST-ROW — suppress double bottom border
   ─────────────────────────────────────────────────────────────*/
.table tbody tr:last-child td,
.conv-table tbody tr:last-child td,
.ins-table tbody tr:last-child td,
.bd-inbox-team-table tbody tr:last-child td,
.op-billing-table tbody tr:last-child td,
.op-kb-table tbody tr:last-child td,
.op-users-table tbody tr:last-child td,
.op-cost-table tbody tr:last-child td,
.op-costs-top-table tbody tr:last-child td,
.op-bd-mini-table tbody tr:last-child td,
.op-kv tbody tr:last-child td,
.op-kv tr:last-child td,
.op-kv tr:last-child th {
  border-bottom: none;
}

/* ─────────────────────────────────────────────────────────────
   HOVER — --bg-hover
   ─────────────────────────────────────────────────────────────*/
.table tbody tr:hover td,
.conv-table tbody tr:hover td,
.ins-table tbody tr:hover td,
.bd-inbox-team-table tbody tr:hover td,
.op-billing-table tbody tr:hover td,
.op-kb-table tbody tr:hover td,
.op-users-table tbody tr:hover td,
.op-cost-table tbody tr:hover td,
.op-costs-top-table tbody tr:hover td,
.op-bd-mini-table tbody tr:hover td,
.op-kv tbody tr:hover td,
.op-kv tr:hover td,
.op-kv tr:hover th {
  background: var(--bg-hover);
}

/* ─────────────────────────────────────────────────────────────
   SELECTED ROW — --brand-soft bg + 2px inset --brand left bar
   Covers: .is-selected (admin billing), .is-kbd-selected (app conv-table),
           .sel (generic), .is-active (any table row JS sets it).
   ─────────────────────────────────────────────────────────────*/
.table tbody tr.sel td,
.table tbody tr.is-selected td,
.conv-table tbody tr.is-kbd-selected td,
.conv-table tbody tr.sel td,
.op-billing-table tbody tr.is-selected td,
.op-users-table tbody tr.is-selected td,
.op-kb-table tbody tr.is-selected td {
  background: var(--brand-soft);
}

.table tbody tr.sel,
.table tbody tr.is-selected,
.conv-table tbody tr.is-kbd-selected,
.conv-table tbody tr.sel,
.op-billing-table tbody tr.is-selected,
.op-users-table tbody tr.is-selected,
.op-kb-table tbody tr.is-selected {
  box-shadow: inset 2px 0 0 0 var(--brand);
}

/* ─────────────────────────────────────────────────────────────
   NUMERIC / CURRENCY CELLS — right-aligned, tabular-nums, mono
   Target both semantic classes (.num, .cost, .op-bd-amt,
   .op-bt-credit, .op-bt-quota-text col) and existing td.cost.
   ─────────────────────────────────────────────────────────────*/
.table td.num,
.conv-table td.num,
.ins-table td.num,
.ins-table th:last-child,
.ins-table td:last-child,
.bd-inbox-team-table td.num,
.bd-inbox-team-table th.num,
.op-billing-table td.num,
.op-billing-table .op-bt-credit,
.op-kb-table td.size,
.op-kb-table td.created,
.op-users-table td.time,
.op-cost-table td.cost,
.op-costs-top-table td.cost,
.op-bd-mini-table td.op-bd-amt,
.op-bd-mini-table th.op-bd-amt {
  text-align: end;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

/* ─────────────────────────────────────────────────────────────
   TOTALS / SUMMARY ROWS — slightly bolder, strong top border
   ─────────────────────────────────────────────────────────────*/
.op-cost-table tr.tot td,
.ins-table tr.is-total td {
  font-weight: 600;
  border-top: 1px solid var(--border-strong);
  border-bottom: none;
}

/* CSAT rating rows that link to a conversation transcript */
.ins-csat-row { cursor: pointer; }

/* ─────────────────────────────────────────────────────────────
   ZEBRA — optional, very low-contrast, only on tables that need it.
   Applied via .is-zebra class on the <table> or direct spec for
   known long-list tables. Uses --surface-1 which is ~2-4% offset.
   ─────────────────────────────────────────────────────────────*/
.op-billing-table tbody tr:nth-child(even) td,
.op-users-table tbody tr:nth-child(even) td,
.op-audit-list .op-audit-row:nth-child(even) {
  background: var(--surface-1, rgba(255,255,255,.03));
}
/* Hover must win over zebra */
.op-billing-table tbody tr:hover td,
.op-users-table tbody tr:hover td {
  background: var(--bg-hover);
}

/* ─────────────────────────────────────────────────────────────
   op-cost-table — PREVIOUSLY UNSTYLED inline <style> override.
   Give it the full spec for the first time as an external rule.
   ─────────────────────────────────────────────────────────────*/
.op-cost-table {
  font-size: var(--fs-body);
}

/* ─────────────────────────────────────────────────────────────
   op-audit-list / op-audit-row — this is a div-grid "table",
   not a real <table>. Remap its hardcoded colors to tokens.
   ─────────────────────────────────────────────────────────────*/
.op-audit-list {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}

.op-audit-row {
  padding: 0 var(--cell-pad-x);
  min-height: var(--row-h);           /* 40px — aligns with table spec */
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: var(--fs-label);         /* 12px — audit is dense metadata */
  font-family: var(--font-mono);
  align-items: center;
}

.op-audit-row:last-child {
  border-bottom: none;
}

.op-audit-row:hover {
  background: var(--bg-hover);
}

.op-audit-type {
  color: var(--text-primary);
}

.op-audit-tid,
.op-audit-ip,
.op-audit-details {
  color: var(--text-tertiary);
}

/* Severity badges within audit rows — keep semantic colors but use tokens */
.op-audit-sev[data-sev="critical"] { background: var(--danger-soft);  color: var(--danger); }
.op-audit-sev[data-sev="high"]     { background: var(--warning-soft); color: var(--warning); }
.op-audit-sev[data-sev="medium"]   { background: var(--brand-soft);   color: var(--brand-text, var(--brand)); }
.op-audit-sev[data-sev="low"]      { background: var(--bg-hover);     color: var(--text-secondary); }

/* ─────────────────────────────────────────────────────────────
   op-kv — key/value detail table used inside modals.
   Row-height spec (height on td + th) applied above.
   mono for .json cells (already present; make sure it uses tokens)
   ─────────────────────────────────────────────────────────────*/
.op-kv td.json {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  color: var(--text-secondary);
  white-space: pre-wrap;
  height: auto;                        /* json cells may be multi-line — let them grow */
  padding: var(--cell-pad-y) var(--cell-pad-x);
}

/* ─────────────────────────────────────────────────────────────
   RTL — numeric columns stay end-aligned.
   Header text-align becomes start (logical, flips for RTL).
   ─────────────────────────────────────────────────────────────*/
[dir="rtl"] .table thead th,
[dir="rtl"] .conv-table thead th,
[dir="rtl"] .ins-table thead th,
[dir="rtl"] .bd-inbox-team-table thead th {
  text-align: start;           /* logical: still right in RTL */
}

[dir="rtl"] .table td.num,
[dir="rtl"] .conv-table td.num,
[dir="rtl"] .ins-table td:last-child,
[dir="rtl"] .bd-inbox-team-table td.num {
  text-align: end;             /* stays end (left in RTL) — numeric col convention */
}

/* Inset selected-bar flips to right side in RTL */
[dir="rtl"] .conv-table tbody tr.is-kbd-selected,
[dir="rtl"] .conv-table tbody tr.sel,
[dir="rtl"] .table tbody tr.sel,
[dir="rtl"] .table tbody tr.is-selected {
  box-shadow: inset -2px 0 0 0 var(--brand);
}

/* ─────────────────────────────────────────────────────────────
   FOCUS — keyboard-navigable table rows
   ─────────────────────────────────────────────────────────────*/
.conv-table tbody tr:focus-visible,
.table tbody tr:focus-visible,
.op-billing-table tbody tr:focus-visible,
.op-users-table tbody tr:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}

/* ─────────────────────────────────────────────────────────────
   OUTBOUND PAGE  (.bd-ob-*)
   ─────────────────────────────────────────────────────────────*/
.bd-ob-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-height: 40px;
}

.bd-ob-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  background: var(--surface-raised, rgba(255,255,255,0.04));
  font-size: 0.875rem;
}

.bd-ob-phone {
  font-weight: 500;
  flex: none;
  min-width: 140px;
}

.bd-ob-reason {
  color: var(--text-muted, #888);
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.bd-ob-remove {
  flex: none;
  margin-left: auto;
}

.bd-ob-error-msg {
  color: var(--color-error, #e05252);
  font-size: 0.85rem;
}

[dir="rtl"] .bd-ob-phone {
  text-align: right;
}

[dir="rtl"] .bd-ob-remove {
  margin-left: 0;
  margin-right: auto;
}

/* ===================================================================
   Dashboard merge (Insights folded into Dashboard) -- 2026-06-30
   All tokens are from app.css :root only.
   New classes: .dash-zone/.dash-zone-h, .dash-sub-*, .dash-att-*,
   details.dash-analytics + summary.dash-analytics-toggle.
   Fixes: .ins-gap flex-wrap, .ins-gap-q grow, .ins-gap-draft styling.
   New: full .ins-ai-* family (was undefined -- caused stacking bugs).
   =================================================================== */

/* -- Zone wrappers ------------------------------------------------------- */
.dash-zone {
  margin-bottom: var(--space-8, 32px);
}
.dash-zone-h {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 12px;
}

/* -- Needs-your-attention list ------------------------------------------- */
.dash-att-row {
  cursor: pointer;
  display: flex;
  gap: 12px;
  align-items: center;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  border-left: 3px solid transparent;
  transition: background var(--transition);
}
.dash-att-row:hover {
  background: var(--bg-subtle);
}
.dash-att-row.is-low {
  border-left-color: var(--danger);
}
.dash-att-text {
  flex: 1 1 auto;
  min-width: 0;
  font-size: 13px;
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-att-meta {
  flex: none;
  font-size: 12px;
  color: var(--text-tertiary);
  white-space: nowrap;
}

/* -- Fix: ins-gap flex layout (3 children -- question / count / draft btn)
   Before: justify-content:space-between on 2 children was fine; a 3rd
   child caused odd stacking. Fix: question grows, count + button are
   fixed trailing children. flex-wrap added for narrow viewports.        -- */
.ins-gap {
  flex-wrap: wrap;
}
.ins-gap-q {
  flex: 1 1 auto;
  min-width: 0;
}
.ins-gap-n,
.ins-gap-draft {
  flex: none;
}

/* -- ins-gap-draft: ghost button for the Draft-answer action ------------- */
.ins-gap-draft {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 28px;
  padding: 0 11px;
  font-size: 13px;
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.ins-gap-draft:hover {
  background: var(--bg-subtle);
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* -- ins-ai-* action-item family (was fully undefined -- stacking bug) --- */
.ins-ai-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}
.ins-ai-item {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 8px 0;
  border-bottom: 1px solid var(--border);
}
.ins-ai-item:last-child {
  border-bottom: none;
}
.ins-ai-check-wrap {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-top: 2px;
}
.ins-ai-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.ins-ai-text {
  font-size: 13px;
  color: var(--text-primary);
  line-height: 1.4;
}
.ins-ai-item.is-done .ins-ai-text {
  text-decoration: line-through;
  color: var(--text-tertiary);
}
.ins-ai-customer {
  font-size: 12px;
  color: var(--text-tertiary);
}
/* ===================================================================
   Dashboard grid redesign — Task 1 (dashgrid-20260630-w112)
   Responsive 2-col widget grid + card shell + compact attention.
   All tokens are from app.css :root only — no new palette values.
   Tasks 2 (markup) and 3 (JS) depend on the class names below;
   do NOT rename them.
   =================================================================== */

/* -- 2-column responsive grid ---------------------------------------- */
.dash-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 860px) {
  .dash-grid { grid-template-columns: 1fr; }
}

/* -- Column flex stack inside a grid cell ---------------------------- */
.dash-col {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* -- Widget card shell (matches .card / .stat-card look) ------------- */
.dash-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 16px;
  box-shadow: var(--shadow-sm);
}

/* -- Card header: title left, optional ghost link right -------------- */
.dash-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 12px;
}
.dash-card-head h2 {
  font-size: 14px;
  font-weight: 600;
  margin: 0;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

/* Ghost link/button — jump to another tab from the card header */
.dash-card-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 26px;
  padding: 0 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1;
  text-decoration: none;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.dash-card-link:hover {
  background: var(--bg-subtle);
  border-color: var(--border-strong);
  color: var(--text-primary);
}

/* -- Attention sub-label: "Follow-ups · N" / "Unhappy · N" ---------- */
.dash-att-sub {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 10px 0 4px;
}
.dash-att-sub:first-child {
  margin-top: 0;
}

/* -- Compact topic chip wrap (tighter than global .ins-chips) --------- */
.dash-topics {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

/* -- KB gaps card (identical shell to .kb-docs-card in app.css) ------ */
.kb-gaps-card {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--space-6);
}

/* =======================================================================
   Dashboard v3 — Shopify cards (dashshop-20260630-w113)
   New classes: is-wide span, attention trigger pill, outcome tiles.
   All tokens resolve from app.css :root — no hardcoded palette values.
   Class names are depended on by Tasks 2 and 3; do NOT rename.
   ======================================================================= */

/* -- Wide card: span both grid columns (e.g. heatmap) ------------------- */
.dash-card.is-wide {
  grid-column: 1 / -1;
}

/* -- Attention trigger pill button (hero header) ------------------------- */
.dash-att-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  font-size: 13px;
  font-weight: 600;
  color: var(--warning);
  background: var(--warning-soft);
  border: 1px solid var(--warning);
  border-radius: var(--radius-full);
  cursor: pointer;
  white-space: nowrap;
  line-height: 1;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.dash-att-trigger:hover {
  background: var(--warning);
  color: var(--bg-elevated);
}
.dash-att-trigger[hidden] { display: none; }

/* -- Badge count inside the trigger pill --------------------------------- */
.dash-att-trigger-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
  color: var(--bg-elevated);
  background: var(--warning);
  border-radius: var(--radius-full);
}

/* -- Outcome tiles wrap container --------------------------------------- */
.dash-oc-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

/* -- Individual outcome tile --------------------------------------------- */
.dash-oc-tile {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 90px;
  padding: 10px 12px;
  background: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.dash-oc-tile.is-other {
  opacity: 0.6;
}

/* -- Outcome tile inner elements ----------------------------------------- */
.dash-oc-label {
  font-size: 12px;
  font-weight: 500;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.dash-oc-pct {
  font-size: 19px;
  font-weight: 600;
  line-height: 1.1;
  color: var(--text-primary);
}
.dash-oc-n {
  font-size: 12px;
  color: var(--text-tertiary);
}

/* Dashboard v4 — header cleanup + clickable quick-actions + feeling */

/* -- Period-selector / Needs-attention toprow ----------------------------- */
.dash-toprow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

/* -- Quick-action row: even gap + wrap so the buttons align on any width -- */
.ov-quick {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 4px;
}

/* -- Quick-action buttons: clearly clickable, elevated, above the page --- */
.ov-quick-btn {
  height: 38px;
  padding: 0 18px;
  background: var(--bg-subtle);
  color: var(--text-primary);
  border: 1px solid var(--border-strong);
  box-shadow: var(--shadow-xs);
  font-weight: 600;
  border-radius: var(--radius-md);
  cursor: pointer;
}
.ov-quick-btn:hover {
  background: var(--bg-hover);
  border-color: var(--brand);
  color: var(--brand-text);
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

/* -- Feeling breakdown (Positive / Neutral / Negative bars) --------------- */
.dash-feel-mood {
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 12px;
}
.dash-feel-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 8px 0;
}
.dash-feel-label {
  font-size: 12px;
  color: var(--text-secondary);
  min-width: 64px;
  flex: none;
}
.dash-feel-track {
  flex: 1 1 auto;
  height: 8px;
  background: var(--bg-subtle);
  border-radius: var(--radius-full);
  overflow: hidden;
}
.dash-feel-fill {
  height: 100%;
  border-radius: var(--radius-full);
}
.dash-feel-fill.is-pos { background: var(--success); }
.dash-feel-fill.is-neu { background: var(--text-tertiary); }
.dash-feel-fill.is-neg { background: var(--danger); }
.dash-feel-pct {
  font-size: 12px;
  color: var(--text-secondary);
  min-width: 40px;
  text-align: right;
  flex: none;
  font-variant-numeric: tabular-nums;
}
.dash-feel-note {
  font-size: 12px;
  color: var(--text-tertiary);
  margin-top: 10px;
}

/* ============================================================
   16. CALENDAR - .cal-* layout + FullCalendar 6 theming (Task 9)
   ------------------------------------------------------------
   FullCalendar 6 ships no CSS file (Task 8: the self-hosted JS bundle
   injects its own base styles at runtime) so everything below is an
   OVERRIDE layer on top of that runtime CSS, not a replacement of it -
   mostly via FullCalendar's own documented --fc-* custom properties, plus
   a few class selectors for things the variables don't cover (toolbar
   title, per-event status/provenance colors). Reuses the same tokens as
   the rest of this theme - no new color system. Markup: agent/
   portal_shell.html #calendar-root (FullCalendar mount) + #calendar-side
   (today/upcoming/no-show widget slots, populated by a later task). Both now
   live inside the Bookings page (Task 11), behind #bk-view-toggle.
   Logic: demo/app.js buildBookingsCalendar() (renamed from onEnterCalendar
   when the calendar moved off its own route). ============================ */

.cal-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--space-4);
  align-items: start;
}

@media (max-width: 900px) {
  .cal-layout { grid-template-columns: 1fr; }
}

.cal-main {
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  padding: var(--space-4);
  min-width: 0;
}

.cal-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.cal-side-card .card-head {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm);
}

/* Empty-state placeholder for the sidebar widget slots. Task 10 fills these
   with real today/upcoming/no-show rows; this task only scaffolds stable
   mount ids, so an empty container should not just look broken. */
#calendar-today-list:empty::after,
#calendar-upcoming-list:empty::after,
#calendar-noshow-list:empty::after {
  content: 'Nothing yet.';
  display: block;
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-sm);
  color: var(--text-tertiary);
}

/* ---- FullCalendar chrome: fold its runtime CSS into this theme via its
   documented CSS custom properties (fullcalendar.io/docs/css-customization),
   the officially supported hook - no fighting internal class names.

   Bug fixed here (Task 13): this rule used to be written
   `#calendar-root .fc { ... }` (a descendant combinator), which never
   matches anything - FullCalendar puts the `fc` class DIRECTLY on the
   #calendar-root mount element itself (root.className ===
   "fc fc-media-screen fc-direction-ltr fc-theme-standard"), it never
   nests a child with class .fc. So every --fc-* variable below was dead:
   FullCalendar ran on its own bundled default border/button/today/now-
   indicator colors, never the brand tokens. Fixed by compounding the
   selector (#calendar-root.fc - both the id AND the class on the SAME
   element, no space) so it actually matches the mount element once
   FullCalendar has initialized it. All the OTHER #calendar-root .fc-*
   rules below (.fc-button, .fc-event, etc) were already correct - those
   target real descendants of the mount element - so only this one
   top-level variable block needed the fix. ---- */

#calendar-root.fc {
  font-family: var(--font-sans);
  --fc-border-color: var(--border);
  --fc-page-bg-color: transparent;
  --fc-neutral-bg-color: var(--bg-subtle);
  --fc-neutral-text-color: var(--text-secondary);
  --fc-list-event-hover-bg-color: var(--bg-hover);
  --fc-today-bg-color: var(--brand-soft);
  --fc-now-indicator-color: var(--danger);
  --fc-button-text-color: var(--text-primary);
  --fc-button-bg-color: var(--surface-1);
  --fc-button-border-color: var(--border-strong);
  --fc-button-hover-bg-color: var(--surface-2);
  --fc-button-hover-border-color: var(--border-strong);
  --fc-button-active-bg-color: var(--brand);
  --fc-button-active-border-color: var(--brand);

  /* ---- Apple-style redesign: per-status accent/text/tint tokens (LIGHT).
     accent = the left bar + dot color; text = the pill's own readable
     text color (never white-on-solid); tint = the soft translucent pill
     background. Same three-token shape repeats for every status so the
     pill rules below stay a simple lookup, not a color decision each
     time. --cal-bar-x flips sign under [dir="rtl"] (below) so the accent
     bar's physical box-shadow offset (inset 3px vs inset -3px - box-
     shadow offsets are physical, not logical, direction:rtl alone won't
     flip them) needs only ONE set of pill rules, not a duplicated RTL
     mirror block. ---- */
  --cal-bar-x: 3px;

  --cal-requested-accent:  #FF9500;
  --cal-requested-text:    #B45309;
  --cal-requested-tint:    rgba(255,149,0,0.13);

  --cal-confirmed-accent:  #34C759;
  --cal-confirmed-text:    #1C7C3B;
  --cal-confirmed-tint:    rgba(52,199,89,0.15);

  --cal-checked_in-accent: #007AFF;
  --cal-checked_in-text:   #0062CC;
  --cal-checked_in-tint:   rgba(0,122,255,0.12);

  --cal-completed-accent:  #8E8E93;
  --cal-completed-text:    #57575C;
  --cal-completed-tint:    rgba(142,142,147,0.14);

  --cal-no_show-accent:    #FF3B30;
  --cal-no_show-text:      #C4271E;
  --cal-no_show-tint:      rgba(255,59,48,0.11);

  --cal-cancelled-accent:  #B0B0B5;
  --cal-cancelled-text:    #86868B;
  --cal-cancelled-tint:    rgba(142,142,147,0.10);
}

[dir="rtl"] #calendar-root.fc { --cal-bar-x: -3px; }

/* ---- Same per-status tokens, DARK palette. Brighter accents + brighter
   text (Apple's dark-mode system colors sit ~1-2 steps brighter than
   their light counterparts so they still read as "the same color" against
   a near-black surface) + a slightly stronger tint alpha (a 12-15% tint
   reads as barely-there on a dark surface; dark tints go ~20-22%). ---- */
html[data-theme="dark"] #calendar-root.fc {
  --cal-requested-accent:  #FF9F0A;
  --cal-requested-text:    #FFB340;
  --cal-requested-tint:    rgba(255,159,10,0.20);

  --cal-confirmed-accent:  #30D158;
  --cal-confirmed-text:    #4CE06A;
  --cal-confirmed-tint:    rgba(48,209,88,0.20);

  --cal-checked_in-accent: #0A84FF;
  --cal-checked_in-text:   #5AA9FF;
  --cal-checked_in-tint:   rgba(10,132,255,0.22);

  --cal-completed-accent:  #98989D;
  --cal-completed-text:    #C7C7CC;
  --cal-completed-tint:    rgba(152,152,157,0.20);

  --cal-no_show-accent:    #FF453A;
  --cal-no_show-text:      #FF7B72;
  --cal-no_show-tint:      rgba(255,69,58,0.20);

  --cal-cancelled-accent:  #636366;
  --cal-cancelled-text:    #98989D;
  --cal-cancelled-tint:    rgba(142,142,147,0.16);
}

#calendar-root .fc-toolbar-title {
  font-size: var(--fs-heading);
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}

/* Phone widths: let the three toolbar chunks (nav / title / views) wrap
   instead of shoving the calendar wider than the viewport. */
@media (max-width: 520px) {
  #calendar-root .fc-header-toolbar { flex-wrap: wrap; gap: 8px; }
  #calendar-root .fc-toolbar-title { font-size: 15px; white-space: nowrap; }
}

/* Pill-shaped toolbar buttons (Apple redesign) - the prev/next/today group
   and the dayGridMonth/timeGridWeek/timeGridDay/listWeek view group both
   read as a clean segmented control this way. Inactive fill/border already
   came from --fc-button-bg-color/--fc-button-border-color above
   (var(--surface-1)/var(--border-strong)) - only shape + padding change. */
#calendar-root .fc-button {
  text-transform: capitalize;
  box-shadow: none;
  border-radius: var(--radius-full, 999px);
  padding: 6px 14px;
  font-weight: 590;
}

#calendar-root .fc-button:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
  box-shadow: none;
}

/* Column header day names (month/week views) - the Apple all-caps small
   label look, tertiary/muted until it's today's column. */
#calendar-root .fc-col-header-cell-cushion {
  text-transform: uppercase;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text-tertiary);
}
#calendar-root .fc-day-today .fc-col-header-cell-cushion {
  color: var(--brand-text);
}

/* The active/pressed toolbar button (e.g. the current view) gets a solid
   brand fill via --fc-button-active-bg-color above; --fc-button-text-color
   stays a theme-neutral color for the inactive buttons, so the active one
   needs an explicit white label to stay readable against the blue fill. */
#calendar-root .fc-button-primary:not(:disabled).fc-button-active,
#calendar-root .fc-button-primary:not(:disabled):active {
  color: #fff;
}

/* ---- Status colors (agent/booking.py VALID_STATUSES) applied via
   buildBookingsCalendar()'s classNames: ['bk-'+status, 'prov-'+provenance].

   REDESIGN (Apple Calendar idiom): the old scheme was a solid saturated
   fill + forced white text - heavy, and on light-mode "requested" the
   --warning token (#b25000, a muddy brown chosen for AA contrast under
   white text) read as dull rather than energetic. Replaced with a
   soft-tinted pill: translucent status tint background + a colored left
   accent bar (inset box-shadow - keeps the pill's own border-radius
   uninterrupted, no extra border layer) + status-colored TEXT (never
   white-on-solid, so the tokens above can be bright/saturated without
   needing a contrast-driven muddy compromise). Applies to month (dayGrid)
   + week/day (timeGrid) event chips only.

   IMPORTANT selector gotcha (found live in the harness, not assumed):
   FullCalendar puts its generic `.fc-event` base class on ALL THREE event
   kinds, INCLUDING list rows (`class="fc-event ... bk-requested ...
   fc-list-event"` - confirmed via a live DOM probe) - it is NOT month/
   timeGrid-exclusive the way the old code's separate `.fc-event.bk-X,
   .fc-list-event.bk-X` comma pair implied (that pair was actually two
   selectors matching the SAME elements, not a month/timeGrid vs list
   split). A first pass of this redesign wrote `.fc-event.bk-<status>`
   for the pill rules and it leaked the soft-tint background onto list
   rows too, which product explicitly asked to stay neutral - caught via
   the redesign-list-light.png screenshot showing a colored wash. Fixed
   by keying off `.fc-daygrid-event`/`.fc-timegrid-event` specifically
   (FullCalendar's real month-vs-timeGrid-vs-list discriminator classes)
   instead of the shared `.fc-event`, so list rows are excluded FOR REAL.
   List stays neutral by design (16d/16f below: the list's own .bk-date
   chip + a small .fc-list-event-dot carry the status color there). ---- */

#calendar-root .fc-daygrid-event.bk-requested,
#calendar-root .fc-daygrid-event.bk-confirmed,
#calendar-root .fc-daygrid-event.bk-checked_in,
#calendar-root .fc-daygrid-event.bk-completed,
#calendar-root .fc-daygrid-event.bk-no_show,
#calendar-root .fc-daygrid-event.bk-cancelled,
#calendar-root .fc-timegrid-event.bk-requested,
#calendar-root .fc-timegrid-event.bk-confirmed,
#calendar-root .fc-timegrid-event.bk-checked_in,
#calendar-root .fc-timegrid-event.bk-completed,
#calendar-root .fc-timegrid-event.bk-no_show,
#calendar-root .fc-timegrid-event.bk-cancelled {
  border: none;
  border-radius: 7px;
  font-weight: 590;
}
/* Month (dayGrid) chips get a touch of horizontal breathing room - the
   week/day (timeGrid) compact label (.fc-bk-grid, section 16e) already
   carries its own tighter padding tuned to fit inside eventMinHeight:20,
   so it is deliberately left alone here to avoid double-padding it past
   that budget. */
#calendar-root .fc-daygrid-event.bk-requested,
#calendar-root .fc-daygrid-event.bk-confirmed,
#calendar-root .fc-daygrid-event.bk-checked_in,
#calendar-root .fc-daygrid-event.bk-completed,
#calendar-root .fc-daygrid-event.bk-no_show,
#calendar-root .fc-daygrid-event.bk-cancelled {
  padding: 2px 6px;
}

#calendar-root .fc-daygrid-event.bk-requested,
#calendar-root .fc-timegrid-event.bk-requested {
  background: var(--cal-requested-tint);
  color: var(--cal-requested-text);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-requested-accent);
}
#calendar-root .fc-daygrid-event.bk-requested:hover,
#calendar-root .fc-timegrid-event.bk-requested:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-requested-accent), var(--shadow-sm);
}

#calendar-root .fc-daygrid-event.bk-confirmed,
#calendar-root .fc-timegrid-event.bk-confirmed {
  background: var(--cal-confirmed-tint);
  color: var(--cal-confirmed-text);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-confirmed-accent);
}
#calendar-root .fc-daygrid-event.bk-confirmed:hover,
#calendar-root .fc-timegrid-event.bk-confirmed:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-confirmed-accent), var(--shadow-sm);
}

#calendar-root .fc-daygrid-event.bk-checked_in,
#calendar-root .fc-timegrid-event.bk-checked_in {
  background: var(--cal-checked_in-tint);
  color: var(--cal-checked_in-text);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-checked_in-accent);
}
#calendar-root .fc-daygrid-event.bk-checked_in:hover,
#calendar-root .fc-timegrid-event.bk-checked_in:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-checked_in-accent), var(--shadow-sm);
}

#calendar-root .fc-daygrid-event.bk-completed,
#calendar-root .fc-timegrid-event.bk-completed {
  background: var(--cal-completed-tint);
  color: var(--cal-completed-text);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-completed-accent);
}
#calendar-root .fc-daygrid-event.bk-completed:hover,
#calendar-root .fc-timegrid-event.bk-completed:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-completed-accent), var(--shadow-sm);
}

/* No-show: tint + accent bar PLUS a dashed 1px accent-colored border, so
   it stays visually distinct from cancelled (solid tint, no border, just
   faded + struck-through) at a glance - not just a color swap. */
#calendar-root .fc-daygrid-event.bk-no_show,
#calendar-root .fc-timegrid-event.bk-no_show {
  background: var(--cal-no_show-tint);
  color: var(--cal-no_show-text);
  border: 1px dashed var(--cal-no_show-accent);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-no_show-accent);
}
#calendar-root .fc-daygrid-event.bk-no_show:hover,
#calendar-root .fc-timegrid-event.bk-no_show:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-no_show-accent), var(--shadow-sm);
}

/* Cancelled: same soft-tint pill, additionally faded + struck-through -
   mirrors .bk-card.is-cancelled's opacity treatment on the Bookings list. */
#calendar-root .fc-daygrid-event.bk-cancelled,
#calendar-root .fc-timegrid-event.bk-cancelled {
  background: var(--cal-cancelled-tint);
  color: var(--cal-cancelled-text);
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-cancelled-accent);
  opacity: 0.72;
}
#calendar-root .fc-daygrid-event.bk-cancelled:hover,
#calendar-root .fc-timegrid-event.bk-cancelled:hover {
  box-shadow: inset var(--cal-bar-x) 0 0 0 var(--cal-cancelled-accent), var(--shadow-sm);
}
#calendar-root .fc-daygrid-event.bk-cancelled .fc-event-title,
#calendar-root .fc-timegrid-event.bk-cancelled .fc-bk-grid-title {
  text-decoration: line-through;
}

/* List view (neutral row + status dot only - see 16d/16f for the chip). */
#calendar-root .fc-list-event.bk-requested .fc-list-event-dot { border-color: var(--cal-requested-accent); background: var(--cal-requested-accent); }
#calendar-root .fc-list-event.bk-confirmed .fc-list-event-dot { border-color: var(--cal-confirmed-accent); background: var(--cal-confirmed-accent); }
#calendar-root .fc-list-event.bk-checked_in .fc-list-event-dot { border-color: var(--cal-checked_in-accent); background: var(--cal-checked_in-accent); }
#calendar-root .fc-list-event.bk-completed .fc-list-event-dot { border-color: var(--cal-completed-accent); background: var(--cal-completed-accent); }
#calendar-root .fc-list-event.bk-cancelled .fc-list-event-dot { border-color: var(--cal-cancelled-accent); background: var(--cal-cancelled-accent); }
/* No-show dot stays hollow (transparent fill) - same "dashed/hollow reads
   distinct from cancelled's solid fill" idea as the pill treatment above. */
#calendar-root .fc-list-event.bk-no_show .fc-list-event-dot { border-color: var(--cal-no_show-accent); background: transparent; }

#calendar-root .fc-list-event.bk-cancelled .fc-list-event-title,
#calendar-root .fc-list-event.bk-cancelled .fc-bk-title {
  text-decoration: line-through;
}

/* List row text: previously inherited a forced --text-inverse (white)
   from the row's OWN solid status-color background, which this redesign
   removes (rows are neutral now - color lives in the chip + the dot
   above). Needs an explicit readable color of its own or the title would
   render in whatever FullCalendar's unstyled default is. */
#calendar-root .fc-list-event-title,
#calendar-root .fc-bk-title {
  color: var(--text-primary);
}

/* Provenance: previously a second inset box-shadow bar on the event
   itself (`.prov-ai`/`.prov-staff`), which collided with the new status
   accent bar above - both used `box-shadow: inset 3px 0 0 0 ...`, so only
   one could ever show. The status accent wins; provenance is still
   surfaced clearly in the event popover badge (.cal-pop-prov below,
   unchanged) - simpler to drop the redundant on-event signal than to
   invent a second visual channel (e.g. a tiny dot) that would only add
   noise next to an already-colored pill. classNames: ['bk-'+status,
   'prov-'+provenance] in app.js is left wired (harmless, no CSS reads it
   at the event level anymore) in case a future pass wants it back. */

/* ----
   16b. CALENDAR INTERACTIONS (Task 10) - #calendar-event-popover content +
   #calendar-side widget rows.

   The popover's own backdrop/panel/close-button/foot chrome comes from the
   .bd-camp-* classes already defined inline in app.html (<style id="bd-camp-
   css">, e.g. .bd-camp-backdrop/.bd-camp-modal/.bd-camp-close/.bd-camp-modal-
   foot) - the same reuse #bookings-add-modal already relies on. Only the
   popover's OWN content (status/provenance row, when/phone rows, summary,
   status-button spacing) and the sidebar widget rows are new here.
   ---- */

.cal-pop-modal { max-width: 440px; }

.cal-pop-meta {
  display: flex;
  align-items: center;
  gap: var(--space-3, 12px);
  flex-wrap: wrap;
  margin: 2px 0 14px;
}

/* AI vs staff badge - reuses the same prov-ai/prov-staff naming idiom as the
   #calendar-root event inset bar above, just as a labeled pill instead of a
   box-shadow accent (a popover has room to spell it out). */
.cal-pop-prov {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.cal-pop-prov.prov-ai    { background: var(--brand-soft); color: var(--brand-text); }
.cal-pop-prov.prov-staff { background: var(--bg-subtle);  color: var(--text-secondary); }

.cal-pop-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3, 12px);
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-sm);
}
.cal-pop-row:last-of-type { border-bottom: none; }
.cal-pop-row .k {
  color: var(--text-tertiary);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: var(--fs-2xs);
  flex-shrink: 0;
}
.cal-pop-row .v {
  color: var(--text-primary);
  font-weight: 600;
  text-align: right;
}

.cal-pop-summary {
  margin-top: 10px;
  padding: 10px 12px;
  border-radius: var(--radius-md);
  background: var(--bg-subtle);
  font-size: var(--fs-sm);
  color: var(--text-secondary);
  line-height: var(--lh-body);
}

/* #calendar-side widget rows (Today / Upcoming / No-shows counts). Each
   .cal-side-card already gets the card/card-head chrome from the existing
   .card / .cal-side-card .card-head rules above - this is just the
   clickable count row demo/app.js's loadCalendarSide() renders into
   #calendar-today-list / #calendar-upcoming-list / #calendar-noshow-list.
   The :empty::after "Nothing yet." placeholder above no longer applies once
   JS fills these (a widget always renders, even at count 0, so :empty never
   matches post-render - the placeholder only ever covers the pre-JS/failed
   state). */
.cal-side-widget {
  width: 100%;
  display: flex;
  align-items: baseline;
  gap: var(--space-2, 8px);
  padding: var(--space-3, 12px) var(--space-4, 16px);
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font: inherit;
  color: inherit;
}
.cal-side-widget:hover { background: var(--bg-hover); }
.cal-side-widget:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: -2px;
}
.cal-side-widget-n {
  font-size: var(--fs-xl, 20px);
  font-weight: 800;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
}
.cal-side-widget-l {
  font-size: var(--fs-sm);
  color: var(--text-secondary);
}

/* ----
   16c. CALENDAR DATE/TIME TYPOGRAPHY MATCH (Task 11 - calendar moved into
   the Bookings page behind #bk-view-toggle; product ask: the calendar's
   dates/times should read as the "same design concept" as the Bookings-
   list .bk-date chip, section 11 above). Reuses the EXACT tokens .bk-date/
   .bk-date .mon/.day/.tm already use - no new palette, no new type scale.
   demo/app.js buildBookingsCalendar() sets eventTimeFormat/slotLabelFormat/
   listDayFormat/listDaySideFormat to produce the same short-month / plain-
   day / 24h zero-padded "HH:MM" strings .bk-date already shows (bkDateParts()
   -> fmtAbs(iso,'time')); this block makes them LOOK the part too, in the
   three places a booking's date/time actually renders on the calendar:
   month-view day numbers, the day/week time-grid axis + event time labels,
   and the list-view day headers + event times.
   ---- */

/* Month view day numbers - same weight/tracking/tabular-nums as .bk-date
   .day (the big bold day number in the list chip). */
#calendar-root .fc-daygrid-day-number {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: var(--tracking-tight);
  color: var(--text-primary);
  font-size: var(--fs-sm);
  padding: 6px 8px;
}
/* Today's day number: a filled brand-color circle, not just a tinted
   column (--fc-today-bg-color above already gives the whole column a
   subtle var(--brand-soft) wash) - the Apple Calendar "today" idiom.
   padding:0 + explicit width/height override the generic 6px/8px padding
   + auto sizing the rule above gives every OTHER day number, so the
   circle comes out a clean ~26px regardless of the number's own digit
   width (1 vs 2 digits). */
#calendar-root .fc-day-today .fc-daygrid-day-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  margin: 3px;
  border-radius: 50%;
  background: var(--brand);
  /* Literal white, NOT var(--text-inverse) - --text-inverse resolves dark
     (#1d1d1f) in the dark palette (it's tuned for text-on-LIGHT-surface
     contexts, e.g. a white button in dark mode), which would put
     near-black text on this bright blue circle and make the date
     unreadable. A colored brand fill wants white text in both themes -
     same reasoning the existing .fc-button-primary.fc-button-active rule
     above already hardcodes color:#fff instead of --text-inverse. */
  color: #fff;
  font-weight: 700;
}

/* Day/week time-grid axis ("HH:MM" rail down the left) - same mono +
   tabular-nums treatment as .bk-date .tm. */
#calendar-root .fc-timegrid-slot-label-cushion {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 600;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

/* Event time text (month-view event chips + day/week event labels) -
   mirrors .bk-date .tm's mono/tabular treatment; sits on a solid status
   color fill (section 16 above) so it inherits that fill's white text. */
#calendar-root .fc-event-time {
  font-family: var(--font-mono);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* List view day headers ("Jul 15" / "Wed") - .fc-list-day-text gets the
   .bk-date .day treatment (bold, primary, tracked-in); .fc-list-day-side-
   text gets the .bk-date .mon treatment (small, uppercase, tertiary,
   tracked-out label). */
#calendar-root .fc-list-day-text {
  font-weight: 800;
  color: var(--text-primary);
  letter-spacing: var(--tracking-tight);
}
#calendar-root .fc-list-day-side-text {
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-tertiary);
}

/* List view event time column - same mono/tabular chip idiom as .bk-date .tm.
   No color override needed: buildBookingsCalendar() sets
   views:{listWeek:{displayEventTime:false}}, so this column never actually
   renders on the one list view this app exposes (listWeek) - the .bk-date
   chip's own .tm already shows the time. Kept for any future list view
   that re-enables it; would inherit the neutral row's default text color
   (section 16 REDESIGN above removed the old forced
   color:var(--text-inverse) row fill - list rows are neutral now). */
#calendar-root .fc-list-event-time {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ----
   16d. CALENDAR LIST-VIEW .bk-date CHIP (Task 12 - product ask: "calendar
   events should show the exact same blue date chip as the booking cards",
   not just matching fonts/weights). demo/app.js's calEventContent() builds
   the SAME .bk-date/.mon/.day/.tm markup renderBookings() uses for the
   Bookings-list cards and returns it as the list-view event's inner
   content, nested inside FullCalendar's own <td class="fc-list-event-title">.
   This block is ONLY the flex glue to lay the chip beside a title inside
   that cell, plus ONE opaque-backing fix (below) - every color/font/weight
   token is .bk-date's own (reused, not new). Month/week/day views are
   untouched: calEventContent() returns undefined there, so they keep the
   section-16c compact treatment.

   IMPORTANT - which ".bk-date" rule actually wins: app.linear.css's own
   section-11 ".bk-date" rule (gray bg-subtle chip) is NOT the one that
   renders on screen. demo/app.html carries a LATER inline
   "<style id=bd-booking-css">" block with its own ".bk-date" rule (same
   0,1,0 specificity - last one in document order wins the tie) that sets
   background:var(--brand-soft) (a translucent ~10% blue tint) and
   .mon{color:var(--brand)} - THIS is the actual blue chip product asked to
   match, confirmed via a live CSSOM rule-match probe against the rendered
   page. calEventContent() reuses the .bk-date/.mon/.day/.tm class names
   verbatim, so it automatically inherits this same rule - no new chip CSS
   needed for that part. ---- */

#calendar-root .fc-bk-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  width: 100%;
}

/* Contrast fix: .bk-date's background is a TRANSLUCENT tint (by design -
   on the plain Bookings-list card it composites over that card's opaque
   var(--bg-elevated) surface). Layering an opaque var(--bg-elevated) base
   UNDER the tint (two background LAYERS - a flat two-stop gradient
   standing in for a plain color layer, since the background shorthand
   allows only one plain-color layer) makes the chip composite identically
   to how it already looks on the booking card, regardless of what the
   list row underneath looks like. Base/default is still the brand tint
   (unstatused fallback); the redesign below (16f) overrides this per
   status with .bk-date.bk-<status>, which app.js's calEventContent() now
   adds alongside the existing .bk-date class. */
#calendar-root .bk-date {
  background: linear-gradient(var(--brand-soft), var(--brand-soft)), var(--bg-elevated);
}

/* ----
   16f. CALENDAR LIST-VIEW CHIP STATUS COLOR (Apple redesign). The chip's
   .mon/.tm text was hardcoded blue (app.html's inline <style id=
   "bd-booking-css"> .mon{color:var(--brand)}, same rule the plain
   Bookings-list date chip uses) - fine there since a booking card has no
   separate status signal on the chip itself, but on the calendar the list
   row is deliberately neutral now (16 above), so the chip is the primary
   place status shows in list view. Higher specificity here
   (#calendar-root .bk-date.bk-<status> .mon = 1 id + 3 classes) beats the
   inline rule's plain .mon (1 class) without touching app.html. .day (the
   big day number) is left alone - spec only calls out .mon/.tm. */
#calendar-root .bk-date.bk-requested { background: linear-gradient(var(--cal-requested-tint), var(--cal-requested-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-requested .mon, #calendar-root .bk-date.bk-requested .tm { color: var(--cal-requested-text); }

#calendar-root .bk-date.bk-confirmed { background: linear-gradient(var(--cal-confirmed-tint), var(--cal-confirmed-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-confirmed .mon, #calendar-root .bk-date.bk-confirmed .tm { color: var(--cal-confirmed-text); }

#calendar-root .bk-date.bk-checked_in { background: linear-gradient(var(--cal-checked_in-tint), var(--cal-checked_in-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-checked_in .mon, #calendar-root .bk-date.bk-checked_in .tm { color: var(--cal-checked_in-text); }

#calendar-root .bk-date.bk-completed { background: linear-gradient(var(--cal-completed-tint), var(--cal-completed-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-completed .mon, #calendar-root .bk-date.bk-completed .tm { color: var(--cal-completed-text); }

#calendar-root .bk-date.bk-no_show { background: linear-gradient(var(--cal-no_show-tint), var(--cal-no_show-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-no_show .mon, #calendar-root .bk-date.bk-no_show .tm { color: var(--cal-no_show-text); }

#calendar-root .bk-date.bk-cancelled { background: linear-gradient(var(--cal-cancelled-tint), var(--cal-cancelled-tint)), var(--bg-elevated); }
#calendar-root .bk-date.bk-cancelled .mon, #calendar-root .bk-date.bk-cancelled .tm { color: var(--cal-cancelled-text); }

#calendar-root .fc-bk-title {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Cancelled rows: section 16 above strikes through .fc-list-event-title
   directly; extend the same treatment to the chip-row title so it still
   reads struck-through now that the text lives one level deeper. */
#calendar-root .fc-list-event.bk-cancelled .fc-bk-title {
  text-decoration: line-through;
}

/* ----
   16e. CALENDAR TIME-GRID COMPACT EVENT LABEL (week/day short-booking
   readability fix). A 30-min booking in an hourly timeGridWeek/timeGridDay
   grid rendered as a bare color bar - FullCalendar's own default time/title
   text was clipped below the block's own (short) height. demo/app.js's
   calEventContent() now returns a compact custom node (.fc-bk-grid) for
   timeGrid* views: one line, start time + title, ellipsis-truncated.
   buildBookingsCalendar()'s eventMinHeight:20 (app.js) keeps every
   time-grid block tall enough to actually show that line.

   Contrast (REDESIGN): reuses the same --fc-event-text-color mechanism the
   original fix established, now pointed at the new per-status TEXT tokens
   (--cal-<status>-text) instead of the old --text-inverse/--danger pair.
   It can't just inherit `color` from `.fc-event.bk-<status>` the way the
   list-view chip does: FullCalendar's OWN bundled CSS (vendor/
   fullcalendar.min.js) carries `.fc-v-event .fc-event-main{
   color:var(--fc-event-text-color)}` with `--fc-event-text-color:#fff` as
   its global default - .fc-event-main sits between our label and the
   .fc-event.bk-<status> ancestor and declares its OWN `color`, which cuts
   the inheritance chain (verified live pre-fix: a no_show label rendered
   white-on-tint before this override existed). Belt-and-suspenders: also
   add a `.bk-<status>` class directly onto the `.fc-bk-grid` wrap itself
   (app.js calEventContent()) with its own `color` rule below - an
   explicitly-set color always wins over an inherited one regardless of
   the ancestor chain, so the label stays correct even if a future
   FullCalendar bump changes how .fc-event-main resolves its color. ---- */
#calendar-root .fc-timegrid-event.bk-requested  { --fc-event-text-color: var(--cal-requested-text); }
#calendar-root .fc-timegrid-event.bk-confirmed  { --fc-event-text-color: var(--cal-confirmed-text); }
#calendar-root .fc-timegrid-event.bk-checked_in { --fc-event-text-color: var(--cal-checked_in-text); }
#calendar-root .fc-timegrid-event.bk-completed  { --fc-event-text-color: var(--cal-completed-text); }
#calendar-root .fc-timegrid-event.bk-no_show    { --fc-event-text-color: var(--cal-no_show-text); }
#calendar-root .fc-timegrid-event.bk-cancelled  { --fc-event-text-color: var(--cal-cancelled-text); }

#calendar-root .fc-timegrid-event .fc-event-main {
  min-height: 20px;   /* belt-and-suspenders for eventMinHeight (app.js) - keeps the label un-clipped even if a future edit removes the JS option */
}

#calendar-root .fc-bk-grid {
  display: flex;
  align-items: baseline;
  gap: 4px;
  width: 100%;
  min-width: 0;
  padding: 1px 3px;
  font-size: var(--fs-2xs);
  line-height: 1.3;
  overflow: hidden;
}
#calendar-root .fc-bk-grid-tm {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
#calendar-root .fc-bk-grid-title {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Direct status color on the label itself (app.js now adds 'bk-'+status
   to .fc-bk-grid alongside the existing wrap class) - see the comment
   above this rule's --fc-event-text-color siblings for why this is
   belt-and-suspenders rather than the only mechanism. */
#calendar-root .fc-bk-grid.bk-requested  { color: var(--cal-requested-text); }
#calendar-root .fc-bk-grid.bk-confirmed  { color: var(--cal-confirmed-text); }
#calendar-root .fc-bk-grid.bk-checked_in { color: var(--cal-checked_in-text); }
#calendar-root .fc-bk-grid.bk-completed  { color: var(--cal-completed-text); }
#calendar-root .fc-bk-grid.bk-no_show    { color: var(--cal-no_show-text); }
#calendar-root .fc-bk-grid.bk-cancelled  { color: var(--cal-cancelled-text); }

/* ----
   16g. CALENDAR MONTH-VIEW DOT+TITLE MINI-ROW (product ask 2026-07-02).
   FullCalendar's own dayGridMonth default rendering ("fc-daygrid-dot-event" -
   a thin color bar, title clipped once a day gets busy) read cramped next to
   Apple Calendar's month idiom: a small status-accent dot + time + title on
   one line, background nearly transparent. calEventContent() (app.js) now
   returns a custom .fc-bk-month node for dayGridMonth, mirroring the
   .fc-bk-grid pattern section 16e already established for week/day.

   This block has two parts:
   (a) the dot+time+title row layout itself, and
   (b) an override of the shared pill background/box-shadow/border/padding
       the REDESIGN rules (section 16 above) put on the SAME
       .fc-daygrid-event.bk-<status> ancestor our custom content still
       renders inside - same selector text, same specificity (1 id + 2
       classes), placed LATER in this file so it wins the cascade tie
       without touching week/day (.fc-timegrid-event.bk-<status> is a
       different ancestor entirely, left alone - that view keeps its
       filled pill). Without this override the month row would still show
       the tinted background + inset accent bar from section 16 UNDER the
       new dot+text row, defeating the "mostly transparent, dot + text"
       Apple look. ---- */

#calendar-root .fc-daygrid-event.bk-requested,
#calendar-root .fc-daygrid-event.bk-confirmed,
#calendar-root .fc-daygrid-event.bk-checked_in,
#calendar-root .fc-daygrid-event.bk-completed,
#calendar-root .fc-daygrid-event.bk-no_show,
#calendar-root .fc-daygrid-event.bk-cancelled {
  background: transparent;
  box-shadow: none;
  border: none;
  padding: 1px 4px;
}
#calendar-root .fc-daygrid-event.bk-requested:hover,
#calendar-root .fc-daygrid-event.bk-confirmed:hover,
#calendar-root .fc-daygrid-event.bk-checked_in:hover,
#calendar-root .fc-daygrid-event.bk-completed:hover,
#calendar-root .fc-daygrid-event.bk-no_show:hover,
#calendar-root .fc-daygrid-event.bk-cancelled:hover {
  background: var(--bg-hover);
  box-shadow: none;
}

#calendar-root .fc-bk-month {
  display: flex;
  align-items: center;
  gap: 5px;
  width: 100%;
  min-width: 0;
  font-size: 11px;
  line-height: 1.35;
  overflow: hidden;
}
#calendar-root .fc-bk-month-dot {
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
}
#calendar-root .fc-bk-month-tm {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
#calendar-root .fc-bk-month-title {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Dot fill = status ACCENT var. No-show stays hollow (transparent fill +
   accent-colored ring) - same "hollow reads distinct from cancelled's solid
   fill" idiom the list-view dot (section 16, .fc-list-event-dot) already
   uses for the same status. */
#calendar-root .fc-bk-month.bk-requested  .fc-bk-month-dot { background: var(--cal-requested-accent); }
#calendar-root .fc-bk-month.bk-confirmed  .fc-bk-month-dot { background: var(--cal-confirmed-accent); }
#calendar-root .fc-bk-month.bk-checked_in .fc-bk-month-dot { background: var(--cal-checked_in-accent); }
#calendar-root .fc-bk-month.bk-completed  .fc-bk-month-dot { background: var(--cal-completed-accent); }
#calendar-root .fc-bk-month.bk-no_show    .fc-bk-month-dot { background: transparent; border: 1.5px solid var(--cal-no_show-accent); }
#calendar-root .fc-bk-month.bk-cancelled  .fc-bk-month-dot { background: var(--cal-cancelled-accent); }

/* Row text (time + title both inherit) = status TEXT var - same wrapper-
   level color idiom as .fc-bk-grid.bk-<status> (section 16e) uses for
   week/day. */
#calendar-root .fc-bk-month.bk-requested  { color: var(--cal-requested-text); }
#calendar-root .fc-bk-month.bk-confirmed  { color: var(--cal-confirmed-text); }
#calendar-root .fc-bk-month.bk-checked_in { color: var(--cal-checked_in-text); }
#calendar-root .fc-bk-month.bk-completed  { color: var(--cal-completed-text); }
#calendar-root .fc-bk-month.bk-no_show    { color: var(--cal-no_show-text); }
#calendar-root .fc-bk-month.bk-cancelled  { color: var(--cal-cancelled-text); }

/* Cancelled: title only (not the time) gets struck-through - mirrors the
   list (.fc-bk-title) and week/day (.fc-bk-grid-title) cancelled treatment
   above. The row's overall fade comes from the existing ancestor rule
   `.fc-daygrid-event.bk-cancelled { opacity: 0.72 }` (section 16, untouched
   by this block) - not repeated here to avoid double-fading. */
#calendar-root .fc-bk-month.bk-cancelled .fc-bk-month-title {
  text-decoration: line-through;
}

/* ----
   16h. CALENDAR EVENT TITLE SENTENCE-CASE (product ask 2026-07-02):
   booking titles are assembled from raw contact/service data (app.js
   bookingToEvent(): `who + ' - ' + svc`) which is often already lowercase
   (e.g. a WhatsApp contact name or a service label typed in lowercase).
   ::first-letter + text-transform:uppercase upper-cases ONLY the very
   first character of the title - NOT text-transform:capitalize, which
   would upper-case the first letter of EVERY word (product explicitly
   asked for sentence case, not Title Case). Scoped to the title element
   ONLY in each view (.fc-bk-title list / .fc-bk-grid-title week+day /
   .fc-bk-month-title month) - never the .bk-date chip's mon/day/tm spans
   or the .fc-bk-grid-tm/.fc-bk-month-tm time spans, so a "HH:MM" time
   string is never touched. Each title element is its own flex-item span/
   div (blockified per the flexbox spec, which is what makes ::first-letter
   apply at all - it only targets block-container boxes) sitting beside,
   never sharing a node with, its view's time element - see calEventContent()
   comments (app.js) for why the title is deliberately its own DOM node. */
#calendar-root .fc-bk-title::first-letter,
#calendar-root .fc-bk-grid-title::first-letter,
#calendar-root .fc-bk-month-title::first-letter {
  text-transform: uppercase;
}
