/* =============================================================================
   Guest CRM — design system
   -----------------------------------------------------------------------------
   Hand-written CSS, served statically at /static/app.css. No build step, no
   preprocessor, no utility framework: this file IS the system, and every screen
   is expected to compose it rather than improvise inline styles.

   Order:
     1. Tokens         — colour, type, space, radius, shadow (light + dark)
     2. Reset & base   — element defaults
     3. Layout         — page shell, header, nav, grids
     4. Components     — card, stat, table, pill, chip, banner, form, button,
                         empty state, key/value list, meter, message bubble
     5. Utilities      — a deliberately SMALL set; if you need a sixth variant,
                         the component is wrong, not the utility set
     6. Responsive     — everything below reads down to 360px

   Rules of the road:
     - No inline `style=` in templates. If a screen needs something this file
       does not have, add it here with a name that says what it MEANS.
     - Status colour is never decoration. `.pill.no` / `.banner.bad` exist so a
       broken sync cannot look like a healthy one; do not reuse them for accent.
   ========================================================================== */

/* ── 1. Tokens ─────────────────────────────────────────────────────────── */

:root {
  /* Surfaces — layered, low contrast between them, so cards read as paper. */
  --bg:            #f7f8fa;
  --bg-sunken:     #eef1f5;
  --surface:       #ffffff;
  --surface-alt:   #f8fafc;
  --surface-hover: #f1f5f9;

  /* Ink */
  --ink:        #16202e;
  --ink-soft:   #47566b;
  --ink-muted:  #6b7a90;
  --ink-invert: #ffffff;

  /* Lines */
  --line:        #e4e8ee;
  --line-strong: #cfd6e0;

  /* Accent — one hue, three weights. Restraint is the point. */
  --accent:        #0f7a8a;
  --accent-hover:  #0b6371;
  --accent-soft:   #e6f4f6;
  --accent-line:   #b8dfe5;
  --accent-ink:    #0a4c57;

  /* Status. Each has a surface, a border and an ink so a state can be shown
     as a pill, a banner or a table row from the same three values. */
  --ok-bg:    #e8f7ef;  --ok-line:    #a7e3c2;  --ok-ink:    #0d6b40;
  --warn-bg:  #fff6e5;  --warn-line:  #f5d08a;  --warn-ink:  #7c4a06;
  --bad-bg:   #fdedee;  --bad-line:   #f3b3b8;  --bad-ink:   #8f1d24;
  --info-bg:  #eef2ff;  --info-line:  #c3cdfa;  --info-ink:  #3a3f96;
  --neutral-bg: #f1f4f8; --neutral-line: #e0e5ec; --neutral-ink: #55637a;

  --star: #e0921a;

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

  --fs-2xs:  0.6875rem;  /* 11px — dense metadata only */
  --fs-xs:   0.75rem;    /* 12px */
  --fs-sm:   0.8125rem;  /* 13px */
  --fs-base: 0.9375rem;  /* 15px */
  --fs-md:   1rem;
  --fs-lg:   1.125rem;
  --fs-xl:   1.375rem;
  --fs-2xl:  1.75rem;
  --fs-3xl:  2.25rem;

  --lh-tight: 1.25;
  --lh:       1.55;

  /* Space — a 4px rhythm. Every gap, pad and margin comes from here. */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-5:  20px;
  --s-6:  24px;
  --s-7:  32px;
  --s-8:  40px;
  --s-9:  56px;

  --r-sm: 6px;
  --r:    10px;
  --r-lg: 14px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(16, 26, 40, .05);
  --shadow:    0 1px 3px rgba(16, 26, 40, .07), 0 6px 16px -8px rgba(16, 26, 40, .12);
  --shadow-lg: 0 12px 32px -10px rgba(16, 26, 40, .28);

  --header-bg:   #101a28;
  --header-ink:  #c9d3e0;
  --header-line: #24334a;

  --page-max: 1160px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:            #0d1219;
    --bg-sunken:     #090d13;
    --surface:       #141b25;
    --surface-alt:   #19212d;
    --surface-hover: #1d2733;

    --ink:        #e7edf5;
    --ink-soft:   #b3c0d1;
    --ink-muted:  #8695a9;

    --line:        #232e3c;
    --line-strong: #33415a;

    --accent:       #45b3c4;
    --accent-hover: #63c6d5;
    --accent-soft:  #12303a;
    --accent-line:  #1d4c5a;
    --accent-ink:   #a6dfe9;

    --ok-bg:    #10291d;  --ok-line:    #1d5238;  --ok-ink:    #7fdcab;
    --warn-bg:  #2b2110;  --warn-line:  #5a441a;  --warn-ink:  #f0c274;
    --bad-bg:   #2c1417;  --bad-line:   #5d2429;  --bad-ink:   #f4a3aa;
    --info-bg:  #171b34;  --info-line:  #2c3466;  --info-ink:  #b3bcf5;
    --neutral-bg: #1a222e; --neutral-line: #26313f; --neutral-ink: #94a2b6;

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow:    0 1px 3px rgba(0, 0, 0, .45), 0 8px 20px -10px rgba(0, 0, 0, .6);
    --shadow-lg: 0 14px 36px -12px rgba(0, 0, 0, .7);

    --header-bg:   #0a0f16;
    --header-line: #1d2836;
  }
}

