/*
 * Hand-written CSS — no build step (no Node on this host). Same visual
 * language (palette, spacing, radii) as the Next.js sibling implementation's
 * Tailwind config, just written directly instead of generated.
 */
:root {
  --ink: #111214;
  --ink-soft: #1c1e22;
  --ink-muted: #6b7280;
  --ink-faint: #9ca3af;
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-sunken: #f6f7f9;
  --surface-raised: #fbfbfc;
  --surface-hover: rgba(17, 18, 20, 0.04);
  --accent: #2563eb;
  --accent-soft: #dbeafe;
  --accent-ink: #1d4ed8;
  /* Primary UI color: black by default; the theme engine overrides --brand
     (and the whole palette) so a chosen theme visibly recolors everything.
     --on-brand is the readable text color to sit on a --brand surface. */
  --brand: var(--ink);
  --brand-hover: var(--ink-soft);
  --on-brand: #ffffff;
  --green: #16a34a;
  --green-soft: #dcfce7;
  --red: #dc2626;
  --red-soft: #fee2e2;
  --danger: var(--red);
  --amber: #b45309;
  --amber-soft: #fef3c7;
  --warn: var(--amber);
  --purple: #7c3aed;
  --purple-soft: #ede9fe;
  --border: rgba(17, 18, 20, 0.1);
  --border-soft: rgba(17, 18, 20, 0.06);
  --hairline: rgba(17, 18, 20, 0.08);
  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --shadow-sm: 0 1px 2px rgba(17, 18, 20, 0.04);
  --shadow-md: 0 4px 16px rgba(17, 18, 20, 0.08);
  --shadow-lg: 0 12px 32px rgba(17, 18, 20, 0.18);
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-5: 20px; --space-6: 24px; --space-8: 32px;
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
h1, h2, h3, p { margin: 0; }
button { font-family: inherit; }

/* ── Layout shell ─────────────────────────────────────────────────────── */
.app-shell { display: flex; min-height: 100vh; }
.sidebar {
  width: 232px; flex-shrink: 0; display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--border);
}
.sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 18px 20px 16px; }
.brand-mark {
  width: 34px; height: 34px; border-radius: 9px;
  background: linear-gradient(135deg, var(--grad-top, var(--ink)) 0%, var(--grad-bottom, var(--ink-soft)) 100%);
  color: #fff; display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 13px; box-shadow: var(--shadow-sm);
}
.brand-name { font-size: 14px; font-weight: 600; line-height: 1.2; }
.brand-tenant { font-size: 11px; color: var(--ink-muted); }
.nav-section-label {
  padding: 14px 12px 5px; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--ink-faint);
}
.nav-link {
  display: flex; align-items: center; gap: 8px; margin: 1px 12px; padding: 7px 10px;
  border-radius: var(--radius-sm); color: var(--ink-muted); font-size: 13.5px;
  transition: background 0.12s ease, color 0.12s ease;
}
.nav-link:hover { background: var(--border-soft); color: var(--ink); }
.nav-link.active { background: var(--brand); color: var(--on-brand); font-weight: 500; }
.nav-icon { width: 16px; text-align: center; opacity: 0.85; font-size: 13px; }

.sidebar-footer {
  margin-top: auto; border-top: 1px solid var(--border); padding: 14px 18px 16px;
  font-size: 12px; display: flex; align-items: center; gap: 10px;
}
.sidebar-footer .avatar {
  width: 30px; height: 30px; border-radius: 999px; background: var(--accent-soft);
  color: var(--accent-ink); display: flex; align-items: center; justify-content: center;
  font-weight: 600; font-size: 12px; flex-shrink: 0;
}
.sidebar-footer .who { min-width: 0; flex: 1; }
.sidebar-footer .name { font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-footer .role { color: var(--ink-muted); font-size: 11px; }
.sidebar-footer form { margin-top: 2px; }
.sidebar-footer button {
  background: none; border: none; padding: 0; color: var(--ink-faint);
  cursor: pointer; font-size: 11px;
}
.sidebar-footer button:hover { color: var(--ink); text-decoration: underline; }

.main-col { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.genre-tabs {
  display: flex; gap: 4px; padding: 10px 24px; background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.genre-tab { padding: 7px 14px; border-radius: var(--radius-sm); font-size: 13.5px; font-weight: 500; color: var(--ink-muted); transition: background 0.12s ease; }
.genre-tab.active { background: var(--brand); color: var(--on-brand); }
.genre-tab:not(.active):hover { background: var(--border-soft); }
.genre-dot { display: inline-block; width: 7px; height: 7px; border-radius: 999px; margin-right: 7px; vertical-align: middle; }
main.content {
  flex: 1; min-width: 0; max-width: 1280px; width: 100%; margin: 0 auto;
  padding: 28px 32px calc(var(--bottombar-h) + var(--safe-bottom) + 32px);
}

.flash {
  margin: 0 auto 20px; max-width: 1280px; padding: 10px 16px; border-radius: var(--radius-sm);
  font-size: 13.5px; background: var(--green-soft); color: #14532d; border: 1px solid rgba(22,163,74,0.2);
}
.flash-error { background: var(--red-soft); color: #7f1d1d; border-color: rgba(220,38,38,0.2); }

/* ── Page header ──────────────────────────────────────────────────────── */
.page-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 26px; flex-wrap: wrap; }
.page-title { font-size: 21px; font-weight: 650; letter-spacing: -0.015em; margin: 0; }
.page-subtitle { margin: 5px 0 0; font-size: 13px; color: var(--ink-muted); max-width: 60ch; }
.page-actions { display: flex; gap: 8px; flex-shrink: 0; }
.breadcrumb { font-size: 12.5px; color: var(--ink-faint); margin-bottom: 8px; }
.breadcrumb a:hover { color: var(--ink); text-decoration: underline; }
.section-title { font-size: 13px; font-weight: 600; margin-bottom: 10px; display: flex; align-items: center; justify-content: space-between; }

/* ── Cards / grid ─────────────────────────────────────────────────────── */
.card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); }
.card.pad { padding: 18px; }
.card-hover { transition: box-shadow 0.15s ease, border-color 0.15s ease; }
.card-hover:hover { box-shadow: var(--shadow-md); border-color: var(--border); }
.grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; }
.col-span-1 { grid-column: span 1; }
.col-span-2 { grid-column: span 2; }
.col-span-3 { grid-column: span 3; }
.col-span-4 { grid-column: span 4; }
@media (max-width: 900px) { .grid { grid-template-columns: repeat(2, 1fr); } .col-span-2, .col-span-3, .col-span-4 { grid-column: span 2; } }
.stack { display: flex; flex-direction: column; gap: 16px; }
.row { display: flex; gap: 16px; align-items: flex-start; }
.row-between { display: flex; align-items: center; justify-content: space-between; }

.kpi-group { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.kpi-slot { position: relative; display: flex; min-width: 0; }
.kpi-slot > .kpi-card, .kpi-slot > .kpi-card-link { flex: 1; min-width: 0; }
.kpi-hide-btn {
  position: absolute; top: 6px; right: 6px; z-index: 2;
  width: 22px; height: 22px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--surface);
  color: var(--ink-muted); font-size: 12px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.kpi-hide-btn:hover { border-color: var(--brand); color: var(--brand); }
.kpi-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 16px; transition: border-color 0.15s ease; }
.kpi-card:hover { border-color: var(--border); }
.kpi-label { font-size: 11.5px; font-weight: 600; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.02em; }
.kpi-value { margin-top: 6px; font-size: 25px; font-weight: 650; letter-spacing: -0.015em; }
.kpi-desc { margin-top: 5px; font-size: 11px; line-height: 1.4; color: var(--ink-faint); }

