/* ─────────────────────────────────────────────────────────────────────────
   Shared design system — dark analytics theme.
   Loaded by every page in /public. Component classes below are the contract
   several pages' inline <script> blocks rely on (they set these classes,
   or read var(--accent)/var(--muted)/var(--bad)/var(--warn)/var(--line)/
   var(--panel) directly in generated markup) — names are load-bearing.

   Two shells share these tokens: `.app-shell` (icon rail, agency side) and
   `.portal-shell` (pill nav, business-owner side).
   ────────────────────────────────────────────────────────────────────── */

:root {
  /* surfaces — near-black page, lifted cards, inset wells */
  --bg: #08080b;
  --bg-shell: #0e0e13;
  --panel: #141419;
  --panel-2: #1b1b22;
  --panel-3: #23232c;
  --line: #26262f;
  --line-strong: #35353f;

  /* text */
  --text: #f4f5f8;
  --muted: #9698ab;
  --muted-2: #6a6c7e;

  /* brand + semantics.
     On a dark surface the "-dark" variants are LIGHTER than the base: they are
     the readable-on-dark text tints, not darker shades. The name is kept
     because page scripts reference it directly. */
  --accent: #7c5cff;
  --accent-dark: #ab9bff;
  --accent-soft: #7c5cff1f;
  --good: #22c55e;
  --good-dark: #5eeb96;
  --good-soft: #22c55e1f;
  --warn: #fb923c;
  --warn-soft: #f973161f;
  --bad: #f87171;
  --bad-soft: #ef44441f;

  /* categorical chart palette — the reference decks' orange / violet / green
     / cyan, in a fixed order so two charts on one page never disagree. */
  --c1: #f9731a;
  --c2: #7c5cff;
  --c3: #22c55e;
  --c4: #22d3ee;
  --c5: #3b82f6;
  --c6: #f43f5e;
  /* The ghost bar sitting behind a real one — "what the full day could hold". */
  --track: #ffffff0f;
  --track-line: #ffffff14;

  /* The one high-contrast lozenge on a page — a selected pill, tab or chip, a
     tooltip, the portal's round mark — which is simply the page's own colours
     inverted. Every one of those elements reads these, so the light theme
     below flips all of them by swapping two values. */
  --invert-bg: #ffffff;
  --invert-fg: #101015;
  --invert-glow: rgba(255, 255, 255, .5);
  /* Dimmer behind a dialog or the portal's sign-in gate. */
  --overlay: rgba(4, 4, 7, .78);
  /* The fade at the bottom of a scrollable well. */
  --fade: rgba(0, 0, 0, .6);

  /* elevation + shape */
  --shadow-xs: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, .45);
  --shadow-md: 0 12px 32px rgba(0, 0, 0, .5);
  --shadow-lg: 0 28px 64px rgba(0, 0, 0, .62);
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-xl: 28px;
  --radius-full: 999px;

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

  --ease: cubic-bezier(.4, 0, .2, 1);
}

/* ─── Reset & base ──────────────────────────────────────────────────────── */

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg); }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 14.5px/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Tells the browser to render its own widgets (scrollbars, date pickers, the
   checkbox tick) dark too — without it a date input on these pages opens a
   blinding white calendar. */
:root { color-scheme: dark; }

/* ─── Light theme ────────────────────────────────────────────────────────
   Opt-in: nothing changes unless something sets data-theme="light" on <html>
   (portal.html's toggle does, from localStorage, before first paint). Only
   TOKENS are redefined here — no component rule is duplicated, so a component
   added later is light-ready without being touched.

   Note the "-dark" variants inverting their meaning: on the dark theme they
   are the LIGHTER, readable-on-black tint; here they have to be genuinely
   darker than the base to stay readable on white. Same for --track, which is
   a white veil on dark and a black one here. */
:root[data-theme="light"] {
  color-scheme: light;

  --bg: #f5f6fa;
  --bg-shell: #ffffff;
  --panel: #ffffff;
  --panel-2: #f2f3f8;
  --panel-3: #e7e9f1;
  --line: #e2e4ee;
  --line-strong: #ccd0dd;

  --text: #14151c;
  --muted: #585d70;
  --muted-2: #7f8497;

  --accent: #6538f0;
  --accent-dark: #4b21c9;
  --accent-soft: #6538f014;
  --good: #16a34a;
  --good-dark: #14743a;
  --good-soft: #16a34a14;
  --warn: #c2620a;
  --warn-soft: #f9731614;
  --bad: #d92626;
  --bad-soft: #ef444414;

  --c1: #e2620d;
  --c2: #6538f0;
  --c3: #16a34a;
  --c4: #0891b2;
  --c5: #2563eb;
  --c6: #e11d48;
  --track: #0f172a0f;
  --track-line: #0f172a1a;

  --invert-bg: #14151c;
  --invert-fg: #ffffff;
  --invert-glow: rgba(20, 21, 28, .35);
  --overlay: rgba(30, 33, 48, .45);
  --fade: rgba(15, 23, 42, .14);

  --shadow-xs: 0 1px 2px rgba(15, 23, 42, .06);
  --shadow-sm: 0 2px 8px rgba(15, 23, 42, .08);
  --shadow-md: 0 12px 32px rgba(15, 23, 42, .12);
  --shadow-lg: 0 28px 64px rgba(15, 23, 42, .18);
}

/* The scrollbar thumb is drawn from --line-strong against --bg, which is the
   one place the dark values don't simply invert. */
:root[data-theme="light"] ::-webkit-scrollbar-thumb { background: #c3c7d6; }
:root[data-theme="light"] ::-webkit-scrollbar-thumb:hover { background: var(--muted-2); }

a { color: inherit; text-decoration: none; }
a[href]:not([class]) { color: var(--accent-dark); text-decoration: underline; text-underline-offset: 2px; }

h1, h2, h3 { margin: 0; font-weight: 650; letter-spacing: -.02em; color: var(--text); }
h1 { font-size: 20px; }
h2 { font-size: 14.5px; }

::selection { background: var(--accent-soft); color: var(--text); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 999px; border: 2.5px solid var(--bg); }
::-webkit-scrollbar-thumb:hover { background: var(--muted-2); }

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

.eyebrow {
  display: flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--accent-dark); margin-bottom: 7px;
}
.eyebrow::before { content: ''; width: 14px; height: 2px; border-radius: 2px; background: var(--accent); flex-shrink: 0; }
.section-head { margin-bottom: 18px; }
.section-head h2 { font-size: 17px; }
.section-head .sub { margin-top: 4px; margin-bottom: 0; }