/* ── 2. Reset & base ───────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font);
  font-size: var(--fs-base);
  line-height: var(--lh);
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { line-height: var(--lh-tight); font-weight: 650; margin: 0; }
h1 { font-size: var(--fs-xl);  letter-spacing: -.015em; }
h2 { font-size: var(--fs-md);  letter-spacing: -.005em; }
h3 { font-size: var(--fs-base); }

p { margin: 0 0 var(--s-3); }
p:last-child { margin-bottom: 0; }

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible,
textarea:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

code {
  font-family: var(--font-mono);
  font-size: .9em;
  background: var(--neutral-bg);
  border: 1px solid var(--neutral-line);
  border-radius: var(--r-sm);
  padding: 1px 5px;
}

hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-5) 0; }

/* ── 3. Layout ─────────────────────────────────────────────────────────── */

.topbar {
  background: var(--header-bg);
  color: var(--header-ink);
  border-bottom: 1px solid var(--header-line);
  position: sticky;
  top: 0;
  z-index: 40;
}

.topbar-inner {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s-3) var(--s-5);
  display: flex;
  align-items: center;
  gap: var(--s-3);
}

.brand {
  color: #fff;
  font-weight: 680;
  font-size: var(--fs-md);
  letter-spacing: -.01em;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  white-space: nowrap;
}
.brand:hover { text-decoration: none; opacity: .85; }

.topbar .spacer { flex: 1 1 auto; }