/* ── Buttons ──────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  border-radius: var(--radius-sm); padding: 8px 14px; font-size: 13.5px; font-weight: 500;
  cursor: pointer; border: 1px solid transparent; transition: background 0.12s ease, border-color 0.12s ease, opacity 0.12s ease;
  line-height: 1.2;
}
.btn-primary { background: var(--brand); color: var(--on-brand); }
.btn-primary:hover { background: var(--brand-hover); }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--border); }
.btn-secondary:hover { background: var(--border-soft); }
.btn-ghost { background: none; color: var(--ink-muted); }
.btn-ghost:hover { background: var(--border-soft); color: var(--ink); }
.btn-danger { background: var(--red-soft); color: #7f1d1d; }
.btn-danger:hover { background: #fecaca; }
.btn-sm { padding: 5px 10px; font-size: 12.5px; }
.btn-block { width: 100%; }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ── Badges ───────────────────────────────────────────────────────────── */
.badge { display: inline-flex; align-items: center; border-radius: 999px; padding: 2px 9px; font-size: 11.5px; font-weight: 500; white-space: nowrap; }
.badge-neutral { background: var(--border-soft); color: var(--ink-muted); }
.badge-accent { background: var(--accent-soft); color: var(--accent-ink); }
.badge-amber { background: var(--amber-soft); color: var(--amber); }
.badge-red { background: var(--red-soft); color: #991b1b; }
.badge-green { background: var(--green-soft); color: #166534; }
.badge-purple { background: var(--purple-soft); color: var(--purple); }
.badge-dot { width: 6px; height: 6px; border-radius: 999px; background: currentColor; margin-right: 5px; display: inline-block; }

/* ── Avatars ──────────────────────────────────────────────────────────── */
.avatar { width: 26px; height: 26px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); display: inline-flex; align-items: center; justify-content: center; font-weight: 600; font-size: 11px; flex-shrink: 0; }
.avatar-lg { width: 44px; height: 44px; font-size: 15px; }

/* ── Toggle switch (settings) ─────────────────────────────────────────── */
.toggle { position: relative; display: inline-block; width: 38px; height: 22px; flex-shrink: 0; }
.toggle input { opacity: 0; width: 0; height: 0; }
.toggle-track { position: absolute; inset: 0; background: var(--border); border-radius: 999px; transition: background 0.15s ease; cursor: pointer; }
.toggle-track::before { content: ""; position: absolute; width: 16px; height: 16px; left: 3px; top: 3px; background: #fff; border-radius: 999px; transition: transform 0.15s ease; box-shadow: 0 1px 2px rgba(0,0,0,0.2); }
.toggle input:checked + .toggle-track { background: var(--ink); }
.toggle input:checked + .toggle-track::before { transform: translateX(16px); }

/* ── Tabs (record detail) ────────────────────────────────────────────── */
.tabbar { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 18px; }
.tab-btn { padding: 9px 4px; margin-right: 18px; font-size: 13.5px; font-weight: 500; color: var(--ink-muted); border-bottom: 2px solid transparent; cursor: pointer; background: none; border-left: none; border-right: none; border-top: none; }
.tab-btn.active { color: var(--ink); border-bottom-color: var(--ink); }

/* ── Timeline ─────────────────────────────────────────────────────────── */
.timeline { position: relative; padding-left: 20px; }
.timeline::before { content: ""; position: absolute; left: 5px; top: 4px; bottom: 4px; width: 1px; background: var(--border); }
.timeline-item { position: relative; padding-bottom: 16px; }
.timeline-item::before { content: ""; position: absolute; left: -20px; top: 3px; width: 8px; height: 8px; border-radius: 999px; background: var(--accent); border: 2px solid var(--surface); }
.timeline-item .t-title { font-size: 13px; }
.timeline-item .t-meta { font-size: 11.5px; color: var(--ink-faint); margin-top: 2px; }

/* ── Progress bar ─────────────────────────────────────────────────────── */
.progress-track { height: 6px; border-radius: 999px; background: var(--border-soft); overflow: hidden; }
.progress-fill { height: 100%; background: var(--accent); border-radius: 999px; }
.progress-fill.over { background: var(--red); }

/* ── Record workspace: list + kanban toggle ──────────────────────────── */
.workspace-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.workspace-title { font-size: 14px; font-weight: 600; }
.view-toggle { display: flex; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 2px; font-size: 12px; }
.view-toggle button { border: none; background: none; padding: 4px 10px; border-radius: 6px; cursor: pointer; color: var(--ink-muted); text-transform: capitalize; }
.view-toggle button.active { background: var(--brand); color: var(--on-brand); }

.kanban-scroll { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 8px; }
.kanban-col { flex-shrink: 0; width: 264px; background: var(--border-soft); border-radius: var(--radius); padding: 8px; }
.kanban-col-header { display: flex; align-items: center; justify-content: space-between; padding: 4px 6px 8px; font-size: 12px; }
.kanban-col-header .name { font-weight: 600; }
.kanban-col-header .count { color: var(--ink-faint); background: var(--surface); border-radius: 999px; padding: 1px 7px; font-size: 11px; }
.kanban-card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
  padding: 12px; margin-bottom: 8px; box-shadow: var(--shadow-sm); cursor: grab;
  transition: box-shadow 0.12s ease, border-color 0.12s ease;
}
.kanban-card:hover { box-shadow: var(--shadow-md); border-color: var(--border); }
.kanban-card.dragging { opacity: 0.5; }
.kanban-card .title { font-size: 13.5px; font-weight: 500; line-height: 1.35; }
.kanban-card .title a:hover { text-decoration: underline; }
.kanban-card .subtitle { margin-top: 3px; font-size: 12px; color: var(--ink-muted); }
.kanban-card .meta { margin-top: 9px; display: flex; align-items: center; justify-content: space-between; }
.kanban-card .amount { font-size: 12px; font-weight: 600; }
.kanban-card .owner { font-size: 11px; color: var(--ink-faint); }
.kanban-empty { border: 1px dashed var(--border); border-radius: var(--radius-sm); padding: 22px 0; text-align: center; font-size: 11px; color: var(--ink-faint); }

table.data-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
table.data-table thead th { text-align: left; font-size: 11.5px; font-weight: 600; color: var(--ink-muted); padding: 9px 16px; background: var(--border-soft); text-transform: uppercase; letter-spacing: 0.02em; }
table.data-table thead th:first-child { border-top-left-radius: var(--radius-sm); }
table.data-table thead th:last-child { border-top-right-radius: var(--radius-sm); }
table.data-table tbody tr { transition: background 0.1s ease; }
table.data-table tbody tr:hover { background: var(--border-soft); }
table.data-table tbody td { padding: 11px 16px; border-top: 1px solid var(--border-soft); }
table.data-table .muted { color: var(--ink-muted); font-size: 12px; }
.empty-row { padding: 36px; text-align: center; color: var(--ink-faint); }
.empty-state { text-align: center; padding: 48px 24px; color: var(--ink-faint); }
.empty-state .icon { font-size: 28px; margin-bottom: 8px; opacity: 0.6; }
.empty-state .title { font-size: 13.5px; font-weight: 500; color: var(--ink-muted); }
.empty-state .sub { font-size: 12px; margin-top: 4px; }

/* ── Forms ────────────────────────────────────────────────────────────── */
.auth-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; background: radial-gradient(circle at top, #fafbfc 0%, var(--surface-sunken) 60%); }
.auth-card { width: 100%; max-width: 380px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 34px; box-shadow: var(--shadow-md); }
.auth-brand { display: flex; align-items: center; gap: 10px; margin-bottom: 24px; }
.field-label { display: block; margin-bottom: 4px; font-size: 12px; font-weight: 500; color: var(--ink-muted); }
.field-input, select.field-input, textarea.field-input {
  width: 100%; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 12px;
  font-size: 13.5px; margin-bottom: 16px; font-family: inherit; background: var(--surface); color: var(--ink);
}
.field-input:focus, select.field-input:focus, textarea.field-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.field-hint { margin-top: -12px; margin-bottom: 16px; font-size: 11.5px; color: var(--ink-faint); }
.btn-primary.btn-block { width: 100%; }
.error-text { color: var(--red); font-size: 13px; margin-bottom: 12px; }
.hint-text { text-align: center; font-size: 12px; color: var(--ink-muted); margin-top: 16px; }
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; }

.list-row { display: flex; align-items: center; justify-content: space-between; padding: 13px 16px; gap: 12px; }
.list-row + .list-row { border-top: 1px solid var(--border-soft); }
.list-row .primary { font-size: 13.5px; font-weight: 500; }
.list-row .secondary { font-size: 12px; color: var(--ink-muted); margin-top: 2px; }

.checkbox-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; font-size: 13.5px; }
.checkbox-row input { width: 16px; height: 16px; }
.checkbox-row.done .label { text-decoration: line-through; color: var(--ink-faint); }

/* ── Lumen QI floating assistant ──────────────────────────────────────── */
[x-cloak] { display: none !important; }
.lumen-dock-btn {
  position: fixed; z-index: 46;
  bottom: calc(var(--safe-bottom) + (var(--bottombar-h) - 58px) / 2);
  left: calc(50% + var(--dock-shift)); transform: translateX(-50%);
  width: 58px; height: 58px; border: none; cursor: pointer; padding: 0; background: none;
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.15s ease, filter 0.15s ease;
}
.lumen-dock-btn:hover { transform: translateX(-50%) scale(1.06); }
.lumen-dock-logo { width: 100%; height: 100%; object-fit: contain; }
/* --glow (0..1, set from live-voice output-audio level) pulses around the bare
   logo while a live call is running, even if the sheet is minimized/closed. */
