:root {
  --bg: #fafaf9;
  --fg: #1c1917;
  --muted: #78716c;
  --border: #e7e5e4;
  --accent: #C2410C;
  --danger: #b91c1c;

  /* Surface tokens — what was previously hard-coded as `white` / `#f5f5f4`
     / `#fafaf9`. These exist so [data-theme="dark"] can re-paint cards,
     tables, hover states, etc. in one place rather than duplicating every
     selector. Keep using the named tokens, not the literal hex values. */
  --surface: #ffffff;          /* card / panel / table / modal background */
  --surface-alt: #f5f5f4;      /* icon tile, code inline, kanban col, kbd */
  --row-hover: #fafaf9;        /* table-row hover, icon-btn hover, selected todo */
  --on-accent: #ffffff;        /* text on a `var(--accent)` background */
  --on-fg: #ffffff;            /* text on a `var(--fg)` background (chip.active, chatbot inverse) */
  --scrim: rgba(28, 25, 23, 0.35);  /* modal backdrops */
}

/* Dark theme — surfaces darken, ink lightens, accent shifts to a brighter
   orange so it still reads as the focus colour against the dark surface. The
   accent buttons flip to dark text on the lighter orange for contrast. */
[data-theme="dark"] {
  --bg: #0c0a09;
  --fg: #f5f5f4;
  --muted: #a8a29e;
  --border: #292524;
  --accent: #fb923c;
  --danger: #f87171;

  --surface: #1c1917;
  --surface-alt: #292524;
  --row-hover: #292524;
  --on-accent: #0c0a09;
  --on-fg: #0c0a09;
  --scrim: rgba(0, 0, 0, 0.55);

  color-scheme: dark;
}
* { box-sizing: border-box; }
/* Honour the HTML5 `hidden` attribute even when a rule like
   `form.meta { display: grid }` would otherwise override it. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
body { font: 14px/1.45 system-ui, sans-serif; margin: 0; background: var(--bg); color: var(--fg); overflow-x: hidden; }

body.centered { display: grid; place-items: center; min-height: 100vh; padding: 16px; box-sizing: border-box; }
.card { background: var(--surface); padding: 32px; border: 1px solid var(--border); border-radius: 8px; max-width: 360px; }

/* ── Primary nav: persistent left sidebar (desktop), slide-in drawer (mobile)
   The same <aside id="sidebar"> serves both presentations — CSS does the
   heavy lifting. Below, the mobile @media block transforms it into a
   drawer; on desktop it sits flush to the left edge full-height and the
   body gets `padding-left` so content never sits beneath it.

   The mobile-only topbar and bottom tab bar are display:none on desktop
   and only surface inside the @media (max-width: 960px) block. */
:root {
  --sidebar-w: 232px;
  --topbar-h: 52px;
  --bottom-tabs-h: 64px;
}

.sidebar {
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: var(--sidebar-w);
  background: var(--surface);
  border-right: 1px solid var(--border);
  padding: 16px 12px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  z-index: 90;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.sidebar-brand { display: flex; align-items: center; height: 28px; padding: 0 10px; }
.sidebar-brand img { height: 22px; width: auto; display: block; }

/* Search button — looks like a press-target field, but it's a link to the
   /search page. The kbd hints at the navigator (g s) shortcut. */
.sidebar-search {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 7px 10px;
  background: var(--surface-alt);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--muted);
  text-align: left;
  text-decoration: none;
  font: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color 120ms, color 120ms, background-color 120ms;
}
.sidebar-search:hover { border-color: var(--accent); color: var(--fg); }
.sidebar-search:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sidebar-search-icon { display: inline-flex; }
.sidebar-search-icon svg { width: 16px; height: 16px; }
.sidebar-search-label { flex: 1 1 auto; }
.sidebar-search-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  padding: 1px 5px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface);
  color: var(--muted);
  white-space: nowrap;
}

.sidebar-nav { display: flex; flex-direction: column; gap: 1px; flex: 1 1 auto; min-height: 0; }

/* Group heading inside the sidebar. Author in sentence case; the CSS
   applies the uppercase styling, matching the rest of the design system. */
h2.sidebar-group {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin: 14px 6px 4px;
  padding: 0;
}
.sidebar-nav > h2.sidebar-group:first-child { margin-top: 2px; }

a.navrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  border-radius: 6px;
  color: var(--fg);
  text-decoration: none;
  font-size: 13px;
  font-weight: 500;
  transition: background-color 120ms, color 120ms;
}
.navrow-icon { display: inline-flex; color: var(--muted); flex: 0 0 18px; }
.navrow-icon svg { width: 18px; height: 18px; }
.navrow-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.navrow-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  color: var(--muted);
  opacity: 0;
  transition: opacity 120ms;
  white-space: nowrap;
}
a.navrow:hover { background: var(--surface-alt); }
a.navrow:hover .navrow-icon { color: var(--fg); }
a.navrow:hover .navrow-key { opacity: 1; }
a.navrow.active { background: var(--surface-alt); color: var(--accent); }
a.navrow.active .navrow-icon { color: var(--accent); }
a.navrow.active .navrow-icon svg { stroke-width: 2.2; }

/* Footer: secondary links + user card. Pinned to the bottom of the sidebar. */
.sidebar-foot {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding-top: 10px;
  margin-top: 4px;
  border-top: 1px solid var(--border);
}