.topbar-user {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--header-ink);
  min-width: 0;
}
.topbar-user .who {
  color: #8fa0b6;
  max-width: 28ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.topbar-user form { margin: 0; }
.topbar-user select {
  background: #1b2637;
  color: #d7e0ec;
  border: 1px solid var(--header-line);
  border-radius: var(--r-sm);
  padding: 5px 10px;
  font-size: var(--fs-sm);
  font-family: inherit;
}
.btn-topbar {
  background: transparent;
  border: 1px solid var(--header-line);
  color: var(--header-ink);
  padding: 5px 12px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-family: inherit;
  cursor: pointer;
}
.btn-topbar:hover { background: #1b2637; color: #fff; }

/* Nav: a tab strip under the identity row. Scrolls sideways on a phone rather
   than wrapping into a ragged block. */
.mainnav {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: 0 var(--s-5);
  display: flex;
  align-items: stretch;
  gap: var(--s-1);
  overflow-x: auto;
  scrollbar-width: none;
}
.mainnav::-webkit-scrollbar { display: none; }

.mainnav a {
  color: #98a8bd;
  font-size: var(--fs-sm);
  font-weight: 550;
  padding: var(--s-2) var(--s-3) var(--s-3);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
}
.mainnav a:hover { color: #fff; text-decoration: none; }
.mainnav a[aria-current="page"] { color: #fff; border-bottom-color: var(--accent); }

.mainnav .navgroup {
  align-self: center;
  width: 1px;
  height: 16px;
  background: var(--header-line);
  margin: 0 var(--s-2);
  flex: none;
}

.navbadge {
  background: #b3202b;
  color: #ffe1e3;
  border-radius: var(--r-pill);
  font-size: var(--fs-2xs);
  font-weight: 650;
  line-height: 1.5;
  padding: 0 6px;
  margin-left: 2px;
}

main {
  max-width: var(--page-max);
  margin: 0 auto;
  padding: var(--s-7) var(--s-5) var(--s-9);
}

/* Page header: title, optional one-line explanation, optional actions. */
.page-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
  margin-bottom: var(--s-5);
}
.page-head .titles { min-width: 0; }
.page-head h1 { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.page-head .actions { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

/* One sentence under a title saying what the screen answers. */
.lede {
  color: var(--ink-soft);
  font-size: var(--fs-sm);
  max-width: 78ch;
  margin: var(--s-2) 0 0;
}

.scope {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-muted);
}

/* Two-column split (detail screens). Collapses on tablet. */
.cols {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: var(--s-4);
  align-items: start;
}

.stack > * + * { margin-top: var(--s-4); }
.stack-sm > * + * { margin-top: var(--s-2); }

.split {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-4);
  flex-wrap: wrap;
}
.split > .grow { flex: 1 1 260px; min-width: 0; }
/* The narrower half of a .split — a counts table, a set of actions. */
.split > .side { flex: 0 1 300px; min-width: 0; }
.split > .side.actions-col { text-align: right; flex-basis: 200px; }
.split > .side.actions-col form + form { margin-top: var(--s-2); }

/* ── 4. Components ─────────────────────────────────────────────────────── */

/* Card ------------------------------------------------------------------ */
.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--s-5);
  margin-bottom: var(--s-4);
  box-shadow: var(--shadow-sm);
}
.card > :last-child { margin-bottom: 0; }
.card-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.card-head h2 { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.card h2 + p, .card-head + p { margin-top: 0; }
/* A card nested inside a card is a note, not a second surface. */
.card .card-note {
  background: var(--surface-alt);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-3) var(--s-4);
  margin: var(--s-3) 0 0;
}
.card-quiet { background: var(--surface-alt); box-shadow: none; }
.card-sticky { position: sticky; bottom: var(--s-3); z-index: 10; box-shadow: var(--shadow); }

/* Stat tiles ------------------------------------------------------------ */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.stat {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: var(--s-4);
  box-shadow: var(--shadow-sm);
}
.stat .n {
  font-size: var(--fs-2xl);
  font-weight: 660;
  letter-spacing: -.02em;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.stat .l {
  color: var(--ink-muted);
  font-size: var(--fs-sm);
  margin-top: var(--s-1);
}
.card .cards { margin-bottom: var(--s-4); }

/* Table ----------------------------------------------------------------- */
/* Wrap any wide table in .table-wrap so the PAGE never scrolls sideways. */
.table-wrap { overflow-x: auto; margin: 0 calc(var(--s-1) * -1); padding: 0 var(--s-1); }

table { width: 100%; border-collapse: collapse; }
th {
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--ink-muted);
  padding: var(--s-2) var(--s-3);
  border-bottom: 1px solid var(--line-strong);
  white-space: nowrap;
}
th a { color: inherit; }
td {
  padding: var(--s-3);
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover td { background: var(--surface-alt); }
.table-plain tbody tr:hover td { background: transparent; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }
td.tight, th.tight { width: 1%; }

.row-bad  td { background: var(--bad-bg) !important; }
.row-warn td { background: var(--warn-bg) !important; }

/* Pill — a STATE. Never decoration. ------------------------------------- */
.pill {
  display: inline-block;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.6;
  padding: 1px 9px;
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
.pill.ok   { background: var(--ok-bg);      color: var(--ok-ink);      border-color: var(--ok-line); }
.pill.no   { background: var(--bad-bg);     color: var(--bad-ink);     border-color: var(--bad-line); }
.pill.warn { background: var(--warn-bg);    color: var(--warn-ink);    border-color: var(--warn-line); }
.pill.info { background: var(--info-bg);    color: var(--info-ink);    border-color: var(--info-line); }
.pill.dim  { background: var(--neutral-bg); color: var(--neutral-ink); border-color: var(--neutral-line); }
/* A pill carrying a whole sentence (a status reason) may wrap. */
.pill.long { white-space: normal; text-align: left; }

/* Chip — a VALUE (a tag, a signal, a facet). ---------------------------- */
.chip {
  display: inline-block;
  background: var(--accent-soft);
  color: var(--accent-ink);
  border: 1px solid var(--accent-line);
  border-radius: var(--r-pill);
  padding: 2px 10px;
  font-size: var(--fs-sm);
  margin: 2px 4px 2px 0;
}
.chip.dim  { background: var(--neutral-bg); color: var(--neutral-ink); border-color: var(--neutral-line); }
.chip.good { background: var(--ok-bg);      color: var(--ok-ink);      border-color: var(--ok-line); }
.chip strong { font-variant-numeric: tabular-nums; }
.chips { display: flex; flex-wrap: wrap; gap: 2px; }

/* Banner — the loud one. A silent sync failure is this product's worst bug,
   so these are deliberately hard to miss. ------------------------------- */
.banner {
  border-radius: var(--r-lg);
  padding: var(--s-4) var(--s-5);
  margin-bottom: var(--s-4);
  border: 1px solid;
  font-size: var(--fs-base);
}
.banner h2 { font-size: var(--fs-base); margin-bottom: var(--s-2); }
.banner ul { margin: var(--s-2) 0 0; padding-left: var(--s-5); }
.banner li + li { margin-top: var(--s-1); }
.banner > :last-child { margin-bottom: 0; }
.banner.bad  { background: var(--bad-bg);  border-color: var(--bad-line);  color: var(--bad-ink); }
.banner.warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-ink); }
.banner.good { background: var(--ok-bg);   border-color: var(--ok-line);   color: var(--ok-ink); }
.banner.info { background: var(--info-bg); border-color: var(--info-line); color: var(--info-ink); }
.banner a { color: inherit; text-decoration: underline; }

/* Inline error/warning detail inside a row or card. */
.errbox {
  font-size: var(--fs-sm);
  line-height: 1.5;
  background: var(--bad-bg);
  border: 1px solid var(--bad-line);
  color: var(--bad-ink);
  border-radius: var(--r-sm);
  padding: var(--s-2) var(--s-3);
  margin-top: var(--s-2);
  overflow-wrap: anywhere;
}
.errbox.warn { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn-ink); }
.errbox.mono { font-family: var(--font-mono); font-size: var(--fs-xs); white-space: pre-wrap; }
.errbox > :last-child { margin-bottom: 0; }