.lumen-dock-btn.lumen-dock-live { filter: drop-shadow(0 0 calc(4px + var(--glow, 0) * 16px) color-mix(in srgb, var(--brand) 65%, transparent)); }
.lumen-logo-sm { width: 24px; height: 24px; border-radius: 50%; object-fit: contain; vertical-align: middle; margin-right: 6px; }
.lumen-brand { display: flex; align-items: center; }
.lumen-sheet {
  position: fixed; bottom: calc(var(--bottombar-h) + var(--safe-bottom) + 14px);
  left: calc(50% + var(--dock-shift)); transform: translateX(-50%); z-index: 47;
  width: min(420px, calc(100vw - 32px)); height: 520px; max-height: 70vh;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md); display: flex; flex-direction: column; overflow: hidden;
}
/* Live-voice mode: the composer/history are hidden and only the glowing orb
   shows, so give the sheet a tighter, brand-tinted frame to signal the mode. */
.lumen-sheet.lumen-sheet-voice {
  height: auto; min-height: 360px;
  border-color: color-mix(in srgb, var(--brand) 45%, var(--border));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--brand) 30%, transparent), var(--shadow-md);
}
.lumen-sheet-header { display: flex; align-items: center; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid var(--border-soft); font-weight: 600; font-size: 13.5px; }
/* Wrapper around history/chat/composer while NOT in live-voice mode. Must be
   a flex column filling the fixed-height sheet — the body's flex:1 scroll and
   the bottom-pinned composer stop working inside a plain block div. */
.lumen-mode-chat { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.lumen-sheet-body { flex: 1; overflow-y: auto; padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.lumen-msg { display: flex; }
.lumen-msg.user { justify-content: flex-end; }
.lumen-bubble { max-width: 85%; padding: 8px 12px; border-radius: 12px; font-size: 13.5px; white-space: pre-wrap; line-height: 1.4; }
.lumen-msg.assistant .lumen-bubble { background: var(--border-soft); color: var(--ink); border-bottom-left-radius: 4px; }
.lumen-msg.user .lumen-bubble { background: var(--brand); color: var(--on-brand); border-bottom-right-radius: 4px; }
.lumen-sheet-input { display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--border-soft); }
.lumen-sheet-input input { flex: 1; border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 12px; font-size: 13.5px; }
.lumen-sheet-input input:focus { outline: none; border-color: var(--accent); }

/* ── Lumen header actions: history, new chat, voice toggle ────────────── */
.lumen-head-actions { display: flex; align-items: center; gap: 2px; }
.lumen-icon-btn { border: none; background: transparent; cursor: pointer; font-size: 15px; line-height: 1; padding: 5px 7px; border-radius: 8px; color: var(--ink-muted); transition: background .12s, color .12s; }
.lumen-icon-btn:hover { background: var(--border-soft); color: var(--ink); }
.lumen-icon-btn.on { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }

/* ── Conversation history panel ───────────────────────────────────────── */
.lumen-history { flex: 1; display: flex; flex-direction: column; min-height: 0; }
.lumen-history-bar { display: flex; align-items: center; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--border-soft); flex-wrap: wrap; }
.lumen-selectall { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--ink-muted); cursor: pointer; }
.lumen-history-list { flex: 1; overflow-y: auto; padding: 6px; display: flex; flex-direction: column; gap: 2px; }
.lumen-history-row { display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: 10px; }
.lumen-history-row:hover { background: var(--border-soft); }
.lumen-history-row.active { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.lumen-history-row input[type=checkbox] { flex: none; }
.lumen-history-open { flex: 1; min-width: 0; text-align: left; border: none; background: transparent; cursor: pointer; display: flex; flex-direction: column; gap: 2px; padding: 0; }
.lumen-history-title { font-size: 13.5px; color: var(--ink); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lumen-history-meta { font-size: 11.5px; color: var(--ink-muted); }

/* ── Voice mic button ─────────────────────────────────────────────────── */
.lumen-mic { flex: none; border: 1px solid var(--border); background: transparent; cursor: pointer; border-radius: var(--radius-sm); width: 38px; font-size: 15px; color: var(--ink-muted); transition: background .12s, color .12s, border-color .12s; }
.lumen-mic:hover { border-color: var(--accent); color: var(--accent); }
.lumen-mic.listening { background: var(--danger); border-color: var(--danger); color: #fff; animation: lumen-pulse 1.1s ease-in-out infinite; }
@keyframes lumen-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 55%, transparent); } 50% { box-shadow: 0 0 0 5px transparent; } }

/* ── Live voice session status line ───────────────────────────────────── */
.lumen-live-status { display: flex; align-items: center; gap: 6px; padding: 6px 16px; font-size: 11.5px; color: var(--ink-muted); border-top: 1px solid var(--border-soft); }
.lumen-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-faint); flex: none; }
.lumen-live-dot.on { background: var(--danger); animation: lumen-pulse 1.1s ease-in-out infinite; }

/* ── Live voice stage: replaces the chat window while a real speech-to-
   speech session with Ara is open. --glow (0..1) is her live output-audio
   level, updated continuously as her voice streams in, so the ring pulses to
   the rhythm of her speaking rather than a generic canned animation. ── */
.lumen-voice-stage { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 18px; padding: 24px; }
.lumen-voice-orb {
  width: 152px; height: 152px;
  position: relative;
  /* drop-shadow traces the logo's own alpha, so the glow hugs the orb
     instead of haloing an invisible square around it. */
  filter: drop-shadow(0 0 calc(6px + var(--glow, 0.15) * 34px) color-mix(in srgb, var(--brand) 60%, transparent));
  transition: filter 90ms linear;
}
.lumen-voice-orb img { width: 100%; height: 100%; object-fit: contain; }
.lumen-voice-caption { font-size: 13px; color: var(--ink-muted); text-align: center; }
.lumen-voice-end { color: var(--danger); }

/* ── Editable dashboard: true grid-unit packing engine ──────────────────
   Widgets occupy w×h grid cells on an 8-column grid with a small fixed row
   height — twice the resolution of the old 4-column/118px grid, so drag and
   preset resizing move in noticeably smaller increments. Positions are NOT
   left to the browser's own auto-flow: the `dashboardGrid` Alpine component
   computes explicit --x/--y for every cell with a deterministic skyline
   packer (see public/js/app.js), which is what guarantees cells never
   overlap or hide one another, on every edit and after every save/reload. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  grid-auto-rows: 59px;
  gap: 12px;
  grid-auto-flow: row dense;
}
.dash-cell {
  grid-column: calc(var(--x, 0) + 1) / span var(--w, 4);
  grid-row: calc(var(--y, 0) + 1) / span var(--h, 4);
  position: relative;
  min-width: 0;
  display: flex;
  flex-direction: column;
  transition: grid-column 120ms ease, grid-row 120ms ease;
}
.dash-cell > .dash-inner { flex: 1 1 auto; min-height: 0; display: flex; }
.dash-cell > .dash-inner > * { flex: 1 1 auto; min-height: 0; width: 100%; }
/* Card-bodied widgets scroll inside their own footprint instead of
   overflowing into the grid row below — this (not the packer) was the
   real source of widgets visually "hiding" each other after a resize. */
.dash-cell > .dash-inner > .card { overflow: auto; }
/* The KPI group SCALES to its footprint instead of scrolling: the stat cards
   share the height (grid rows stretch) and their padding + type shrink with
   the widget via container-query units, so dragging the corner shrinks the
   contents rather than clipping them. */
.dash-cell > .dash-inner > .kpi-group {
  overflow: hidden;
  height: 100%;
  container-type: size;
  grid-auto-rows: 1fr;
  align-content: stretch;
}
.dash-cell > .dash-inner > .kpi-group .kpi-slot { min-height: 0; }
.dash-cell > .dash-inner > .kpi-group .kpi-card {
  display: flex; flex-direction: column; justify-content: center;
  overflow: hidden;
  padding: clamp(6px, 5cqmin, 16px);
}
.dash-cell > .dash-inner > .kpi-group .kpi-label { font-size: clamp(8px, 4cqmin, 12px); }
.dash-cell > .dash-inner > .kpi-group .kpi-value { font-size: clamp(13px, 11cqmin, 30px); line-height: 1.1; }
.dash-cell > .dash-inner > .kpi-group .kpi-desc  { font-size: clamp(8px, 3cqmin, 12px); }
/* The per-stat hide toggle must stay clickable even though edit mode sets
   pointer-events:none on the widget body to prevent stray card clicks. */
.kpi-hide-btn { pointer-events: auto; }