.sub { color: var(--muted); font-size: 13px; }
.meta { color: var(--muted); font-size: 12.5px; }
.mono { font-family: var(--font-mono); font-size: 12.5px; font-variant-numeric: tabular-nums; }
.hidden { display: none !important; }
.grow { flex: 1; }

/* ─── App shell: icon rail + topbar (agency side) ───────────────────────── */

.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: 82px;
  flex-shrink: 0;
  background: var(--bg-shell);
  border-right: 1px solid var(--line);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
  overflow-x: hidden;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 20px 10px 14px;
}
.sidebar-brand .mark {
  width: 38px; height: 38px; border-radius: 12px;
  background: linear-gradient(150deg, var(--accent), #4f2fd6);
  display: flex; align-items: center; justify-content: center;
  color: #fff; flex-shrink: 0;
  box-shadow: 0 6px 16px -6px rgba(124, 92, 255, .9);
}
.sidebar-brand .mark svg { width: 19px; height: 19px; }
/* The wordmark is what the rail trades away for its width. Kept in the DOM for
   screen readers and for the wide-screen fallback below. */
.sidebar-brand div { display: none; }
.sidebar-brand b { font-size: 14.5px; font-weight: 700; letter-spacing: -.01em; display: block; line-height: 1.2; }
.sidebar-brand span { font-size: 11px; color: var(--muted-2); text-transform: uppercase; letter-spacing: .06em; }

.sidebar-nav { padding: 4px 10px; display: flex; flex-direction: column; gap: 4px; }
.sidebar-section-label { display: none; }

.sidebar-nav a {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  padding: 11px 4px 9px; border-radius: var(--radius-md);
  font-size: 9.5px; font-weight: 600; letter-spacing: .01em; color: var(--muted-2);
  text-align: center; line-height: 1.15;
  transition: background .14s var(--ease), color .14s var(--ease);
}
/* The generic `a[href]:not([class])` rule below outweighs a plain
   `.sidebar-nav a`, so without matching its specificity here every nav item
   except the active one renders as an underlined body link. */
.sidebar-nav a[href] { color: var(--muted-2); text-decoration: none; }
.sidebar-nav a[href]:hover { color: var(--text); }
.sidebar-nav a[href].active { color: #fff; }
.sidebar-nav a svg { width: 19px; height: 19px; flex-shrink: 0; opacity: .9; }
.sidebar-nav a:hover { background: var(--panel-2); color: var(--text); }
.sidebar-nav a.active {
  background: linear-gradient(150deg, var(--accent), #5b39e8);
  color: #fff;
  box-shadow: 0 8px 20px -8px rgba(124, 92, 255, .95);
}
.sidebar-nav a.active svg { opacity: 1; }
.sidebar-nav a.cta {
  margin-top: 8px; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line-strong);
}
.sidebar-nav a.cta:hover { background: var(--panel-3); }
.sidebar-nav a.cta svg { opacity: 1; }

.sidebar-foot {
  margin-top: auto; padding: 14px 8px 18px;
  border-top: 1px solid var(--line);
  font-size: 9.5px; color: var(--muted-2); text-align: center; line-height: 1.4;
}

.topbar {
  padding: 18px 30px;
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  background: var(--bg-shell);
}
.topbar h1 { font-size: 19px; }
.topbar-actions { display: flex; align-items: center; gap: 10px; margin-left: auto; flex-wrap: wrap; }

.main { flex: 1; min-width: 0; }
main.content, .content { padding: 26px 30px 72px; max-width: 1480px; }

/* Search field in the topbar — a pill, per the reference. */
.search-pill {
  display: flex; align-items: center; gap: 9px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius-full); padding: 0 16px; min-width: 220px; max-width: 340px; flex: 1;
}
.search-pill svg { width: 15px; height: 15px; color: var(--muted-2); flex-shrink: 0; }
.search-pill input {
  border: 0; background: none; padding: 10px 0; font-size: 13px; box-shadow: none; width: 100%;
}
.search-pill input:focus { outline: none; box-shadow: none; border: 0; }

/* "14 Jan — 20 Jan" / "Jun 6, 2026" chips that label a card's range. */
.date-chip {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius-full); padding: 7px 14px;
  font-size: 12px; font-weight: 600; color: var(--muted); white-space: nowrap;
}
.date-chip svg { width: 13px; height: 13px; opacity: .8; }

.status-pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; color: var(--muted); font-weight: 500;
}
.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--muted-2); }
.dot.open { background: var(--good); box-shadow: 0 0 0 4px var(--good-soft); }

/* ─── Portal shell: centred pill nav (business-owner side) ──────────────── */

.portal-shell { max-width: 1420px; margin: 0 auto; padding: 18px 22px 70px; }

.portal-topbar {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 18px; margin-bottom: 24px;
  background: var(--bg-shell); border: 1px solid var(--line);
  border-radius: var(--radius-xl);
}
.portal-topbar .mark {
  width: 42px; height: 42px; border-radius: var(--radius-full); flex-shrink: 0;
  background: var(--invert-bg); color: var(--invert-fg);
  display: flex; align-items: center; justify-content: center;
}
.portal-topbar .mark svg { width: 21px; height: 21px; }

/* The pill group. Active tab is a solid white lozenge, exactly as in the
   reference — the one high-contrast element on the whole page. */