/* Key/value list -------------------------------------------------------- */
.kv {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: var(--s-2) var(--s-4);
  font-size: var(--fs-sm);
  margin: 0;
}
.kv dt { color: var(--ink-muted); }
.kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }

/* Meter ----------------------------------------------------------------- */
.bar {
  height: 8px;
  border-radius: var(--r-pill);
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  overflow: hidden;
  min-width: 90px;
}
.bar > i { display: block; height: 100%; background: var(--accent); }

/* Buttons --------------------------------------------------------------- */
.btn, button.primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  font-family: inherit;
  font-size: var(--fs-base);
  font-weight: 550;
  line-height: 1.4;
  padding: 9px 18px;
  border-radius: var(--r);
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition: background .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--surface-hover); text-decoration: none; }

.btn-primary, button.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-primary:hover, button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); text-decoration: none; }

.btn-danger { color: var(--bad-ink); border-color: var(--bad-line); background: var(--bad-bg); }
.btn-danger:hover { background: var(--bad-bg); border-color: var(--bad-ink); }

.btn-sm { padding: 6px 12px; font-size: var(--fs-sm); }
.btn-block, button.primary.btn-block { width: 100%; }

/* Quiet text button — dismiss, retry, refresh. */
.xbtn {
  background: none;
  border: 0;
  color: var(--ink-muted);
  font-family: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--r-sm);
}
.xbtn:hover { color: var(--bad-ink); background: var(--bad-bg); }

/* Forms ----------------------------------------------------------------- */
input[type=text], input[type=search], input[type=email], input[type=password],
input[type=number], input[type=date], select, textarea {
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--ink);
  background: var(--surface);
  padding: 9px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  width: 100%;
  max-width: 100%;
}
select { padding-right: var(--s-7); }
textarea { line-height: var(--lh); resize: vertical; }
textarea.mono { font-family: var(--font-mono); font-size: var(--fs-sm); }
input::placeholder, textarea::placeholder { color: var(--ink-muted); }
input[type=search] { -webkit-appearance: none; }

.field { margin-bottom: var(--s-5); }
.field > label, .field-label {
  display: block;
  font-weight: 600;
  font-size: var(--fs-sm);
  margin-bottom: var(--s-1);
}
.field-hint {
  color: var(--ink-muted);
  font-size: var(--fs-xs);
  margin-top: var(--s-1);
  max-width: 70ch;
}
.field-w-md { max-width: 440px; }
.field-w-sm { max-width: 280px; }
.field-w-lg { max-width: 580px; }
.field-w-xs { max-width: 130px; }

/* A form laid out as a single horizontal line (search + submit, id + save). */
.form-row {
  display: flex;
  gap: var(--s-2);
  align-items: center;
  flex-wrap: wrap;
}
.form-row .grow { flex: 1 1 300px; min-width: 0; }
.form-inline { display: inline; margin: 0; }
form.bare { margin: 0; }