/* "Choose stats" picker — which stats live in a KPI widget. */
.dash-stats-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 30;
  min-width: 210px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
}
.dash-stats-head {
  padding: 6px 8px 8px; font-size: 11px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-muted);
}
.dash-stats-item {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 8px; border-radius: 6px; cursor: pointer;
  font-size: 13px; color: var(--ink); font-weight: 500;
}
.dash-stats-item:hover { background: var(--surface-hover); }
.dash-stats-item input { cursor: pointer; }
/* The calendar fills its footprint and scales its cells to fit — it must NOT
   scroll like a list widget, or month view gets clipped when the widget is
   resized small. Clip + flex so the internal grid shrinks to show all days. */
.dash-cell > .dash-inner > .cal-card { overflow: hidden; display: flex; flex-direction: column; }
.dash-cell > .dash-inner > .cal-card > .cal-root { flex: 1; min-height: 0; }

.dash-grid.editing .dash-cell { outline: 1.5px dashed var(--border); outline-offset: 2px; border-radius: var(--radius); }
.dash-controls {
  display: flex; align-items: center; gap: 4px;
  background: var(--surface-hover); border-radius: 8px;
  padding: 4px 8px; margin-bottom: 6px; font-size: 12px;
}
.dash-controls .dash-handle { cursor: grab; font-weight: 600; margin-right: auto; user-select: none; }
.dash-controls button { padding: 2px 8px; border-radius: 4px; background: var(--border-soft); border: none; cursor: pointer; font: inherit; }
.dash-resize {
  position: absolute; right: 2px; bottom: 2px;
  width: 22px; height: 22px; padding: 0; border: none;
  background: transparent; cursor: nwse-resize; z-index: 6; touch-action: none;
}
.dash-resize::after {
  content: ''; position: absolute; right: 5px; bottom: 5px;
  width: 11px; height: 11px;
  border-right: 2.5px solid var(--brand); border-bottom: 2.5px solid var(--brand);
  border-bottom-right-radius: 3px;
}
.dash-resizing { user-select: none; }
.dash-resizing .dash-cell { transition: none !important; }

@media (max-width: 900px) {
  .dash-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 54px; }
  /* Full-width, naturally-flowed on phones. grid-row:auto is REQUIRED — the
     base rule pins each cell to an explicit --y computed for the 8-col
     desktop packing, and leaving that in place made every widget stack onto
     the same rows and visually overlap on mobile. */
  .dash-cell { grid-column: 1 / -1; grid-row: auto / span var(--h, 4); }
}

/* ── Mobile-first responsive + Capacitor-ready (safe-area insets) ─────────
 * The app is wrapped by Capacitor in a native WebView for iOS/Android, so the
 * shell must respect notch / home-indicator safe areas and collapse the fixed
 * sidebar into an off-canvas drawer on phones. See Docs/CAPACITOR.md.
 * ---------------------------------------------------------------------- */
:root {
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  /* Bottom dock: the bar's height, and how far its centre sits right of the
     viewport centre (half the sidebar width) so the orb centres in the
     CONTENT area rather than the whole window. */
  --bottombar-h: 68px;
  --dock-shift: 116px;
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* No horizontal page scroll / iOS rubber-band on the app shell. */
html, body { overflow-x: hidden; }
body { overscroll-behavior-y: none; }

/* Sign-out / footer clears the home indicator. */
.sidebar-footer { padding-bottom: calc(16px + var(--safe-bottom)); }

/* Desktop-only chrome hidden by default; revealed at the mobile breakpoint. */
.mobile-topbar { display: none; }
.sidebar-overlay { display: none; }

@media (max-width: 900px) {
  /* Stack the shell so the sticky top bar spans full width above content
     (the sidebar is fixed/off-canvas, out of normal flow). */
  .app-shell { display: block; }

  /* Sticky mobile top bar with the drawer trigger. */
  .mobile-topbar {
    display: flex; align-items: center; gap: 10px;
    position: sticky; top: 0; z-index: 45;
    padding: calc(9px + var(--safe-top)) calc(14px + var(--safe-right)) 9px calc(14px + var(--safe-left));
    background: var(--surface); border-bottom: 1px solid var(--border);
  }
  .mobile-topbar .hamburger {
    width: 40px; height: 40px; flex-shrink: 0; border-radius: var(--radius-sm);
    border: 1px solid var(--border); background: var(--surface); color: var(--ink);
    font-size: 18px; display: flex; align-items: center; justify-content: center;
  }
  .mobile-topbar .mt-title { font-weight: 600; font-size: 15px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

  /* Sidebar becomes an off-canvas drawer. */
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 60;
    width: 268px; max-width: 84vw; height: 100dvh; overflow-y: auto;
    padding-top: var(--safe-top); padding-left: var(--safe-left);
    transform: translateX(-100%); transition: transform 0.22s ease;
    box-shadow: var(--shadow-md);
  }
  .sidebar.open { transform: none; }
  .sidebar-overlay {
    display: block; position: fixed; inset: 0; z-index: 55;
    background: rgba(0, 0, 0, 0.38);
  }

  main.content { padding: 18px calc(16px + var(--safe-right)) calc(var(--bottombar-h) + var(--safe-bottom) + 28px) calc(16px + var(--safe-left)); }
  .genre-tabs { padding: 8px 12px; flex-wrap: nowrap; }
  .genre-tabs-scroll { flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
  .genre-tab { flex-shrink: 0; }
  .page-title { font-size: 19px; }
  /* Vertical placement now comes from --bottombar-h; no phone override. */
}

@media (max-width: 640px) {
  /* One column on phones; every span collapses to full width. */
  .grid { grid-template-columns: 1fr; }
  .col-span-1, .col-span-2, .col-span-3, .col-span-4 { grid-column: 1 / -1; }
  .card.pad { padding: 14px; }
  /* Wide tables scroll inside their card instead of overflowing the page. */
  .card { overflow-x: auto; }
  .row { flex-wrap: wrap; }
  .page-header { margin-bottom: 18px; }
  .page-actions { width: 100%; }
  /* Comfortable touch targets. */
  .nav-link { padding: 10px 12px; }
  .btn { min-height: 40px; }
  .field-input, input, select, textarea { font-size: 16px; } /* iOS: avoid input zoom */
}

/* Inline stage click-and-dropdown on cards & list rows */
.stage-select { margin-top: 6px; font-size: 11px; padding: 3px 6px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--ink); max-width: 100%; cursor: pointer; }
.stage-select:focus { outline: none; border-color: var(--accent); }
.kanban-card .stage-select { width: 100%; }

/* Inbound "Get an Offer" leads — highlighted until worked */
.kanban-card.card-new { border-left: 3px solid var(--accent); background: var(--accent-soft); }
.new-badge { display:inline-block; margin-left:6px; font-size:9.5px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; color:var(--on-brand); background:var(--brand); border-radius:999px; padding:1px 7px; vertical-align:middle; }

/* Clickable KPI cards + admin back button */
.kpi-card-link { display:block; cursor:pointer; }
.kpi-card-link:hover { border-color: var(--brand); box-shadow: var(--shadow-md); }
.admin-back { display:inline-flex; align-items:center; gap:6px; font-size:13px; color:var(--ink-muted); margin-bottom:12px; }
.admin-back:hover { color: var(--ink); }

/* ---------------------------------------------------------------------
   Messages — chat threads, bubbles, media, link previews
   --------------------------------------------------------------------- */
.chat-thread-item:hover { background: var(--surface-hover, rgba(0,0,0,0.035)); }
.chat-bubble {
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 14px 14px 14px 4px;
  padding: 8px 12px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.04);
}
.chat-bubble.mine {
  background: var(--brand);
  color: var(--on-brand);
  border: none;
  border-radius: 14px 14px 4px 14px;
}
.chat-bubble.mine a { color: var(--on-brand) !important; }
.chat-bubble.mine [style*="color:var(--ink-faint)"],
.chat-bubble.mine [style*="color:var(--ink-muted)"] { color: rgba(255,255,255,0.75) !important; }
@media (max-width: 900px) {
  .chat-shell { grid-template-columns: 1fr !important; }
  .chat-threads { display: none !important; } /* thread list collapses; back via Messages nav */
  .chat-shell:has(> div:only-child) .chat-threads { display: flex !important; }
}