.pill-nav {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin: 0 auto;
}
.pill-nav button {
  background: var(--panel-2); color: var(--muted);
  border: 1px solid var(--line); box-shadow: none;
  border-radius: var(--radius-full); padding: 10px 20px;
  font-size: 13px; font-weight: 600; letter-spacing: -.005em;
}
.pill-nav button:hover { background: var(--panel-3); color: var(--text); }
.pill-nav button[aria-selected="true"],
.pill-nav button.active {
  background: var(--invert-bg); color: var(--invert-fg); border-color: var(--invert-bg);
  box-shadow: 0 6px 18px -8px var(--invert-glow);
}
.pill-nav .badge {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 18px; height: 18px; margin-left: 7px; padding: 0 5px;
  border-radius: var(--radius-full); background: var(--bad); color: #fff;
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.pill-nav button[aria-selected="true"] .badge { background: var(--bad); color: #fff; }

/* Round icon buttons at the top-right of the portal bar. */
.icon-btn {
  width: 40px; height: 40px; padding: 0; flex-shrink: 0;
  border-radius: var(--radius-full);
  background: var(--panel-2); color: var(--muted);
  border: 1px solid var(--line); box-shadow: none;
}
.icon-btn:hover { background: var(--panel-3); color: var(--text); }
.icon-btn svg { width: 17px; height: 17px; }

/* ─── Page head ─────────────────────────────────────────────────────────── */

.page-head {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 20px;
}
.page-head h1 {
  font-size: 34px; font-weight: 600; letter-spacing: -.035em; line-height: 1.1;
}
.page-head .page-head-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ─── Buttons ────────────────────────────────────────────────────────────── */

button, .btn {
  appearance: none; border: 0; cursor: pointer;
  font: 600 13px/1 var(--font); letter-spacing: -.005em;
  padding: 10px 17px; border-radius: var(--radius-sm);
  background: linear-gradient(150deg, var(--accent), #5b39e8); color: #fff;
  transition: filter .12s var(--ease), transform .06s var(--ease), box-shadow .12s var(--ease), border-color .12s var(--ease), opacity .12s var(--ease), background .12s var(--ease);
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  box-shadow: 0 6px 16px -8px rgba(124, 92, 255, .9);
}
button:hover, .btn:hover { filter: brightness(1.12); box-shadow: 0 8px 20px -8px rgba(124, 92, 255, 1); }
button:active, .btn:active { transform: translateY(1px); }
button:disabled, .btn:disabled { opacity: .4; cursor: default; transform: none; box-shadow: none; filter: none; }

button.ghost, .btn.ghost, a.ghost {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line-strong); box-shadow: none;
}
button.ghost:hover, .btn.ghost:hover, a.ghost:hover { background: var(--panel-3); border-color: var(--muted-2); filter: none; }

button.danger, .btn.danger {
  background: var(--bad-soft); color: var(--bad);
  border: 1px solid #f8717140; box-shadow: none;
}
button.danger:hover, .btn.danger:hover { background: #ef444433; filter: none; }

button.live { background: var(--bad); color: #fff; box-shadow: 0 6px 16px -8px rgba(248, 113, 113, .9); }
button.live:hover { background: #ef4444; }

a.ghost { display: inline-flex; align-items: center; padding: 10px 17px; border-radius: var(--radius-sm); font-weight: 600; font-size: 13px; }

.navbtn {
  display: inline-flex; align-items: center; gap: 6px; padding: 9px 15px; border-radius: var(--radius-full);
  border: 1px solid var(--line-strong); color: var(--text); font-size: 13px; font-weight: 600; background: var(--panel-2);
  transition: background .12s var(--ease), border-color .12s var(--ease);
}
.navbtn:hover { background: var(--panel-3); border-color: var(--muted-2); }
.navbtn.primary { background: var(--invert-bg); color: var(--invert-fg); border-color: var(--invert-bg); }
.navbtn.primary:hover { filter: brightness(.93); }

/* ─── Cards, stats, banners ──────────────────────────────────────────────── */

.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 22px 24px; box-shadow: var(--shadow-xs);
}

/* Card header row: title on the left, a date chip or "…" on the right. */
.card-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 18px;
}
.card-head h2, .card-head h3 { font-size: 17px; font-weight: 600; letter-spacing: -.02em; margin: 0; }
.card-head .card-head-right { margin-left: auto; display: flex; align-items: center; gap: 8px; }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); gap: 12px; margin-bottom: 26px; }
.stat {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-md);
  padding: 17px 19px; box-shadow: var(--shadow-xs); transition: border-color .15s var(--ease), transform .15s var(--ease);
}
.stat:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.stat b { display: block; font-size: 27px; font-weight: 650; letter-spacing: -.03em; line-height: 1.15; margin-bottom: 3px; }
.stat span { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .07em; font-weight: 650; }
.stat.dim b { color: var(--muted-2); font-size: 20px; }

