/* =====================================================================
   Bill Snak Pool Services — Design Tokens
   ---------------------------------------------------------------------
   Cool & calm palette. Pure white page, deep teal primary, slate ink.
   Accents kept restrained — water-blue does most work; a single sun
   amber appears only on critical/needs-attention states.
   ===================================================================== */

:root {
  /* Paper / surfaces — pure whites with the faintest cool wash */
  --paper:       #ffffff;                /* page background */
  --paper-2:     oklch(98.5% 0.005 220); /* card / sunken (barely-blue) */
  --paper-3:     oklch(96% 0.008 220);   /* hover / active */
  --surface:     #ffffff;                /* card on paper */
  --line:        oklch(92% 0.01 220);    /* hairlines */
  --line-strong: oklch(85% 0.015 220);

  /* Ink — cool slate */
  --ink:         oklch(22% 0.02 235);
  --ink-2:       oklch(34% 0.02 235);    /* body */
  --ink-3:       oklch(50% 0.02 235);    /* muted */
  --ink-4:       oklch(68% 0.015 235);   /* placeholder */

  /* Brand — deep pool teal */
  --pool-deep:   oklch(38% 0.10 215);    /* deep end */
  --pool:        oklch(52% 0.12 210);    /* primary */
  --pool-bright: oklch(68% 0.13 205);    /* shallow end */
  --pool-tint:   oklch(95% 0.025 210);   /* washes */
  --pool-ink:    oklch(26% 0.06 215);    /* on-pool text */

  /* Accents — quiet, only one warm color reserved for needs-attention */
  --sun:         oklch(82% 0.13 80);     /* soft amber — used sparingly */
  --sun-ink:     oklch(40% 0.10 70);
  --clay:        oklch(58% 0.10 220);    /* repurposed: cool steel-blue */
  --clay-tint:   oklch(95% 0.025 220);
  --sage:        oklch(62% 0.08 175);    /* mint-teal for ok/chem */
  --sage-tint:   oklch(95% 0.025 175);
  --alert:       oklch(58% 0.16 28);     /* tomato — reserved, rare */
  --alert-tint:  oklch(96% 0.03 28);

  /* Coral — second accent, complement to teal. Used for the AI agent
     (OpenClaw), warm highlights, and any "in-progress / human" cue. */
  --coral:       oklch(68% 0.16 28);     /* primary coral */
  --coral-deep:  oklch(54% 0.16 25);     /* on-light text / borders */
  --coral-tint:  oklch(96% 0.035 28);    /* washes / bubble bg */
  --coral-ink:   oklch(34% 0.12 25);     /* text on coral */

  /* Tile — pool ceramic */
  --tile:        oklch(55% 0.10 210);

  /* Radii + shadow */
  --r-sm: 8px;
  --r:    12px;
  --r-lg: 18px;
  --r-xl: 24px;
  --shadow-xs: 0 1px 0 rgba(30,40,50,.04);
  --shadow-sm: 0 2px 6px -2px rgba(30,50,70,.10), 0 1px 2px rgba(30,50,70,.06);
  --shadow-md: 0 8px 24px -10px rgba(30,50,70,.18), 0 2px 6px -2px rgba(30,50,70,.08);
  --shadow-lg: 0 24px 60px -20px rgba(20,40,60,.28), 0 6px 18px -6px rgba(20,40,60,.12);

  /* Type */
  --font-display: "Bricolage Grotesque", "Iowan Old Style", Georgia, serif;
  --font-ui:      "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono:    "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

  /* Density — toggled via tweaks */
  --density: 1;
  --tap:     44px;
}

/* Mood variants — all stay in the cool/calm family */
[data-mood="clean"] {
  /* default — pure white page */
}
[data-mood="deep"] {
  /* page picks up a faint teal wash */
  --paper:    oklch(98% 0.012 215);
  --paper-2:  oklch(96% 0.018 215);
  --paper-3:  oklch(93% 0.025 215);
  --pool-tint: oklch(94% 0.035 210);
}
[data-mood="sky"] {
  /* palest blue page, slightly higher chroma teal */
  --paper:    oklch(98.5% 0.012 230);
  --paper-2:  oklch(96.5% 0.018 230);
  --paper-3:  oklch(94% 0.024 230);
  --pool:        oklch(50% 0.14 220);
  --pool-deep:   oklch(36% 0.12 220);
  --pool-bright: oklch(66% 0.15 215);
}

[data-density="compact"] { --density: 0.82; }
[data-density="cozy"]    { --density: 1.12; }

/* =====================================================================
   Dark theme — "night pool"
   Slate-teal page, ink-deep surfaces, brand teal kept saturated so the
   live-call hero / pool accents still glow. Composes with [data-mood].
   ===================================================================== */
[data-theme="dark"] {
  /* Paper / surfaces */
  --paper:       oklch(16% 0.018 230);
  --paper-2:     oklch(20% 0.020 228);   /* card / sunken */
  --paper-3:     oklch(24% 0.022 226);   /* hover / active */
  --surface:     oklch(22% 0.022 228);   /* card on paper */
  --line:        oklch(30% 0.020 225);
  --line-strong: oklch(38% 0.022 222);

  /* Ink — flipped */
  --ink:         oklch(96% 0.012 220);
  --ink-2:       oklch(86% 0.012 220);
  --ink-3:       oklch(68% 0.012 222);
  --ink-4:       oklch(52% 0.014 224);

  /* Brand — slightly brighter so it reads on dark */
  --pool-deep:   oklch(46% 0.12 215);
  --pool:        oklch(60% 0.13 210);
  --pool-bright: oklch(74% 0.14 205);
  --pool-tint:   oklch(28% 0.05 215);     /* deep wash for backgrounds */
  --pool-ink:    oklch(92% 0.04 215);     /* on-pool text */

  /* Accents */
  --sun:         oklch(78% 0.14 80);
  --sun-ink:     oklch(28% 0.08 70);
  --clay:        oklch(66% 0.11 220);
  --clay-tint:   oklch(28% 0.05 220);
  --sage:        oklch(68% 0.09 175);
  --sage-tint:   oklch(28% 0.04 175);
  --alert:       oklch(70% 0.16 28);
  --alert-tint:  oklch(28% 0.06 28);

  /* Coral */
  --coral:       oklch(72% 0.15 28);
  --coral-deep:  oklch(64% 0.16 25);
  --coral-tint:  oklch(28% 0.06 28);
  --coral-ink:   oklch(92% 0.04 25);

  --tile:        oklch(60% 0.10 210);

  /* Shadows — much subtler on dark, mostly outlines */
  --shadow-xs: 0 1px 0 rgba(0,0,0,.30);
  --shadow-sm: 0 2px 8px -2px rgba(0,0,0,.45), 0 1px 2px rgba(0,0,0,.35);
  --shadow-md: 0 10px 28px -10px rgba(0,0,0,.55), 0 2px 6px -2px rgba(0,0,0,.40);
  --shadow-lg: 0 28px 60px -20px rgba(0,0,0,.70), 0 6px 18px -6px rgba(0,0,0,.45);

  color-scheme: dark;
}

/* Mood overrides on top of dark theme — keep page tone consistent */
[data-theme="dark"][data-mood="deep"] {
  --paper:    oklch(15% 0.024 215);
  --paper-2:  oklch(19% 0.026 215);
  --paper-3:  oklch(23% 0.028 215);
  --pool-tint: oklch(30% 0.06 210);
}
[data-theme="dark"][data-mood="sky"] {
  --paper:    oklch(16% 0.022 230);
  --paper-2:  oklch(20% 0.024 230);
  --paper-3:  oklch(24% 0.026 230);
  --pool:        oklch(62% 0.14 220);
  --pool-deep:   oklch(48% 0.13 220);
  --pool-bright: oklch(76% 0.15 215);
}

/* Component tweaks for dark — places where light values are hard-coded */
[data-theme="dark"] .brand-mark::after {
  background: rgba(255,255,255,.35);
}
[data-theme="dark"] .brand-mark {
  box-shadow: inset 0 -2px 4px rgba(0,0,0,.4), 0 2px 6px -2px rgba(0,0,0,.5);
}
[data-theme="dark"] .nav-item.active .nav-icon { color: var(--pool-bright); }
[data-theme="dark"] .stat-tile.attention {
  background: linear-gradient(180deg, var(--clay-tint), var(--surface) 60%);
}
[data-theme="dark"] .stat-tile.attention .stat-value { color: oklch(80% 0.13 38); }
[data-theme="dark"] .chip.pool { border-color: oklch(40% 0.08 210); }
[data-theme="dark"] .chip.sun  { background: oklch(28% 0.07 78); color: oklch(86% 0.13 78); border-color: oklch(40% 0.10 70); }
[data-theme="dark"] .chip.clay { border-color: oklch(40% 0.09 40); color: oklch(82% 0.10 38); }
[data-theme="dark"] .chip.sage { color: oklch(82% 0.09 155); border-color: oklch(40% 0.07 155); }
[data-theme="dark"] .chip.alert { color: oklch(82% 0.14 25); border-color: oklch(42% 0.10 25); }
[data-theme="dark"] .chip.ink { background: var(--ink); color: var(--paper); }