.sidebar-user-row {
  display: flex;
  align-items: stretch;
  border-radius: 6px;
  transition: background-color 120ms;
  min-width: 0;
}
.sidebar-user-row:hover { background: var(--surface-alt); }
.sidebar-user-row.active { background: var(--surface-alt); }
a.sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 8px 8px 10px;
  border-radius: 6px;
  color: var(--fg);
  text-decoration: none;
  min-width: 0;
  flex: 1 1 auto;
}
.sidebar-user-avatar {
  flex: 0 0 28px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 11px;
  font-weight: 600;
  overflow: hidden;
  text-transform: uppercase;
  background: var(--muted);
}
.sidebar-user-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sidebar-user-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1 1 auto;
  line-height: 1.2;
}
.sidebar-user-name {
  font-size: 12px;
  font-weight: 600;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-user-email {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sidebar-user-signout { margin: 0; padding: 0; flex: 0 0 auto; display: inline-flex; align-items: center; padding-right: 6px; }
/* The chained button[type=submit] selector is what actually paints this
   button — plain `.sidebar-user-signout-btn` (specificity 0,1,0) loses to
   the global `button[type=submit]` rule (0,1,1) and the sign-out ends up
   accent-orange with white text. Sign-out is used maybe once a month; it
   should be muted at rest and only wake up on hover. */
button.sidebar-user-signout-btn[type=submit],
.sidebar-user-signout-btn {
  background: transparent;
  border: none;
  padding: 6px;
  border-radius: 4px;
  color: var(--muted);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 120ms, color 120ms;
}
button.sidebar-user-signout-btn[type=submit]:hover,
.sidebar-user-signout-btn:hover { background: var(--surface-alt); color: var(--fg); }
.sidebar-user-signout-btn svg { width: 14px; height: 14px; }

/* Backdrop is only visible when the mobile drawer is open. */
.sidebar-backdrop {
  position: fixed;
  inset: 0;
  background: var(--scrim);
  z-index: 80;
}
.sidebar-backdrop[hidden] { display: none; }

/* Mobile-only surfaces: hide on desktop. */
.topbar { display: none; }
.bottom-tabs { display: none; }

/* Push content over so the sidebar never covers <main>. Scoped via `:has`
   so the login page (which doesn't render a sidebar) stays centred. */
body:has(.sidebar) { padding-left: var(--sidebar-w); }

/* ── Settings index ─────────────────────────────────────────────────────── */
/* The global `header { background: white; border-bottom: ... }` rule was
   inheriting onto our <header class="settings-header"> tag; reset it so
   only the page-nav header keeps the white bar. */
header.settings-header { background: transparent; border-bottom: none; display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 8px; padding: 0; }
header.settings-header h1 { margin: 0; }

/* Same override for the deals page-header and the kanban column heads -
   the global `header` rule above would otherwise drop a white bar with a
   grey underline across those rows. */
header.page-header,
header.kanban-col-head { background: transparent; border-bottom: none; padding: 0; }

/* `button[type=submit]` lower down would otherwise win on equal specificity
   and zero out our border / padding here. Combining the class + attribute
   selector bumps us above it so the resting border stays 1px transparent
   (no layout shift on hover). */
button.signout-btn[type=submit] { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; background: #15803d; color: white; border: 1px solid #15803d; border-radius: 4px; cursor: pointer; font: inherit; font-size: 13px; }
button.signout-btn[type=submit]:hover { background: #dcfce7; color: var(--fg); border: 1px solid #15803d; }
button.signout-btn svg { width: 16px; height: 16px; }

section.settings-group { margin-top: 24px; }
section.settings-group > h2 { margin: 0 0 10px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); font-weight: 600; }
/* Section heading + trailing add button. The heading keeps its native
   styling (settings-group h2 is small + muted, task-section h2 is bigger);
   we just put the + tile on the same baseline. */
header.section-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 10px; background: transparent; border: none; padding: 0; }
section header.section-head > h2 { margin: 0; }
header.section-head .icon-button-add { width: 28px; height: 28px; }

/* Footer-row for a tab section: a single trailing action button that
   opens an "add X" modal. Replaces the old `<details class="newform">`
   inline expander; sits flush-left below the table or list. */
.section-actions { display: flex; gap: 8px; margin-top: 12px; }

.settings-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
@media (min-width: 720px) { .settings-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

a.settings-card { display: flex; align-items: flex-start; gap: 12px; padding: 14px 16px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; color: var(--fg); text-decoration: none; transition: border-color 120ms, transform 120ms; position: relative; }
a.settings-card:hover { border-color: var(--accent); }
a.settings-card:hover .settings-card-arrow { transform: translateX(2px); color: var(--accent); }

.settings-icon-wrap { flex: 0 0 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; background: var(--surface-alt); color: var(--accent); border-radius: 6px; }
.settings-icon-wrap svg { width: 20px; height: 20px; }

.settings-card-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.settings-card-title { font-weight: 600; font-size: 14px; color: var(--fg); }
.settings-card-desc { font-size: 12px; color: var(--muted); line-height: 1.5; }
.settings-card-desc code { font-size: 11px; background: var(--surface-alt); padding: 1px 5px; border-radius: 3px; color: var(--fg); }
.settings-card-arrow { color: var(--muted); font-size: 16px; align-self: center; flex: 0 0 auto; transition: transform 120ms, color 120ms; }
main { max-width: 1100px; margin: 24px auto; padding: 0 24px; }
h1 { font-size: 22px; margin: 0 0 16px; }
h2 { font-size: 16px; margin-top: 24px; }
.back { color: var(--muted); text-decoration: none; }
small.slug { color: var(--muted); font-weight: 400; font-size: 14px; }

.filters { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 16px; }
.chip { padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); text-decoration: none; color: var(--fg); font-size: 12px; }
.chip.active { background: var(--fg); color: var(--on-fg); border-color: var(--fg); }

table.grid { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
table.grid th, table.grid td { padding: 10px 14px; text-align: left; vertical-align: middle; }
table.grid th { background: var(--surface); font-weight: 500; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); border-bottom: 1px solid var(--border); }
table.grid td { border-bottom: 1px solid var(--surface-alt); }
table.grid tr:last-child td { border-bottom: none; }
table.grid tbody tr:hover td { background: var(--row-hover); }
table.grid a { color: var(--fg); text-decoration: none; }
table.grid a:hover { color: var(--accent); }

/* Sortable / filterable table headers.
   Opt-in via <table class="grid grid-sortable">. Removes the outer overflow
   clip so per-column filter popovers can escape the table box, and restores
   rounded corners via per-cell radii on the four corners. */
table.grid.grid-sortable { overflow: visible; }
table.grid.grid-sortable thead th:first-child { border-top-left-radius: 8px; }
table.grid.grid-sortable thead th:last-child { border-top-right-radius: 8px; }
table.grid.grid-sortable tbody tr:last-child td:first-child { border-bottom-left-radius: 8px; }
table.grid.grid-sortable tbody tr:last-child td:last-child { border-bottom-right-radius: 8px; }
table.grid.grid-sortable th { position: relative; }
table.grid.grid-sortable th .col-header {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* Sort link — the header text acts as a button that toggles asc↔desc. */
.col-sort {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--muted) !important;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 500;
    font-size: 11px;
    padding: 2px 2px;
    border-radius: 3px;
}
.col-sort:hover { color: var(--fg) !important; }
.col-sort.active { color: var(--fg) !important; }
.col-sort-ind {
    font-size: 10px;
    opacity: 0.35;
    line-height: 1;
    transition: opacity 120ms;
}
.col-sort.active .col-sort-ind { opacity: 1; }
.col-sort:hover .col-sort-ind { opacity: 0.9; }

/* Filter popover — plain <details>, no JS required. */
.col-filter {
    position: relative;
    display: inline-flex;
}
.col-filter > summary {
    list-style: none;
    cursor: pointer;
    padding: 3px 4px;
    border-radius: 4px;
    display: inline-flex;
    align-items: center;
    color: var(--muted);
    opacity: 0.5;
    transition: opacity 120ms, color 120ms, background 120ms;
}
.col-filter > summary::-webkit-details-marker { display: none; }
.col-filter > summary:hover { opacity: 1; color: var(--fg); background: var(--surface-alt); }
.col-filter[open] > summary { opacity: 1; color: var(--fg); background: var(--surface-alt); }
.col-filter.active > summary { opacity: 1; color: var(--accent); }

.col-filter-menu {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    min-width: 170px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 6px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08);
    padding: 4px;
    z-index: 30;
}
/* Right-align popover for trailing columns so it doesn't overflow the table. */
table.grid.grid-sortable th:last-child .col-filter-menu,
table.grid.grid-sortable th:nth-last-child(2) .col-filter-menu {
    left: auto;
    right: 0;
}

.col-filter-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.col-filter-list a {
    display: block;
    padding: 6px 10px;
    border-radius: 4px;
    color: var(--fg);
    text-decoration: none;
    font-size: 12px;
    text-transform: none;
    letter-spacing: 0;
    font-weight: 400;
    white-space: nowrap;
}
.col-filter-list a:hover { background: var(--surface-alt); color: var(--accent); }
.col-filter-list a.selected {
    background: var(--fg);
    color: var(--on-fg);
    font-weight: 500;
}

/* Small "N filter(s) active — clear" hint that sits above the table. */
.col-filters-summary {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 10px;
    font-size: 12px;
    color: var(--muted);
}
.col-filters-summary a.clear-filters {
    color: var(--accent);
    text-decoration: none;
}
.col-filters-summary a.clear-filters:hover { text-decoration: underline; }

.dstage { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 11px; font-weight: 500; letter-spacing: 0.01em; }
/* Active funnel: cool → warm as the deal progresses. Pastel, low chroma. */
.dstage-PROSPECT          { background: #f1f5f9; color: #475569; }  /* slate */
.dstage-CONNECTED         { background: #ede9fe; color: #5b21b6; }  /* lavender */
.dstage-SCHEDULED         { background: #e0e7ff; color: #3730a3; }  /* indigo */
.dstage { white-space: nowrap; }
.dstage .dstage-sep { color: #fff; }
table.deals-list th.col-stage, table.deals-list td.col-stage { min-width: 16ch; white-space: nowrap; }

/* ── Deals list: header row (title + view toggle) ─────────────────────── */
.page-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 16px; }
.page-header h1 { margin: 0; }
.page-header-actions { display: inline-flex; align-items: center; gap: 12px; }

.view-toggle { display: inline-flex; gap: 2px; padding: 2px; background: var(--surface-alt); border: 1px solid var(--border); border-radius: 8px; }
.view-toggle a.view-toggle-btn { width: 32px; height: 28px; display: inline-flex; align-items: center; justify-content: center; color: var(--muted); border-radius: 5px; text-decoration: none; transition: background-color 120ms, color 120ms; }
.view-toggle a.view-toggle-btn:hover { color: var(--fg); }
.view-toggle a.view-toggle-btn.active { background: var(--surface); color: var(--fg); }
.view-toggle a.view-toggle-btn svg { width: 16px; height: 16px; }

/* ── Deals list: filters + show-empty toggle row ──────────────────────── */
.deals-toolbar { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.deals-toolbar .filters { margin-bottom: 0; flex: 1; }

/* Pill chips on the deals page: muted by default, active is the same dark
   bg as elsewhere. Stage chip inside stays its native palette. */
.deals-toolbar .filters a.chip { display: inline-flex; align-items: center; gap: 6px; opacity: 0.55; transition: opacity 120ms; }
.deals-toolbar .filters a.chip.active { opacity: 1; background: var(--surface); color: var(--fg); border-color: var(--border); }
.deals-toolbar .filters a.chip:hover { opacity: 1; }

/* ── Toggle switch (Show empty columns) ───────────────────────────────── */
a.toggle-switch { display: inline-flex; align-items: center; gap: 8px; padding: 4px 4px 4px 10px; font-size: 12px; color: var(--muted); text-decoration: none; border-radius: 999px; border: 1px solid transparent; transition: color 120ms, border-color 120ms; }
a.toggle-switch:hover { color: var(--fg); }
a.toggle-switch.on { color: var(--fg); }
a.toggle-switch .toggle-track { position: relative; display: inline-block; width: 28px; height: 16px; background: var(--border); border-radius: 999px; transition: background-color 120ms; }
a.toggle-switch .toggle-thumb { position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; background: var(--surface); border-radius: 50%; transition: transform 140ms ease; }
a.toggle-switch.on .toggle-track { background: var(--accent); }
a.toggle-switch.on .toggle-thumb { transform: translateX(12px); }
a.toggle-switch .toggle-label { line-height: 1; }

/* ── Kanban ────────────────────────────────────────────────────────────── */
.kanban { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 8px; align-items: flex-start; scrollbar-width: none; -ms-overflow-style: none; cursor: grab; user-select: none; }
.kanban::-webkit-scrollbar { display: none; }
/* Desktop only: let the column row break out of main's 1100px max-width and
   span the full body content area (viewport minus sidebar), with a 12px gap
   on either side. The page-header + deals-toolbar above stay constrained.
   Centering trick: main's content box is itself centered between the sidebar
   and the viewport edge, so `left: 50%; translateX(-50%)` aligns the wider
   .kanban to that same axis. Mobile flex-chain at the bottom of the file
   relies on the default position/transform and stays untouched. */
@media (min-width: 721px) {
  .kanban {
    position: relative;
    left: 50%;
    transform: translateX(-50%);
    width: calc(100vw - var(--sidebar-w) - 24px);
    max-width: calc(100vw - var(--sidebar-w) - 24px);
  }
}
.kanban.is-dragging { cursor: grabbing; }
.kanban.is-dragging a.kanban-card { pointer-events: none; }
.kanban-col { flex: 0 0 280px; width: 280px; background: var(--surface-alt); border: 1px solid var(--border); border-radius: 8px; padding: 12px; display: flex; flex-direction: column; gap: 10px; max-height: calc(100vh - 240px); }
.kanban-col-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 0 2px; }
.kanban-col-count { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.kanban-col-body { display: flex; flex-direction: column; gap: 8px; overflow-y: auto; min-height: 60px; scrollbar-width: none; -ms-overflow-style: none; }
.kanban-col-body::-webkit-scrollbar { display: none; }
a.kanban-card { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 12px 14px; color: var(--fg); text-decoration: none; transition: border-color 120ms, transform 120ms; }
a.kanban-card:hover { border-color: var(--accent); }
.kanban-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 6px; margin-bottom: 4px; }
.kanban-card-head .kanban-card-title { margin-bottom: 0; }
.kanban-card-title { font-weight: 600; font-size: 13px; line-height: 1.35; margin-bottom: 4px; }
.kanban-card-meta { font-size: 11px; line-height: 1.4; }
.kanban-sub-tag { flex: 0 0 auto; background: var(--surface-alt); color: var(--muted); font-size: 10px; font-weight: 500; padding: 2px 7px; border-radius: 999px; white-space: nowrap; line-height: 1.35; }
.kanban-col-blank { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; padding: 20px 8px; color: var(--muted); opacity: 0.6; font-size: 12px; user-select: none; }
.kanban-col-blank-icon svg { width: 22px; height: 22px; display: block; }

.dstage-INFO_SHARED       { background: #cffafe; color: #155e75; }  /* cyan */
.dstage-PROPOSAL_SENT     { background: #fef9c3; color: #854d0e; }  /* soft yellow */
.dstage-NEGOTIATION       { background: #ffedd5; color: #9a3412; }  /* peach */
/* Terminal outcomes: muted green / dusty rose. */
.dstage-CLOSED_WON      { background: #d1fae5; color: #065f46; }  /* mint */
.dstage-CLOSED_LOST     { background: #fce7f3; color: #9d174d; }  /* dusty rose */
/* Recruitment funnel: same cool→warm→terminal palette, mapped stage-by-stage. */
.dstage-SOURCED         { background: #f1f5f9; color: #475569; }  /* slate */
.dstage-CONTACTED       { background: #ede9fe; color: #5b21b6; }  /* lavender */
.dstage-APPLIED         { background: #e0e7ff; color: #3730a3; }  /* indigo */
.dstage-CALL_SCHEDULED  { background: #cffafe; color: #155e75; }  /* cyan */
.dstage-INTERVIEWING    { background: #fef9c3; color: #854d0e; }  /* soft yellow */
.dstage-OFFER           { background: #ffedd5; color: #9a3412; }  /* peach */
.dstage-HIRED           { background: #d1fae5; color: #065f46; }  /* mint */
.dstage-REJECTED        { background: #fce7f3; color: #9d174d; }  /* dusty rose */

form.meta { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; background: var(--surface); padding: 16px; border: 1px solid var(--border); border-radius: 6px; margin-bottom: 24px; }
form.meta .row { display: flex; gap: 12px; grid-column: 1 / -1; }
form.meta .row > label { flex: 1; }
form.meta div.full { grid-column: 1 / -1; }
form.meta label { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--muted); }
form.meta label.full { grid-column: 1 / -1; }
form.meta input, form.meta select, form.meta textarea { font: inherit; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--fg); }
form.meta button { grid-column: 1 / -1; justify-self: start; padding: 6px 14px; background: var(--accent); color: var(--on-accent); border: none; border-radius: 4px; cursor: pointer; }

.tabs { display: flex; gap: 4px; margin: 24px 0 12px; border-bottom: 1px solid var(--border); }
.tab { background: none; border: none; padding: 8px 14px; cursor: pointer; color: var(--muted); border-bottom: 2px solid transparent; font: inherit; }
.tab.active { color: var(--fg); border-color: var(--accent); }
.tab.disabled { color: #d6d3d1; cursor: not-allowed; }

.inline-add { display: flex; gap: 8px; margin-top: 12px; }
.inline-add input, .inline-add select { font: inherit; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--fg); }
.inline-add button { padding: 6px 14px; background: var(--surface); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; cursor: pointer; font: inherit; transition: border-color 120ms, color 120ms; }
.inline-add button:hover { border-color: var(--accent); color: var(--accent); }

form.inline { display: inline; margin: 0; }
/* Both selectors set the same "subtle red text, no chrome" style. The
   `[type=submit]` variant is needed because plain `button.link` and
   `button[type=submit]` have equal specificity — without the bumped
   selector the accent primary rule wins and .link submit buttons
   render as huge orange primaries. */
button.link, button[type=submit].link { background: none; border: none; color: var(--danger); cursor: pointer; font: inherit; padding: 0; border-radius: 0; }
button.link:hover, button[type=submit].link:hover { opacity: 0.7; }

ul.domains, ul.emails { list-style: none; padding: 0; margin: 8px 0; }
ul.domains li, ul.emails li { padding: 6px 0; display: flex; gap: 12px; align-items: baseline; }

details.newform { margin-top: 16px; }
details.newform summary { cursor: pointer; color: var(--accent); }
details.newform form { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; margin-top: 12px; padding: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; }
details.newform form label { display: flex; flex-direction: column; font-size: 12px; color: var(--muted); }
details.newform form input, details.newform form select { font: inherit; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface); color: var(--fg); }
details.newform form button { grid-column: 1 / -1; justify-self: start; padding: 6px 14px; background: var(--accent); color: var(--on-accent); border: none; border-radius: 4px; cursor: pointer; }

button { font: inherit; }
button[type=submit] { padding: 6px 14px; background: var(--accent); color: var(--on-accent); border: none; border-radius: 4px; cursor: pointer; }
button.secondary { background: var(--surface); color: var(--fg); border: 1px solid var(--border); transition: border-color 120ms, color 120ms; }
button.secondary:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
button.secondary:disabled { opacity: 0.55; cursor: not-allowed; }
p.status { color: var(--danger); min-height: 1.2em; }
.row { display: flex; gap: 8px; }
.muted { color: var(--muted); }
.small { font-size: 12px; }
details.enrol { margin-top: 16px; }
details.enrol summary { cursor: pointer; color: var(--muted); font-size: 13px; }
details.enrol button { margin-top: 8px; padding: 6px 14px; background: var(--surface); color: var(--fg); border: 1px solid var(--border); border-radius: 4px; cursor: pointer; }
.card button#loginBtn { padding: 8px 16px; background: var(--accent); color: var(--on-accent); border: none; border-radius: 4px; cursor: pointer; width: 100%; font-size: 15px; }
.card button#loginBtn:hover { opacity: 0.9; }
form.inline-rename { display: inline-flex; gap: 6px; align-items: center; }
form.inline-rename input { font: inherit; padding: 2px 6px; border: 1px solid var(--border); border-radius: 3px; min-width: 140px; }
code.tiny { font-size: 11px; color: var(--muted); }

table.emails th:first-child, table.emails td.nowrap { width: 6rem; white-space: nowrap; }
table.emails th:nth-child(2), table.emails td.dir { width: 5rem; white-space: nowrap; }
table.emails td.nowrap { color: var(--muted); font-variant-numeric: tabular-nums; text-transform: uppercase; letter-spacing: 0.02em; }
table.emails td.dir { font-size: 11px; font-weight: 600; color: var(--muted); }
table.emails tr.email-out td.dir { color: var(--accent); }
table.emails td.addr code { font-size: 11px; color: var(--muted); word-break: break-all; }
table.emails td.addr.nowrap { white-space: nowrap; color: var(--fg); font-variant-numeric: normal; }
table.emails td.addr.clip { max-width: 20ch; overflow: hidden; text-overflow: ellipsis; }

/* View tabs (e.g. /customers/?view=cold). */
nav.view-tabs { display: flex; gap: 4px; margin: 0 0 12px; }
nav.view-tabs a.view-tab {
  padding: 6px 12px;
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
nav.view-tabs a.view-tab:hover { color: var(--fg); }
nav.view-tabs a.view-tab.active { color: var(--fg); border-bottom-color: var(--accent); font-weight: 600; }

/* Per-row external link icon - hidden until the row is hovered. */
table.grid a.ext-link {
  display: inline-flex;
  vertical-align: middle;
  margin-left: 6px;
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.12s ease;
}
table.grid tr:hover a.ext-link { opacity: 1; }
table.grid a.ext-link:hover { color: var(--accent); }
/* Keyboard accessibility - show on focus too. */
table.grid a.ext-link:focus-visible { opacity: 1; outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 2px; }
table.emails a.email-subject { color: var(--fg); text-decoration: none; font-weight: 500; }
table.emails a.email-subject:hover { color: var(--accent); text-decoration: underline; }
table.emails .preview { font-size: 12px; color: var(--muted); margin-top: 4px; line-height: 1.4; }
.empty { color: var(--muted); font-size: 13px; padding: 12px 0; }

a.chip, span.chip { padding: 2px 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); font-size: 11px; margin-right: 4px; display: inline-block; }
a.chip { color: var(--fg); text-decoration: none; }
a.chip:hover { border-color: var(--accent); color: var(--accent); }
span.chip.orphan { background: #fef3c7; border-color: #fcd34d; color: #92400e; }

.note-body { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 16px 20px; font: 14px/1.55 system-ui, sans-serif; word-wrap: break-word; margin: 16px 0; color: var(--fg); }
.note-body > :first-child { margin-top: 0; }
.note-body > :last-child { margin-bottom: 0; }
.note-body h1, .note-body h2, .note-body h3, .note-body h4, .note-body h5, .note-body h6 { margin: 18px 0 8px; line-height: 1.3; text-transform: none; letter-spacing: 0; color: var(--fg); }
.note-body h1 { font-size: 18px; font-weight: 600; }
.note-body h2 { font-size: 16px; font-weight: 600; }
.note-body h3 { font-size: 14px; font-weight: 600; }
.note-body h4, .note-body h5, .note-body h6 { font-size: 13px; font-weight: 600; }
.note-body p { margin: 8px 0; }
.note-body ul, .note-body ol { margin: 8px 0; padding-left: 24px; }
.note-body li { margin: 2px 0; }
.note-body li > p { margin: 4px 0; }
.note-body blockquote { margin: 10px 0; padding: 4px 12px; border-left: 3px solid var(--border); color: var(--muted); }
.note-body code { background: #f5f5f4; border-radius: 3px; padding: 1px 4px; font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; }
.note-body pre { background: #f5f5f4; border: 1px solid var(--border); border-radius: 6px; padding: 12px 14px; overflow-x: auto; margin: 10px 0; }
.note-body pre code { background: transparent; padding: 0; font-size: 12px; }
.note-body a { color: var(--accent); }
.note-body table { border-collapse: collapse; margin: 10px 0; }
.note-body th, .note-body td { border: 1px solid var(--border); padding: 4px 8px; text-align: left; }
.note-body th { background: #f5f5f4; font-weight: 600; }
.note-body hr { border: 0; border-top: 1px solid var(--border); margin: 16px 0; }
.note-meta p { margin: 4px 0; }
form.note-type-form { margin: 12px 0; align-items: end; }
.note-link-edit { margin: 12px 0 16px; padding: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; }
.note-link-edit > p.lbl { margin: 0 0 8px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
.note-link-edit > p.empty { margin: 0 0 8px; padding: 0; }
ul.chip-edit-list { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
ul.chip-edit-list li { display: flex; align-items: center; gap: 8px; }

/* Card-wrapped section on settings sub-pages (/me, /settings/tasks,
   /settings/users, /settings/blocklist, etc.). The white surface + border
   + radius gives each group a clear boundary — without it the sub-page
   reads as one big list of headings and forms with no visual grouping. */
section.task-section { margin: 20px 0; padding: 16px 18px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; }
/* Aligned with section.settings-group > h2 (style-guide §3). Both
   selectors render section headings identically - same 11px / 0.08em
   uppercase muted look across the site. */
section.task-section h2 { margin: 0 0 10px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); font-weight: 600; }
section.task-section table.grid { margin-top: 8px; }

/* ── Detail-page title row + edit toggle ──────────────────────────────── */

.title-row { display: flex; align-items: center; gap: 12px; margin: 0 0 12px; flex-wrap: wrap; }
.title-row h1 { margin: 0; flex: 0 0 auto; }
.title-row .edit-toggle { margin-left: auto; }
button.icon-btn.edit-toggle { width: 28px; height: 28px; }
button.icon-btn.edit-toggle svg { width: 16px; height: 16px; }
button.icon-btn.edit-toggle.active { color: var(--accent); border-color: var(--border); background: var(--surface-alt); }

.entity-summary { margin: 0 0 20px; color: var(--fg); }
.entity-summary p { margin: 4px 0; }

/* ── Person detail polish ──────────────────────────────────────────────── */

form.meta label.checkbox-label { flex-direction: row; align-items: center; gap: 8px; font-size: 13px; color: var(--fg); grid-column: 1 / -1; }
form.meta label.checkbox-label input { padding: 0; }

ul.link-list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 8px 12px; align-items: center; }
ul.link-list li { display: flex; align-items: center; gap: 8px; }

ul.email-list { list-style: none; padding: 0; margin: 0 0 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
ul.email-list li { display: flex; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--surface-alt); }
ul.email-list li:last-child { border-bottom: none; }
ul.email-list code { font-size: 13px; }
ul.email-list .primary-chip { background: #dcfce7; color: #065f46; border-color: #86efac; font-size: 10px; padding: 1px 8px; }

/* Hide reorder/remove until hover so each row reads as one line of address. */
.row-actions { margin-left: auto; display: inline-flex; gap: 4px; opacity: 0; transition: opacity 120ms; }
ul.email-list li:hover .row-actions,
ul.email-list li:focus-within .row-actions { opacity: 1; }

button.icon-btn,
a.icon-btn { width: 24px; height: 24px; padding: 0; display: inline-flex; align-items: center; justify-content: center; background: transparent; color: var(--muted); border: 1px solid transparent; border-radius: 4px; cursor: pointer; font: inherit; font-size: 14px; line-height: 1; text-decoration: none; }
button.icon-btn:hover,
a.icon-btn:hover { color: var(--fg); border-color: var(--border); background: var(--row-hover); }
button.icon-btn.destructive:hover { color: var(--danger); border-color: var(--danger); background: var(--surface); }

section.danger-zone { margin-top: 40px; padding: 16px 18px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
section.danger-zone > h2 { margin: 0 0 10px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--danger); font-weight: 600; }
button.secondary.destructive { background: var(--surface); color: var(--fg); border: 1px solid var(--border); padding: 6px 14px; border-radius: 4px; cursor: pointer; font: inherit; font-size: 13px; }
button.secondary.destructive:hover { color: var(--danger); border-color: var(--danger); }

/* Email captured-by-mailbox table: cap the Subject column so long subjects
   don't push the From/To and Matched columns off the right edge. */
table.emails { table-layout: fixed; }
table.emails th:nth-child(4), table.emails td:nth-child(4) { width: 50%; }
table.emails th:nth-child(5), table.emails td:nth-child(5) { width: 21ch; }
section.task-section .inline-add { gap: 6px; flex-wrap: wrap; align-items: center; }
section.task-section .inline-add label { display: inline-flex; align-items: center; gap: 4px; }
section.task-section .inline-add input[name=slug] { width: 110px; }
section.task-section .inline-add input[name=name] { width: 180px; }
.week-picker { display: flex; gap: 8px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }
.metric-headline { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 14px 20px; margin-bottom: 20px; }
.metric-headline ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 6px; }
.metric-headline li { font-size: 14px; }
pre.copy-md { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 14px 18px; font: 12px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace; white-space: pre-wrap; word-wrap: break-word; }
form.send-form textarea { font: inherit; padding: 6px 8px; border: 1px solid var(--border); border-radius: 4px; width: 100%; resize: vertical; background: var(--surface); color: var(--fg); }
p.send-status { padding: 8px 12px; border-radius: 4px; }
p.send-status.success { background: #d1fae5; color: #065f46; }
p.send-status.error { background: #fee2e2; color: #991b1b; }

p.form-error { background: #fee2e2; color: #991b1b; padding: 8px 12px; border-radius: 4px; border: 1px solid #fca5a5; margin: 12px 0; font-size: 13px; }
.req { color: var(--danger); margin-left: 2px; font-weight: 700; }
.req-conditional { color: var(--danger); opacity: 0.55; margin-left: 2px; font-weight: 700; }
h3.task-bucket-title { font-size: 14px; margin: 18px 0 6px; display: flex; gap: 8px; align-items: baseline; }
h3.task-bucket-title a { text-decoration: none; color: var(--fg); }
h3.task-bucket-title a:hover { color: var(--accent); }
table.email-discoveries td { vertical-align: top; }
table.email-discoveries .inline-add { margin: 0; }
table.email-discoveries .inline-add select,
table.email-discoveries .inline-add input { font: inherit; padding: 4px 6px; }

/* Hidden-tasks disclosure at the bottom of each /settings/tasks section.
   Muted summary + full-opacity when open so the collapsed state doesn't
   compete with the live task list above. */
details.hidden-tasks { margin-top: 12px; }
details.hidden-tasks > summary { cursor: pointer; color: var(--muted); font-size: 12px; padding: 4px 0; user-select: none; }
details.hidden-tasks > summary:hover { color: var(--accent); }
details.hidden-tasks > table.grid { margin-top: 8px; }
details.hidden-tasks tr.row-hidden td { opacity: 0.75; }

/* ── Navigator mode — full-screen overlay opened with `g`; single-letter
   shortcuts jump to top-level pages. See the script in layout.html. ───── */
.nav-mode-overlay { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: center; justify-content: center; }
.nav-mode-overlay[hidden] { display: none; }
.nav-mode-backdrop { position: absolute; inset: 0; background: rgba(12, 10, 9, 0.45); }
.nav-mode-card { position: relative; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; min-width: 280px; max-width: 380px; padding: 18px 20px 16px; }
.nav-mode-card header { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.nav-mode-card h2 { margin: 0; font-size: 14px; font-weight: 600; color: var(--fg); text-transform: none; letter-spacing: 0; }
.nav-mode-hint { font-size: 11px; color: var(--muted); }
.nav-mode-hint kbd { font-family: ui-monospace, 'SF Mono', monospace; font-size: 10px; padding: 1px 5px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface-alt); color: var(--fg); }
.nav-mode-section { margin-bottom: 10px; }
.nav-mode-section:last-child { margin-bottom: 0; }
.nav-mode-section h3 { margin: 0 0 4px; font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); padding: 0 4px; }
.nav-mode-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.nav-mode-list li { display: flex; align-items: center; gap: 10px; padding: 6px 8px; border-radius: 4px; font-size: 13px; color: var(--fg); }
.nav-mode-list li:hover { background: var(--surface-alt); }
.nav-mode-list kbd { font-family: ui-monospace, 'SF Mono', monospace; font-size: 12px; min-width: 22px; text-align: center; padding: 2px 6px; border: 1px solid var(--border); border-radius: 4px; background: var(--surface-alt); color: var(--fg); }

/* ── Version badge — stamped at commit time, shown bottom-left on every
   authed page (login.html doesn't extend layout.html). ────────────────── */
.app-version {
  position: fixed;
  bottom: 8px;
  left: calc(var(--sidebar-w) + 12px);
  font-size: 11px;
  color: var(--muted);
  opacity: 0.65;
  font-family: ui-monospace, 'SF Mono', monospace;
  pointer-events: none;
  user-select: none;
  z-index: 9999;
}

/* ── Chatbot sidebar ───────────────────────────────────────────────────── */
#chatbot-toggle {
  position: fixed;
  right: 1.2rem;
  bottom: 1.2rem;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--fg);
  color: var(--on-fg);
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}
#chatbot-toggle:hover { opacity: 0.85; }

#chatbot-panel {
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  width: 400px;
  max-width: 100vw;
  background: var(--surface);
  border-left: 1px solid var(--border);
  box-shadow: -4px 0 18px rgba(0, 0, 0, 0.1);
  display: flex;
  flex-direction: column;
  transform: translateX(100%);
  transition: transform 0.2s ease;
  z-index: 1001;
}
#chatbot-panel.open { transform: translateX(0); }

#chatbot-panel header {
  padding: 0.75rem 1rem;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--surface-alt);
}
#chatbot-close {
  background: none;
  border: none;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
  padding: 0 0.25rem;
}
#chatbot-close:hover { color: var(--fg); }

#chatbot-log {
  flex: 1;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.chatbot-msg {
  padding: 0.55rem 0.75rem;
  border-radius: 0.6rem;
  font-size: 0.93rem;
  line-height: 1.4;
  word-wrap: break-word;
}
.chatbot-msg-user {
  align-self: flex-end;
  background: var(--fg);
  color: var(--on-fg);
  max-width: 85%;
  white-space: pre-wrap;
}
.chatbot-msg-assistant {
  align-self: flex-start;
  background: var(--surface-alt);
  color: var(--fg);
  border: 1px solid var(--border);
  max-width: 90%;
}
.chatbot-msg-assistant p { margin: 0 0 0.45rem; }
.chatbot-msg-assistant p:last-child { margin-bottom: 0; }
.chatbot-msg-assistant ul,
.chatbot-msg-assistant ol { margin: 0 0 0.45rem; padding-left: 1.25rem; }
.chatbot-msg-assistant li { margin-bottom: 0.2rem; }
.chatbot-msg-assistant strong { font-weight: 600; }
.chatbot-msg-assistant code { font-family: monospace; background: var(--border); border-radius: 3px; padding: 0 3px; font-size: 0.88em; }
.chatbot-msg-error {
  background: #fee2e2;
  color: var(--danger);
  border-color: #fca5a5;
}

/* Tool-call trace card — collapsed to one line by default, click to expand.
   Slots between assistant text bubbles so the operator can see what the
   chatbot is doing on the API. */
.chatbot-tool {
  margin: 0.35rem 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  font-size: 12px;
  overflow: hidden;
}
.chatbot-tool[open] { border-color: var(--accent); }
.chatbot-tool-head {
  list-style: none;
  cursor: pointer;
  padding: 5px 9px;
  display: flex;
  align-items: center;
  gap: 6px;
  user-select: none;
}
.chatbot-tool-head::-webkit-details-marker { display: none; }
.chatbot-tool-arrow {
  color: var(--muted);
  font-size: 12px;
  width: 14px;
  display: inline-flex;
  justify-content: center;
}
.chatbot-tool-write .chatbot-tool-arrow {
  color: var(--accent);
}
.chatbot-tool-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  color: var(--fg);
  background: transparent;
  padding: 0;
}
.chatbot-tool-args {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1;
}
.chatbot-tool-status {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted);
  flex-shrink: 0;
}
.chatbot-tool-status.chatbot-tool-error { color: var(--danger); }
.chatbot-tool-failed { border-color: #fca5a5; }
.chatbot-tool-failed[open] { border-color: var(--danger); }
.chatbot-tool-body {
  padding: 6px 9px 9px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.chatbot-tool-body pre {
  margin: 0;
  padding: 6px 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--fg);
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 240px;
  overflow: auto;
}
.chatbot-tool-input { color: var(--muted) !important; }

#chatbot-form {
  padding: 0.6rem;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 0.5rem;
  align-items: flex-end;
}
#chatbot-input {
  flex: 1;
  font: inherit;
  padding: 0.5rem;
  border: 1px solid var(--border);
  border-radius: 0.4rem;
  resize: none;
  background: var(--surface);
  color: var(--fg);
}
#chatbot-send {
  padding: 0.5rem 0.9rem;
  background: var(--fg);
  color: var(--on-fg);
  border: none;
  border-radius: 0.4rem;
  cursor: pointer;
  font: inherit;
}
#chatbot-send:disabled { opacity: 0.55; cursor: progress; }

#chatbot-title {
  font-weight: 600;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 180px;
}

/* ── Dedicated /chats page ─────────────────────────────────────────────────
   Two-pane layout: history / room list on the left, message log + composer
   on the right. The page hosts two panes (Users tab / Agents tab) toggled
   by .chats-tabs above them. The .chatbot-msg / .chatbot-tool / .chatbot-modal
   styles defined earlier are still reused by the Agents pane. */
.chats-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.chats-tab {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 8px 16px;
  font: inherit;
  font-size: 13px;
  color: var(--muted);
  cursor: pointer;
  transition: color 120ms, border-color 120ms;
  margin-bottom: -1px;
}
.chats-tab:hover { color: var(--fg); }
.chats-tab.active {
  color: var(--fg);
  border-bottom-color: var(--accent);
  font-weight: 600;
}
.chats-page {
  display: flex;
  gap: 16px;
  /* Fill the viewport below the header + tabs. Adds the tab bar height (~34px)
     to the previous 110px reservation. */
  height: calc(100vh - 150px);
  min-height: 480px;
}
.chats-page[hidden] { display: none; }
.chats-sidebar {
  flex: 0 0 280px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
.chats-sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
}
.chats-sidebar-head h2 {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.chats-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--muted);
  cursor: pointer;
}
.chats-icon-btn:hover { color: var(--fg); background: var(--surface-alt); border-color: var(--border); }
.chats-history-empty { padding: 12px; }
.chats-history-list {
  list-style: none;
  margin: 0;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  flex: 1;
}
.chats-history-item {
  display: flex;
  align-items: stretch;
  gap: 2px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
}
.chats-history-item.current { border-color: var(--accent); }
.chats-history-open {
  flex: 1;
  text-align: left;
  background: transparent;
  border: none;
  padding: 8px 10px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 2px;
  color: var(--fg);
  font: inherit;
  overflow: hidden;
}
.chats-history-open:hover { background: var(--row-hover); }
.chats-history-title {
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chats-history-meta { font-size: 11px; }
.chats-history-actions {
  display: flex;
  align-items: center;
  padding-right: 4px;
  gap: 2px;
}

.chats-main {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  min-width: 0;
}
.chats-main-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
}
.chats-main-head h1 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chats-main-head label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  user-select: none;
}
.chats-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.chats-form {
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  display: flex;
  gap: 8px;
  align-items: flex-end;
  background: var(--surface);
}
.chats-form textarea {
  flex: 1;
  font: inherit;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  resize: none;
  background: var(--surface);
  color: var(--fg);
}
.chats-form button[type=submit] {
  padding: 8px 16px;
  background: var(--fg);
  color: var(--on-fg);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font: inherit;
}
.chats-form button[type=submit]:disabled { opacity: 0.55; cursor: progress; }

/* ── Users tab: DM / group room list ─────────────────────────────────────── */
.chats-rooms-list {
  list-style: none;
  margin: 0;
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  flex: 1;
}
.chats-rooms-empty { padding: 12px; }
.chats-room-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 100ms;
}
.chats-room-item:hover { background: var(--row-hover, var(--surface-alt)); }
.chats-room-item.current { background: var(--surface-alt); }
.chats-room-item-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.chats-room-item-title-row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  justify-content: space-between;
}
.chats-room-item-title {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chats-room-item-time {
  flex-shrink: 0;
  font-size: 11px;
}
.chats-room-item-preview {
  font-size: 12px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Avatar chip — square-ish rounded photo/initial swatch used in the room
   list, the room header, and next to inbound group-chat messages. */
.chats-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  color: #fff;
  font-size: 14px;
  font-weight: 600;
  flex-shrink: 0;
  overflow: hidden;
  user-select: none;
}
.chats-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.chats-avatar-sm { width: 28px; height: 28px; font-size: 12px; }
.chats-avatar-servo7 {
  background: var(--surface-alt);
  padding: 4px;
}
.chats-avatar-servo7 img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 0;
}

/* Room header on the right-hand pane. */
.chats-room-head-info {
  display: flex;
  align-items: center;
  gap: 10px;
}
.chats-room-head-titles {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.chats-room-subtitle {
  font-size: 11px;
}

.chats-empty {
  padding: 32px 16px;
  text-align: center;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* WhatsApp-style bubbles. Own messages align right, dark bubble; others
   align left with an avatar. In group chats the sender name shows above
   the body. */
.chats-room-log {
  gap: 6px;
}
.chats-msg {
  display: flex;
  gap: 8px;
  max-width: 80%;
}
.chats-msg-me {
  align-self: flex-end;
  justify-content: flex-end;
}
.chats-msg-them {
  align-self: flex-start;
}
.chats-msg-bubble {
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 14px;
  line-height: 1.4;
  word-wrap: break-word;
  max-width: 100%;
}
.chats-msg-me .chats-msg-bubble {
  background: var(--fg);
  color: var(--on-fg);
  border-bottom-right-radius: 4px;
}
.chats-msg-them .chats-msg-bubble {
  background: var(--surface-alt);
  color: var(--fg);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}
.chats-msg-sender {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 2px;
}
.chats-msg-body {
  white-space: pre-wrap;
  word-break: break-word;
}
.chats-msg-time {
  font-size: 10.5px;
  margin-top: 2px;
  text-align: right;
  opacity: 0.75;
}
.chats-msg-me .chats-msg-time { color: rgba(255,255,255,0.8); }

/* New-DM picker modal. */
.chats-dm-picker {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.chats-dm-picker[hidden] { display: none; }
.chats-dm-picker-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}
.chats-dm-picker-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: min(480px, 92vw);
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.chats-dm-picker-card > header {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.chats-dm-picker-card > header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}
#chats-dm-picker-search {
  margin: 8px 12px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font: inherit;
  background: var(--surface);
  color: var(--fg);
}
.chats-dm-picker-list {
  list-style: none;
  margin: 0;
  padding: 4px 8px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
}
.chats-dm-picker-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
}
.chats-dm-picker-item:hover { background: var(--surface-alt); }
.chats-dm-picker-info { display: flex; flex-direction: column; min-width: 0; }
.chats-dm-picker-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--fg);
}
.chats-dm-picker-empty { padding: 8px 10px; }

/* Approval modal — surfaces the exact HTTP request the chatbot wants to run
   in beast mode. White card, 1px border, no drop-shadow, sentence-case copy. */
.chatbot-modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.chatbot-modal[hidden] { display: none; }
.chatbot-modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}
.chatbot-modal-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: min(560px, 92vw);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.chatbot-modal-card > header {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
}
.chatbot-modal-card h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--fg);
  text-transform: none;
  letter-spacing: 0;
}
#chatbot-modal-body {
  padding: 12px 16px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.chatbot-modal-card > footer {
  padding: 10px 16px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}