/* KPI tile with a sparkline beside the number (agency dashboard reference). */
.kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px; margin-bottom: 22px;
}
.kpi {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; border-radius: var(--radius-md);
  background: var(--panel); border: 1px solid var(--line);
}
.kpi-main { min-width: 0; flex: 1; }
.kpi-label {
  font-size: 11px; color: var(--muted-2); font-weight: 600;
  letter-spacing: .04em; margin-bottom: 4px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.kpi-value {
  font-size: 22px; font-weight: 650; letter-spacing: -.03em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.kpi-side { display: flex; flex-direction: column; align-items: flex-end; gap: 5px; flex-shrink: 0; }
.kpi-side svg { display: block; }

/* Delta chip — a coloured triangle plus the number, as in both references. */
.delta {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.delta::before {
  content: ''; width: 0; height: 0;
  border-left: 4px solid transparent; border-right: 4px solid transparent;
}
.delta.up { color: var(--good); }
.delta.up::before { border-bottom: 5px solid var(--good); }
.delta.down { color: var(--bad); }
.delta.down::before { border-top: 5px solid var(--bad); }
.delta.flat { color: var(--muted-2); }
.delta.flat::before { border-bottom: 0; border-top: 0; width: 7px; height: 2px; background: var(--muted-2); border-radius: 2px; }

.banner {
  background: var(--warn-soft); border: 1px solid #f9731640; border-radius: var(--radius-md);
  padding: 15px 19px; margin-bottom: 22px; font-size: 13.5px; color: var(--text); line-height: 1.6;
}
.banner b { color: var(--warn); }
.banner ul { margin: 8px 0 0; padding-left: 20px; color: var(--muted); }
.banner code { font-family: var(--font-mono); font-size: 12.5px; background: var(--track); padding: 2px 6px; border-radius: 5px; }

/* ─── "What changed" ─────────────────────────────────────────────────────
   The system-update notice. It lives in the top bar next to Sign out rather
   than in the page body: a deploy changes how live calls behave, and that is
   worth a permanent, always-visible marker of WHEN it last happened — not a
   card that scrolls away and is only ever seen on the dashboard.

   Green means an update landed that hasn't been opened yet. Once read it goes
   quiet but keeps reporting how long ago it was, because "when did this
   version go live" is the question being answered even when nothing is new. */
.update-chip {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 13px; border-radius: 999px; cursor: pointer;
  font-size: 12.5px; font-weight: 600; letter-spacing: -.01em; white-space: nowrap;
  background: var(--panel-2); color: var(--muted);
  border: 1px solid var(--line-strong); box-shadow: none;
}
.update-chip:hover { background: var(--panel-3); color: var(--text); }
.update-chip[hidden] { display: none; }
.update-chip .pip {
  width: 7px; height: 7px; border-radius: 50%; background: var(--muted-2); flex-shrink: 0;
}
.update-chip.is-new {
  background: var(--good-soft); color: var(--good-dark); border-color: #22c55e5c;
}
.update-chip.is-new:hover { background: #22c55e2e; color: var(--good-dark); }
.update-chip.is-new .pip { background: var(--good); animation: update-pulse 2.4s ease-in-out infinite; }
@keyframes update-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--good-soft); }
  50% { box-shadow: 0 0 0 5px transparent; }
}
@media (prefers-reduced-motion: reduce) { .update-chip.is-new .pip { animation: none; } }

.update-card {
  border: 1px solid var(--line); border-radius: var(--radius-md);
  background: var(--panel); padding: 15px 19px; margin-bottom: 22px;
  font-size: 13.5px; line-height: 1.6;
}
.update-card.is-new { border-color: #7c5cff59; background: var(--accent-soft); }
/* Inside the popup the card IS the popup — it brings its own frame. */
.update-card.plain { border: 0; background: none; padding: 0; margin: 0; }
.update-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.update-head h3 { margin: 0; font-size: 14.5px; font-weight: 600; letter-spacing: -.01em; }
.update-head .spacer { margin-left: auto; }
.update-tag {
  font-size: 10.5px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase;
  padding: 3px 8px; border-radius: 999px; white-space: nowrap;
  background: var(--accent-soft); color: var(--accent-dark); border: 1px solid #7c5cff40;
}
.update-tag.fix { background: var(--good-soft); color: var(--good-dark); border-color: #22c55e40; }
.update-tag.maintenance { background: var(--track); color: var(--muted); border-color: var(--line-strong); }
.update-why { color: var(--muted); margin: 8px 0 0; }
.update-card ul { margin: 10px 0 0; padding-left: 20px; color: var(--muted); }
.update-card li { margin-bottom: 5px; }
.update-card li:last-child { margin-bottom: 0; }
.update-actions { display: flex; gap: 8px; align-items: center; margin-top: 12px; flex-wrap: wrap; }
.update-when { color: var(--muted-2); font-size: 12px; }
.update-older { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--line); }
.update-older > summary {
  cursor: pointer; color: var(--muted); font-size: 12.5px; list-style: none;
}
.update-older > summary::-webkit-details-marker { display: none; }
.update-older > summary::before { content: '▸ '; color: var(--muted-2); }
.update-older[open] > summary::before { content: '▾ '; }
.update-older h4 { margin: 12px 0 0; font-size: 13px; font-weight: 600; }

/* ─── Charts ─────────────────────────────────────────────────────────────
   Everything is inline SVG built by the pages themselves — no chart library,
   nothing loaded off a CDN (the CSP forbids it). These classes are the shared
   frame those SVGs are drawn into. */

.chart { width: 100%; display: block; overflow: visible; }
/* A donut has no reason to grow with the card — past a point it is just a
   bigger ring, and its centre label scales with it. */
.chart.donut-chart { max-width: 340px; margin: 0 auto; }
.chart-grid { stroke: var(--track-line); stroke-width: 1; stroke-dasharray: 4 6; }
.chart-axis { fill: var(--muted-2); font-size: 11px; font-weight: 600; font-family: var(--font); }
.chart-label { fill: var(--muted); font-size: 11px; font-family: var(--font); }

/* Rounded-cap bars. `stroke-linecap: round` on a zero-length line is what
   gives the reference's lozenge shape at both ends of every bar. */
.bar-track { stroke: var(--track); stroke-linecap: round; }
.bar-value { stroke-linecap: round; }

/* Value flags floating off a donut (the white "32%" pills). */
.donut-flag {
  fill: var(--invert-bg); }
.donut-flag-text { fill: var(--invert-fg); font-size: 11.5px; font-weight: 700; font-family: var(--font); }
.donut-center { fill: var(--text); font-weight: 650; letter-spacing: -.03em; font-family: var(--font); }

/* Legend under a chart. */
.legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 14px; }
.legend-item { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; color: var(--muted); font-weight: 500; }
.legend-swatch { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; }

/* Segmented proportion bar — the green / violet / orange strip. */
.split-bar { display: flex; gap: 6px; align-items: stretch; height: 34px; }
.split-bar div {
  border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; color: #0b0b0f; min-width: 42px;
}

/* Thin progress rail used at the foot of the small summary cards. */
.meter { height: 5px; border-radius: var(--radius-full); background: var(--track); overflow: hidden; }
.meter i { display: block; height: 100%; border-radius: var(--radius-full); }

/* A row inside a card: icon puck, label + value, then a delta on the right. */
.metric-row {
  display: flex; align-items: center; gap: 12px;
  padding: 13px 0; border-top: 1px solid var(--line);
}
.metric-row:first-child { border-top: 0; }
.metric-puck {
  width: 34px; height: 34px; border-radius: var(--radius-full); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center; color: var(--muted);
  background: var(--panel-2); border: 1px solid var(--line);
}
.metric-puck svg { width: 16px; height: 16px; }
.metric-row .metric-body { flex: 1; min-width: 0; }
.metric-row .metric-label { font-size: 11.5px; color: var(--muted-2); font-weight: 600; }
.metric-row .metric-value { font-size: 18px; font-weight: 650; letter-spacing: -.025em; font-variant-numeric: tabular-nums; }

/* Month / range selector strip along the bottom of a chart card. */
.range-strip { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 14px; }
.range-strip button {
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--line);
  border-radius: var(--radius-full); padding: 6px 14px; font-size: 12px; font-weight: 600;
  box-shadow: none;
}
.range-strip button:hover { background: var(--panel-3); color: var(--text); filter: none; }
.range-strip button[aria-selected="true"] {
  background: var(--invert-bg); color: var(--invert-fg); border-color: var(--invert-bg); box-shadow: none;
}

/* Dashboard grid — the reference's 2/3 + 1/3 then 1/3 × 3 arrangement. */
.grid { display: grid; gap: 14px; margin-bottom: 14px; }
/* A grid item defaults to `min-width: auto`, so a wide child (an SVG chart, a
   long legend) pushes its own column past the track and the whole page scrolls
   sideways. Every card here is allowed to shrink instead. */