[data-theme="dark"] .avatar { background: var(--pool-tint); color: var(--pool-bright); }
[data-theme="dark"] .avatar.clay { background: var(--clay-tint); color: oklch(82% 0.10 38); }
[data-theme="dark"] .avatar.sun  { background: oklch(28% 0.07 78); color: oklch(86% 0.13 78); }
[data-theme="dark"] .avatar.sage { background: var(--sage-tint); color: oklch(82% 0.09 155); }

/* Live-hero: the gradient already reads well on dark, just adjust the
   transparent overlays so they don't get muddy */
[data-theme="dark"] .live-hero {
  background:
    radial-gradient(circle at 100% 0%, oklch(60% 0.16 70 / .25), transparent 55%),
    linear-gradient(135deg, oklch(28% 0.10 215), oklch(40% 0.13 210) 55%, oklch(54% 0.14 205));
}
[data-theme="dark"] .live-hero .live-transcript { background: rgba(0,0,0,.22); }

/* Outgoing message bubble — darken so it isn't a punchy near-white teal */
[data-theme="dark"] .msg-bubble.out { background: var(--pool-deep); }
[data-theme="dark"] .msg-bubble.out.agent { background: oklch(48% 0.14 70); color: oklch(96% 0.04 75); }

/* Buttons */
[data-theme="dark"] .btn.primary:hover { background: oklch(52% 0.13 210); }

/* Drawer/sheet backdrop — deeper */
[data-theme="dark"] .drawer-backdrop { background: rgba(0,0,0,.55); }
[data-theme="dark"] .sheet-backdrop  { background: rgba(0,0,0,.55); }

/* Toasts */
[data-theme="dark"] .toast { background: var(--surface); color: var(--ink); border: 1px solid var(--line); }

/* Search/topbar tweaks */
[data-theme="dark"] .topbar .search-global .kbd { background: var(--paper); color: var(--ink-3); border-color: var(--line-strong); }

/* Vehicle card top-fade */
[data-theme="dark"] .vehicle-card::before { background: linear-gradient(180deg, var(--paper-3), transparent); }

/* Recording player waveform — keep contrast */
[data-theme="dark"] .recording-player .waveform {
  background-image: repeating-linear-gradient(to right, var(--line-strong) 0 1px, transparent 1px 3px);
}

/* Img placeholder needs more contrast on dark */
[data-theme="dark"] .img-placeholder {
  background:
    repeating-linear-gradient(135deg,
      var(--paper-2) 0 8px,
      var(--paper-3) 8px 16px);
}

/* Scrollbar thumb on dark */
[data-theme="dark"] ::-webkit-scrollbar-thumb {
  background: var(--line-strong);
  border-color: var(--paper);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font-family: var(--font-ui);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-size: 15px;
  line-height: 1.45;
  letter-spacing: -0.005em;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
}

button { font-family: inherit; }
input, select, textarea { font-family: inherit; color: var(--ink); }

/* A tiny pool-tile motif — faint ceramic grid */
.tile-bg {
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 24px 24px;
  background-position: -1px -1px;
}

/* Ripple — three concentric arcs, very light */
.ripple-bg {
  background:
    radial-gradient(closest-side, transparent calc(100% - 1px), var(--line) 100%) 50% 50% / 160px 160px no-repeat,
    radial-gradient(closest-side, transparent calc(100% - 1px), var(--line) 100%) 50% 50% / 320px 320px no-repeat,
    radial-gradient(closest-side, transparent calc(100% - 1px), var(--line) 100%) 50% 50% / 480px 480px no-repeat;
}

/* Cursor */
.clickable { cursor: pointer; }

/* Scrollbars — slim, paper-toned */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong); border-radius: 10px;
  border: 2px solid var(--paper);
}
::-webkit-scrollbar-track { background: transparent; }

/* Focus */
:focus-visible {
  outline: 2px solid var(--pool);
  outline-offset: 2px;
  border-radius: 4px;
}

/* =====================================================================
   Shell
   ===================================================================== */

.app {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 232px 1fr;
  grid-template-rows: auto 1fr;
  grid-template-areas:
    "brand topbar"
    "nav    main";
}

.brand {
  grid-area: brand;
  padding: 20px 20px 16px;
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px;
  background: var(--paper-2);
}
.brand-mark {
  width: 38px; height: 38px; border-radius: 50%;
  background: radial-gradient(circle at 32% 30%, var(--pool-bright), var(--pool) 55%, var(--pool-deep));
  position: relative;
  box-shadow: inset 0 -2px 4px rgba(0,0,0,.1), 0 2px 6px -2px rgba(30,80,120,.4);
  flex-shrink: 0;
}
.brand-mark::after {
  content: "";
  position: absolute;
  top: 6px; left: 9px;
  width: 10px; height: 6px;
  border-radius: 50%;
  background: rgba(255,255,255,.55);
  filter: blur(.5px);
}
.brand-wordmark {
  line-height: 1;
  display: flex; flex-direction: column; gap: 3px;
}
.brand-wordmark .brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.brand-wordmark .brand-sub {
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
}

.topbar {
  grid-area: topbar;
  /* Same iOS-notch handling as drawer-head — push the topbar contents
     below the status bar in standalone PWA mode. On desktop and Android
     env(safe-area-inset-top) is 0 so this is a no-op. */
  padding: calc(14px + env(safe-area-inset-top)) 22px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
  display: flex; align-items: center; gap: 16px;
  min-height: 71px;
}
.topbar .greeting {
  display: flex; flex-direction: column; gap: 2px;
}
.topbar .greeting h1 {
  font-size: 20px;
  line-height: 1.1;
}
.topbar .greeting .date {
  font-size: 12.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.topbar .topbar-spacer { flex: 1; }
/* Topbar theme-toggle — give the button a real, sized clickable area
   on DESKTOP too. Without this rule the <button> shrinks to its
   16-px icon on desktop, and miss-clicks bleed onto the neighboring
   live-call indicator (which navigates to the call log). Real bug
   2026-05-02: user reported "clicking the sun/moon brings up a call
   log" — turned out to be a hit-target-too-small issue. */
.topbar .theme-toggle {
  width: 36px; height: 36px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: transparent;
  color: var(--ink-2);
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 0.15s;
}
.topbar .theme-toggle:hover { background: var(--line); }

.topbar .conn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px; border-radius: 999px;
  font-size: 12px; color: var(--ink-3);
  background: var(--paper-2); border: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.topbar .conn .conn-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--ink-4);
}
.topbar .conn.ok .conn-dot { background: var(--sage); box-shadow: 0 0 0 3px var(--sage-tint); }
.topbar .conn.live .conn-dot { background: var(--clay); animation: pulse 1.4s infinite; }
@keyframes pulse { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: .4; transform: scale(.85); } }
/* When .conn is rendered as a <button> (live-calls pill), strip browser
   defaults and add subtle interactivity. Lit-up clay color matches the
   .conn.live pulse so the whole pill reads as "active call." */
button.conn {
  font: inherit; cursor: pointer;
}
button.conn.live {
  color: var(--clay); border-color: var(--clay-tint, color-mix(in srgb, var(--clay) 30%, transparent));
  background: color-mix(in srgb, var(--clay) 8%, var(--paper-2));
}
button.conn.live:hover {
  background: color-mix(in srgb, var(--clay) 14%, var(--paper-2));
}

.topbar .search-global {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper-2);
  width: 280px;
  max-width: 40vw;
}
.topbar .search-global input {
  border: 0; outline: 0; background: transparent;
  flex: 1; font-size: 14px;
  min-width: 0;
}
.topbar .search-global input::placeholder { color: var(--ink-4); }
.topbar .search-global .kbd {
  font-family: var(--font-mono);
  font-size: 10px; color: var(--ink-4);
  padding: 2px 5px; border: 1px solid var(--line);
  border-radius: 4px; background: var(--paper);
}

.nav {
  grid-area: nav;
  border-right: 1px solid var(--line);
  background: var(--paper-2);
  padding: 16px 12px 20px;
  display: flex; flex-direction: column; gap: 2px;
  position: sticky; top: 0;
  align-self: start;
  min-height: calc(100vh - 71px);
}
.nav-section {
  font-size: 10px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink-4);
  font-weight: 600;
  padding: 12px 10px 6px;
}
.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink-2);
  cursor: pointer;
  border: none;
  background: transparent;
  text-align: left;
  min-height: var(--tap);
  width: 100%;
  position: relative;
  transition: background .1s ease;
}
.nav-item:hover { background: var(--paper-3); }
.nav-item.active {
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.nav-item .nav-icon {
  width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-3);
}
.nav-item.active .nav-icon { color: var(--pool-deep); }
.nav-item .nav-badge {
  margin-left: auto;
  background: var(--clay); color: #fff;
  font-size: 10.5px; font-weight: 600;
  padding: 1px 7px; border-radius: 999px;
  min-width: 20px; text-align: center;
  font-variant-numeric: tabular-nums;
}