/* Toolbar: search inputs + facets, the row above a table. */
.searchbar {
  display: flex;
  gap: var(--s-2);
  flex-wrap: wrap;
  margin-bottom: var(--s-3);
}
.searchbar .grow    { flex: 2 1 200px; min-width: 0; }
.searchbar .grow-sm { flex: 1 1 160px; min-width: 0; }

.toolbar {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  justify-content: space-between;
}

/* Filter links / tabs --------------------------------------------------- */
.filters { display: flex; flex-wrap: wrap; gap: var(--s-1); align-items: center; }
.filters a {
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--ink-soft);
  padding: 5px 10px;
  border-radius: var(--r-pill);
  white-space: nowrap;
}
.filters a:hover { background: var(--surface-hover); text-decoration: none; }
.filters a.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 650;
  text-decoration: none;
}

/* Dropdown panel (the month picker) ------------------------------------- */
.dropdown { position: relative; }
.dropdown > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  padding: 9px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--r);
  background: var(--surface);
  font-size: var(--fs-base);
  white-space: nowrap;
}
.dropdown > summary::-webkit-details-marker { display: none; }
.dropdown[open] > summary, .dropdown > summary.active {
  border-color: var(--accent);
  color: var(--accent);
}
.dropdown-panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  box-shadow: var(--shadow-lg);
  padding: var(--s-4);
  min-width: 300px;
}
.dropdown-panel .divider {
  border-top: 1px solid var(--line);
  margin-top: var(--s-3);
  padding-top: var(--s-3);
}
.checkgrid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s-1); }
.checkline {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  font-size: var(--fs-sm);
  cursor: pointer;
  margin: 3px 10px 3px 0;
}

/* Disclosure ------------------------------------------------------------ */
details.evidence { margin-top: var(--s-1); }
details.evidence > summary {
  cursor: pointer;
  font-size: var(--fs-sm);
  color: var(--ink-muted);
  list-style-position: outside;
}
details.evidence > summary:hover { color: var(--ink); }

blockquote {
  margin: var(--s-2) 0;
  padding: var(--s-2) var(--s-3);
  background: var(--warn-bg);
  border-left: 3px solid var(--warn-line);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  font-size: var(--fs-sm);
  color: var(--ink);
}
blockquote.plain { background: var(--surface-alt); border-left-color: var(--line-strong); }

/* Message bubbles ------------------------------------------------------- */
.msg {
  padding: var(--s-3) var(--s-4);
  border-radius: var(--r);
  margin-bottom: var(--s-2);
  max-width: 85%;
  font-size: var(--fs-sm);
  overflow-wrap: anywhere;
}
.msg.guest { background: var(--accent-soft); border: 1px solid var(--accent-line); }
.msg.host  { background: var(--surface-alt); border: 1px solid var(--line); margin-left: auto; }
.msg .meta { font-size: var(--fs-xs); color: var(--ink-muted); margin-bottom: var(--s-1); }

/* Empty state ----------------------------------------------------------- */
.empty {
  text-align: center;
  color: var(--ink-muted);
  padding: var(--s-7) var(--s-5);
  font-size: var(--fs-sm);
}
.empty .empty-title {
  display: block;
  color: var(--ink);
  font-weight: 600;
  font-size: var(--fs-base);
  margin-bottom: var(--s-1);
}
td .empty { padding: var(--s-6) var(--s-4); }

/* Auth screens ---------------------------------------------------------- */
.auth {
  max-width: 400px;
  margin: var(--s-9) auto;
}
.auth .card { padding: var(--s-6); }
.auth h1 { margin-bottom: var(--s-4); }
.auth .field { margin-bottom: var(--s-3); }

/* Signal group heading (guest 360) -------------------------------------- */
.group-label {
  font-size: var(--fs-xs);
  font-weight: 650;
  color: var(--ink-muted);
  text-transform: uppercase;
  letter-spacing: .05em;
  margin-bottom: var(--s-1);
}
.group + .group { margin-top: var(--s-3); }

.stars { color: var(--star); letter-spacing: .05em; }

/* ── 5. Utilities (small on purpose) ───────────────────────────────────── */