.chatbot-action {
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  background: var(--surface);
}
.chatbot-action.resolved { opacity: 0.6; }
.chatbot-action-head {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px;
}
.chatbot-action-method {
  font-weight: 600;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.chatbot-action-path { color: var(--fg); }
.chatbot-action-summary {
  margin: 8px 0 4px;
  font-size: 13px;
  color: var(--fg);
}
.chatbot-action-form {
  margin: 6px 0 10px;
  padding: 8px 10px;
  background: var(--surface-alt);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  line-height: 1.45;
  white-space: pre-wrap;
  word-break: break-word;
  max-height: 240px;
  overflow-y: auto;
}
.chatbot-action-row {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

/* ── inline-rename: compact secondary save button next to the small input.
   The default button[type=submit] padding (6px 14px) is too tall next to
   the inline-rename input (padding 2px 6px); pair it with .secondary so it
   reads as a non-destructive small save, distinct from the .link revoke
   action on the same row. */
form.inline-rename button[type=submit].secondary { padding: 2px 10px; font-size: 12px; border-radius: 3px; }

/* ── Page-header search (top-right of list pages) ─────────────────────
   Lives inside `.page-header-actions` next to the page h1. The input
   visually matches the height of the h1 line-box so the title row stays
   level. Same htmx live-filter pattern as the global /search/ page. */
form.page-search { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
form.page-search input[type=search] {
  width: 260px;
  padding: 6px 12px;
  font: inherit;
  font-size: 13px;
  line-height: 1.4;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--fg);
  transition: border-color 120ms;
}
form.page-search input[type=search]:focus { outline: none; border-color: var(--accent); }
form.page-search .search-spinner { font-size: 11px; }

/* ── Search page ──────────────────────────────────────────────────────── */
form.search-form { display: flex; gap: 8px; margin: 0 0 16px; align-items: center; }
form.search-form input[type=search] {
  flex: 1;
  padding: 10px 14px;
  font: inherit;
  font-size: 15px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--fg);
  transition: border-color 120ms;
}
form.search-form input[type=search]:focus { outline: none; border-color: var(--accent); }
form.search-form button[type=submit] { padding: 8px 16px; }

p.search-meta { margin: 0 0 12px; }
p.search-meta strong { color: var(--fg); font-weight: 600; }

ul.search-results { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
li.search-result { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; transition: border-color 120ms; }
li.search-result:hover { border-color: var(--accent); }

a.search-result-link { display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px; color: var(--fg); text-decoration: none; }
.search-result-icon { flex: 0 0 32px; height: 32px; display: inline-flex; align-items: center; justify-content: center; background: var(--surface-alt); color: var(--accent); border-radius: 6px; }
.search-result-icon svg { width: 18px; height: 18px; }

.search-result-body { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.search-result-title { font-weight: 600; font-size: 14px; color: var(--fg); }
a.search-result-link:hover .search-result-title { color: var(--accent); }
.search-result-subtitle { font-size: 12px; color: var(--muted); }
.search-result-snippet { font-size: 12px; color: var(--muted); line-height: 1.5; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.search-result-snippet mark { background: #fef3c7; color: #1c1917; padding: 0 2px; border-radius: 2px; }

.search-result-type { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); align-self: center; flex: 0 0 auto; }

/* htmx-indicator: hidden by default; shown while an htmx request is in
   flight on the search input. opacity (not display) so it doesn't shift
   the form layout. */
.search-spinner { font-size: 12px; color: var(--muted); opacity: 0; transition: opacity 200ms; }
.htmx-request .search-spinner,
.htmx-request.search-spinner { opacity: 1; }

/* ── Page-header "+" add button ────────────────────────────────────────
   Sits in `.page-header-actions` next to the search box. Visually echoes
   the settings cards: white surface, 1px border, accent on hover, no
   drop-shadow. */
.icon-button-add {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--fg);
  cursor: pointer;
  transition: border-color 120ms, color 120ms;
}
.icon-button-add:hover { border-color: var(--accent); color: var(--accent); }
.icon-button-add:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── Generic modal ────────────────────────────────────────────────────
   Centered white card on a translucent backdrop. No drop-shadow — the
   border + bg do the elevation work, matching the rest of the product.
   Open/close is class-based (`.is-open`) so we can fade the backdrop
   and slide the card in. Resting state stays inert (visibility hidden
   + pointer-events none), so the markup is safe to leave in the DOM. */
.modal {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.16s ease, visibility 0s linear 0.16s;
}
.modal.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.16s ease, visibility 0s linear 0s;
}
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: var(--scrim);
}
.modal-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  width: min(440px, 92vw);
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: translateY(-8px) scale(0.98);
  transition: transform 0.16s ease;
}
.modal.is-open .modal-card { transform: none; }
.modal-card > header {
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-alt);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.modal-card h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--fg);
  text-transform: none;
  letter-spacing: 0;
}
.modal-close {
  background: none;
  border: none;
  font-size: 1.4rem;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 0 0.25rem;
}
.modal-close:hover { color: var(--fg); }