.grid > * { min-width: 0; }
.grid.two-one { grid-template-columns: 2fr 1fr; }
.grid.thirds { grid-template-columns: repeat(3, 1fr); }
.grid.halves { grid-template-columns: 1fr 1fr; }
@media (max-width: 1100px) {
  .grid.two-one, .grid.thirds, .grid.halves { grid-template-columns: 1fr; }
}

/* ─── Tables ─────────────────────────────────────────────────────────────── */

.table-card { background: var(--panel); border: 1px solid var(--line); border-radius: var(--radius-lg); overflow-x: auto; box-shadow: var(--shadow-xs); }
table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th {
  text-align: left; font-weight: 650; color: var(--muted-2); font-size: 10.5px;
  text-transform: uppercase; letter-spacing: .07em; padding: 13px 18px;
  border-bottom: 1px solid var(--line); background: var(--panel-2);
  white-space: nowrap;
}
td { padding: 14px 18px; border-bottom: 1px solid var(--line); vertical-align: top; }
tbody tr { transition: background .1s var(--ease); }
tbody tr:hover { background: var(--panel-2); }
tr:last-child td { border-bottom: 0; }

.empty { padding: 56px 16px; text-align: center; color: var(--muted-2); font-size: 13.5px; }

/* ─── Tags / badges ──────────────────────────────────────────────────────── */

.tag {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 650;
  padding: 3px 9px; border-radius: var(--radius-full); white-space: nowrap;
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--line);
}
.tag.ok { color: var(--good-dark); background: var(--good-soft); border-color: #22c55e40; }
.tag.warn { color: var(--warn); background: var(--warn-soft); border-color: #f9731640; }
.tag.bad, .tag.hot { color: var(--bad); background: var(--bad-soft); border-color: #f8717140; }

.pill {
  display: inline-block; font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: var(--radius-full);
  border: 1px solid var(--line-strong); color: var(--muted); margin: 0 6px 6px 0; background: var(--panel-2);
}
.pill.tag-active { color: var(--accent-dark); border-color: #7c5cff50; background: var(--accent-soft); }

/* ─── Forms ──────────────────────────────────────────────────────────────── */

label { display: block; font-size: 12.5px; color: var(--text); margin-bottom: 6px; font-weight: 600; }
input, textarea, select {
  width: 100%; padding: 10px 13px; border-radius: var(--radius-sm); font: inherit; font-size: 13.5px;
  background: var(--panel-2); border: 1px solid var(--line-strong); color: var(--text);
  transition: border-color .12s var(--ease), box-shadow .12s var(--ease);
}
input::placeholder, textarea::placeholder { color: var(--muted-2); }
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
input:disabled { background: var(--panel); color: var(--muted-2); }
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }

.row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-bottom: 16px; }
@media (max-width: 640px) { .row { grid-template-columns: 1fr; } }

/* ─── Segmented tab nav (e.g. Bookings / Contact / Leads) ───────────────── */

nav.tabs { display: flex; gap: 6px; margin-bottom: 18px; flex-wrap: wrap; }
nav.tabs button {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-full);
  box-shadow: none; color: var(--muted); font-weight: 600;
  padding: 9px 18px; font-size: 13px;
}
nav.tabs button:hover { background: var(--panel-3); color: var(--text); filter: none; }
nav.tabs button[aria-selected="true"] { background: var(--invert-bg); color: var(--invert-fg); border-color: var(--invert-bg); }

/* ─── Call transcript / chat-bubble log (monitor.html + demo.html) ──────── */

.transcript {
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-lg);
  padding: 16px 18px; overflow-y: auto; display: flex; flex-direction: column; gap: 10px;
}
.turn { font-size: 13.5px; padding: 9px 13px; border-radius: 13px; max-width: 84%; line-height: 1.45; }
.turn .role { display: block; font-size: 10px; color: var(--muted-2); text-transform: uppercase; letter-spacing: .06em; margin-bottom: 3px; font-weight: 650; }
.turn.sys { align-self: center; font-size: 11.5px; color: var(--muted-2); font-style: italic; background: none; text-align: center; }

/* ─── Misc shared bits ───────────────────────────────────────────────────── */

.tooltip {
  position: fixed; pointer-events: none; background: var(--invert-bg); color: var(--invert-fg);
  font-size: 12px; padding: 7px 10px; border-radius: 7px; z-index: 30; opacity: 0;
  transition: opacity .1s var(--ease); white-space: nowrap; box-shadow: var(--shadow-md);
  font-weight: 600;
}
.tooltip b { font-variant-numeric: tabular-nums; }
.tooltip.show { opacity: 1; }

details summary { cursor: pointer; color: var(--muted); font-size: 12.5px; }
details pre {
  white-space: pre-wrap; font-size: 12px; color: var(--muted); font-family: var(--font-mono);
  margin: 8px 0 0; max-height: 260px; overflow: auto; background: var(--panel-2);
  border-radius: var(--radius-sm); padding: 10px 12px;
}

/* ─── Reviews ────────────────────────────────────────────────────────────
   Shared by /reviews.html (agency admin) and the Reviews page of
   /portal.html (a business owner's own account) — both render through
   /reviews-ui.js, so these class names are that file's contract. */

.stars { color: #fbbf24; letter-spacing: 1px; font-size: 15px; }
.stars.dim { color: var(--line-strong); }

.review-list { display: flex; flex-direction: column; gap: 14px; }
.review-card { padding: 20px 22px; }

/* A bad review is meant to be impossible to scroll past: it is pinned to the
   top of the list by the server, and marked in red here. */
.review-card.flagged { border-left: 3px solid var(--bad); background: linear-gradient(90deg, var(--bad-soft), transparent 40%); }

.review-top { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; margin-bottom: 8px; }
.review-top .who { flex: 1; min-width: 180px; }
.review-top .who b { display: block; font-size: 14.5px; }
.review-top .who .meta { margin-top: 2px; }
.review-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.review-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }
.review-comment { font-size: 13.5px; line-height: 1.6; margin: 10px 0 14px; white-space: pre-wrap; }
.review-comment.empty-comment { color: var(--muted-2); font-style: italic; }

.panel { background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--radius-md); padding: 14px 16px; margin-top: 10px; }
.panel-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.panel-head h3 { font-size: 12.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 700; margin: 0; }
.panel textarea { min-height: 88px; resize: vertical; margin-bottom: 10px; }
.panel-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