.muted { color: var(--ink-muted); }
.soft  { color: var(--ink-soft); }
.strong { font-weight: 650; }
.t-sm  { font-size: var(--fs-sm); }
.t-xs  { font-size: var(--fs-xs); }
.t-2xs { font-size: var(--fs-2xs); }
.t-lg  { font-size: var(--fs-lg); }
.pre   { white-space: pre-wrap; overflow-wrap: anywhere; }
.mono  { font-family: var(--font-mono); }
.mt-0 { margin-top: 0; }
.mt-2 { margin-top: var(--s-2); }
.mt-3 { margin-top: var(--s-3); }
.mt-4 { margin-top: var(--s-4); }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--s-2); }
.mb-3 { margin-bottom: var(--s-3); }
.mb-4 { margin-bottom: var(--s-4); }
.grow { flex: 1 1 auto; min-width: 0; }
.right { text-align: right; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Campaigns ------------------------------------------------------------- */

/* `.cols` puts the narrow column first. The message editor is the other way round: the body
   is the work and the evidence sits beside it (§4.3). Both collapse to one column below. */
.cols.cols-wide-first { grid-template-columns: minmax(0, 1fr) minmax(0, 380px); }

/* Sub-navigation INSIDE a page. Campaigns parents the types screen, the queue and the
   editor; the main nav is already long, so its children live here (requirements §4). */
.subnav {
  display: flex;
  gap: var(--s-1);
  flex-wrap: wrap;
  margin-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
  padding-bottom: var(--s-2);
}
.subnav a {
  padding: 6px 12px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  color: var(--ink-muted);
}
.subnav a:hover { background: var(--surface-hover); text-decoration: none; }
.subnav a[aria-current="page"] { background: var(--accent-soft); color: var(--ink); font-weight: 600; }

/* The queue is DENSE on purpose: the stated complaint about the old screens was "hard to
   follow and lots of unnecessary info", so detail lives behind the row, not in it. */
table.queue th, table.queue td { padding: var(--s-2) var(--s-3); font-size: var(--fs-sm); }
table.queue td.tick, table.queue th.tick { width: 1%; padding-right: 0; }
table.queue td.subject { max-width: 320px; }

/* The calendar (§4.1) ---------------------------------------------------
   One cell per day, past and future drawn the same way, because the continuity between
   "what went out" and "what is due" is the whole reason the screen exists.

   NOTHING HERE IS COLOUR ALONE. Today carries the word "Today", every count carries its
   status word, and a held-back message says "not sent" in the pill. The colours are the
   second signal, never the only one. */
table.cal { width: 100%; table-layout: fixed; border-collapse: separate; border-spacing: 2px; }
table.cal th {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-muted);
  font-weight: 650;
  padding: var(--s-1) var(--s-2);
  text-align: left;
}
table.cal td {
  vertical-align: top;
  height: 92px;
  padding: var(--s-2);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
}
/* Days from the neighbouring month, and days already gone. Recessive, still readable. */
table.cal td.is-outside { background: var(--surface-alt); }
table.cal td.is-outside .cal-num { color: var(--ink-muted); }
table.cal td.is-past { background: var(--bg-sunken); }
table.cal td.is-today { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
table.cal.cal-week td { height: 200px; }

.cal-head { display: flex; align-items: center; gap: var(--s-2); justify-content: space-between; }
.cal-pick { display: inline-flex; align-items: center; gap: var(--s-1); cursor: pointer; }
.cal-num { font-size: var(--fs-sm); font-weight: 650; font-variant-numeric: tabular-nums; }
.cal-long { display: none; font-size: var(--fs-sm); font-weight: 650; }

.cal-item {
  display: block;
  margin-top: 3px;
  padding: 2px 5px;
  border-radius: var(--r-sm);
  font-size: var(--fs-2xs);
  color: var(--ink);
  overflow-wrap: anywhere;
}
.cal-item:hover { background: var(--surface-hover); text-decoration: none; }
.cal-item-head { display: block; }
.cal-item .chips { margin-top: 2px; }
.cal-item .pill { font-size: var(--fs-2xs); padding: 0 6px; }
.cal-guests { display: block; color: var(--ink-muted); margin-top: 2px; }
/* A suppression reason is a sentence, and a month cell is not a sentence wide. Clamped to
   two lines here, in full in the title, in full again in the panel beside the grid — trimmed
   for space, never hidden. */
.cal-supp .cal-guests {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* The type legend, down the side. Each entry toggles the whole grid. */
.cal-legend { list-style: none; padding: 0; margin: 0; }
.cal-legend a {
  display: block;
  padding: 6px 8px;
  border-radius: var(--r-sm);
  color: var(--ink);
  border: 1px solid transparent;
}
.cal-legend a:hover { background: var(--surface-hover); text-decoration: none; }
.cal-legend a.on { background: var(--accent-soft); border-color: var(--accent-line); }
.cal-legend a.off .cal-legend-name { color: var(--ink-muted); text-decoration: line-through; }
.cal-legend-name { display: block; font-size: var(--fs-sm); font-weight: 600; }

/* The messages that were held back, with the reasons, on the same screen. */
.cal-reasons { list-style: none; padding: 0; margin: 0; font-size: var(--fs-sm); }
.cal-reasons > li { margin-bottom: var(--s-1); }

/* The evidence panel: the guest's own words, and the sentence each one produced. */
.evidence-list { list-style: none; padding: 0; margin: 0; }
.evidence-list > li + li { margin-top: var(--s-4); border-top: 1px solid var(--line); padding-top: var(--s-3); }
.used-for {
  margin-top: var(--s-1);
  padding-left: var(--s-3);
  border-left: 2px solid var(--accent-line);
  color: var(--ink-muted);
}

/* ── 6. Responsive ─────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  .cols, .cols.cols-wide-first { grid-template-columns: minmax(0, 1fr); }
}

/* The queue collapses to CARDS, one per message, so it stays usable one-handed — that is
   the "hosts have no time" promise made concrete (§4.5). Each cell keeps its column name,
   because a bare value with no label is worse than a table you have to scroll. */
@media (max-width: 720px) {
  table.queue, table.queue tbody, table.queue tr, table.queue td { display: block; width: 100%; }
  table.queue thead { display: none; }
  table.queue tr {
    border: 1px solid var(--line);
    border-radius: var(--r);
    padding: var(--s-3);
    margin-bottom: var(--s-3);
    background: var(--surface);
  }
  table.queue td { border: 0; padding: 2px 0; }
  table.queue td::before {
    content: attr(data-label);
    display: block;
    font-size: var(--fs-2xs);
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--ink-muted);
  }
  table.queue td:empty { display: none; }
}

/* THE CALENDAR DOES NOT SCROLL SIDEWAYS ON A PHONE. A seven-column grid shrunk to 360px is
   unreadable, and a grid you drag horizontally is worse. It becomes an AGENDA instead: the
   days that have something, in order, each one a card carrying its own full date. Empty days
   are dropped entirely — density over completeness (§4.1) — except today, which stays so the
   "you are here" marker never disappears. This is the same collapse the queue makes, for the
   same stated reason: the campaign builder that failed this host was the one he could not
   use on a phone. */
@media (max-width: 720px) {
  table.cal, table.cal tbody, table.cal tr, table.cal td { display: block; width: 100%; }
  table.cal thead, table.cal caption { display: none; }
  table.cal { border-spacing: 0; }
  table.cal td { height: auto; margin-bottom: var(--s-2); border-radius: var(--r); }
  table.cal.cal-week td { height: auto; }
  table.cal td.is-empty:not(.is-today) { display: none; }
  .cal-num { display: none; }
  .cal-long { display: inline; }
  .cal-item { font-size: var(--fs-sm); padding: var(--s-2) var(--s-1); }
  .cal-item .pill { font-size: var(--fs-xs); }
  .cal-supp .cal-guests { display: block; -webkit-line-clamp: none; overflow: visible; }
}

@media (max-width: 720px) {
  :root { --fs-2xl: 1.5rem; }
  main { padding: var(--s-5) var(--s-4) var(--s-8); }
  .topbar-inner, .mainnav { padding-left: var(--s-4); padding-right: var(--s-4); }
  .card { padding: var(--s-4); border-radius: var(--r); }
  .cards { grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: var(--s-2); }
  .stat { padding: var(--s-3); }
  .page-head { margin-bottom: var(--s-4); }
  .msg { max-width: 100%; }
  .dropdown-panel { min-width: min(300px, 78vw); }
  .kv { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .kv dt { margin-top: var(--s-2); }
  .kv dt:first-child { margin-top: 0; }
  th, td { padding: var(--s-2); }
  .topbar-user .who { display: none; }
}

@media (max-width: 460px) {
  .checkgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .btn, button.primary { padding: 9px 14px; }
}

/* INSTALLED TO A HOME SCREEN (#33). `display: standalone` in the manifest means there is no
   browser chrome to absorb the notch, the rounded corners or the iOS home indicator, and the
   viewport tag says `viewport-fit=cover`, so the page must inset itself. env() is ignored
   entirely by browsers that do not know it, and the fallback is 0 — nothing changes in a tab.

   Scoped to the standalone display mode rather than applied everywhere, because in a normal
   tab the browser has already done this and doubling it wastes a phone's scarcest axis. */
@media (display-mode: standalone) {
  .topbar { padding-top: env(safe-area-inset-top, 0); }
  .topbar-inner, .mainnav {
    padding-left: max(var(--s-5), env(safe-area-inset-left, 0));
    padding-right: max(var(--s-5), env(safe-area-inset-right, 0));
  }
  main {
    padding-left: max(var(--s-5), env(safe-area-inset-left, 0));
    padding-right: max(var(--s-5), env(safe-area-inset-right, 0));
    padding-bottom: calc(var(--s-8) + env(safe-area-inset-bottom, 0));
  }
}

/* ONE-HANDED. A finger is not a mouse pointer: the queue and the editor are worked through
   from a phone, and a 28px-tall link between two other 28px-tall links is a mis-tap. 44px is
   Apple's number and Android's is close enough. Applied on POINTER capability rather than on
   width, so a small laptop window keeps the dense layout it was designed for and a tablet in
   landscape does not. */
@media (pointer: coarse) {
  .mainnav a { padding-top: var(--s-3); padding-bottom: var(--s-3); min-height: 44px; }
  .btn, button.primary, .btn-topbar { min-height: 44px; }
  /* Row-level controls in the queue: the checkbox is the target that decides what a batch
     acts on, so it is the one that must not be missed. */
  table.queue input[type="checkbox"] { width: 22px; height: 22px; }
}

@media print {
  .topbar, .mainnav, .page-head .actions { display: none; }
  .card { box-shadow: none; break-inside: avoid; }
}

/* ── 7. The campaigns workspace (#45) ──────────────────────────────────── */

/* The kill switch when it is NOT thrown. It has to be visible on the workspace itself — that
   is the sole reason /campaigns was made the landing page (#32) — without shouting, because a
   red banner on a page where nothing is wrong is a banner people stop reading. Thrown, it is a
   .banner.bad like any other emergency. */
.killbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--s-3);
  flex-wrap: wrap;
  margin-bottom: var(--s-4);
}