/* Forms hosted inside the modal: stacked full-width labels with the action
   row pinned at the bottom. Mirrors `form.meta`'s label styling (12px muted
   label text, accent border on focus) without inheriting its outer card
   chrome — the modal card supplies the border / padding. */
form.modal-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 12px;
  margin: 0;
}
form.modal-form label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted);
}
form.modal-form label.full { width: 100%; }
form.modal-form input,
form.modal-form select,
form.modal-form textarea {
  font: inherit;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  color: var(--fg);
}
form.modal-form input:focus,
form.modal-form select:focus,
form.modal-form textarea:focus { outline: none; border-color: var(--accent); }
form.modal-form label.checkbox-label {
  flex-direction: row;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--fg);
}
form.modal-form label.checkbox-label input { padding: 0; }
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

/* ── Command palette (⌘K) ─────────────────────────────────────────────
   Spotlight-style search that replaces the standalone /search/ page.
   Uses the generic `.modal` open/close plumbing (see the driver in
   layout.html) but positions its card near the top of the viewport
   instead of dead-centre — the results list needs room to breathe. */
.cmdk-modal { align-items: flex-start; padding-top: 15vh; }
.cmdk-card {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  width: min(600px, 92vw);
  max-height: 70vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 20px 48px rgba(0, 0, 0, 0.18);
  transform: translateY(-8px) scale(0.98);
  transition: transform 0.16s ease;
}
.cmdk-modal.is-open .cmdk-card { transform: none; }
[data-theme="dark"] .cmdk-card { box-shadow: 0 20px 48px rgba(0, 0, 0, 0.55); }