/* Topbar action cluster (message bubble, bell, avatar) */
.topbar-actions {
  position: fixed;
  top: 14px;
  right: 18px;
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 60;
}
.topbar-icon-btn {
  position: relative;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid var(--hairline);
  background: var(--surface);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 17px;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
  transition: box-shadow .18s ease, border-color .18s ease;
  text-decoration: none;
  color: var(--ink);
}
.topbar-icon-btn:hover { border-color: var(--brand); }
/* Illuminated state — glows with the brand color while anything is unread. */
.topbar-icon-btn.lit {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--accent-soft, rgba(0,0,0,0.06)), 0 0 14px var(--brand);
}
.topbar-count {
  position: absolute;
  /* Rides the bubble's top-right corner rather than sitting on top of it. */
  top: -1px;
  right: -1px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  /* Not --brand: the bubble itself is now the business colour, so a matching
     badge would disappear into it. Unread counts are red by convention. */
  background: #e0245e;
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--surface);
  font-variant-numeric: tabular-nums;
}
/* .topbar-dot retired: the bell now carries the same red count as the message
   bubble, so the two read as one system and "how many" is answered at a
   glance rather than just "some". */
/* Ring, then rest. Swinging without pause reads as decoration, not an alert. */
@keyframes bell-ring {
  0%, 34%, 100% { transform: rotate(0); }
  5% { transform: rotate(13deg); }
  11% { transform: rotate(-11deg); }
  17% { transform: rotate(7deg); }
  23% { transform: rotate(-5deg); }
  29% { transform: rotate(2deg); }
}
.topbar-icon-btn.ringing .bell-glyph { display:inline-block; animation: bell-ring 1s ease-in-out infinite; transform-origin: top center; }

/* --- Message bubble ---------------------------------------------------
   The glyph IS the button: no coloured blob behind an outline icon, and no
   corner faked into a tail. The hit area stays a comfortable 38px while the
   bubble draws at 26px, and it takes the active business colour like the
   rest of the chrome. */
.topbar-bubble {
  position: relative;
  width: 38px; height: 38px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; text-decoration: none;
  background: none;
  color: var(--brand);
  transition: transform .14s cubic-bezier(.34,1.4,.64,1), filter .14s ease;
  /* drop-shadow follows the bubble's silhouette; box-shadow would draw a
     rectangle around a shape that isn't one. */
  filter: drop-shadow(0 2px 5px color-mix(in srgb, var(--brand) 38%, transparent));
  -webkit-tap-highlight-color: transparent;
}
.topbar-bubble-glyph { display: block; }
.topbar-bubble:hover {
  transform: translateY(-1px) scale(1.06);
  filter: drop-shadow(0 4px 9px color-mix(in srgb, var(--brand) 52%, transparent));
}
.topbar-bubble:active { transform: scale(.94); }

/* Heartbeat while messages are unread: two beats, then rest. A scale reads
   on the bubble's own shape, where the old expanding ring could not. */
@keyframes msg-pulse {
  0%, 42%, 100% { transform: scale(1); }
  12% { transform: scale(1.13); }
  24% { transform: scale(1); }
  33% { transform: scale(1.09); }
}
.topbar-bubble.pulsing { animation: msg-pulse 2.2s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .topbar-bubble.pulsing { animation: none; }
  .topbar-bubble, .topbar-bubble:hover, .topbar-bubble:active { transition: none; transform: none; }
}

/* --- Notification bell -------------------------------------------------
   Matched to the message bubble: a drawn glyph that IS the button, in the
   active business colour, with a silhouette-following shadow. Sits quieter
   than the bubble at rest — a bell that shouts with nothing to say teaches
   people to stop looking at it. */
.topbar-bell {
  position: relative;
  width: 38px; height: 38px;
  border: none;
  background: none;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; padding: 0;
  color: var(--ink-muted);
  transition: transform .14s cubic-bezier(.34,1.4,.64,1), color .14s ease, filter .14s ease;
  -webkit-tap-highlight-color: transparent;
}
.bell-glyph { display: block; line-height: 0; }
.topbar-bell:hover { transform: translateY(-1px) scale(1.06); color: var(--ink); }
.topbar-bell:active { transform: scale(.94); }

/* Something to report: takes the business colour and lifts off the bar. */
.topbar-bell.ringing {
  color: var(--brand);
  filter: drop-shadow(0 2px 5px color-mix(in srgb, var(--brand) 38%, transparent));
}
.topbar-bell.ringing .bell-glyph {
  animation: bell-ring 2.4s ease-in-out infinite;
  transform-origin: top center;
}
@media (prefers-reduced-motion: reduce) {
  .topbar-bell.ringing .bell-glyph { animation: none; }
  .topbar-bell, .topbar-bell:hover, .topbar-bell:active { transition: none; transform: none; }
}

/* Right-click context menus for the bubble & bell */
.topbar-menu {
  position: absolute;
  top: 44px; right: 0;
  z-index: 80;
  min-width: 210px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  padding: 5px;
  overflow: hidden;
}
.topbar-menu-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; text-align: left;
  padding: 9px 11px; border: none; background: none;
  font: inherit; font-size: 13px; color: inherit; cursor: pointer;
  border-radius: 8px; text-decoration: none;
}
.topbar-menu-item:hover { background: var(--surface-hover); }
.topbar-panel {
  position: fixed;
  top: 58px;
  right: 18px;
  width: 340px;
  max-width: calc(100vw - 24px);
  max-height: 70vh;
  overflow-y: auto;
  z-index: 70;
  border-radius: 14px;
  border: 1px solid var(--hairline);
  background: var(--surface);
  box-shadow: 0 16px 48px rgba(0,0,0,0.22);
}
.topbar-panel .panel-head { padding: 12px 14px; font-weight: 700; font-size: 13px; border-bottom: 1px solid var(--hairline); display:flex; justify-content:space-between; align-items:center; }
.notif-item { display:flex; gap:10px; padding:11px 14px; border-bottom:1px solid var(--hairline); text-decoration:none; color:inherit; font-size:13px; }
.notif-item:hover { background: var(--surface-hover, rgba(0,0,0,0.03)); }
.notif-item.unread { background: var(--accent-soft); }
.notif-item .notif-time { font-size: 11px; color: var(--ink-faint); }
@media (max-width: 900px) {
  /* The cluster is NOT a child of .mobile-topbar in the DOM, so making it
     static dropped it into normal flow — the avatar landed on its own row
     above the business tabs. Keep it fixed and park it on the topbar's right. */
  .topbar-actions {
    position: fixed;
    top: calc(env(safe-area-inset-top) + 10px);
    right: 12px;
    left: auto;
    margin-left: 0;
    z-index: 60;
  }
  .mobile-topbar { display: flex; align-items: center; gap: 8px; }
  .topbar-panel { top: 62px; right: 8px; }
}

/* ---------------------------------------------------------------------
   Calendar — high-contrast, professional grid
   --------------------------------------------------------------------- */
.cal-root { --cal-line: color-mix(in srgb, var(--ink) 16%, transparent); }
.cal-frame {
  border: 1.5px solid var(--cal-line);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
  min-height: 0;
  min-width: 0;
}
/* display lives in a class (not inline) because Alpine x-show drives
   style.display and would otherwise wipe an inline display value, collapsing
   the grid back to block. When shown, x-show clears style.display and these win. */
.cal-month { display: grid; grid-template-rows: auto minmax(0, 1fr); }
.cal-week { display: block; }
.cal-week-grid { display: grid; height: 100%; }
.cal-dow-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  background: color-mix(in srgb, var(--ink) 5%, var(--surface));
  border-bottom: 1.5px solid var(--cal-line);
}
.cal-dow {
  padding: 8px 6px;
  text-align: center;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink);
}
.cal-cell {
  min-height: 0;
  min-width: 0;
  overflow: hidden;
  border-right: 1px solid var(--cal-line);
  border-bottom: 1px solid var(--cal-line);
  padding: 5px;
  cursor: pointer;
  transition: background .12s ease;
}
.cal-cell:hover { background: color-mix(in srgb, var(--ink) 4%, var(--surface)); }
.cal-cell.out-month { background: color-mix(in srgb, var(--ink) 3%, var(--surface)); }
.cal-cell.out-month .cal-daynum { color: var(--ink-faint); }
.cal-cell.is-today { background: color-mix(in srgb, var(--brand) 7%, var(--surface)); box-shadow: inset 0 2.5px 0 var(--brand); }
.cal-daynum {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 24px;
  width: 24px;
  border-radius: 50%;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}