/* The + Create menu: one row per campaign, each its own form. */
.menu-list { list-style: none; padding: 0; margin: 0; }
.menu-list > li + li { margin-top: var(--s-3); }

/* A calendar cell: the campaign, then its messages, then what was held back. */
.cal-group + .cal-group { margin-top: var(--s-2); }
.cal-group-head {
  display: block;
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-muted);
  padding: 1px 2px;
}
.cal-group-head strong { color: var(--ink); font-variant-numeric: tabular-nums; }
.cal-item-head { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.cal-who { font-weight: 600; }
/* The piece of the guest's own words the copy came from. Two lines at most in a month cell —
   the whole of it is in the message, one click away. */
.cal-why {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--ink-muted);
  font-size: var(--fs-2xs);
  margin-top: 1px;
}
.cal-more { display: block; font-size: var(--fs-2xs); padding: 1px 2px; }

/* ── THE SLIDE-OVER ─────────────────────────────────────────────────────
   One message over the workspace, so editing never costs a host their place in the month they
   were reading. A side sheet on a desktop; on a phone it is the whole screen, because a 420px
   panel inside a 390px viewport is the unusable-on-mobile failure this whole rework exists to
   answer. No client framework is involved: it is markup htmx swapped in, and it closes by
   swapping the empty panel back. */