.cmdk-input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.cmdk-input-icon { display: inline-flex; color: var(--muted); }
.cmdk-input-icon svg { width: 18px; height: 18px; }
#cmdk-input {
  flex: 1;
  min-width: 0;
  border: none;
  outline: none;
  background: transparent;
  color: var(--fg);
  font: inherit;
  font-size: 15px;
  padding: 4px 0;
}
#cmdk-input::placeholder { color: var(--muted); }
.cmdk-spinner {
  width: 12px; height: 12px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  opacity: 0;
  transition: opacity 200ms;
  animation: cmdk-spin 0.7s linear infinite;
}
.htmx-request .cmdk-spinner,
.htmx-request.cmdk-spinner { opacity: 1; }
@keyframes cmdk-spin { to { transform: rotate(360deg); } }
.cmdk-esc {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface-alt);
  color: var(--muted);
  cursor: pointer;
  user-select: none;
}
.cmdk-esc:hover { border-color: var(--accent); color: var(--fg); }

.cmdk-results {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 8px;
}
.cmdk-hint { padding: 20px 12px; text-align: center; margin: 0; }
.cmdk-results .search-meta { padding: 6px 8px 4px; font-size: 11px; }
.cmdk-results .search-results { gap: 2px; }
.cmdk-results .search-result { border: 1px solid transparent; background: transparent; }
.cmdk-results .search-result:hover,
.cmdk-results .search-result.selected { background: var(--surface-alt); border-color: var(--border); }
.cmdk-results .search-result.selected .search-result-title { color: var(--accent); }
.cmdk-results .search-result-link { padding: 8px 10px; gap: 10px; }
.cmdk-results .search-result-icon { width: 28px; height: 28px; flex: 0 0 28px; }
.cmdk-results .search-result-icon svg { width: 16px; height: 16px; }
.cmdk-results .search-result-snippet { -webkit-line-clamp: 1; }

.cmdk-foot {
  display: flex;
  gap: 16px;
  padding: 8px 14px;
  border-top: 1px solid var(--border);
  background: var(--surface-alt);
  font-size: 11px;
  color: var(--muted);
}
.cmdk-foot kbd {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 10px;
  padding: 1px 5px;
  margin-right: 4px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--surface);
  color: var(--muted);
}

@media (max-width: 720px) {
  .cmdk-modal { padding-top: 8vh; }
  .cmdk-card { max-height: 80vh; }
  .cmdk-foot { display: none; }
}

/* ── Todos list (crm.tasks rows) ─────────────────────────────────────── */
/* ── Todos list (clone of legacy todo.becking.dev rows) ────────────── */
.todo-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 64px; }
.todo-row { display: flex; gap: 12px; padding: 12px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; cursor: pointer; transition: border-color 120ms ease; align-items: flex-start; outline: none; }
.todo-row:hover { border-color: var(--accent); }
.todo-row.selected { border-color: var(--accent); background: var(--row-hover); }
.todo-row.done .todo-text { text-decoration: line-through; color: var(--muted); }
.todo-row.done { opacity: 0.7; }
.todo-row.overdue .todo-remind { color: var(--danger); font-weight: 500; }
.todo-row .todo-check-form { margin-top: 1px; }
/* `button.todo-check` (incl. the [type=submit] attribute selector below)
   is needed to outrank the global `button[type=submit]` rule, which
   otherwise paints every checkbox as a solid accent rectangle. */