.cal-daynum.today { background: var(--brand); color: var(--on-brand); box-shadow: 0 1px 4px color-mix(in srgb, var(--brand) 55%, transparent); }
.cal-chip {
  display: block;
  width: 100%;
  text-align: left;
  color: #fff;
  border: none;
  border-radius: 5px;
  padding: 2.5px 6px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: pointer;
  text-shadow: 0 1px 1px rgba(0,0,0,0.28);
  box-shadow: 0 1px 2px rgba(0,0,0,0.14);
  transition: filter .12s ease, transform .12s ease;
}
.cal-chip:hover { filter: brightness(1.08); transform: translateY(-1px); }
.cal-chip-lg { border-radius: 7px; padding: 5px 8px; white-space: normal; }
.cal-more {
  border: none;
  background: none;
  text-align: left;
  padding: 1px 4px;
  font-size: 10.5px;
  font-weight: 700;
  color: var(--brand);
  cursor: pointer;
}
.cal-more:hover { text-decoration: underline; }
.cal-col { min-width: 0; border-right: 1px solid var(--cal-line); display: flex; flex-direction: column; overflow: hidden; }
.cal-col-body { padding: 8px; flex: 1; min-height: 0; overflow-y: auto; cursor: pointer; display: flex; flex-direction: column; gap: 5px; }
.cal-col-head {
  position: sticky;
  top: 0;
  z-index: 1;
  background: color-mix(in srgb, var(--ink) 5%, var(--surface));
  border-bottom: 1.5px solid var(--cal-line);
  padding: 8px 6px;
  text-align: center;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--ink);
}
.cal-col-head.today { color: var(--brand); box-shadow: inset 0 -2.5px 0 var(--brand); }

/* ---------------------------------------------------------------------
   Inbound-lead celebration + gold/green priority glow
   --------------------------------------------------------------------- */