.slideover { position: fixed; inset: 0; z-index: 60; display: flex; justify-content: flex-end; }
.slideover-scrim {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 35, .45);
  display: block;
}
.slideover-sheet {
  position: relative;
  width: min(720px, 100%);
  max-width: 100%;
  height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--bg);
  border-left: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  padding: 0 var(--s-5) calc(var(--s-8) + env(safe-area-inset-bottom, 0));
}
.slideover-bar {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  justify-content: flex-end;
  gap: var(--s-2);
  padding: var(--s-3) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  padding-top: max(var(--s-3), env(safe-area-inset-top, 0));
}
.slideover-body { padding-top: var(--s-4); }
/* Inside a sheet there is no room for the editor's two columns: the evidence goes under the
   words rather than beside them. Same markup, one grid rule. */
.slideover .cols, .slideover .cols.cols-wide-first { grid-template-columns: minmax(0, 1fr); }
.msg-head { margin-bottom: var(--s-3); }

@media (max-width: 720px) {
  .slideover-sheet { width: 100%; border-left: 0; padding-left: var(--s-4); padding-right: var(--s-4); }
  .killbar { justify-content: space-between; }
}

/* A finger, not a pointer: the close control and the sheet's own actions are the ones a
   mis-tap costs the most. */
@media (pointer: coarse) {
  .slideover-close { min-height: 44px; }
  .cal-item { min-height: 44px; }
}