button.todo-check[type=submit] { width: 18px; height: 18px; min-width: 0; border: 1.5px solid var(--border); border-radius: 4px; background: var(--surface); padding: 0; cursor: pointer; color: var(--on-accent); display: inline-flex; align-items: center; justify-content: center; transition: border-color 120ms, background 120ms; flex: 0 0 18px; font-size: 0; }
button.todo-check[type=submit]:hover { border-color: var(--accent); background: var(--surface); }
button.todo-check.checked[type=submit] { background: var(--accent); border-color: var(--accent); }
button.todo-check.checked[type=submit]:hover { background: var(--accent); border-color: var(--accent); opacity: 0.85; }
.todo-body { flex: 1; min-width: 0; }
.todo-text { font-size: 14px; color: var(--fg); line-height: 1.35; word-break: break-word; }
.todo-description { font-size: 12px; color: var(--muted); margin-top: 4px; white-space: pre-wrap; word-break: break-word; max-height: 72px; overflow: hidden; mask-image: linear-gradient(to bottom, black 60%, transparent); }
.todo-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 6px; font-size: 11px; color: var(--muted); }
.todo-meta a { color: var(--muted); }
.todo-meta a:hover { color: var(--accent); }
.todo-meta .todo-sub { max-width: 28ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.todo-meta .todo-remind { font-weight: 500; }
.todo-meta .todo-owner { font-style: italic; }
.todo-meta .chip { padding: 2px 8px; font-size: 11px; }
/* Top-right link icon on a task card — opens a task-specific URL (e.g. the
   LinkedIn profile for `linkedin-webhook` tasks) in a new tab. Carries
   `data-stop-row` so the row's click-to-edit / swipe handlers ignore it. */
.todo-row .todo-link {
  align-self: flex-start;
  margin-top: 1px;
  margin-left: 6px;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px; height: 22px;
  color: var(--muted);
  border-radius: 4px;
  transition: color 120ms ease, background 120ms ease;
}
.todo-row .todo-link:hover { color: var(--accent); background: var(--row-hover); }
.todo-row .todo-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.overdue { color: var(--danger); font-weight: 500; }

/* ── Swipe-to-action shell (mobile /todos) ────────────────────────────
   JS wraps each `.todo-row` in a `.swipe-shell` and inserts two backdrop
   panes — swipe left reveals the green "done" pane, swipe right reveals
   the amber "remind" pane. The row translates over them; `overflow: hidden`
   on the shell clips the row when it leaves on a successful swipe. */
.swipe-shell { position: relative; overflow: hidden; border-radius: 6px; }
.swipe-shell > .swipe-action {
  position: absolute; inset: 0;
  display: flex; align-items: center; gap: 8px;
  padding: 0 22px;
  font-size: 13px; font-weight: 600; color: white;
  pointer-events: none;
  opacity: 0;
  transition: opacity 120ms ease;
}
.swipe-shell > .swipe-action svg { width: 18px; height: 18px; }
.swipe-shell > .swipe-action-done    { background: #16a34a; justify-content: flex-end; }
.swipe-shell > .swipe-action-remind  { background: #d97706; justify-content: flex-start; }
.swipe-shell.swiping-left  > .swipe-action-done    { opacity: 1; }
.swipe-shell.swiping-right > .swipe-action-remind  { opacity: 1; }
.swipe-shell > .todo-row {
  position: relative; z-index: 1;
  touch-action: pan-y;
  will-change: transform;
}
.swipe-shell > .todo-row.snap-back {
  transition: transform 200ms ease-out, border-color 120ms ease;
}

/* ── Keyboard-shortcut hint bar ──────────────────────────────────── */
.kbd-bar { position: fixed; bottom: 0; left: var(--sidebar-w); right: 0; padding: 8px 16px; background: var(--surface); border-top: 1px solid var(--border); font-size: 11px; color: var(--muted); text-align: center; z-index: 90; }
.kbd-bar kbd { display: inline-block; padding: 1px 5px; border: 1px solid var(--border); border-radius: 3px; background: var(--surface-alt); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; color: var(--fg); }
@media (max-width: 720px) { .kbd-bar { display: none; } }

/* ════════════════════════════════════════════════════════════════════════
   MOBILE (≤ 720px)
   Target: native-app feel — no horizontal page scroll anywhere, bottom
   tab-bar nav, single-column forms, full-width chatbot, scroll-inside
   for wide tables. Touch tap targets ≥ 40px.
   ════════════════════════════════════════════════════════════════════════ */

@media (max-width: 720px) {
  /* Mobile nav: the sidebar becomes a slide-in drawer, the topbar takes
     over the fixed top strip, and the bottom tab bar replaces the
     sidebar's primary entry points for thumb reach. */
  body:has(.sidebar) { padding-left: 0; padding-top: var(--topbar-h); padding-bottom: calc(var(--bottom-tabs-h) + env(safe-area-inset-bottom, 0px)); }

  .topbar {
    display: flex;
    align-items: center;
    gap: 4px;
    position: fixed;
    top: 0; left: 0; right: 0;
    height: var(--topbar-h);
    padding: 0 8px;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    z-index: 95;
  }
  .topbar-brand { display: inline-flex; align-items: center; margin: 0 auto; padding: 0 6px; }
  .topbar-brand img { height: 20px; width: auto; display: block; }
  .topbar-btn {
    width: 40px; height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--fg);
    background: transparent;
    border: none;
    border-radius: 6px;
    text-decoration: none;
    cursor: pointer;
    padding: 0;
    transition: background-color 120ms, color 120ms;
  }
  .topbar-btn:hover { background: var(--surface-alt); color: var(--accent); }
  .topbar-btn svg { width: 22px; height: 22px; }
  .topbar-btn-icon { display: inline-flex; }

  /* Sidebar becomes a left-anchored drawer. */
  .sidebar {
    width: min(86vw, 320px);
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    z-index: 110;
    padding-top: 16px;
    padding-bottom: max(16px, env(safe-area-inset-bottom, 0px));
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-backdrop { z-index: 105; }
  body.drawer-open { overflow: hidden; }

  /* Larger row hit-areas in the drawer so they're thumb-friendly. */
  a.navrow { padding: 10px 12px; font-size: 14px; }
  .navrow-icon svg { width: 20px; height: 20px; }
  .navrow-key { display: none; }
  .sidebar-search { padding: 10px 12px; font-size: 14px; }
  .sidebar-search-icon svg { width: 18px; height: 18px; }
  .sidebar-search-key { display: none; }
  h2.sidebar-group { font-size: 11px; margin: 16px 8px 4px; }

  /* Page shell — tighter gutters; padding-top/bottom now handled by body. */
  main {
    margin: 16px auto;
    padding: 0 14px;
    max-width: 100%;
  }

  /* Bottom tab bar — five fast-reach slots, last one opens the drawer. */
  .bottom-tabs {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 100;
    background: var(--surface);
    border-top: 1px solid var(--border);
    padding: 0 0 env(safe-area-inset-bottom, 0px);
  }
  .bottom-tabs-item {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 4px 10px;
    color: var(--muted);
    text-decoration: none;
    background: transparent;
    border: none;
    cursor: pointer;
    font-family: inherit;
    font-size: 10px;
    font-weight: 500;
    line-height: 1.1;
    transition: color 120ms;
    height: var(--bottom-tabs-h);
  }
  .bottom-tabs-item svg { width: 22px; height: 22px; }
  .bottom-tabs-item span {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .bottom-tabs-item.active { color: var(--accent); font-weight: 700; }
  .bottom-tabs-item.active svg { stroke-width: 2.4; }

  /* Page header — stack title above its actions row so search + buttons
     have room. Inside the actions row, the search input flex-grows to
     fill whatever space is left after the icon buttons, keeping the
     whole row on a single line. */
  .page-header { flex-direction: column; align-items: stretch; gap: 10px; }
  /* Headers without a search input (e.g. /todos) keep the title and the
     add button on a single row — no need to stack when there's nothing
     wide to give a full row to. */
  .page-header:not(:has(form.page-search)) { flex-direction: row; align-items: center; }
  .page-header-actions { flex-wrap: nowrap; gap: 6px; align-items: center; }
  form.page-search { flex: 1 1 0; min-width: 0; }
  form.page-search input[type=search] { width: 100%; min-width: 0; }
  /* Compact icon buttons in the actions row keep them tappable but
     leave the search bar most of the row. */
  .page-header-actions .icon-button-add { flex: 0 0 auto; }

  /* Wide tables — promote the table to its own horizontally-scrollable
     block so it never pushes the body past the viewport. The inner
     thead/tbody/tr/td keep their default `table-*` displays so the grid
     still reads as a table; only the outer element changes. Rounded
     corners drop here so overflow can scroll cleanly. */
  table.grid {
    display: block;
    width: 100%;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    border-radius: 6px;
  }
  table.grid th, table.grid td { padding: 10px 12px; }

  /* Long inline strings (emails, URLs in code) — let them wrap rather
     than push their row wider. */
  table.emails td.addr code,
  table.emails td.addr.nowrap { word-break: break-all; white-space: normal; }

  /* Forms — collapse multi-column grids to a single column. */
  form.meta { grid-template-columns: 1fr; padding: 14px; }
  form.meta .row { flex-direction: column; gap: 12px; }
  details.newform form { grid-template-columns: 1fr; }

  /* Inputs need to be ≥16px text to stop iOS auto-zoom on focus. */
  form.meta input, form.meta select, form.meta textarea,
  .inline-add input, .inline-add select,
  details.newform form input, details.newform form select,
  form.modal-form input, form.modal-form select, form.modal-form textarea,
  form.page-search input[type=search],
  form.search-form input[type=search],
  #chatbot-input { font-size: 16px; }

  /* Inline-add row wraps so the button doesn't overflow on narrow rows. */
  form.inline-add { flex-wrap: wrap; }
  form.inline-add input,
  form.inline-add select { flex: 1 1 60%; min-width: 0; }

  /* Settings index drops to one column (already auto-fill, but the
     720px override above forced 2-col; below 720px we want 1-col). */
  .settings-grid { grid-template-columns: 1fr; }

  /* Modal — fits the viewport with breathing room. */
  .modal-card { width: calc(100vw - 24px); max-height: calc(100vh - 80px); }
  .chatbot-modal-card { width: calc(100vw - 24px); }

  /* Version badge — hide on mobile; the bottom tab bar occupies the same
     corner and the badge is a casual desktop reference. */
  .app-version { display: none; }

  /* Chats page — stack history above the message column on narrow viewports.
     History gets a capped height so it doesn't push the composer off-screen;
     a swipe scrolls through it inline. */
  .chats-page {
    flex-direction: column;
    height: auto;
    min-height: 0;
    gap: 10px;
  }
  .chats-sidebar {
    flex: 0 0 auto;
    max-height: 220px;
  }
  .chats-main {
    flex: 1;
    min-height: calc(100vh - 280px);
  }
  .chats-form textarea { font-size: 16px; }

  /* Chatbot — full-width sheet from the bottom rather than side panel.
     The toggle button floats just above the bottom tab bar. */
  #chatbot-toggle {
    right: 14px;
    bottom: calc(var(--bottom-tabs-h) + 8px + env(safe-area-inset-bottom, 0px));
    width: 48px; height: 48px;
  }
  #chatbot-panel {
    width: 100vw;
    max-width: 100vw;
    border-left: none;
    box-shadow: none;
  }

  /* Kanban — narrower columns so two columns hint at the side-swipe
     affordance instead of one column filling the viewport. */
  .kanban-col { flex: 0 0 78vw; width: 78vw; }

  /* Kanban fills the remaining viewport (between sticky top nav and the
     fixed bottom tab bar) and absorbs scrolling internally — both
     horizontally between columns and vertically inside a single column.
     The h1 + filter chips above the kanban stay anchored because the
     flex column lets each upper item keep its natural height while the
     kanban (flex: 1) takes whatever vertical space is left.

     The .kanban node is wrapped in #page-list (added for htmx swaps),
     so the flex chain has to go: main → #page-list → .kanban — every
     intermediate node needs flex: 1 + min-height: 0 to forward the
     bounded height all the way down. */
  main:has(.kanban) {
    display: flex;
    flex-direction: column;
    /* Viewport minus the fixed topbar + bottom-tab bar; main's own padding
       provides breathing room above/below the kanban. */
    height: calc(100dvh - var(--topbar-h) - var(--bottom-tabs-h) - env(safe-area-inset-bottom, 0px));
    margin-top: 0;
  }
  main:has(.kanban) #page-list {
    display: flex;
    flex-direction: column;
    flex: 1 1 0;
    min-height: 0;
  }
  main:has(.kanban) .kanban {
    flex: 1 1 0;
    min-height: 0;
    margin-bottom: 0;
    padding-bottom: 0;
  }
  main:has(.kanban) .kanban-col { max-height: 100%; }

  /* Title row + small slug — keep the chevron edit button aligned, but
     let the title wrap naturally on narrow screens. */
  .title-row { gap: 8px; }
  .title-row h1 { font-size: 20px; flex: 1 1 100%; }
  .title-row .edit-toggle { margin-left: 0; }
  small.slug { font-size: 12px; display: block; margin-top: 2px; }

  /* Long word-break for free-form chip / code content. */
  code, pre, .chip, .dstage { word-break: break-word; }
  .note-body { padding: 12px; font-size: 13px; }
  pre.copy-md { padding: 12px; font-size: 12px; }

  /* Tabs row — let it scroll horizontally if there are too many. */
  .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; }
  .tab { white-space: nowrap; }

  /* View-tabs (e.g. /customers/?view=cold) — scrollable too. */
  nav.view-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  nav.view-tabs a.view-tab { white-space: nowrap; }

  /* Deals toolbar — wrap chips, drop the view toggle to its own line
     after the filter chips. */
  .deals-toolbar { gap: 10px; }
  .deals-toolbar .filters { flex: 1 1 100%; }

  /* Increase chip / button tap targets without enlarging visual weight. */
  .chip { padding: 6px 12px; }
  button[type=submit], .inline-add button, details.newform form button,
  form.meta button { padding: 10px 16px; }

  /* Headings shrink slightly to give the content more room. */
  h1 { font-size: 20px; }

  /* Footer "danger zone" — full-width destructive button on mobile. */
  section.danger-zone button.secondary.destructive { width: 100%; }

  /* Home dashboard "Open todos" — unwind the 4-column table into a
     stacked card per row: task text on its own line, the customer /
     owner / remind details collapsed into a single muted line below. */
  table.grid.dash-todos { display: block; overflow: visible; border: none; border-radius: 0; background: transparent; }
  table.grid.dash-todos thead { display: none; }
  table.grid.dash-todos tbody { display: block; }
  table.grid.dash-todos tr { display: block; background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin-bottom: 6px; }
  table.grid.dash-todos tr:last-child { margin-bottom: 0; }
  table.grid.dash-todos tr:hover { background: var(--surface); }
  table.grid.dash-todos td { display: inline; padding: 0; border: none; font-size: 12px; color: var(--muted); }
  table.grid.dash-todos td:first-child { display: block; font-size: 14px; color: var(--fg); margin-bottom: 4px; white-space: normal; }
  table.grid.dash-todos td:nth-child(n+3)::before { content: "·"; margin: 0 6px; color: var(--border); }
  table.grid.dash-todos td .chip { padding: 2px 8px; font-size: 11px; }
}