.lumen-celebrate {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  pointer-events: auto; cursor: pointer;
  background: radial-gradient(circle at center, rgba(0,0,0,0.28), rgba(0,0,0,0.5));
  animation: celebrate-in .25s ease;
}
.lumen-celebrate.fading { opacity: 0; transition: opacity .4s ease; }
@keyframes celebrate-in { from { opacity: 0; } to { opacity: 1; } }
.lumen-confetti { position: absolute; inset: 0; width: 100%; height: 100%; }
.lumen-celebrate-text { position: relative; text-align: center; z-index: 1; }
.lumen-celebrate-emoji { font-size: 64px; animation: coin-bounce .8s ease infinite alternate; }
@keyframes coin-bounce { from { transform: translateY(0) scale(1);} to { transform: translateY(-14px) scale(1.08);} }
.lumen-celebrate-flash {
  font-size: clamp(36px, 8vw, 84px);
  font-weight: 900;
  letter-spacing: 0.04em;
  background: linear-gradient(180deg, #fde68a 0%, #f59e0b 45%, #b45309 100%);
  -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 3px 10px rgba(0,0,0,0.5));
  animation: gold-flash 0.5s steps(1) infinite;
  margin-top: 6px;
}
@keyframes gold-flash { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.lumen-celebrate-sub { margin-top: 10px; color: #eafce9; font-size: 15px; font-weight: 600; text-shadow: 0 1px 6px rgba(0,0,0,0.6); }

/* A new inbound lead card glows gold + green until it's worked. */
@keyframes inbound-glow {
  0%, 100% { box-shadow: 0 0 0 1px #16a34a, 0 0 14px 2px rgba(22,163,74,0.55); }
  50% { box-shadow: 0 0 0 1px #eab308, 0 0 20px 4px rgba(234,179,8,0.6); }
}
.kanban-card.card-new, .list-row.card-new, .card.card-new {
  border-left: 3px solid #16a34a;
  background: linear-gradient(90deg, rgba(234,179,8,0.10), rgba(22,163,74,0.08));
  animation: inbound-glow 1.8s ease-in-out infinite;
}
.new-badge {
  background: linear-gradient(135deg, #eab308, #16a34a) !important;
  color: #fff !important;
}
@media (prefers-reduced-motion: reduce) {
  .lumen-celebrate-emoji, .lumen-celebrate-flash, .kanban-card.card-new, .topbar-bubble.pulsing, .topbar-bell.ringing .bell-glyph { animation: none !important; }
}

/* ── Platform owner's business-type selector (sits in the tab strip) ──────
   With 50+ business types a flat tab row is unusable, so the operator gets a
   grouped dropdown instead. Also keeps the strip from colliding with the
   top-right icons. */
/* Only the TABS scroll. The picker is a sibling of the scroller, never a
   child — an overflow container clips absolutely positioned descendants
   regardless of z-index, which is what buried the dropdown. */
.genre-tabs { overflow: visible; align-items: center; padding-right: 68px; }
.genre-tabs-scroll { display: flex; gap: 4px; min-width: 0; flex: 0 1 auto; overflow-x: auto; scrollbar-width: thin; }
.bt-picker { position: relative; flex: 0 0 auto; }
.bt-picker-btn { white-space: nowrap; cursor: pointer; border: 1px dashed var(--border); background: none; font: inherit; }
.bt-picker-menu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 200;
  width: 300px; max-width: calc(100vw - 32px); max-height: 70vh; overflow-y: auto; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
}
.bt-picker-group {
  padding: 8px 8px 4px; font-size: 10.5px; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-muted);
}
.bt-picker-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  width: 100%; padding: 7px 8px; border: none; background: none; cursor: pointer;
  border-radius: 6px; font: inherit; font-size: 13px; color: var(--ink); text-align: left;
}
.bt-picker-item:hover { background: var(--surface-hover); }
.bt-picker-item.on { font-weight: 650; }
.bt-picker-on { font-size: 10px; font-weight: 700; text-transform: uppercase; color: var(--brand); }


/* ── Bottom dock bar ──────────────────────────────────────────────────
   A permanent strip the Lumen assistant lives in, with Messages and the
   notification bell on either side of it. Starts after the sidebar so the
   orb centres on the CONTENT, not the window. */
.bottombar {
  position: fixed; left: 232px; right: 0; bottom: 0; z-index: 45;
  height: calc(var(--bottombar-h) + var(--safe-bottom));
  padding-bottom: var(--safe-bottom);
  background: var(--surface);
  border-top: 1px solid var(--border);
  box-shadow: 0 -2px 14px rgba(0, 0, 0, 0.05);
}
.bottombar-inner {
  height: var(--bottombar-h);
  display: flex; align-items: center; justify-content: center;
  /* The gap element reserves the orb's footprint between the two icons. */
  gap: 26px;
}
.bb-slot { position: relative; display: flex; align-items: center; }
.bb-orb-gap { width: 58px; flex: 0 0 auto; }

/* Menus and panels anchored to the dock open UPWARD. */
.topbar-menu.menu-up { top: auto; bottom: 50px; right: auto; left: 50%; transform: translateX(-50%); }
.topbar-panel.panel-up {
  position: absolute; top: auto; bottom: 50px;
  right: auto; left: 50%; transform: translateX(-50%);
  width: 340px; max-width: calc(100vw - 24px);
}

@media (max-width: 900px) {
  /* Sidebar is a drawer on phones, so the bar spans the full width and the
     orb centres on the window. */
  :root { --dock-shift: 0px; --bottombar-h: 62px; }
  .bottombar { left: 0; }
}

/* In the dock the bell sits opposite the solid blue message bubble, so give it
   the same visual weight instead of a bare glyph on the bar. */
/* The bell used to need a chip to stand out on the old bottom bar. It is now
   a drawn glyph that carries itself, and the chip fought that everywhere the
   bell was re-homed — most visibly on phones, where it read as a stray box
   next to the bare profile avatar. */
.bottombar .topbar-bell:hover { transform: translateY(-1px) scale(1.06); }
.bottombar .topbar-bell.ringing {
  filter: drop-shadow(0 2px 5px color-mix(in srgb, var(--brand) 38%, transparent));
}

/* A test-driven workspace carries a × so the operator can close it from the
   tab strip instead of going to Settings and toggling it off. */
.genre-tab-wrap { position: relative; display: inline-flex; align-items: center; flex: 0 0 auto; }
.genre-tab-wrap .genre-tab.is-test { padding-right: 28px; border: 1px dashed var(--border); }
.genre-tab-close-form { position: absolute; right: 4px; top: 50%; transform: translateY(-50%); line-height: 0; }
.genre-tab-close {
  border: none; background: none; cursor: pointer; padding: 0;
  width: 18px; height: 18px; border-radius: 999px;
  font: inherit; font-size: 15px; line-height: 1; color: var(--ink-muted);
  display: inline-flex; align-items: center; justify-content: center;
}
.genre-tab-close:hover { background: var(--border-soft); color: var(--ink); }
.genre-tab.active.is-test + .genre-tab-close-form .genre-tab-close { color: var(--on-brand); }

/* ── Estimates / quotes ───────────────────────────────────────────────
   The estimate is a document a customer sees, so it is laid out like one:
   a paper-ish sheet with a ruled line table, right-aligned money, and a
   totals block that reads top-to-bottom the way an invoice does. */
.qt-status {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
}
.qt-status::before { content: ''; width: 6px; height: 6px; border-radius: 999px; background: currentColor; }
.qt-status-draft { background: var(--border-soft); color: var(--ink-muted); }
.qt-status-sent { background: #e8f0fe; color: #1a56db; }
.qt-status-accepted { background: #e8f7ee; color: #1c7c43; }
.qt-status-declined { background: #fdecea; color: #c0392b; }
.qt-status-expired { background: #fff4e5; color: #a05a00; }

/* List */
.qt-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.qt-table th {
  text-align: left; padding: 10px 16px; white-space: nowrap;
  font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-muted); border-bottom: 1px solid var(--border);
}
.qt-table td { padding: 12px 16px; border-bottom: 1px solid var(--hairline); vertical-align: middle; }
.qt-table tbody tr:last-child td { border-bottom: none; }
.qt-table tbody tr:hover { background: var(--surface-hover, rgba(0,0,0,.02)); }
.qt-num { font-weight: 600; text-decoration: none; color: var(--ink); }
.qt-num:hover { color: var(--brand); }
.qt-money { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.qt-empty { padding: 44px 20px; text-align: center; color: var(--ink-muted); font-size: 13.5px; }
.qt-empty strong { display: block; color: var(--ink); font-size: 15px; margin-bottom: 6px; }

/* Document layout */
.qt-layout { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: 18px; align-items: start; }
@media (max-width: 1080px) { .qt-layout { grid-template-columns: 1fr; } }

.qt-doc { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
.qt-doc-head { padding: 22px 24px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.qt-doc-title { font-size: 19px; font-weight: 650; letter-spacing: -0.01em; margin: 0 0 3px; }
.qt-doc-sub { font-size: 12.5px; color: var(--ink-muted); margin: 0; }
.qt-doc-meta { text-align: right; font-size: 12.5px; color: var(--ink-muted); line-height: 1.8; }
.qt-doc-meta strong { color: var(--ink); font-weight: 600; }

.qt-lines { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.qt-lines th {
  text-align: left; padding: 10px 24px; font-size: 11px; font-weight: 700;
  letter-spacing: .07em; text-transform: uppercase; color: var(--ink-muted);
  border-bottom: 1px solid var(--border); background: var(--surface-2, rgba(0,0,0,.015));
}
.qt-lines td { padding: 12px 24px; border-bottom: 1px solid var(--hairline); }
.qt-lines tbody tr:last-child td { border-bottom: none; }
.qt-line-desc { font-weight: 500; }
.qt-line-tag {
  margin-left: 7px; padding: 1px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  background: var(--border-soft); color: var(--ink-muted); vertical-align: middle;
}
.qt-x { border: none; background: none; cursor: pointer; color: var(--ink-faint); font-size: 17px; line-height: 1; padding: 2px 6px; border-radius: 6px; }
.qt-x:hover { background: var(--red-soft, #fdecea); color: var(--danger, #c0392b); }

/* Builder */
.qt-builder { padding: 18px 24px; border-top: 1px solid var(--border); background: var(--surface-2, rgba(0,0,0,.015)); }
.qt-builder + .qt-builder { border-top: 1px solid var(--hairline); }
.qt-builder-label { font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--ink-muted); margin-bottom: 10px; }
.qt-presets { display: flex; flex-wrap: wrap; gap: 7px; }
.qt-preset {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 7px 12px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface); cursor: pointer; font: inherit; font-size: 12.5px; color: var(--ink);
  transition: border-color .12s ease, transform .12s ease;
}
.qt-preset:hover { border-color: var(--brand); transform: translateY(-1px); }
.qt-preset-price { color: var(--ink-muted); font-variant-numeric: tabular-nums; font-size: 11.5px; }
.qt-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.qt-row .field { margin: 0; }
.qt-row .field-input { margin-bottom: 0; }
.qt-check { display: inline-flex; gap: 6px; align-items: center; font-size: 12.5px; color: var(--ink-muted); padding-bottom: 9px; white-space: nowrap; }

/* Totals */
.qt-totals { font-size: 13.5px; }
.qt-total-row { display: flex; justify-content: space-between; gap: 16px; padding: 7px 0; }
.qt-total-row span:last-child { font-variant-numeric: tabular-nums; }
.qt-total-row.muted { color: var(--ink-muted); }
.qt-total-row.grand {
  border-top: 1px solid var(--border); margin-top: 6px; padding-top: 12px;
  font-size: 18px; font-weight: 650; letter-spacing: -0.01em;
}
.qt-total-row.optional { border-top: 1px dashed var(--hairline); margin-top: 6px; padding-top: 10px; color: var(--ink-muted); font-size: 12.5px; }

/* Printing an estimate should produce the document, not the app. */
@media print {
  .sidebar, .genre-tabs, .topbar-actions, .bottombar, .lumen-dock-btn,
  .page-actions, .qt-builder, .qt-side-form, .qt-x { display: none !important; }
  main.content { padding: 0 !important; max-width: none !important; }
  .qt-layout { grid-template-columns: 1fr !important; }
  .qt-doc, .card { border: none !important; box-shadow: none !important; }
}

/* Invoice states reuse the estimate pills; these three are invoice-only. */
.qt-status-partial { background: #fff4e5; color: #a05a00; }
.qt-status-overdue { background: #fdecea; color: #c0392b; }
.qt-status-void { background: var(--border-soft); color: var(--ink-faint); }

/* "Needs attention" strip above the dashboard grid — money owed and work due. */
.attn-bar { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 18px; }
.attn-item {
  display: flex; flex-direction: column; gap: 2px;
  padding: 12px 18px; min-width: 150px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  text-decoration: none; color: var(--ink);
  transition: border-color .12s ease, transform .12s ease;
}
.attn-item:hover { border-color: var(--brand); transform: translateY(-1px); }
.attn-value { font-size: 21px; font-weight: 650; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.attn-label { font-size: 11.5px; color: var(--ink-muted); }
.attn-item.attn-urgent { border-color: color-mix(in srgb, var(--danger, #c0392b) 45%, var(--border)); }
.attn-item.attn-urgent .attn-value { color: var(--danger, #c0392b); }


/* ── Modern polish ────────────────────────────────────────────────────
   Deliberately small. The app's character — calm, dense, per-business-type
   colour — is right; these close the gaps that make an otherwise clean UI
   feel unfinished, and every one of them inherits the active business
   type's --brand rather than introducing a new palette. */

:root {
  /* Native UI the stylesheet cannot style — scrollbars, date pickers, the
     select popup, autofill backgrounds — follows this. Emitted per theme by
     ThemeCatalog, so a dark workspace stops getting white scrollbars. */
  color-scheme: var(--scheme, light);

  /* One line that themes every checkbox, radio, range and progress bar to the
     business type you are standing in. Previously they were browser blue in
     all 53 workspaces. */
  accent-color: var(--brand);
}

/* Keyboard focus. There was none: inputs killed the outline and replaced it
   only on :focus, and buttons/links/tabs had nothing at all — so tabbing
   through the app was invisible. :focus-visible keeps mouse clicks clean
   while making keyboard navigation obvious. */
:where(a, button, [role="button"], input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}
.field-input:focus-visible,
select.field-input:focus-visible,
textarea.field-input:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 1px;
}

/* Buttons acknowledge the press. 1px is enough to feel responsive without
   turning into an animation. */
.btn { transition: background .12s ease, border-color .12s ease, opacity .12s ease, transform .08s ease; }
.btn:active { transform: translateY(1px); }

/* Money and metrics must not jitter between rows. */
.kpi-value, .data-table td, .qt-money, .attn-value, .stat-value {
  font-variant-numeric: tabular-nums;
}

/* Headlines rag better when the browser balances them; harmless where
   unsupported. */
.page-title, .section-title, .ld-hero h1, .ld-section-head h2 { text-wrap: balance; }
.page-subtitle, .field-hint { text-wrap: pretty; }

/* Selection picks up the workspace colour instead of system blue. */
::selection { background: var(--accent-soft); color: var(--accent-ink); }

/* Scrollbars inside panels, matched to the theme rather than the OS default. */
.bt-list, .topbar-panel, .dash-grid, .board-col { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }

/* Honour the system setting — the app already animates lightly, but a press
   state and hover lift should still stop when asked. */
@media (prefers-reduced-motion: reduce) {
  .btn:active { transform: none; }
  .card-hover:hover, .attn-card:hover, .ld-card:hover, .bt-trigger:hover { transform: none; }
}

/* ── Phone shell ──────────────────────────────────────────────────────
   Hidden above 900px, where the sidebar and desktop dock take over. Every
   colour here is the active business type's --brand, so a phone feels like
   the workspace it is in rather than like a generic app. */
.mob { display: none; }

@media (max-width: 900px) {
  .mob { display: block; }

  /* The desktop dock's BAR would collide with the phone tab bar, but hiding
     the whole thing took the notification bell with it — and the phone dock
     has no bell, so notifications became unreachable. Strip the bar instead
     and re-home the bell beside the profile, where there is room. */
  .bottombar {
    position: static;
    height: auto;
    padding: 0;
    background: none;
    border: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none;
    pointer-events: none;   /* only the re-homed bell stays interactive */
  }
  .bottombar-inner { display: contents; }

  /* Messages already has its own dock tab — a second entry point is clutter.
     Targeted by content rather than position so reordering the dock can't
     silently hide the wrong control. */
  .bottombar .bb-slot:has(.topbar-bubble) { display: none; }

  /* The bell rides the sticky top bar, immediately left of the avatar:
     38px avatar + 10px gap, inside the bar's own 14px + safe-area padding. */
  .bottombar .bb-slot:has(.topbar-bell) {
    position: fixed;
    top: calc(var(--safe-top) + 9px);
    right: calc(62px + var(--safe-right));
    z-index: 46;
    pointer-events: auto;
  }
  .bottombar .topbar-menu { top: 44px; right: 0; }
  main.content { padding-bottom: calc(var(--mob-dock-h) + var(--safe-bottom) + 24px); }

  :root { --mob-dock-h: 62px; }

  .mob-dock {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
    height: calc(var(--mob-dock-h) + var(--safe-bottom));
    padding-bottom: var(--safe-bottom);
    display: grid; grid-template-columns: repeat(5, 1fr); align-items: center;
    background: color-mix(in srgb, var(--surface) 92%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-top: 1px solid var(--hairline);
  }
  .mob-tab {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    height: var(--mob-dock-h); position: relative;
    font: inherit; font-size: 10.5px; font-weight: 550; letter-spacing: .01em;
    color: var(--ink-faint); text-decoration: none; background: none; border: none; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .mob-tab .mob-ico { font-size: 19px; line-height: 1; }
  .mob-tab.on { color: var(--brand); }
  .mob-tab:active { opacity: .6; }
  .mob-orb-gap { display: block; }
  .mob-badge {
    position: absolute; top: 6px; left: 50%; margin-left: 6px;
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
    background: var(--brand); color: var(--on-brand);
    font-size: 10px; font-weight: 700; display: grid; place-items: center;
  }

  /* Create. Above the dock and to the right — thumb-reachable, and clear of
     Lumen in the centre. What it makes follows the section you are on. */
  .mob-fab-form { position: fixed; right: 16px; bottom: calc(var(--mob-dock-h) + var(--safe-bottom) + 16px); z-index: 51; }

  /* One object, not a button with a caption floating beside it — detached,
     the label read as a stray tooltip sitting on the page's content. */
  .mob-fab {
    position: fixed; right: 16px;
    bottom: calc(var(--mob-dock-h) + var(--safe-bottom) + 16px);
    z-index: 51;
    height: 46px; padding: 0 18px 0 14px;
    display: inline-flex; align-items: center; gap: 7px;
    border-radius: 999px; border: none; cursor: pointer;
    background: var(--brand); color: var(--on-brand);
    font: inherit; font-size: 14px; font-weight: 600; white-space: nowrap;
    text-decoration: none;
    box-shadow: 0 6px 18px color-mix(in srgb, var(--brand) 40%, transparent), 0 2px 6px rgba(0,0,0,.2);
    transition: transform .12s ease;
  }
  .mob-fab-plus { font-size: 20px; line-height: 1; font-weight: 400; }
  .mob-fab-text { line-height: 1; }
  .mob-fab-form .mob-fab { position: static; }
  .mob-fab:active { transform: scale(.94); }


  /* Everything else, as a sheet. */
  .mob-scrim { position: fixed; inset: 0; z-index: 58; background: rgba(0,0,0,.42); }
  .mob-sheet {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 59;
    max-height: 88vh; display: flex; flex-direction: column;
    background: var(--surface); border-top-left-radius: 20px; border-top-right-radius: 20px;
    box-shadow: 0 -8px 40px rgba(0,0,0,.28);
    padding-bottom: var(--safe-bottom);
  }
  .mob-sheet-grip { width: 38px; height: 4px; border-radius: 999px; background: var(--border); margin: 10px auto 4px; flex: none; }
  .mob-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 18px 14px; border-bottom: 1px solid var(--hairline); flex: none; }
  .mob-sheet-title { font-size: 16px; font-weight: 650; letter-spacing: -.01em; }
  .mob-sheet-sub { font-size: 12.5px; color: var(--ink-muted); margin-top: 1px; }
  .mob-sheet-x { border: none; background: var(--border-soft); color: var(--ink-muted); width: 32px; height: 32px; border-radius: 999px; font-size: 14px; cursor: pointer; }
  .mob-sheet-body { overflow-y: auto; overscroll-behavior: contain; padding: 6px 12px 22px; }

  .mob-group { margin-top: 14px; }
  .mob-group-head { font-size: 10.5px; font-weight: 800; letter-spacing: .09em; text-transform: uppercase; color: var(--ink-faint); padding: 6px 8px; }
  .mob-row {
    display: flex; align-items: center; gap: 12px; padding: 13px 10px; border-radius: 12px;
    font-size: 15px; color: var(--ink); text-decoration: none; min-height: 46px;
  }
  .mob-row:active { background: var(--surface-hover); }
  .mob-row-ico { width: 22px; text-align: center; font-size: 15px; color: var(--ink-muted); flex: none; }
  .mob-row-go { margin-left: auto; color: var(--ink-faint); }

  .mob-switch { display: flex; flex-wrap: wrap; gap: 8px; padding: 4px 8px 0; }
  .mob-switch-item {
    display: inline-flex; align-items: center; gap: 8px; padding: 9px 14px; border-radius: 999px;
    border: 1px solid var(--border); font-size: 14px; color: var(--ink); text-decoration: none;
  }
  .mob-switch-item.on { border-color: var(--brand); background: var(--accent-soft); }
  .mob-dot { width: 8px; height: 8px; border-radius: 999px; flex: none; }

  /* Lumen keeps the centre of the dock on every screen. */
  .lumen-dock-btn { bottom: calc(var(--safe-bottom) + 4px); left: 50%; width: 54px; height: 54px; z-index: 52; }
  .lumen-sheet { bottom: calc(var(--mob-dock-h) + var(--safe-bottom) + 12px); left: 50%; }
}

/* Swipe feedback on phone kanban cards: the edge you are flinging toward
   tints with what will happen — brand for advance, amber for snooze. */
@media (max-width: 900px) {
  .kanban-card { touch-action: pan-y; will-change: transform; }
  .kanban-card.swipe-advance { box-shadow: inset 4px 0 0 var(--brand); }
  .kanban-card.swipe-snooze { box-shadow: inset -4px 0 0 var(--amber); }
}

/* The orb acknowledges the first tap instantly, so the short wait that lets
   a double-tap register is never felt as lag. */
.lumen-dock-btn { transition: transform .12s ease, box-shadow .12s ease; }
.lumen-dock-btn.lumen-dock-armed {
  transform: translateX(-50%) scale(.92);
  filter: drop-shadow(0 0 7px color-mix(in srgb, var(--brand) 55%, transparent));
}
@media (prefers-reduced-motion: reduce) {
  .lumen-dock-btn { transition: none; }
  .lumen-dock-btn.lumen-dock-armed { transform: none; }
}

/* ── Native shell ──────────────────────────────────────────────────────
   Only applies inside the iOS/Android app, where <html> carries .is-native.
   The web build is untouched. */
.native-offline {
  position: fixed; left: 0; right: 0; top: 0; z-index: 200;
  padding: calc(var(--safe-top, env(safe-area-inset-top)) + 8px) 16px 9px;
  background: var(--amber, #b45309); color: #fff;
  font-size: 12.5px; font-weight: 550; text-align: center;
  transform: translateY(-100%); transition: transform .22s ease;
}
.native-offline.on { transform: translateY(0); }

.is-native {
  /* Inside an app, a text selection lasso on chrome feels broken; inputs and
     record content still select normally below. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.is-native input, .is-native textarea, .is-native [contenteditable],
.is-native .card, .is-native table {
  -webkit-user-select: text;
  user-select: text;
}
/* Rubber-band scrolling past the top reveals the page background behind a
   fixed dock, which reads as a rendering fault rather than a gesture. */
.is-native body { overscroll-behavior-y: none; }