.candidate-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.candidate, .rv-candidate {
  display: flex; align-items: center; gap: 10px; padding: 9px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong); background: var(--panel); font-size: 13px;
}
.candidate { cursor: pointer; }
.candidate.selected { border-color: var(--accent); background: var(--accent-soft); }
.candidate .meta { margin-left: auto; }
.rv-candidate .rv-send-actions { margin-left: auto; display: flex; gap: 6px; }
.rv-candidate .rv-send-actions button { padding: 5px 11px; font-size: 12.5px; }

.sent-note { font-size: 13px; color: var(--good-dark); background: var(--good-soft); border: 1px solid #22c55e40; border-radius: var(--radius-sm); padding: 10px 12px; }
.err-note { font-size: 13px; color: var(--bad); }
.rv-sent { color: var(--good-dark); font-weight: 600; }

.toolbar { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }

/* Rating filter. Each chip carries its own count, so "are there any 1-stars"
   is answered without clicking anything, and an empty bucket is disabled
   rather than leading to a blank list. */
.rv-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.rv-chip {
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--line-strong);
  box-shadow: none; padding: 7px 12px; font-size: 12.5px; font-weight: 600;
  display: inline-flex; align-items: center; gap: 6px; border-radius: var(--radius-full);
}
.rv-chip:hover:not(:disabled) { background: var(--panel-3); color: var(--text); filter: none; }
.rv-chip .n {
  font-variant-numeric: tabular-nums; font-size: 11px; padding: 1px 6px;
  border-radius: var(--radius-full); background: var(--panel); color: var(--muted);
}
.rv-chip.active { background: var(--invert-bg); color: var(--invert-fg); border-color: var(--invert-bg); }
.rv-chip.active .n { background: color-mix(in srgb, var(--invert-fg) 12%, transparent); color: var(--invert-fg); }
.rv-chip.bad { color: var(--bad); border-color: #f8717150; }
.rv-chip.bad .n { background: var(--bad-soft); color: var(--bad); }
.rv-chip.bad.active { background: var(--bad); color: #fff; border-color: var(--bad); }
.rv-chip.bad.active .n { background: rgba(255, 255, 255, .22); color: #fff; }
.rv-chip:disabled { opacity: .4; cursor: default; }

/* Why a control next to this line is greyed out, and what to use instead. */
.rv-unavailable {
  margin-top: 10px; font-size: 12.5px; color: var(--muted);
  background: var(--panel-2); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: 9px 12px; line-height: 1.5;
}

.rv-connect, .rv-ask { margin-bottom: 18px; }
.rv-connect h3, .rv-ask h3 { font-size: 15px; margin: 0 0 4px; }
.rv-coverage { margin-top: 10px; font-size: 12.5px; color: var(--warn); background: var(--warn-soft); border-radius: var(--radius-sm); padding: 9px 12px; line-height: 1.55; }
.rv-coverage.ok { color: var(--good-dark); background: var(--good-soft); }
.stat.rv-alert b { color: var(--bad); }

/* ─── Sub-navigation: sections within one page ───────────────────────────
   System Monitor and Analytics are each several screens' worth of material,
   split into addressable sections. Every section is a real URL (#/backups),
   so a bookmark, the back button, a link in an alert email and the sidebar
   all land on the section they name. */

.subnav {
  display: flex; align-items: center; gap: 6px;
  padding: 10px 30px;
  background: var(--bg-shell); border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none;
  position: sticky; top: 0; z-index: 20;
}
.subnav::-webkit-scrollbar { display: none; }
.subnav a[href] {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
  padding: 9px 15px; border-radius: var(--radius-full);
  font-size: 13px; font-weight: 600; color: var(--muted); text-decoration: none;
  transition: background .12s var(--ease), color .12s var(--ease);
}
.subnav a[href]:hover { background: var(--panel-2); color: var(--text); }
.subnav a[href].active { background: var(--invert-bg); color: var(--invert-fg); }

/* A number on a tab. Hidden at zero rather than shown as "0" — the whole
   point of these is that a visible one means go and look. */
.subnav-count {
  font-size: 11px; font-weight: 700; line-height: 1; padding: 3px 7px;
  border-radius: var(--radius-full); background: var(--panel-3); color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.subnav-count.bad { background: var(--bad-soft); color: var(--bad); }
.subnav-count.warn { background: var(--warn-soft); color: var(--warn); }
.subnav a[href].active .subnav-count { background: color-mix(in srgb, var(--invert-fg) 12%, transparent); color: var(--invert-fg); }
/* `hidden` is a no-op against any author `display` on the same selector. */
.subnav-count[hidden] { display: none; }

/* One section of such a page. Deliberately given no `display` of its own, so
   the plain `hidden` attribute the router sets is what decides. */
.page[hidden] { display: none; }

/* Anything too wide for a phone (a table, a chart) scrolls inside its own box
   instead of pushing the whole page sideways. */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* A stat tile that is also a link to the section explaining the number. */
a.stat { display: block; color: inherit; text-decoration: none; }

/* ─── Phone navigation ──────────────────────────────────────────────────────
   The agency pages navigate from the icon rail; the business portal navigates
   from its row of pills. Both work by being wide, and a phone is not. Below
   880px the rail becomes a "Menu" bar plus a drawer (mobile-nav.js), and the
   pills become a grid where every section is visible at once.

   The rule behind both: on a phone, nothing you need may be reachable only by
   discovering that a strip scrolls sideways. */

.m-bar { display: none; }

/* Only once mobile-nav.js has actually built the drawer — otherwise a blocked
   script would leave the page with no navigation whatsoever. */
html.has-mnav .m-bar {
  display: none;
  position: sticky; top: 0; z-index: 30;
  align-items: center; gap: 12px;
  padding: 9px 14px;
  background: var(--bg-shell); border-bottom: 1px solid var(--line);
}
.m-menu-btn {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 8px 15px 8px 12px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--radius-full);
  font-size: 14px; font-weight: 650; box-shadow: none;
}
.m-menu-btn:hover { background: var(--panel-3); filter: none; }
.m-menu-btn svg { width: 19px; height: 19px; }
.m-bar-title {
  font-size: 14.5px; font-weight: 650; letter-spacing: -.01em; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

.m-scrim {
  position: fixed; inset: 0; z-index: 998;
  background: var(--overlay); backdrop-filter: blur(2px);
  opacity: 0; pointer-events: none; transition: opacity .18s var(--ease);
}
body.m-nav-open .m-scrim { opacity: 1; pointer-events: auto; }

.m-drawer {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 999;
  width: min(320px, 86vw); box-sizing: border-box;
  display: flex; flex-direction: column;
  background: var(--bg-shell); border-right: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
  /* Closed state is `visibility: hidden` rather than `display: none` so the
     panel can slide; the zero-length visibility transition is delayed to the
     end of the slide out, and runs immediately on the way in. */
  visibility: hidden; transform: translateX(-100%);
  transition: transform .22s var(--ease), visibility 0s linear .22s;
}
body.m-nav-open .m-drawer {
  visibility: visible; transform: none;
  transition: transform .22s var(--ease), visibility 0s;
}
/* The page behind must not scroll under an open drawer. */
body.m-nav-open { overflow: hidden; }

.m-drawer-head {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 14px 14px; border-bottom: 1px solid var(--line);
}
.m-drawer-brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
.m-drawer-brand .mark {
  width: 38px; height: 38px; border-radius: 12px; flex-shrink: 0;
  background: linear-gradient(150deg, var(--accent), #4f2fd6);
  display: flex; align-items: center; justify-content: center; color: #fff;
}
.m-drawer-brand .mark svg { width: 19px; height: 19px; }
/* The rail hides its own wordmark to stay narrow; in the drawer there's room. */
.m-drawer-brand div { display: block; min-width: 0; }
.m-drawer-brand b { font-size: 14.5px; font-weight: 700; display: block; line-height: 1.2; }
.m-drawer-brand span { font-size: 11.5px; color: var(--muted-2); text-transform: uppercase; letter-spacing: .06em; }
.m-drawer-close {
  margin-left: auto; flex-shrink: 0;
  width: 44px; height: 44px; padding: 0; border-radius: var(--radius-full);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--line); box-shadow: none;
}
.m-drawer-close:hover { background: var(--panel-3); color: var(--text); filter: none; }
.m-drawer-close svg { width: 18px; height: 18px; }

.m-drawer-nav { padding: 10px 10px 26px; display: flex; flex-direction: column; gap: 3px; }
.m-group {
  font-size: 11.5px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted-2); padding: 16px 12px 7px;
}
.m-group:first-child { padding-top: 6px; }
.m-drawer-nav a.m-item,
.m-drawer-nav a.m-item:link,
.m-drawer-nav a.m-item:visited {
  display: flex; align-items: center; gap: 13px;
  min-height: 52px; padding: 12px 14px; border-radius: var(--radius-md);
  font-size: 15px; font-weight: 600; letter-spacing: -.01em;
  color: var(--text); text-decoration: none; text-align: left;
}
.m-item svg { width: 20px; height: 20px; flex-shrink: 0; opacity: .75; }
.m-item:hover { background: var(--panel-2); }
.m-drawer-nav a.m-item.is-current,
.m-drawer-nav a.m-item.is-current:link,
.m-drawer-nav a.m-item.is-current:visited {
  background: linear-gradient(150deg, var(--accent), #5b39e8); color: #fff;
  box-shadow: 0 8px 20px -10px rgba(124, 92, 255, .95);
}
.m-item.is-current svg { opacity: 1; }
.m-drawer-nav a.m-item.is-cta,
.m-drawer-nav a.m-item.is-cta:link,
.m-drawer-nav a.m-item.is-cta:visited {
  margin-top: 10px; background: var(--panel-2); border: 1px solid var(--line-strong);
}

/* ─── Responsive ────────────────────────────────────────────────────────── */

@media (max-width: 880px) {
  .app-shell { flex-direction: column; }
  .sidebar {
    width: 100%; height: auto; position: static; border-right: 0; border-bottom: 1px solid var(--line);
    flex-direction: row; align-items: center; padding-right: 8px;
  }
  .sidebar-brand { padding: 12px 14px; }
  .sidebar-nav { flex-direction: row; overflow-x: auto; padding: 8px 6px; flex: 1; scrollbar-width: none; }
  .sidebar-nav::-webkit-scrollbar { display: none; }
  .sidebar-nav a { flex-direction: row; gap: 8px; font-size: 12.5px; padding: 10px 13px; white-space: nowrap; }
  .sidebar-nav a.cta { margin-top: 0; }
  .sidebar-foot { display: none; }
  .topbar, main.content, .content, .subnav { padding-left: 18px; padding-right: 18px; }

  /* The drawer takes over from the rail. */
  html.has-mnav .sidebar { display: none; }
  html.has-mnav .m-bar { display: flex; }
  /* The section tabs of a multi-screen page (Analytics, System) stick below
     the menu bar rather than under it. */
  html.has-mnav .subnav { top: 53px; }

  .portal-shell { padding: 12px 14px 60px; }
  .portal-topbar { flex-wrap: wrap; border-radius: var(--radius-lg); }
  /* Every portal section visible at once, as a grid of full-width buttons —
     the horizontally scrolling strip this replaces cut off Reviews, Insights
     and Settings with nothing on screen to say they were there. */
  .pill-nav {
    order: 3; width: 100%; margin: 2px 0 0;
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
    overflow: visible; flex-wrap: wrap;
  }
  .pill-nav button {
    width: 100%; min-height: 46px; padding: 10px 8px;
    justify-content: center; white-space: nowrap; font-size: 13.5px;
  }
  .page-head h1 { font-size: 26px; }

  /* ── Touch sizing ──────────────────────────────────────────────────────────
     Everything from here down is about fingers rather than layout, so it
     starts at the same width the rail gives way at — a tablet is touched
     exactly like a phone is, and a 26px month button is as easy to miss on
     one as on the other. The layout changes stay in the phone block below.

     44px is the size below which a fingertip starts landing on the wrong
     control, and every one of these can cancel an appointment or delete a
     company. */
  button, .btn, a.ghost, a.navbtn, input[type="submit"] {
    padding: 11px 16px; min-height: 44px;
  }
  .icon-btn { width: 44px; height: 44px; }
  .icon-btn svg { width: 19px; height: 19px; }
  nav.tabs button { min-height: 44px; padding: 10px 18px; font-size: 13.5px; }
  .range-strip { gap: 7px; }
  .range-strip button { min-height: 42px; padding: 9px 16px; font-size: 13px; }
  .subnav { gap: 7px; }
  .subnav a[href] { min-height: 42px; padding: 10px 15px; }
  /* Filter chips that are really buttons (Reports, Reviews). */
  button.pill { min-height: 40px; padding: 9px 16px; font-size: 12.5px; }
  /* Row actions inside a table that is still a table at this width — below
     620px these become pill buttons instead (see `table.stack`), but on a
     tablet they stay inline and just need height under the finger. */
  td a { display: inline-block; padding: 8px 0; }
  /* Links that are standalone controls rather than words inside a sentence —
     "← Dashboard", "Call the receptionist →", "Add a company", and the
     "Connect" that is the only action on an integration row. Named one by one
     on purpose: a blanket rule would also pad out links sitting mid paragraph,
     where the extra height collides with the lines above and below. */
  a.navbtn, a.sub, .topstrip > a, .console-topbar > a, .sheets-line a, .tenant .meta a,
  #banner a, .banner a, #dashLink, #testLink, #onboardLink {
    display: inline-block; padding: 8px 0; min-height: 40px; line-height: 24px;
  }

  /* Under 16px, iOS Safari zooms the whole page in when a field is focused and
     never zooms back out — which is what makes a form feel broken on a phone
     even when the layout is fine. The search box sets its own smaller size, so
     it needs saying twice. */
  input, textarea, select, .search-pill input { font-size: 16px; }
}

/* A table with more columns than a phone is wide stops being a table and
   becomes one labelled card per row. Opt-in via `table.stack`, so the wide
   diagnostic tables elsewhere keep their existing sideways scroll — this
   treatment is for the tables someone actually works through: the bookings,
   messages and leads lists on the dashboard and in the portal.

   The alternative was leaving them scrolling sideways, where a phone shows
   two of ten columns and the Cancel link is somewhere off to the right. */
@media (max-width: 620px) {
  table.stack, table.stack tbody, table.stack tr, table.stack td { display: block; width: 100%; }
  table.stack thead { display: none; }
  table.stack { font-size: 14px; }
  /* Alternating fills, because ten stacked fields is tall enough that the line
     between one customer and the next has to be unmissable. */
  table.stack tr { padding: 6px 0 10px; border-bottom: 1px solid var(--line-strong); }
  table.stack tr:nth-child(even) { background: var(--panel-2); }
  table.stack tr:last-child { border-bottom: 0; }
  table.stack tr.busy { opacity: .6; }
  table.stack td { padding: 7px 15px 8px; border: 0; }
  /* The column heading travels with the value, since the header row is gone.
     Deliberately a block above the value rather than a column beside it: these
     cells hold several elements each (a name and a phone split by <br>, three
     action links separated by dots), and any two-column layout puts each of
     those pieces on a line of its own. */
  table.stack td[data-label]::before {
    content: attr(data-label); display: block; margin-bottom: 2px;
    font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--muted-2); line-height: 1.5;
  }
  /* Row links (Reschedule / Cancel / Delete) become real buttons — on a phone
     they are the only way to act on a booking, and an 18px-tall underlined
     word in a list of them is a coin flip to hit. */
  table.stack td[data-label="Actions"] a {
    display: inline-flex; align-items: center; min-height: 40px;
    padding: 0 15px; margin: 4px 6px 2px 0;
    border: 1px solid var(--line-strong); border-radius: var(--radius-full);
    background: var(--panel-2); text-decoration: none; font-weight: 600; font-size: 13px;
  }
  table.stack .mono { font-size: 13px; }
  /* The row-select box, which is the one cell with no heading to inherit. */
  table.stack .rowsel { display: inline-flex; align-items: center; gap: 10px; min-height: 40px; }
  table.stack .rowsel span {
    display: inline; font-size: 11px; font-weight: 700; letter-spacing: .06em;
    text-transform: uppercase; color: var(--muted-2);
  }
  table.stack .called { display: inline-flex; align-items: center; min-height: 34px; }
}

/* Phones. Everything here is about the three things that actually break on a
   360px screen: horizontal overflow, controls too small to hit, and type too
   small to read. */
@media (max-width: 560px) {
  .topbar { padding: 14px 16px; gap: 10px; }
  .topbar h1 { font-size: 17px; }
  /* The actions wrap onto their own full-width row and share it, rather than
     being squeezed against the title. */
  .topbar-actions { margin-left: 0; width: 100%; }
  .topbar-actions > button, .topbar-actions > .btn { flex: 1; }
  .topbar, main.content, .content, .subnav { padding-left: 14px; padding-right: 14px; }
  main.content, .content { padding-top: 20px; padding-bottom: 56px; }

  .card { padding: 18px 16px; }
  .card-head { margin-bottom: 14px; }
  .card-head h2, .card-head h3 { font-size: 15.5px; }
  .stats { gap: 10px; margin-bottom: 20px; }
  .stat { padding: 14px 15px; }
  .stat b { font-size: 23px; }
  .stat.dim b { font-size: 18px; }
  th, td { padding: 11px 12px; }
  h1 { font-size: 18px; }
  .page-head h1 { font-size: 23px; }
  .empty { padding: 36px 12px; }

  /* Nothing on a phone should be smaller than this to read. The desktop sizes
     are fine at desktop viewing distance; 10.5px on a handset is not.
     Counters inside a badge or a dot are left alone — those are sized by the
     circle around them, and the number is not the thing being read. */
  .eyebrow, .sub, .stat span, .tag, .pill, .kpi-label, .kpi-sub, .metric-label,
  .mini-label, .subnav-count, .notif-item .when, .list-panel-head, .sidebar-section-label,
  .metric-row .metric-label, .mini-card .mini-label, .portal-topbar .who span {
    font-size: 12px;
  }

  .search-pill { min-width: 0; max-width: none; }

  /* A dialog on a phone is the screen, not a card floating on one. Anything
     taller than the viewport scrolls inside itself so the buttons at the
     bottom stay reachable. */
  .modal-overlay, .gate-overlay { padding: 10px; align-items: flex-start; }
  .modal-card, .modal, .gate {
    width: 100%; max-width: none; max-height: calc(100dvh - 20px);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
  }
  .modal-actions { flex-direction: column-reverse; align-items: stretch; gap: 8px; }
  .modal-actions > button, .modal-actions > .btn { width: 100%; }

  /* Toolbars above a table: full-width buttons stacked, rather than four
     half-legible ones crushed onto one line. */
  .table-toolbar { flex-wrap: wrap; gap: 8px; }
  .table-toolbar > button { flex: 1 1 auto; }
  .table-toolbar .spacer { display: none; }

  .page-head { gap: 10px; }
  .page-head .page-head-actions { margin-left: 0; width: 100%; }
  .page-head .page-head-actions > button { flex: 1; }
}