/* ── Anonymous login card ────────────────────────────────────────────── */
/* No branding, no copy, no app-name. Just enough chrome to make the form
   look intentional. Kept visually distinct (.anon-card) so changes here
   don't bleed into the authed UI. */
.anon-card { padding: 24px; width: 100%; }
.anon-card h1 { margin: 0 0 16px; }
.anon-card form { display: flex; flex-direction: column; gap: 10px; margin: 0; }
.anon-card form input[type=email] { padding: 9px 12px; border: 1px solid var(--border); border-radius: 4px; font: inherit; background: var(--surface); color: var(--fg); }
.anon-card form input[type=email]::placeholder { color: var(--muted); }
.anon-card form input[type=email]:focus { outline: none; border-color: var(--accent); }
.anon-card form button[type=submit] { width: 100%; padding: 9px 14px; }
.anon-card .status { min-height: 1.2em; margin: 10px 0 0; color: var(--muted); font-size: 12px; }

/* ── Permissions matrix (admin) ──────────────────────────────────────── */
.permissions-scroll { overflow-x: auto; margin-bottom: 16px; }
table.permissions-grid th, table.permissions-grid td { vertical-align: top; }
table.permissions-grid td:first-child { min-width: 200px; }
table.permissions-grid code { font-size: 11px; }
.perm-cell { border: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 2px; font-size: 12px; }
.perm-cell label { display: inline-flex; align-items: center; gap: 4px; }
.permissions-actions { display: flex; justify-content: flex-end; }
.visually-hidden { position: absolute !important; height: 1px; width: 1px; overflow: hidden; clip: rect(1px,1px,1px,1px); white-space: nowrap; }

/* ── Todo tab-titles: inherit h1, only colour the inactive ones muted. */
h1.todo-tabs { display: flex; gap: 18px; flex-wrap: wrap; }
h1.todo-tabs a { color: var(--muted); text-decoration: none; transition: color 120ms; }
h1.todo-tabs a:hover, h1.todo-tabs a.active { color: var(--fg); }
h1.todo-tabs .todo-tab-count { font-size: 12px; font-weight: 500; color: var(--muted); }

/* ── Owner filter avatar pills on /todos ─────────────────────────── */
.owner-pills { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
a.owner-pill {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  color: white; font-size: 11px; font-weight: 600; line-height: 1;
  text-transform: uppercase; text-decoration: none;
  overflow: hidden; box-sizing: border-box;
  border: 2px solid transparent;
  opacity: 0.55; transition: opacity 120ms, border-color 120ms;
  -webkit-font-smoothing: antialiased;
}
a.owner-pill:hover { opacity: 0.85; }
a.owner-pill.active { opacity: 1; border-color: var(--accent); }
a.owner-pill img { width: 100%; height: 100%; object-fit: cover; display: block; }
a.owner-pill.has-photo { background: transparent; }
a.owner-pill-all { background: var(--surface); color: var(--muted); border: 1px solid var(--border); opacity: 1; }
a.owner-pill-all:hover { color: var(--fg); border-color: var(--accent); }
a.owner-pill-all.active { color: var(--accent); border-color: var(--accent); }

/* ── Avatar chip becomes a photo when uploaded ───────────────────── */
nav a.user-avatar.has-photo { background: transparent !important; padding: 0; overflow: hidden; }
nav a.user-avatar.has-photo img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 50%; image-rendering: -webkit-optimize-contrast; image-rendering: smooth; }
nav a.user-avatar { text-decoration: none; }

/* ── Profile page ──────────────────────────────────────────────── */
/* Sub-block heading inside a task-section card (Theme / Accent under
   Appearance). Smaller weight than h2 (the card heading) but still bold
   enough to separate the two form groups inside the same card. */
section.task-section h3.subheading { margin: 16px 0 6px; font-size: 12px; font-weight: 600; color: var(--fg); }
section.task-section h3.subheading:first-of-type { margin-top: 4px; }
.profile-photo-row { display: flex; gap: 20px; align-items: center; padding: 0; flex-wrap: wrap; }
.profile-photo-preview { width: 96px; height: 96px; border-radius: 50%; overflow: hidden; flex: 0 0 96px; display: grid; place-items: center; }
.profile-photo-preview img { width: 100%; height: 100%; object-fit: cover; display: block; image-rendering: -webkit-optimize-contrast; image-rendering: smooth; }
.profile-photo-initial { width: 100%; height: 100%; display: grid; place-items: center; color: white; font-size: 36px; font-weight: 600; text-transform: uppercase; -webkit-font-smoothing: antialiased; }
.profile-photo-actions { display: flex; flex-direction: column; gap: 8px; }
.profile-photo-actions .inline-add { margin: 0; flex-wrap: wrap; }
/* Upload form + trash-icon delete on one row so the trash sits right of
   the upload button rather than dropping to its own row. */
.profile-photo-row-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.profile-photo-row-actions .inline-add { margin: 0; }
/* One-click upload: the file input stays in the DOM (change event fires
   from it) but is hidden — the "upload photo" button triggers it via JS. */
form.avatar-upload-form { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
input.avatar-upload-input { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); border: 0; }
dl.profile-meta { display: grid; grid-template-columns: 120px 1fr; gap: 8px 16px; margin: 8px 0 0; }
dl.profile-meta dt { color: var(--muted); font-size: 12px; }
dl.profile-meta dd { margin: 0; color: var(--fg); }

/* Theme toggle — light/dark segmented control on /me. Two label tiles
   sharing a 1px border, the active one paints with the accent. The radios
   submit on change (no separate save button on JS-on browsers). */
form.theme-toggle { display: inline-flex; gap: 0; padding: 2px; background: var(--surface-alt); border: 1px solid var(--border); border-radius: 8px; margin-top: 4px; }
form.theme-toggle .theme-option { display: inline-flex; align-items: center; gap: 6px; padding: 6px 14px; border-radius: 6px; cursor: pointer; color: var(--muted); font-size: 13px; font-weight: 500; transition: background-color 120ms, color 120ms; }
form.theme-toggle .theme-option:hover { color: var(--fg); }
form.theme-toggle .theme-option.active { background: var(--surface); color: var(--fg); }
form.theme-toggle .theme-option input { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
form.theme-toggle .theme-option-icon { display: inline-flex; align-items: center; color: var(--accent); }
form.theme-toggle .theme-option-icon svg { width: 16px; height: 16px; }
form.theme-toggle noscript button { margin-left: 8px; }

/* Accent picker — row of round swatches on /me. Each swatch's colour is
   passed in via `--swatch-color` (the user's light-mode hex) so the picker
   reads the same in either theme. Active swatch gets a ring in its own
   colour so the selection is obvious without leaning on --accent (which
   is in the middle of changing during the click). */
form.accent-picker { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 4px; }
form.accent-picker .accent-swatch { position: relative; display: inline-flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; padding: 4px; border-radius: 8px; }
form.accent-picker .accent-swatch input { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
form.accent-picker .accent-swatch-dot { width: 28px; height: 28px; border-radius: 50%; background: var(--swatch-color); border: 2px solid var(--surface); box-shadow: 0 0 0 1px var(--border); transition: box-shadow 120ms; }
form.accent-picker .accent-swatch:hover .accent-swatch-dot { box-shadow: 0 0 0 1px var(--swatch-color); }
form.accent-picker .accent-swatch.active .accent-swatch-dot { box-shadow: 0 0 0 2px var(--swatch-color); }
form.accent-picker .accent-swatch-label { font-size: 11px; color: var(--muted); font-weight: 500; }
form.accent-picker .accent-swatch.active .accent-swatch-label { color: var(--fg); }
form.accent-picker noscript button { align-self: center; }

/* ── Calendar (month grid) ────────────────────────────────────────────
   Renders synced Outlook events as a 7-column month grid. Monday-first
   week. Same token palette as everything else — surfaces on `--surface`,
   separators on `--border`, "today" highlighted with `--accent`. No
   drop-shadows; elevation via border + subtle bg only. */
.cal-toolbar { display: flex; align-items: center; gap: 16px; margin: 4px 0 12px; flex-wrap: wrap; }
.cal-toolbar .cal-title { font-size: 16px; font-weight: 600; color: var(--fg); }
.cal-toolbar .cal-info { margin-left: auto; }
.cal-nav { display: inline-flex; align-items: center; gap: 6px; }
.cal-navbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--fg); text-decoration: none; font-size: 14px; line-height: 1; transition: border-color 120ms, color 120ms; }
.cal-navbtn:hover { border-color: var(--accent); color: var(--accent); }
.cal-today { display: inline-flex; align-items: center; padding: 4px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--fg); text-decoration: none; font-size: 12px; transition: border-color 120ms, color 120ms; }
.cal-today:hover { border-color: var(--accent); color: var(--accent); }