.main {
  grid-area: main;
  padding: 24px 28px 56px;
  max-width: 1280px;
  width: 100%;
  /* CRITICAL: grid items default to min-width:auto (= min-content). When a
   * view has wide intrinsic content (e.g. the Debug page's 11-column
   * timings table with nowrap cells, or its cards with long unwrapped
   * command-line subs), min-content is huge — the 1fr track expands past
   * its allocation, the whole .app grid widens, and the topbar gets
   * pushed off-screen on the right. Setting min-width:0 lets the 1fr
   * track honor its allocated space and forces wide content to scroll
   * INSIDE its own container (e.g. .dbg-table-wrap's overflow-x:auto). */
  min-width: 0;
}

/* Same fix at the outer grid level, defensive: prevent a wide grid item
 * from making the whole .app grid wider than the viewport. */
.app { max-width: 100vw; overflow-x: hidden; }

/* =====================================================================
   Reusable primitives
   ===================================================================== */

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-xs);
}
.card.flat { box-shadow: none; }
.card-header {
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 10px;
}
.card-header h2, .card-header h3 {
  font-size: 15px;
  font-family: var(--font-ui);
  font-weight: 600;
  letter-spacing: -0.01em;
  flex: 1;
}
.card-body { padding: 18px; }

.eyebrow {
  font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-3); font-weight: 600;
}

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  margin-bottom: 22px; gap: 16px;
  flex-wrap: wrap;
}
.page-head h1 {
  font-size: 32px;
  font-family: var(--font-display);
  font-weight: 600;
  letter-spacing: -0.025em;
  line-height: 1.1;
}
.page-head .subtitle {
  font-size: 14px; color: var(--ink-3);
  margin-top: 4px;
  max-width: 56ch;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 0 16px;
  border-radius: 10px;
  font-size: 14px; font-weight: 600;
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform .04s ease, background .1s ease, border-color .1s ease;
}
.btn:active { transform: translateY(1px); }
.btn.primary {
  background: var(--pool-deep); color: #fff;
  border-color: var(--pool-deep);
}
.btn.primary:hover { background: oklch(38% 0.11 210); }
.btn.secondary {
  background: var(--surface); color: var(--ink);
  border-color: var(--line-strong);
}
.btn.secondary:hover { background: var(--paper-2); }
.btn.ghost {
  background: transparent; color: var(--ink-2);
  border-color: transparent;
}
.btn.ghost:hover { background: var(--paper-2); }
.btn.danger {
  background: var(--alert-tint); color: var(--alert);
  border-color: var(--alert);
}
.btn.sun {
  background: var(--sun); color: var(--sun-ink);
  border-color: oklch(72% 0.16 65);
}
.btn.sun:hover { filter: brightness(0.96); }
.btn.sm { min-height: 34px; padding: 0 12px; font-size: 13px; }
.btn.xs { min-height: 28px; padding: 0 10px; font-size: 12px; font-weight: 500; }

.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 500;
  padding: 3px 9px;
  border-radius: 999px;
  background: var(--paper-2);
  color: var(--ink-2);
  border: 1px solid var(--line);
  white-space: nowrap;
}
.chip.pool { background: var(--pool-tint); color: var(--pool-deep); border-color: oklch(82% 0.06 210); }
.chip.sun  { background: oklch(96% 0.04 78); color: var(--sun-ink); border-color: oklch(86% 0.08 70); }
.chip.clay { background: var(--clay-tint); color: oklch(38% 0.11 38); border-color: oklch(86% 0.08 40); }
.chip.sage { background: var(--sage-tint); color: oklch(38% 0.08 155); border-color: oklch(85% 0.06 155); }
.chip.alert { background: var(--alert-tint); color: var(--alert); border-color: oklch(85% 0.09 25); }
.chip.ink { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--ink-4);
}
.dot.pool { background: var(--pool); }
.dot.sun { background: var(--sun); }
.dot.clay { background: var(--clay); }
.dot.sage { background: var(--sage); }
.dot.alert { background: var(--alert); animation: pulse 1.4s infinite; }

.avatar {
  width: 36px; height: 36px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 13px;
  background: var(--pool-tint); color: var(--pool-deep);
  flex-shrink: 0;
  letter-spacing: -0.02em;
}
.avatar.lg { width: 52px; height: 52px; font-size: 17px; }
.avatar.sm { width: 28px; height: 28px; font-size: 11px; }
.avatar.clay { background: var(--clay-tint); color: oklch(40% 0.12 38); }
.avatar.sun  { background: oklch(94% 0.06 78); color: var(--sun-ink); }
.avatar.sage { background: var(--sage-tint); color: oklch(38% 0.08 155); }

.input, input[type="text"].input, input[type="search"].input, select.input, textarea.input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font-size: 14px;
  font-family: inherit;
}
.input:focus { border-color: var(--pool); outline: none; box-shadow: 0 0 0 3px var(--pool-tint); }

.hairline { border: 0; border-top: 1px solid var(--line); margin: 0; }

.empty-state {
  padding: 48px 24px;
  text-align: center;
  color: var(--ink-3);
  font-size: 14px;
}

/* Placeholder "image" tile used in docs */
.img-placeholder {
  width: 100%; aspect-ratio: 4/3;
  background:
    repeating-linear-gradient(135deg,
      var(--paper-2) 0 8px,
      var(--paper-3) 8px 16px);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-3);
  font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: 0.12em; text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}

/* =====================================================================
   Page: Today (landing)
   ===================================================================== */

.today-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: 20px;
  align-items: start;
}
@media (max-width: 1180px) {
  .today-grid { grid-template-columns: minmax(0, 1fr); }
  .today-side { position: static; }
}
.today-main { display: flex; flex-direction: column; gap: 20px; min-width: 0; }
.today-side { display: flex; flex-direction: column; gap: 20px; position: sticky; top: 16px; }