.cal-grid { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.cal-weekdays { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); background: var(--surface-alt); border-bottom: 1px solid var(--border); }
.cal-weekday { padding: 8px 10px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--muted); border-right: 1px solid var(--border); }
.cal-weekday:last-child { border-right: none; }

.cal-week { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); border-bottom: 1px solid var(--border); }
.cal-week:last-child { border-bottom: none; }

.cal-day { min-height: 108px; padding: 6px 8px 8px; border-right: 1px solid var(--border); display: flex; flex-direction: column; gap: 4px; background: var(--surface); position: relative; }
.cal-day:last-child { border-right: none; }
.cal-day-other { background: var(--bg); }
.cal-day-other .cal-daynum-n { color: var(--muted); }
.cal-day-weekend:not(.cal-day-other):not(.cal-day-today) { background: var(--bg); }
.cal-day-today { background: color-mix(in srgb, var(--accent) 6%, var(--surface)); }
.cal-day-today .cal-daynum-n { color: var(--accent); font-weight: 700; }

.cal-daynum { display: flex; align-items: baseline; gap: 6px; font-size: 12px; color: var(--fg); }
.cal-daynum-month { font-size: 10px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; }
.cal-daynum-n { font-size: 13px; font-weight: 600; }

.cal-events { display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.cal-event { display: flex; align-items: baseline; gap: 6px; padding: 2px 6px; border-radius: 4px; background: var(--surface-alt); border: none; border-left: 2px solid var(--accent); color: var(--fg); text-decoration: none; text-align: left; font: inherit; font-size: 11px; line-height: 1.3; min-width: 0; cursor: pointer; transition: background 120ms, border-color 120ms; }
.cal-event:hover { background: color-mix(in srgb, var(--accent) 10%, var(--surface-alt)); }
.cal-event-time { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 500; flex: 0 0 auto; }
.cal-event-subj { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1 1 auto; }

/* Event-detail modal body. Uses the generic .modal shell; this block just
   lays out the rows and preview text inside the card. */
.cal-modal-card { width: min(520px, 92vw); }
.cal-modal-body { padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; }
.cal-modal-when { display: flex; align-items: baseline; gap: 8px; font-size: 13px; color: var(--fg); }
.cal-modal-when .cal-modal-date { font-weight: 600; }
.cal-modal-row { display: flex; gap: 12px; align-items: flex-start; font-size: 13px; }
.cal-modal-lbl { flex: 0 0 84px; font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); font-weight: 600; padding-top: 2px; }
.cal-modal-atts .cal-modal-att-list { display: flex; flex-wrap: wrap; gap: 4px; flex: 1 1 auto; }
.cal-modal-body-preview p { margin: 0; font-size: 13px; color: var(--fg); white-space: pre-wrap; max-height: 240px; overflow-y: auto; }

/* Info popover — anchored to the (i) button in the toolbar. Shows on
   hover (desktop) or click (mobile / keyboard). Click-outside and Escape
   dismiss it. Same visual family as .cal-modal-* rows. */
.cal-info { position: relative; }
.cal-info-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  width: min(340px, 92vw);
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 120ms, transform 120ms, visibility 0s linear 120ms;
}
.cal-info:hover .cal-info-popover,
.cal-info.is-open .cal-info-popover,
.cal-info-btn:focus-visible + .cal-info-popover {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transform: translateY(0);
  transition: opacity 120ms, transform 120ms, visibility 0s linear 0s;
}
.cal-info-row { display: flex; gap: 12px; font-size: 12px; line-height: 1.5; }
.cal-info-row + .cal-info-row { margin-top: 2px; }
.cal-info-lbl { flex: 0 0 84px; color: var(--muted); text-transform: uppercase; font-size: 10px; letter-spacing: 0.06em; font-weight: 600; padding-top: 3px; }
.cal-info-note { margin: 10px 0 0; padding-top: 8px; border-top: 1px solid var(--border); font-size: 11px; color: var(--muted); line-height: 1.5; }
.cal-info-note + .cal-info-note { margin-top: 4px; padding-top: 0; border-top: none; }

@media (max-width: 720px) {
  .cal-day { min-height: 72px; padding: 4px 5px 5px; }
  .cal-daynum-n { font-size: 12px; }
  .cal-event { font-size: 10px; padding: 1px 4px; }
  .cal-event-time { display: none; }
  .cal-weekday { padding: 6px 5px; font-size: 10px; }
}

/* ── Dark-mode targeted overrides ───────────────────────────────────────
   Most of the dark theme is handled by re-pointing the surface tokens at
   `[data-theme="dark"]` (see :root). The rules below cover the few spots
   that can't be tokenized cleanly:
   - The toggle thumb needs a fixed-light dot so it stays visible against
     both the resting (dark border) track and the on (light accent) track.
   - Form errors / send-status pills, primary-chip, chatbot-msg-error and
     similar pastel pills keep their authored bg + text colours; we only
     dim the bg slightly and lift the text so the contrast lands.
   - The native autofill yellow that Chrome paints over inputs gets pulled
     back to the surface tokens via -webkit-text-fill-color + box-shadow.
   - Custom scrollbar tinting so the thin rails don't show as bright bars
     on the dark surfaces (most visible in long tables + the chatbot log). */
[data-theme="dark"] a.toggle-switch .toggle-thumb { background: #f5f5f4; }

/* Pastel pills authored against a light-mode surface — keep them light so
   they still read as the warm/cool palette they were designed in. */
[data-theme="dark"] p.send-status.success,
[data-theme="dark"] p.send-status.error,
[data-theme="dark"] p.form-error,
[data-theme="dark"] ul.email-list .primary-chip,
[data-theme="dark"] span.chip.orphan,
[data-theme="dark"] .chatbot-msg-error { filter: brightness(0.92); }

/* Native input autofill — Chrome paints a yellow box over saved fields;
   neutralise it back to surface/fg in dark mode so password / email inputs
   don't strobe yellow against the dark form. */
[data-theme="dark"] input:-webkit-autofill,
[data-theme="dark"] input:-webkit-autofill:hover,
[data-theme="dark"] input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--fg);
  box-shadow: 0 0 0 1000px var(--surface) inset;
  caret-color: var(--fg);
}

[data-theme="dark"] {
  scrollbar-color: var(--border) transparent;
}
[data-theme="dark"] ::-webkit-scrollbar { width: 10px; height: 10px; }
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 8px; }
[data-theme="dark"] ::-webkit-scrollbar-track { background: transparent; }

/* ── Email-sync settings: foldable per-mailbox + per-block panels ────────
   Each connected mailbox renders as a `details.sync-account` row, like
   one collapsed message in an email client: name + status line. Inside,
   sub-blocks (Backfill / Live listener / Per-domain) are themselves
   `details.sync-block` so each can be folded independently. */

.sync-toolbar { display: flex; gap: 6px; align-items: center; margin: 8px 0 16px; }
.link-btn { background: none; border: none; padding: 0; color: var(--accent); font: inherit; cursor: pointer; }
.link-btn:hover { text-decoration: underline; }

details.sync-account {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  margin: 10px 0;
  overflow: hidden;
}
details.sync-account > summary {
  list-style: none;
  cursor: pointer;
  padding: 12px 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  user-select: none;
  transition: background 120ms;
}
details.sync-account > summary::-webkit-details-marker { display: none; }
details.sync-account > summary:hover { background: var(--surface-alt); }
details.sync-account[open] > summary { border-bottom: 1px solid var(--border); }

.sync-chev {
  display: inline-block;
  color: var(--muted);
  font-size: 11px;
  width: 12px;
  transition: transform 120ms;
}
details[open] > summary > .sync-chev { transform: rotate(90deg); }

.sync-account-name { font-weight: 600; color: var(--fg); }
.sync-account-meta { margin-left: auto; }
.sync-account-body { padding: 4px 16px 14px; }

details.sync-block {
  border-top: 1px solid var(--surface-alt, #f5f5f4);
  margin: 0;
  padding: 0;
}
details.sync-block:first-child { border-top: none; }
details.sync-block > summary {
  list-style: none;
  cursor: pointer;
  padding: 10px 0 8px;
  display: flex;
  align-items: center;
  gap: 8px;
  user-select: none;
}
details.sync-block > summary::-webkit-details-marker { display: none; }
.sync-block-title { font-size: 11px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.sync-block-meta { margin-left: auto; text-align: right; }
details.sync-block > *:not(summary) { margin-top: 6px; }
details.sync-block > p:first-of-type { margin-top: 0; }
details.sync-block > form { margin-top: 10px; }

@media (max-width: 600px) {
  details.sync-account > summary { flex-wrap: wrap; }
  .sync-account-meta { margin-left: 22px; flex-basis: 100%; }
  .sync-block-meta { margin-left: 20px; text-align: left; flex-basis: 100%; }
}

/* ── Container contribution graph (Home page).
   Colour palette + block dimensions mirror github.com's contribution
   heatmap so the widget reads instantly as "activity per day". Levels
   0–4 map from empty → dark green (light theme) / bright green (dark). */
.contrib-section .contrib-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.contrib-summary { display: flex; align-items: baseline; gap: 8px; }
.contrib-summary strong { font-size: 18px; font-weight: 600; color: var(--fg); }
.contrib-scroll { overflow-x: auto; margin: 0 -16px; padding: 0 16px 4px; }
.contrib-graph { display: block; max-width: 100%; height: auto; }
.contrib-label {
  font-family: system-ui, sans-serif;
  font-size: 10px;
  fill: var(--muted);
  user-select: none;
}
.contrib-cell {
  outline: 1px solid rgba(27, 31, 35, 0.06);
  outline-offset: -1px;
  shape-rendering: geometricPrecision;
}
.contrib-cell:hover { stroke: var(--fg); stroke-width: 1; }

/* GitHub light palette. */
.contrib-cell[data-level="0"] { fill: #ebedf0; }
.contrib-cell[data-level="1"] { fill: #9be9a8; }
.contrib-cell[data-level="2"] { fill: #40c463; }
.contrib-cell[data-level="3"] { fill: #30a14e; }
.contrib-cell[data-level="4"] { fill: #216e39; }

/* GitHub dark palette. */
[data-theme="dark"] .contrib-cell { outline-color: rgba(255, 255, 255, 0.04); }
[data-theme="dark"] .contrib-cell[data-level="0"] { fill: #161b22; }
[data-theme="dark"] .contrib-cell[data-level="1"] { fill: #0e4429; }
[data-theme="dark"] .contrib-cell[data-level="2"] { fill: #006d32; }
[data-theme="dark"] .contrib-cell[data-level="3"] { fill: #26a641; }
[data-theme="dark"] .contrib-cell[data-level="4"] { fill: #39d353; }

/* Wrapper sizes to the SVG's intrinsic width so the legend inside it
   right-aligns to the graph's right edge — not the card's, which would
   stretch to the section width and float the legend past the graph.
   margin: 0 auto centers the wrapper in the card's horizontal padding
   box so the graph sits visually centered instead of hugging the left. */
.contrib-graph-wrap { width: max-content; margin: 0 auto; }
.contrib-legend {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  margin-top: 6px;
}
.contrib-legend svg { display: block; }

/* Floating hover tooltip — positioned in JS relative to .contrib-card.
   Translate offsets center it above the cell instead of anchoring at its
   own top-left. Arrow tail points down at the hovered day. */
.contrib-card { position: relative; }
.contrib-tooltip {
  position: absolute;
  pointer-events: none;
  transform: translate(-50%, -100%);
  background: var(--fg);
  color: var(--on-fg);
  font-size: 12px;
  line-height: 1.3;
  padding: 6px 8px;
  border-radius: 4px;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  z-index: 10;
}
.contrib-tooltip::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  border: 4px solid transparent;
  border-top-color: var(--fg);
}