/* Live call hero — the one "hot" element */
.live-hero {
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(circle at 100% 0%, oklch(85% 0.14 70 / .35), transparent 55%),
    linear-gradient(135deg, var(--pool-deep), var(--pool) 55%, var(--pool-bright));
  color: #fff;
  border-radius: var(--r-lg);
  padding: 22px 24px;
  box-shadow: var(--shadow-md);
}
.live-hero::before {
  /* wave lines along bottom */
  content: "";
  position: absolute; inset: auto 0 0 0; height: 60px;
  background:
    radial-gradient(ellipse 120px 10px at 25% 100%, rgba(255,255,255,.18), transparent 60%),
    radial-gradient(ellipse 160px 12px at 75% 100%, rgba(255,255,255,.12), transparent 60%);
  pointer-events: none;
}
.live-hero .live-head {
  display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.live-hero .live-tag {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; letter-spacing: 0.14em;
  text-transform: uppercase; font-weight: 700;
  padding: 4px 10px; border-radius: 999px;
  background: var(--clay); color: #fff;
}
.live-hero .live-dur {
  margin-left: auto;
  font-family: var(--font-mono);
  font-size: 13px; opacity: 0.8;
}
.live-hero h2 {
  font-family: var(--font-display);
  font-size: 26px; color: #fff; line-height: 1.1;
  margin-bottom: 4px;
}
.live-hero .live-meta { font-size: 13px; opacity: .85; }
.live-hero .live-transcript {
  margin-top: 16px;
  background: rgba(255,255,255,.12);
  border-radius: 10px;
  padding: 12px 14px;
  max-height: 140px; overflow-y: auto;
  backdrop-filter: blur(8px);
}
.live-hero .live-transcript .turn {
  font-size: 13px; line-height: 1.4; margin-bottom: 6px;
  display: flex; gap: 10px;
  padding: 6px 10px;
  border-radius: 6px;
  border-left: 3px solid transparent;
}
.live-hero .live-transcript .turn.agent {
  background: rgba(255, 165, 140, 0.16);
  border-left-color: var(--coral);
  color: oklch(96% 0.04 28);
}
.live-hero .live-transcript .turn.user {
  background: rgba(255, 255, 255, 0.08);
  border-left-color: rgba(255,255,255,.5);
  color: #fff;
}
.live-hero .live-transcript .role {
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 700; opacity: 0.95;
  min-width: 48px; margin-top: 2px;
}
.live-hero .live-transcript .turn.agent .role { color: oklch(86% 0.10 30); }
.live-hero .live-transcript .turn.user .role { color: rgba(255,255,255,.85); }
.live-hero .live-actions {
  display: flex; gap: 8px; margin-top: 14px;
}
.live-hero .live-actions .btn.on-pool {
  background: rgba(255,255,255,.15); color: #fff;
  border-color: rgba(255,255,255,.3);
  backdrop-filter: blur(8px);
}
.live-hero .live-actions .btn.on-pool:hover { background: rgba(255,255,255,.25); }
.live-hero .live-actions .btn.on-pool.primary { background: #fff; color: var(--pool-deep); border-color: #fff; }

.today-stats {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 1180px) {
  .today-stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .today-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.stat-tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px 16px;
  box-shadow: var(--shadow-xs);
  cursor: pointer;
  transition: transform .1s ease, border-color .1s ease, box-shadow .1s ease;
}
.stat-tile:hover { transform: translateY(-1px); border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.stat-tile .stat-label {
  font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 600; margin-bottom: 8px;
  display: flex; align-items: center; gap: 6px;
}
.stat-tile .stat-value {
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600; line-height: 1;
  letter-spacing: -0.025em;
  color: var(--ink);
}
.stat-tile .stat-sub {
  font-size: 12px; color: var(--ink-3); margin-top: 6px;
}
.stat-tile.attention {
  border-color: oklch(82% 0.08 40);
  background: linear-gradient(180deg, var(--clay-tint), var(--surface) 60%);
}
.stat-tile.attention .stat-value { color: oklch(42% 0.15 38); }

/* Route list */
.route-list { display: flex; flex-direction: column; gap: 0; }
.route-item {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  gap: 14px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  align-items: center;
  cursor: pointer;
  transition: background .08s ease;
}
.route-item:last-child { border-bottom: 0; }
.route-item:hover { background: var(--paper-2); }
.route-item .route-time {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  color: var(--ink);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.route-item .route-time small {
  display: block;
  font-family: var(--font-ui);
  font-size: 10px; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 2px;
}
.route-item .route-body .route-customer {
  font-size: 14.5px; font-weight: 600;
  color: var(--ink); line-height: 1.2;
  margin-bottom: 2px;
}
.route-item .route-body .route-meta {
  font-size: 12.5px; color: var(--ink-3);
  display: flex; gap: 10px; flex-wrap: wrap;
}
.route-item .route-body .route-tags {
  display: flex; gap: 6px; margin-top: 6px; flex-wrap: wrap;
}
.route-item.done .route-customer { text-decoration: line-through; opacity: 0.55; }
.route-item.now {
  background: linear-gradient(90deg, var(--pool-tint), transparent 60%);
  border-left: 3px solid var(--pool);
  padding-left: 15px;
}

/* Inbox preview */
.inbox-item {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  cursor: pointer;
  align-items: center;
}
.inbox-item:last-child { border-bottom: 0; }
.inbox-item:hover { background: var(--paper-2); }
.inbox-item .inbox-name {
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.inbox-item .inbox-preview {
  font-size: 12.5px; color: var(--ink-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.inbox-item .inbox-time {
  font-size: 11px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.inbox-item.unread .inbox-name::after {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  background: var(--clay); border-radius: 50%;
  margin-left: 6px;
  vertical-align: middle;
}

/* =====================================================================
   Pages: tables and rosters
   ===================================================================== */

.filters-bar {
  display: flex; align-items: center; gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.filters-bar .filter-group {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 10px 6px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px;
  color: var(--ink-2);
}
.filters-bar .filter-group label {
  font-size: 11px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink-3);
  font-weight: 600;
}
.filters-bar .filter-group select {
  border: 0; background: transparent;
  font-size: 13px; color: var(--ink);
  outline: 0;
  min-width: 50px;
}
.filters-bar .search-inline {
  flex: 1; min-width: 220px;
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
}
.filters-bar .search-inline input {
  border: 0; background: transparent; outline: 0;
  flex: 1; font-size: 14px; min-width: 0;
}
.filters-bar .results-count {
  margin-left: auto;
  font-size: 12px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.filters-bar .filter-toggle {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 13px; cursor: pointer;
  color: var(--ink-2);
}
.filters-bar .filter-toggle.active {
  background: var(--pool-tint);
  border-color: oklch(78% 0.08 210);
  color: var(--pool-deep);
}

/* Softer table, no harsh lines */
.roster {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.roster-row {
  display: grid;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  align-items: center;
  cursor: pointer;
  transition: background .08s;
}
.roster-row:last-child { border-bottom: 0; }
.roster-row:hover { background: var(--paper-2); }
.roster-head {
  background: var(--paper-2);
  padding: 10px 18px;
  font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3); font-weight: 600;
  display: grid;
  border-bottom: 1px solid var(--line);
}

/* Calls */
.roster.calls .roster-row, .roster.calls .roster-head {
  grid-template-columns: 80px 1.4fr 1.2fr 1fr 80px 32px;
  gap: 14px;
}
.call-time {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}
.call-time small {
  display: block;
  font-size: 10px;
  color: var(--ink-4);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 2px;
}
.call-caller { display: flex; align-items: center; gap: 10px; min-width: 0; }
.call-caller .call-name {
  font-size: 14px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.call-caller .call-phone {
  font-size: 12px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.call-service { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.call-service .call-outcome {
  font-size: 13px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.call-address {
  font-size: 13px; color: var(--ink-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.call-dur {
  font-family: var(--font-mono);
  font-size: 12.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.call-chev {
  color: var(--ink-4);
  font-size: 16px;
  text-align: center;
}

/* Customers */
.customer-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 14px;
}
.customer-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px;
  cursor: pointer;
  transition: transform .1s ease, border-color .1s ease, box-shadow .1s ease;
  display: flex; flex-direction: column;
  gap: 10px;
  position: relative;
}
.customer-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
.customer-card.weekly {
  background:
    linear-gradient(180deg, var(--pool-tint) 0%, transparent 40%),
    var(--surface);
}
.customer-card.weekly::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0;
  height: 3px; background: var(--pool);
  border-radius: var(--r) var(--r) 0 0;
}
.customer-card .cc-head {
  display: flex; align-items: center; gap: 12px;
}
.customer-card .cc-name {
  font-size: 16px; font-weight: 600; color: var(--ink);
  line-height: 1.2; letter-spacing: -0.01em;
}
.customer-card .cc-phone {
  font-size: 12.5px; color: var(--ink-3); margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
.customer-card .cc-address {
  font-size: 13px; color: var(--ink-2);
  line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.customer-card .cc-tags {
  display: flex; gap: 4px; flex-wrap: wrap;
}
.customer-card .cc-foot {
  margin-top: auto;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.customer-card .cc-foot b { color: var(--ink); font-weight: 600; }

/* Appointments list (denser calendar grouping) */
.appt-day {
  margin-bottom: 24px;
}
.appt-day-head {
  display: flex; align-items: baseline; gap: 14px;
  margin-bottom: 10px;
  padding: 0 4px;
}
.appt-day-head .appt-day-name {
  font-family: var(--font-display);
  font-size: 20px; font-weight: 600; color: var(--ink);
  letter-spacing: -0.02em;
}
.appt-day-head .appt-day-date {
  font-size: 12px; color: var(--ink-3);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.appt-day-head .appt-day-count {
  margin-left: auto;
  font-size: 12px; color: var(--ink-3);
}
.appt-row {
  display: grid;
  grid-template-columns: 90px 1fr auto auto auto;
  gap: 16px;
  padding: 14px 18px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  align-items: center;
  margin-bottom: 8px;
  cursor: pointer;
  transition: border-color .1s ease, box-shadow .1s ease;
}
.appt-row:hover { border-color: var(--line-strong); box-shadow: var(--shadow-sm); }
.appt-row.past { opacity: 0.6; }
.appt-row .appt-time {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  line-height: 1.1;
}
.appt-row .appt-time small {
  display: block;
  font-family: var(--font-ui);
  font-size: 10.5px; color: var(--ink-3);
  letter-spacing: 0.08em; text-transform: uppercase;
  margin-top: 2px; font-weight: 500;
}
.appt-row .appt-customer { min-width: 0; }
.appt-row .appt-customer .appt-name {
  font-weight: 600; font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.appt-row .appt-customer .appt-address {
  font-size: 12.5px; color: var(--ink-3); margin-top: 2px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.appt-reminder-dots { display: inline-flex; gap: 3px; }
.appt-reminder-dots .rd {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--line-strong);
}
.appt-reminder-dots .rd.sent { background: var(--sage); }
.appt-reminder-dots .rd.due { background: var(--sun); }

/* Messages layout */
.messages-layout {
  display: grid;
  grid-template-columns: 320px 1fr;
  height: calc(100vh - 200px);
  min-height: 560px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.threads-col { display: flex; flex-direction: column; border-right: 1px solid var(--line); min-width: 0; }
.threads-col .thread-search {
  padding: 12px; border-bottom: 1px solid var(--line);
}
.threads-col .thread-list { flex: 1; overflow-y: auto; }
.thread-item {
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 10px;
  cursor: pointer;
  align-items: start;
}
.thread-item:hover { background: var(--paper-2); }
.thread-item.active { background: var(--pool-tint); }
.thread-item .ti-main { min-width: 0; }
.thread-item .ti-name {
  font-size: 14px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  line-height: 1.2;
}
.thread-item .ti-preview {
  font-size: 12.5px; color: var(--ink-3); margin-top: 3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.thread-item .ti-meta {
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
}
.thread-item .ti-when {
  font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.thread-item .ti-unread {
  background: var(--clay); color: #fff;
  font-size: 10.5px; font-weight: 600;
  padding: 1px 6px; border-radius: 999px;
  min-width: 18px; text-align: center;
}
.thread-item.active.unread .ti-name::after { display: none; }

.pane-col { display: flex; flex-direction: column; background: var(--paper); min-width: 0; }
.pane-head {
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  display: flex; align-items: center; gap: 12px;
}
.pane-head .back-btn {
  display: none; background: none; border: 0;
  color: var(--pool-deep); font-size: 14px; font-weight: 600;
  padding: 4px 8px 4px 0; cursor: pointer;
}
.pane-head .pane-title { flex: 1; min-width: 0; }
.pane-head .pane-title .pt-name {
  font-size: 15px; font-weight: 600; color: var(--ink);
}
.pane-head .pane-title .pt-meta {
  font-size: 12px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.pane-body {
  flex: 1; overflow-y: auto;
  padding: 16px; display: flex; flex-direction: column; gap: 8px;
  background: var(--paper-2);
}
.msg-bubble {
  max-width: 75%;
  padding: 9px 13px;
  border-radius: 16px;
  font-size: 13.5px; line-height: 1.4;
  box-shadow: var(--shadow-xs);
}
.msg-bubble .msg-meta {
  font-size: 10.5px;
  color: var(--ink-4);
  margin-top: 4px;
  letter-spacing: 0.04em;
}
.msg-bubble.in {
  align-self: flex-start;
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-bottom-left-radius: 4px;
}
.msg-bubble.out {
  align-self: flex-end;
  background: var(--pool-deep); color: #fff;
  border-bottom-right-radius: 4px;
}
.msg-bubble.out .msg-meta { color: rgba(255,255,255,0.7); }
.msg-bubble.out.agent {
  background: var(--sun); color: var(--sun-ink);
}
.msg-bubble.out.agent .msg-meta { color: oklch(45% 0.12 55); }
.msg-date-divider {
  text-align: center; font-size: 11px; color: var(--ink-4);
  letter-spacing: 0.1em; text-transform: uppercase;
  margin: 12px 0 4px;
}
.compose-row {
  display: flex; gap: 10px; padding: 12px 14px;
  border-top: 1px solid var(--line);
  background: var(--surface);
  align-items: flex-end;
}
.compose-row .channel-select {
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  padding: 8px 10px;
  background: var(--paper);
  font-size: 12px;
  color: var(--ink-2);
  min-height: var(--tap);
}
.compose-row textarea {
  flex: 1; resize: none;
  min-height: var(--tap); max-height: 160px;
  padding: 11px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  background: var(--paper);
  font-size: 14px; line-height: 1.4;
}
.compose-row textarea:focus { outline: 0; border-color: var(--pool); box-shadow: 0 0 0 3px var(--pool-tint); }

/* Assistant — OpenClaw */
.assistant-frame {
  display: grid;
  grid-template-columns: 260px 1fr;
  height: calc(100vh - 200px); min-height: 560px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.assistant-sidebar {
  border-right: 1px solid var(--line);
  background: var(--paper-2);
  padding: 16px;
  display: flex; flex-direction: column; gap: 16px;
  overflow-y: auto;
}
.assistant-intro {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px;
}
.assistant-intro .ai-mark {
  width: 36px; height: 36px; border-radius: 10px;
  background: linear-gradient(135deg, var(--coral), var(--coral-deep));
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-family: var(--font-display); font-weight: 700;
  font-size: 16px;
  margin-bottom: 10px;
}
.assistant-intro h3 { font-size: 15px; margin-bottom: 2px; }
.assistant-intro p { font-size: 12.5px; color: var(--ink-3); margin: 0; line-height: 1.45; }
.assistant-suggestions h4 {
  font-size: 10.5px; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 8px; font-weight: 600;
}
.assistant-suggestions .suggest {
  display: block; width: 100%; text-align: left;
  font-size: 13px; color: var(--ink-2);
  padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface);
  margin-bottom: 6px; cursor: pointer;
  line-height: 1.35;
}
.assistant-suggestions .suggest:hover { border-color: var(--line-strong); background: var(--paper); }

.assistant-main { display: flex; flex-direction: column; min-width: 0; }

/* Empty-state shown inside .assistant-body when history is empty.
 * Primarily for mobile, where the sidebar is hidden and there'd
 * otherwise be no welcome content or suggestions visible. Hidden on
 * desktop because the sidebar already shows the same intro + prompts.
 * The breakpoint matches the sidebar's `display: none` rule below. */
.assistant-empty {
  max-width: 520px;
  margin: 0 auto;
  padding: 8px 4px;
  text-align: center;
}
.assistant-empty .ai-mark {
  width: 48px; height: 48px; border-radius: 12px;
  background: linear-gradient(135deg, var(--coral), var(--coral-deep));
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-family: var(--font-display); font-weight: 700;
  font-size: 18px;
  margin: 0 auto 12px;
}
.assistant-empty h3 {
  font-size: 18px; font-weight: 600; margin: 0 0 4px;
  color: var(--ink-1);
}
.assistant-empty p {
  font-size: 14px; color: var(--ink-3); margin: 0 0 20px;
  line-height: 1.5;
}
.assistant-empty-suggestions {
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 12px;
}
.assistant-empty-suggestions .suggest {
  display: block; width: 100%; text-align: left;
  font-size: 14px; color: var(--ink-2);
  padding: 12px 14px; border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface);
  cursor: pointer;
  line-height: 1.4;
  min-height: 44px;
}
.assistant-empty-suggestions .suggest:hover { border-color: var(--line-strong); background: var(--paper); }
.assistant-empty-suggestions .suggest:active { background: var(--paper-2); }
/* Hide on desktop: the sidebar already shows intro + suggestions. */
@media (min-width: 901px) {
  .assistant-empty { display: none; }
}
.assistant-body {
  flex: 1; overflow-y: auto;
  padding: 24px 28px;
  display: flex; flex-direction: column; gap: 16px;
  background: var(--paper);
}
.ai-msg {
  display: flex; gap: 12px;
  max-width: 720px;
}
.ai-msg.user { flex-direction: row-reverse; margin-left: auto; }
.ai-msg .ai-av {
  width: 32px; height: 32px; border-radius: 8px;
  background: linear-gradient(135deg, var(--coral), var(--coral-deep));
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 12px; font-weight: 700;
  flex-shrink: 0;
  box-shadow: 0 1px 2px rgba(180, 80, 60, .25);
}
.ai-msg.user .ai-av {
  background: linear-gradient(135deg, var(--pool), var(--pool-deep));
  color: #fff;
  box-shadow: 0 1px 2px rgba(40, 80, 110, .25);
}
.ai-msg .ai-bubble {
  background: var(--coral-tint);
  border: 1px solid oklch(90% 0.04 28);
  padding: 12px 16px;
  border-radius: var(--r);
  border-top-left-radius: 4px;
  font-size: 14px; line-height: 1.55;
  color: var(--coral-ink);
}
.ai-msg.user .ai-bubble {
  background: var(--pool-deep);
  color: #fff;
  border-color: var(--pool-deep);
  border-radius: var(--r);
  border-top-right-radius: 4px;
}
.ai-msg .ai-bubble strong { color: inherit; }
.ai-msg .ai-bubble a { color: inherit; text-decoration: underline; }

/* Fleet */
.fleet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.vehicle-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 18px;
  display: flex; flex-direction: column; gap: 12px;
  position: relative;
  overflow: hidden;
}
.vehicle-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 40px;
  background: linear-gradient(180deg, var(--paper-2), transparent);
  pointer-events: none;
}
.vehicle-head {
  display: flex; align-items: flex-start; gap: 12px;
  position: relative;
}
.vehicle-icon {
  width: 44px; height: 44px; border-radius: 10px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-2);
  flex-shrink: 0;
}
.vehicle-label {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.015em;
}
.vehicle-sub {
  font-size: 12.5px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}
.vehicle-due-grid {
  display: grid; grid-template-columns: 1fr 1fr;
  gap: 10px;
}
.due-cell {
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--paper-2);
  border: 1px solid var(--line);
}
.due-cell.overdue { background: var(--alert-tint); border-color: oklch(80% 0.1 25); }
.due-cell.due-soon { background: oklch(94% 0.06 70); border-color: oklch(82% 0.09 70); }
.due-cell .dc-label {
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3); font-weight: 600; margin-bottom: 4px;
}
.due-cell .dc-date {
  font-size: 13.5px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.due-cell .dc-in {
  font-size: 11.5px; color: var(--ink-3); margin-top: 2px;
}
.due-cell.overdue .dc-in { color: var(--alert); font-weight: 600; }
.due-cell.due-soon .dc-in { color: var(--sun-ink); font-weight: 600; }
.vehicle-foot {
  display: flex; gap: 8px; align-items: center;
  padding-top: 10px; border-top: 1px solid var(--line);
  font-size: 12px; color: var(--ink-3);
}

/* Docs */
.doc-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}
.doc-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
  cursor: pointer;
  display: flex; flex-direction: column;
  transition: transform .1s, box-shadow .1s, border-color .1s;
}
.doc-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--line-strong); }
.doc-card .doc-body {
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 6px;
  min-height: 100px;
}
.doc-card .doc-summary {
  font-size: 13px; color: var(--ink); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.doc-card .doc-meta {
  margin-top: auto; padding-top: 8px;
  border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; align-items: center;
  font-size: 11px; color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.doc-card .doc-amount { font-weight: 700; color: var(--ink); font-size: 13px; }

/* Drawer */
.drawer-backdrop {
  position: fixed; inset: 0;
  background: rgba(20, 30, 40, .35);
  backdrop-filter: blur(2px);
  z-index: 50;
  opacity: 0; pointer-events: none;
  transition: opacity .15s;
}
.drawer-backdrop.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; bottom: 0;
  width: 520px; max-width: 100vw;
  background: var(--surface);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  z-index: 60;
  transform: translateX(100%);
  transition: transform .2s ease;
  display: flex; flex-direction: column;
}
.drawer.open { transform: translateX(0); }
.drawer-head {
  /* Top inset respects iOS notch / status bar — without env(safe-area-
     inset-top) the page title sits behind the iPhone's clock + battery
     bar in standalone PWA mode. Real bug 2026-05-02: "Settings" title
     was overlapping with "10:24" on iPhone (viewport-fit=cover is set
     in index.html, but the actual padding has to be applied by us). */
  padding: calc(16px + env(safe-area-inset-top)) 20px 16px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 14px;
}
.drawer-head .dh-title { flex: 1; }
.drawer-head .dh-title h2 { font-size: 18px; letter-spacing: -0.02em; }
.drawer-head .dh-title .dh-sub { font-size: 12.5px; color: var(--ink-3); margin-top: 2px; font-variant-numeric: tabular-nums; }
.drawer-head .close-btn {
  width: 36px; height: 36px; border-radius: 10px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; color: var(--ink-2);
  cursor: pointer;
}

/* Leading "Back" button in the drawer header. Always visible — it's
 * the primary dismiss affordance on mobile (where the drawer fills
 * the viewport and the backdrop isn't tappable) and a secondary one on
 * desktop. Touch-target is 44 px tall to meet iOS Human Interface
 * Guidelines (smaller targets are unreliable for touch dismiss). */
.drawer-head .drawer-back-btn {
  display: flex; align-items: center; gap: 4px;
  height: 44px;
  padding: 0 12px 0 8px;
  margin-left: -8px;
  border: none;
  background: transparent;
  color: var(--ink-2);
  font-size: 15px; font-weight: 500;
  border-radius: 10px;
  cursor: pointer;
  flex-shrink: 0;
}
.drawer-head .drawer-back-btn:hover { background: var(--paper-2); color: var(--ink-1); }
.drawer-head .drawer-back-btn:active { background: var(--line); }
.drawer-head .drawer-back-text { display: inline; }
.drawer-body { flex: 1; overflow-y: auto; padding: 20px; }
.drawer-foot {
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  display: flex; gap: 8px;
  background: var(--paper-2);
}

.intake-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px 20px;
  padding: 16px 18px;
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  margin-bottom: 16px;
}
.intake-field .if-label {
  font-size: 10.5px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-3);
  font-weight: 600; margin-bottom: 3px;
}
.intake-field .if-value {
  font-size: 13.5px; color: var(--ink);
  word-break: break-word;
}
.intake-field .if-value.missing { color: var(--ink-4); font-style: italic; }

.recording-player {
  background: var(--paper-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 14px;
  margin-bottom: 16px;
  display: flex; align-items: center; gap: 12px;
}
.recording-player .play-btn {
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--pool-deep); color: #fff;
  border: 0; display: flex; align-items: center; justify-content: center;
  cursor: pointer; flex-shrink: 0;
}
.recording-player .waveform {
  flex: 1; height: 36px;
  background-image: repeating-linear-gradient(
    to right,
    var(--line-strong) 0 1px,
    transparent 1px 3px);
  border-radius: 4px;
  position: relative;
}
.recording-player .waveform::before {
  content: ""; position: absolute; inset: 0 calc(100% - var(--pct, 0%)) 0 0;
  background-image: repeating-linear-gradient(
    to right,
    var(--pool) 0 1px,
    transparent 1px 3px);
  transition: inset .3s linear;
}
.recording-player .timing {
  font-family: var(--font-mono); font-size: 12px;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}

.transcript-log {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--paper);
  padding: 14px;
  border-radius: var(--r);
  border: 1px solid var(--line);
  max-height: 400px; overflow-y: auto;
}
.transcript-log .tr {
  display: grid; grid-template-columns: 60px 1fr;
  gap: 10px;
  font-size: 13.5px; line-height: 1.4;
  padding: 6px 8px 6px 10px;
  border-radius: 6px;
  border-left: 3px solid transparent;
}
.transcript-log .tr.user {
  background: var(--pool-tint);
  border-left-color: var(--pool);
}
.transcript-log .tr.user .tr-role { color: var(--pool-deep); }
.transcript-log .tr.user .tr-text { color: var(--pool-ink); }
.transcript-log .tr.agent {
  background: var(--coral-tint);
  border-left-color: var(--coral);
}
.transcript-log .tr.agent .tr-role { color: var(--coral-deep); }
.transcript-log .tr.agent .tr-text { color: var(--coral-ink); }
.transcript-log .tr.system { opacity: 0.7; padding-left: 10px; }
.transcript-log .tr.system .tr-text { font-style: italic; color: var(--ink-3); }
/* When the recording is playing, future turns desaturate to a neutral
   gray and "light up" to their role color as the playhead crosses each
   turn's offset. The transition is short so scrubbing feels responsive
   without flicker. */
.transcript-log .tr.pending {
  background: var(--paper-2);
  border-left-color: var(--line);
  transition: background 120ms ease, border-left-color 120ms ease;
}
.transcript-log .tr.pending .tr-role,
.transcript-log .tr.pending .tr-text {
  color: var(--ink-4);
  transition: color 120ms ease;
}
/* Each turn is click-to-seek (jumps audio to the turn's start). Subtle
   hover cue so it feels interactive without changing the read flow. */
.transcript-log .tr.clickable {
  cursor: pointer;
}
.transcript-log .tr.clickable:hover {
  background: color-mix(in srgb, var(--ink-1) 4%, var(--paper));
}
.transcript-log .tr.clickable.pending:hover {
  background: color-mix(in srgb, var(--ink-1) 8%, var(--paper-2));
}
.transcript-log .tr-role {
  font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase;
  font-weight: 700; padding-top: 2px;
}

/* Mobile bottom nav */
.mobile-nav {
  display: none;
  position: fixed; bottom: 0; left: 0; right: 0;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  z-index: 40;
  box-shadow: 0 -8px 24px -12px rgba(20,40,60,.12);
}
.mobile-nav-inner {
  display: grid; grid-template-columns: repeat(5, 1fr);
  gap: 2px;
}
.mobile-nav-item {
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 8px 4px;
  border: 0; background: transparent;
  color: var(--ink-3);
  font-size: 10.5px;
  font-weight: 500;
  min-height: 54px;
  cursor: pointer;
  position: relative;
}
.mobile-nav-item.active { color: var(--pool-deep); }
.mobile-nav-item .mn-icon { width: 22px; height: 22px; }
.mobile-nav-item .mn-badge {
  position: absolute;
  top: 4px; right: 24%;
  min-width: 16px; height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--clay); color: #fff;
  font-size: 9.5px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}

/* =====================================================================
   Responsive — mobile
   ===================================================================== */
@media (max-width: 900px) {
  .app {
    grid-template-columns: 1fr;
    grid-template-areas:
      "topbar"
      "main";
  }
  .nav { display: none; }

  /* Brand row folds into the topbar on mobile */
  .brand { display: none; }

  .topbar {
    /* iOS notch / Dynamic Island clearance — env(safe-area-inset-top) is
       ~47-59 px on a notched iPhone in standalone PWA mode. Without this
       the brand mark + "Today" title sit behind the status bar. */
    padding: calc(10px + env(safe-area-inset-top)) 14px 10px;
    min-height: 56px;
    background: var(--surface);
    gap: 10px;
  }
  /* Re-introduce the brand mark inline, left of the view title */
  .topbar::before {
    content: "";
    width: 32px; height: 32px; border-radius: 50%;
    background: radial-gradient(circle at 32% 30%, var(--pool-bright), var(--pool) 55%, var(--pool-deep));
    box-shadow: inset 0 -2px 3px rgba(0,0,0,.1), 0 1px 4px -1px rgba(30,80,120,.4);
    flex-shrink: 0;
  }
  .topbar .greeting h1 { font-size: 18px; }
  .topbar .greeting .date { font-size: 11.5px; }
  /* On mobile, the search box collapses to icon-only when blurred so the
     greeting + theme toggle + live-call indicator all still fit in the
     320-px wide topbar. Tapping it expands to full width via :focus-within.
     Hiding it entirely (the old behavior) meant Bill had no search on his
     phone — which is exactly when search is most useful. */
  .topbar .search-global {
    flex: 0 0 auto;
    padding: 6px 8px;
    transition: flex 0.2s, padding 0.2s;
  }
  .topbar .search-global input {
    width: 0;
    transition: width 0.2s;
  }
  .topbar .search-global .kbd { display: none; }
  .topbar .search-global:focus-within {
    flex: 1 1 100%;
    order: 99;       /* drop to its own row when expanded so it doesn't crush the greeting */
    width: 100%;
    padding: 8px 12px;
  }
  .topbar .search-global:focus-within input { width: auto; flex: 1; }
  .topbar .conn { padding: 5px 9px; font-size: 11.5px; }
  /* Hide the static Connected/Offline pill on mobile — Bill doesn't
     need a constant indicator taking up topbar real estate on a small
     screen, and the bottom nav already shows the same status implicitly
     (greyed out items when the agent's down). The .conn.live pill (live
     call indicator) is intentionally kept visible — that's actionable
     information Bill should see immediately. */
  .topbar > .conn:not(.live) { display: none; }
  .topbar { flex-wrap: wrap; }

  .main { padding: 14px 14px 110px; }
  .mobile-nav { display: block; }

  /* The view h1 is already in the top bar — hide the duplicate in-page head */
  .page-head {
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    padding-top: 0;
    border-bottom: 0;
    margin-bottom: 14px;
  }
  .page-head .eyebrow { display: none; }
  .page-head h1 { display: none; }
  .page-head .subtitle { font-size: 13.5px; margin-top: 0; }
  .page-head.page-head-today .eyebrow { display: block; }
  .page-head.page-head-today h1 { display: block; font-size: 24px; }

  .today-grid { grid-template-columns: 1fr; }
  .today-side { position: static; }
  .today-stats { grid-template-columns: repeat(2, 1fr); }

  .page-head { flex-direction: column; align-items: stretch; }
  .page-head h1 { font-size: 26px; }

  .roster.calls .roster-head { display: none; }
  .roster.calls .roster-row {
    grid-template-columns: 1fr auto;
    grid-template-areas:
      "caller dur"
      "service service"
      "address address"
      "tags tags";
    gap: 6px; padding: 14px 16px;
  }
  .roster.calls .call-time { display: none; }
  .roster.calls .call-caller { grid-area: caller; }
  .roster.calls .call-service { grid-area: service; }
  .roster.calls .call-address { grid-area: address; font-size: 12.5px; color: var(--ink-3); }
  .roster.calls .call-dur { grid-area: dur; }
  .roster.calls .call-chev { display: none; }

  .appt-row {
    grid-template-columns: 72px 1fr auto;
    grid-template-areas:
      "time customer status"
      "time meta reminders";
    gap: 8px 14px;
  }
  .appt-row .appt-time { grid-area: time; }
  .appt-row .appt-customer { grid-area: customer; }
  .appt-row .appt-status-chip { grid-area: status; }
  .appt-row .appt-reminder-dots { grid-area: reminders; }

  .messages-layout {
    grid-template-columns: 1fr;
    height: calc(100vh - 180px);
  }
  .messages-layout.has-selection .threads-col { display: none; }
  .messages-layout:not(.has-selection) .pane-col { display: none; }
  .pane-head .back-btn { display: inline-flex; }

  .assistant-frame {
    grid-template-columns: 1fr;
    /* Override the desktop `min-height: 560px` — on a 667 px-tall phone
     * with topbar + brand + page-head + bottom-nav eating ~250 px of
     * vertical space, 560 px overflows past viewport AND past the
     * `overflow: hidden` clip, so the compose-row at the bottom of the
     * frame ends up off-screen. With no chat history yet, the user
     * sees only the empty body and can't even reach the textarea —
     * looks like a "white screen." Letting min-height shrink fixes it. */
    height: calc(100dvh - 180px);
    min-height: 0;
  }
  .assistant-sidebar { display: none; }

  /* Full-bleed chat on mobile: when the OpenClaw view is active, hide
   * the desktop chrome (brand, topbar, page-head) so the chat fills
   * the viewport — no page-level scrolling, just internal body scroll
   * + a sticky compose row, like a real messaging app. The bottom-nav
   * stays so the user can navigate away. Other views keep their
   * normal mobile layout (topbar with search, page-head with title). */
  .app[data-view="assistant"] {
    /* `.app` defaults to `min-height: 100vh`. On iOS Safari `100vh`
     * is the URL-bar-COLLAPSED viewport height (taller than the
     * actual visible area when the bar is shown), so it forces the
     * app to be taller than the dynamic viewport and makes the page
     * scrollable even when content fits within the visible area.
     * Override to `100dvh` (dynamic) so the app shrinks WITH the
     * URL bar and the page never overflows the visible viewport. */
    min-height: 100dvh;
    height: 100dvh;
    overflow: hidden;
    /* Prevent iOS Safari rubber-band drag (the bounce when you swipe
     * down at the top of a page). Without this the user can drag the
     * whole page down and reveal the gray Safari background even
     * when there's nothing to scroll to. */
    overscroll-behavior: none;
  }
  /* Also clamp the html/body when assistant is active so iOS doesn't
   * fall back to the page-level rubber-band. `position: fixed` on
   * body would also work but breaks the bottom-nav fixed position;
   * overscroll-behavior is the safer combo. */
  html:has(.app[data-view="assistant"]),
  body:has(.app[data-view="assistant"]) {
    overflow: hidden;
    overscroll-behavior: none;
    height: 100dvh;
  }
  .app[data-view="assistant"] .brand,
  .app[data-view="assistant"] .topbar,
  .app[data-view="assistant"] .page-head { display: none; }
  .app[data-view="assistant"] .main { padding: 0; padding-bottom: 0; }
  .app[data-view="assistant"] .assistant-frame {
    /* Bottom-nav is ~80px (54 min-height + 6+6 padding + safe-area).
     * Use 100dvh so iOS Safari's collapsing URL bar doesn't shift
     * heights mid-scroll. */
    height: calc(100dvh - 80px);
    border: none;
    border-radius: 0;
  }
  .app[data-view="assistant"] .compose-row {
    /* Add iPhone home-bar inset so the textarea isn't hidden behind
     * the gesture indicator. env(safe-area-inset-bottom) is 0 on
     * notch-less phones, ~34px on iPhone X+. */
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
  }

  .customer-grid { grid-template-columns: 1fr; }
  .fleet-grid { grid-template-columns: 1fr; }

  .drawer { width: 100%; }
  /* On phone-sized drawers the title is tight — drop the "Back" text
   * and keep just the chev. The button still has a generous touch
   * target via padding. */
  .drawer-head .drawer-back-text { display: none; }

  /* iOS Safari auto-zooms when the user taps any input/textarea/select
   * with `font-size < 16px`. The chat textarea, search bars, and
   * filter inputs are 14px on desktop for density — bump them to 16px
   * on mobile so tapping doesn't pinch the whole UI. The visual size
   * difference is small enough that the desktop look is preserved. */
  input[type="text"],
  input[type="search"],
  input[type="email"],
  input[type="tel"],
  input[type="number"],
  input:not([type]),
  textarea,
  select {
    font-size: 16px;
  }

  /* iOS Human Interface Guidelines: tap targets must be ≥ 44 px.
   * The filter chips on Calls/Customers/Documents (`.filter-toggle`)
   * default to ~30 px tall for desktop density. Bump to 44 px on
   * mobile by adding vertical padding so finger taps land reliably
   * without the visual look changing on desktop. */
  .filters-bar .filter-toggle {
    padding-top: 11px;
    padding-bottom: 11px;
    min-height: 44px;
    font-size: 14px;
  }

  /* Messages thread back button — only visible on mobile (when the
   * thread pane covers the whole viewport, replacing the threads list).
   * Desktop hides it because both panes are always visible side-by-side.
   * Default padding made it 26 px tall — too small for a finger. */
  .pane-head .back-btn {
    min-height: 44px;
    padding: 8px 12px 8px 4px;
    font-size: 15px;
  }

  /* Topbar theme-toggle button — has no explicit CSS rule (relies on
   * default <button> sizing), which puts it at ~31x25 on mobile. Bump
   * to 44x44 touch target. Affects only mobile; desktop keeps its
   * compact default. */
  .topbar .theme-toggle {
    width: 44px; height: 44px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--line);
    border-radius: 10px;
    background: transparent;
    color: var(--ink-2);
    cursor: pointer;
  }

  .today-stats .stat-tile {
    padding: 12px 14px;
  }
  .today-stats .stat-tile .stat-value { font-size: 24px; }

  .filters-bar .results-count { margin-left: 0; }

  .live-hero { padding: 18px 18px; border-radius: var(--r); }
  .live-hero h2 { font-size: 22px; }
}

@media (max-width: 420px) {
  .today-stats { grid-template-columns: 1fr 1fr; }
  .page-head h1 { font-size: 22px; }
  .topbar { gap: 10px; }
}

/* Toasts */
#toast-root {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex; flex-direction: column-reverse; gap: 8px;
  pointer-events: none;
}
.toast {
  background: var(--ink);
  color: #fff;
  padding: 10px 16px;
  border-radius: 999px;
  font-size: 13.5px;
  font-weight: 500;
  box-shadow: var(--shadow-lg);
  opacity: 0; transform: translateY(8px);
  transition: opacity .18s ease, transform .18s ease;
  max-width: min(420px, 90vw);
  text-align: center;
  pointer-events: auto;
}
.toast.show { opacity: 1; transform: translateY(0); }
@media (max-width: 768px) {
  #toast-root { bottom: 96px; } /* clear mobile bottom nav */
}

/* Bottom sheet (mobile "More" overflow) */
.sheet-backdrop {
  position: fixed; inset: 0;
  background: rgba(15, 25, 35, .35);
  z-index: 50;
  animation: sheet-fade .18s ease;
}
.sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  background: var(--surface);
  border-top-left-radius: 18px;
  border-top-right-radius: 18px;
  padding: 8px 16px calc(20px + env(safe-area-inset-bottom));
  z-index: 51;
  box-shadow: 0 -16px 48px -16px rgba(15, 30, 45, .25);
  animation: sheet-up .22s cubic-bezier(.2,.8,.3,1);
}
.sheet-handle {
  width: 40px; height: 4px;
  background: var(--line-strong);
  border-radius: 999px;
  margin: 6px auto 14px;
}
.sheet-title {
  font-family: var(--font-display);
  font-size: 18px; font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 12px;
}
.sheet-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.sheet-tile {
  display: flex; flex-direction: column; align-items: center;
  gap: 8px;
  padding: 16px 8px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--paper-2);
  color: var(--ink-2);
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 500;
  min-height: 76px;
}
.sheet-tile:hover { background: var(--paper-3); }
.sheet-tile.active {
  background: var(--pool-tint);
  color: var(--pool-deep);
  border-color: oklch(82% 0.06 210);
}
.sheet-tile .sheet-icon {
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  display: flex; align-items: center; justify-content: center;
  color: var(--ink-2);
}
.sheet-tile.active .sheet-icon {
  background: var(--surface);
  color: var(--pool-deep);
  border-color: oklch(82% 0.06 210);
}
.sheet-label { line-height: 1.2; }

@keyframes sheet-up {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}
@keyframes sheet-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Sheet only relevant on mobile but harmless on desktop — keep visible if forced open */

/* ====================================================================
 * Debug view — internal-only diagnostics page. Style is utilitarian on
 * purpose: dense rows, monospace numbers, clear up/down dot indicators.
 * Not intended to match the rest of the hub's calm aesthetic — this is
 * a tool, not a customer-facing page.
 *
 * Sizing model: same as Calls/Customers/etc. — fits inside the .main
 * 1280px cap, never busts out horizontally. The debug page has wider
 * intrinsic content than other views (an 11-column timings table, long
 * process command paths in cards), so every container here uses the
 * `min-width:0 + max-width:100%` pair. This is the canonical fix for
 * "grid/flex child overflows because its intrinsic min-content is
 * wider than its track" — without it, a wide child (the timings table
 * or a long unwrapped log line) silently expands .main past the cap
 * and forces body horizontal scroll, especially when the user zooms in
 * (which shrinks the CSS viewport relative to the unchanged content).
 * ==================================================================== */
.debug-view {
  padding-bottom: 60px;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
}

.dbg-section {
  margin-top: 24px;
  padding: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  min-width: 0;
  max-width: 100%;
  width: 100%;
  box-sizing: border-box;
  /* No overflow:hidden here — that would clip the table-wrap's
   * horizontal scrollbar. Each child container manages its own overflow. */
}
.dbg-section-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.dbg-section-head h2 {
  font-size: 15px; font-weight: 600; margin: 0;
  color: var(--ink-1);
  display: flex; align-items: center; gap: 8px;
}

/* Small "live" pill at the right of page-head — green when SSE is open
 * and events are flowing, grey when we're degraded to polling. */
.dbg-live-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  font-size: 11px; font-weight: 500;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink-2);
}

/* Inline tag next to a section's H2 — shows the auto-refresh cadence
 * (e.g. "live · 2s" or "live · SSE") so it's obvious each panel is
 * polling itself, not requiring manual refresh. */
.dbg-live-tag {
  font-size: 10px; font-weight: 500;
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 999px;
  background: oklch(95% 0.04 145);
  color: oklch(40% 0.10 145);
  font-family: "Geist Mono", ui-monospace, monospace;
}
[data-theme="dark"] .dbg-live-tag {
  background: oklch(28% 0.06 145);
  color: oklch(80% 0.12 145);
}
.dbg-meta {
  font-size: 12px; color: var(--ink-3);
  display: flex; gap: 8px; align-items: center;
}

.dbg-grid {
  display: grid;
  /* `minmax(0, ...)` (NOT `minmax(180px, ...)`) is critical: the leading
   * `0` lets each track shrink below its content min-content, which is
   * what stops a long process command path inside a card from forcing
   * the grid wider than .main. The visual minimum becomes the card's
   * own ellipsis-clipping (white-space:nowrap + overflow:hidden on
   * .dbg-card-sub). Without minmax(0, ...) the card never shrinks past
   * the unwrapped command's width and the page overflows on zoom. */
  grid-template-columns: repeat(auto-fill, minmax(min(180px, 100%), 1fr));
  gap: 10px;
  margin-bottom: 10px;
  min-width: 0;
  max-width: 100%;
}
.dbg-card { min-width: 0; max-width: 100%; }
.dbg-card {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg);
}
.dbg-card.ok    { border-left: 3px solid #2e8b57; }
.dbg-card.down  { border-left: 3px solid #c1543a; }
.dbg-card-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-3); margin-bottom: 4px;
}
.dbg-card-value {
  font-size: 14px; font-weight: 500;
  font-family: "Geist Mono", ui-monospace, monospace;
  color: var(--ink-1);
  display: flex; align-items: center; gap: 6px;
}
.dbg-card-sub {
  font-size: 11px; color: var(--ink-3); margin-top: 4px;
  font-family: "Geist Mono", ui-monospace, monospace;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.dbg-dot {
  width: 8px; height: 8px; border-radius: 50%;
  display: inline-block; flex-shrink: 0;
}
.dbg-dot.up   { background: #2e8b57; }
.dbg-dot.down { background: #c1543a; }

.dbg-table-wrap {
  /* Bound the wrapper to its section's content box so the inner table's
   * 11 nowrap columns scroll horizontally INSIDE the wrapper instead of
   * busting out and pushing the whole page wider. min-width:0 + width:100%
   * is the canonical fix for "grid/flex child overflows because its
   * intrinsic min-content is wide". */
  overflow-x: auto;
  overflow-y: auto;
  max-height: 520px;
  width: 100%;
  min-width: 0;
}
.dbg-table {
  width: 100%; border-collapse: collapse;
  font-size: 12px;
  font-family: "Geist Mono", ui-monospace, monospace;
}
.dbg-table th, .dbg-table td {
  padding: 6px 8px; text-align: left;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.dbg-table th {
  font-weight: 600; color: var(--ink-2);
  background: var(--surface);
  position: sticky; top: 0;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em;
}
.dbg-table td.dbg-text {
  font-family: "Geist", ui-sans-serif, sans-serif;
  max-width: 240px; overflow: hidden; text-overflow: ellipsis;
}
.dbg-table td.dbg-warn { color: #b87a1e; font-weight: 600; }
.dbg-table td.dbg-bad  { color: #c1543a; font-weight: 600; }

.dbg-log {
  margin: 0;
  padding: 12px;
  background: #1a1d20;
  color: #d3d7d8;
  border-radius: var(--r-sm);
  font-family: "Geist Mono", ui-monospace, monospace;
  font-size: 11.5px;
  line-height: 1.5;
  max-height: 480px;
  overflow: auto;
  /* pre-wrap respects newlines but wraps long lines; combined with
   * overflow-wrap:anywhere this prevents a single 500-char trace line
   * (e.g. JSON with no spaces) from forcing horizontal scroll. */
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
}

.dbg-btn {
  padding: 6px 12px;
  font-size: 12px; font-weight: 500;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg);
  color: var(--ink-1);
  cursor: pointer;
}
.dbg-btn:hover:not(:disabled) { background: var(--surface); }
.dbg-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.dbg-select {
  padding: 5px 8px;
  font-size: 12px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--bg);
  color: var(--ink-1);
}

.dbg-section.dbg-danger {
  border-color: oklch(75% 0.10 25);
  background: oklch(98% 0.01 25);
}
[data-theme="dark"] .dbg-section.dbg-danger {
  background: oklch(20% 0.03 25);
  border-color: oklch(45% 0.08 25);
}
.dbg-btn-danger {
  background: #c1543a;
  color: white;
  border-color: #c1543a;
}
.dbg-btn-danger:hover:not(:disabled) {
  background: #a64530;
  border-color: #a64530;
}
.dbg-confirm {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--ink-1);
  padding: 8px 0;
  flex-wrap: wrap;
}
.dbg-result {
  margin-top: 14px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: 12px;
  font-family: "Geist Mono", ui-monospace, monospace;
}
.dbg-result-row {
  display: flex; justify-content: space-between;
  padding: 2px 0;
}

/* ====================================================================
 * Debug view — internal-only diagnostics page. Style is utilitarian on
 * purpose: dense rows, monospace numbers, clear up/down dot indicators.
 * Not intended to match the rest of the hubs
