:root {
  color-scheme: light dark;

  /* Colour. Only three things are allowed to carry colour: the brand accent
     on a primary action, the goal-status dots, and links. Everything else is
     text / muted / border. */
  --bg: #faf9f6;
  --card: #ffffff;
  --text: #252423;
  --muted: #74716c;
  --border: #e5e2da;
  --accent: #c9980a; /* darkened brand yellow #f3c300 for AA contrast on light bg */
  --accent-contrast: #252423;
  --danger: #b3261e;

  /* Goal status -- the one semantic colour set. */
  --status-red: #d64545;
  --status-yellow: #d6a545;
  --status-green: #4a9d5c;

  /* Spacing scale. Every margin/padding in this file comes from here, so
     vertical rhythm stays consistent across cards, tables and forms. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.75rem;

  /* Radius: containers, controls, pills. Three values, no others. */
  --radius-lg: 8px;   /* cards, panels */
  --radius: 6px;      /* inputs, buttons, tiles */
  --radius-full: 999px;

  /* One control height for every input, select and button. */
  --control-h: 1.9rem;

  /* Type scale. */
  --fs-xs: 0.72rem;
  --fs-sm: 0.78rem;
  --fs-base: 0.82rem;
  --fs-md: 0.9rem;
  --fs-lg: 1.02rem;
  --fs-stat: 1.35rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a19;
    --card: #232221;
    --text: #f2f0ea;
    --muted: #a7a49c;
    --border: #38362f;
    --accent: #f3c300;
    --accent-contrast: #252423;
    --danger: #f2b8b5;
  }
}

/* Digits line up column-to-column and row-to-row. Required for any table
   you read down rather than across. */
.num, .stat-row strong, .funnel-row strong, table td.num, table th.num {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  padding: 1.5rem 2rem 2.5rem;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, "Segoe UI", Roboto, sans-serif;
}

.brand-header {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}

.brand-header img { height: 2rem; width: auto; }
.logo-light { display: inline; }
.logo-dark { display: none; }
@media (prefers-color-scheme: dark) {
  .logo-light { display: none; }
  .logo-dark { display: inline; }
}

.brand-header h1 {
  margin: 0;
  font-size: 1.35rem;
  font-weight: 700;
  border-left: 1px solid var(--border);
  padding-left: 1rem;
}

.muted { color: var(--muted); font-size: 0.82rem; line-height: 1.4; }

.tabnav {
  display: flex;
  gap: 0.25rem;
  margin-top: 1.25rem;
  border-bottom: 1px solid var(--border);
}

.tabnav a {
  padding: 0.55rem 1rem;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}

.tabnav a.active {
  color: var(--text);
  border-bottom-color: var(--accent);
}

.tabnav a:hover { color: var(--text); }

/* Per-report filter bar. Tinted and inset so it reads as a control surface
   rather than as the first row of data -- the old version was a bare row
   with a bottom rule, which looked like a table header. */
.filters {
  display: flex;
  gap: 0.6rem 0.75rem;
  flex-wrap: wrap;
  align-items: center;
  margin: 0 0 0.85rem;
  padding: 0.5rem 0.6rem;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}

.filters label, .filters .filter-field {
  display: flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--fs-xs);
  color: var(--muted);
  white-space: nowrap;
}

/* Segmented control -- the right control for a two- or three-way choice.
   These were <select> dropdowns, which cost a click to even see the options
   and hid the current state behind a chevron. Radios, so no JS. */
/* Multi-select user picker. A plain <select multiple> so it stays zero-JS:
   nothing selected means everyone, which is why the "All" option is gone --
   it would have been a selectable value competing with the real people. */
.filters select.multi {
  height: auto;
  min-width: 11rem;
  padding: var(--space-1);
  line-height: 1.5;
}

.filters select.multi option {
  padding: 0.1rem var(--space-2);
  border-radius: var(--radius-sm, 4px);
}

/* Label stacked above its control, for the taller multi-selects -- inline
   labels would sit against the middle of a four-row list box. */
.filters label.stacked, .filters .filter-field.stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  align-self: flex-start;
}

.filters label.stacked .hint {
  font-size: 0.66rem;
  color: var(--muted);
  font-weight: 400;
}

.filters label.stacked > .hint + select { margin-top: 0.1rem; }

.segmented {
  display: inline-flex;
  height: var(--control-h);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  overflow: hidden;
}

.segmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

.segmented label {
  display: flex;
  align-items: center;
  padding: 0 var(--space-3);
  font-size: var(--fs-sm);
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}

.segmented label:not(:first-of-type) { border-left: 1px solid var(--border); }
.segmented label:hover { color: var(--text); }

.segmented input:checked + label {
  background: var(--bg);
  color: var(--text);
  font-weight: 600;
}

.segmented input:focus-visible + label {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}

.filters select, .filters input {
  font: inherit;
  font-size: 0.8rem;
  padding: 0.2rem 0.4rem;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text);
  height: var(--control-h);
}

.filters input[type="number"] { width: 4.5rem; }
.filters input[type="text"] { width: 9rem; }

/* One button component for the whole app. Primary = brand accent (the only
   place it appears); secondary and danger are bordered, so a destructive
   action never looks like the main one. */
button, .btn {
  font: inherit;
  font-size: var(--fs-sm);
  padding: 0 var(--space-3);
  height: var(--control-h);
  border-radius: var(--radius);
  border: 1px solid transparent;
  background: var(--accent);
  color: var(--accent-contrast);
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

button:hover, .btn:hover { opacity: 0.85; }

button.btn-secondary {
  background: var(--card);
  border-color: var(--border);
  color: var(--text);
}

button.btn-danger {
  background: transparent;
  border-color: var(--border);
  color: var(--danger);
  font-weight: 600;
}

button.btn-danger:hover { border-color: var(--danger); opacity: 1; }

/* Keyboard users need to see where they are -- there was no focus style at
   all before this. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-radius: var(--radius);
}

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
  gap: 1.25rem;
  margin-top: 1.25rem;
  /* Each card takes its own height. Grid's default stretch made a short card
     next to a tall one (Email Campaigns beside the SMS list) render as a
     mostly-empty white box the height of its neighbour. */
  align-items: start;
}

@media (min-width: 1300px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
}

.card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1rem 1.25rem;
  overflow-x: auto;
}

.card.wide {
  grid-column: 1 / -1;
}

/* Two populations shown side by side inside one card (New Buyer Leads:
   real Leads/Contacts on the left, Raw Leads on the right). Collapses to a
   single column below the breakpoint so each table keeps its width. */
.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

@media (min-width: 860px) {
  .split { grid-template-columns: 1fr 1fr; }
}

.card.brand-card {
  display: flex;
  align-items: center;
  align-content: center;
  gap: 1.25rem;
  flex-wrap: wrap;
  /* Without this, CSS Grid's default row-stretch matches this card's height
     to its tallest sibling (e.g. Full Cycle Funnel with its filters) -- with
     flex-wrap active on narrow screens, the wrapped logo/text lines then
     spread apart to fill that extra height instead of sitting together. */
  align-self: start;
}

.card.brand-card img { height: 2.75rem; width: auto; flex-shrink: 0; }

.card h2 {
  font-size: 1.02rem;
  margin: 0 0 0.15rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}

/* One-line orientation under a card title: what this answers, in plain
   words. Distinct from .notes, which holds the methodology caveats. */
.card-sub {
  margin: 0 0 0.7rem;
  font-size: 0.8rem;
  color: var(--muted);
  line-height: 1.45;
}

/* Headline numbers as tiles rather than a run-on sentence of bold text.
   Markup stays "<span><strong>42</strong> label</span>" -- the span is a
   block so the number sits on its own line with the caption (and any goal
   dot, which is inline) beneath it. Every card that already used .stat-row
   picks this up with no template change. */
.stat-row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin: 0 0 0.85rem;
  font-size: 0.88rem;
}

.stat-row > span {
  display: block;
  flex: 1 1 auto;
  min-width: 7rem;
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  font-size: 0.72rem;
  color: var(--muted);
  line-height: 1.3;
}

.stat-row > span strong {
  display: block;
  font-size: var(--fs-stat);
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
  margin-bottom: 0.1rem;
}

/* Two consecutive stat rows (the Facebook overview) should read as one block. */
.stat-row + .stat-row { margin-top: -0.35rem; }

/* Funnel stages are a sequence, so give every tile the same width and let
   them share one row -- unequal boxes read as unrelated numbers. */
.funnel-row > span { flex: 1 1 0; min-width: 5.5rem; }

/* Full-width divider that chunks a long tab into labelled sections. Sits
   inside .grid, so it has to span every column. */
.section-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 0.7rem;
  margin: 0.9rem 0 -0.4rem;
}

.section-head:first-child { margin-top: 0; }

.section-head h2 {
  margin: 0;
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text);
  white-space: nowrap;
}

.section-head .note {
  font-size: 0.74rem;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.section-head .rule {
  flex: 1;
  height: 1px;
  min-width: 1rem;
  background: var(--border);
}

/* Anchor chips under the tab bar -- these pages are long, and scrolling to
   find one report is the main navigation cost. */
.jump-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 1rem;
}

.jump-nav a {
  font-size: 0.74rem;
  font-weight: 600;
  padding: 0.28rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  background: var(--card);
  color: var(--muted);
  text-decoration: none;
}

.jump-nav a:hover { color: var(--text); border-color: var(--accent); }

/* One automatically-detected finding: claim on top, evidence beneath. */
.finding {
  border-left: 2px solid var(--border);
  padding: 0.05rem 0 0.05rem 0.7rem;
  margin: 0 0 0.8rem;
}

.finding:last-child { margin-bottom: 0; }

.finding b {
  display: block;
  font-size: 0.86rem;
  font-weight: 700;
  margin-bottom: 0.1rem;
}

.finding span {
  display: block;
  font-size: 0.78rem;
  color: var(--muted);
  line-height: 1.45;
}

/* Sub-heading inside a card. Plain by default, because some h3s hold user
   data (campaign names in the Telemarketing/SMS/Email cards) that must not
   be uppercased or greyed out. */
.card h3 {
  font-size: 0.82rem;
  font-weight: 700;
  color: var(--text);
  margin: 0.9rem 0 0.4rem;
}

/* Eyebrow style, for structural labels only (Body copy / Headlines,
   Leads & Contacts / Raw Leads, Results / Delivery). */
.split h3, .card h3.label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  margin: 0 0 0.45rem;
}

/* Methodology, caveats and data-source warnings. These are genuinely useful
   -- they encode why a number means what it means -- but on most cards they
   ran two or three paragraphs ABOVE the data, so the numbers you came for
   started below the fold. Collapsed by default, one click away, no JS. */
.notes {
  margin: 0 0 0.8rem;
  font-size: 0.8rem;
}

.notes > summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.15rem 0;
  user-select: none;
}

.notes > summary::-webkit-details-marker { display: none; }

.notes > summary::before {
  content: "";
  width: 0.36rem;
  height: 0.36rem;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
}

.notes[open] > summary::before { transform: rotate(45deg); }
.notes > summary:hover { color: var(--text); }

.notes-body {
  padding: 0.5rem 0.75rem;
  margin-top: 0.4rem;
  border-left: 2px solid var(--border);
  color: var(--muted);
  line-height: 1.5;
}

.notes-body p { margin: 0 0 0.6rem; }
.notes-body p:last-child { margin-bottom: 0; }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.82rem;
}

th, td {
  text-align: left;
  padding: 0.3rem 0.5rem;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

th { color: var(--muted); font-weight: 600; }

/* Row hover: the wide tables run to 13 columns, and tracking one person
   across that width with no guide is the main reason they're tiring. */
tbody tr:hover td, table tr:hover td { background: var(--bg); }

/* Header band over a group of columns (Calls / SMS / Tasks). */
th.group {
  text-align: center;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: none;
  padding-bottom: 0.1rem;
}

th.group.divider, td.divider, th.divider { border-left: 1px solid var(--border); }

/* Long lists get their own scroll area with a pinned header, so one report
   can't push the next one three screens down the page. */
.table-scroll {
  max-height: 24rem;
  overflow-y: auto;
  border-bottom: 1px solid var(--border);
}

.table-scroll th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--card);
  box-shadow: inset 0 -1px 0 var(--border);
}

.table-scroll table tr:last-child td { border-bottom: none; }

/* Consistent empty state: same voice, same weight, everywhere. */
td.empty, .empty {
  color: var(--muted);
  font-style: italic;
  font-size: 0.8rem;
}

/* Numeric column: right-aligned so digits line up on the ones place (3 vs 30
   vs 300 read as comparable magnitudes instead of a ragged left edge). */
th.num, td.num { text-align: right; }

/* Long text labels (placement names, ad copy) wrap instead of forcing the
   numeric columns off the edge of the card. */
td.label-cell { white-space: normal; min-width: 8rem; }

.goal-dot {
  display: inline-block;
  width: 0.55rem;
  height: 0.55rem;
  border-radius: 50%;
  margin-left: 0.35rem;
  vertical-align: middle;
  cursor: default;
}
.goal-dot.red { background: var(--status-red); }
.goal-dot.yellow { background: var(--status-yellow); }
.goal-dot.green { background: var(--status-green); }
.goal-dot.changed { box-shadow: 0 0 0 2px var(--bg), 0 0 0 3px currentColor; }

footer {
  margin-top: 1.5rem;
  text-align: center;
}


/* ---------------------------------------------------------------------
   Goals screen. Same table/control components as the dashboard -- the
   page used to be a stack of filter bars, one per goal, with delete
   living in a separate card.
   --------------------------------------------------------------------- */

.goals-table td { vertical-align: middle; }

.goals-table input[type="number"] {
  width: 5.5rem;
  font: inherit;
  font-size: var(--fs-base);
  text-align: right;
  padding: 0 var(--space-2);
  height: var(--control-h);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

.goals-table input[type="checkbox"] { width: 0.95rem; height: 0.95rem; accent-color: var(--accent); }

/* The metric key is needed occasionally (it is what the weekly email and
   goals.db use) but it must not compete with the human label. */
.row-key {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: var(--fs-xs);
  color: var(--muted);
  margin-top: 0.1rem;
}

/* Section band inside a table -- groups related rows without starting a
   whole new card for each section. */
.row-section td {
  background: var(--bg);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
  padding-top: var(--space-2);
  padding-bottom: var(--space-2);
}

/* Status reads as a phrase, not a raw colour name; the dot carries the
   colour so the words stay neutral. */
.status { display: inline-flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.status .goal-dot { margin-left: 0; }

.row-actions { white-space: nowrap; }
.row-actions button + button { margin-left: var(--space-2); }

.wide-select { min-width: 22rem; max-width: 100%; }


/* Ad creative thumbnail. Small enough to keep the table scannable, big
   enough to recognise the picture -- the point of the column is that a
   32-character image hash tells a human nothing. */
.creative-thumb {
  display: block;
  width: 64px;
  height: 64px;
  object-fit: cover;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg);
}

/* ============================================================
   SAFETYNET BRAND (2026-09-24)
   From the logo (#F3C300 yellow, #252423 charcoal) and
   safetynetinv.com (Poppins headings, Roboto text, green
   #00922C / red #E21B1B). Yellow is the brand's voice: the active
   tab, the primary button, the logo mark. Status keeps its own
   green / amber / red so a brand-yellow never reads as "at risk".
   ============================================================ */
:root {
  --brand: #f3c300;
  --brand-ink: #252423;
  --brand-hover: #e0b400;
  --charcoal: #252423;
  --charcoal-2: #34322f;
  --bg: #f5f5f3;
  --card: #ffffff;
  --text: #1f1e1c;
  --muted: #6f6c66;
  --border: #e4e2dd;
  --accent: #a67c00;             /* yellow darkened for text/links on white (AA) */
  --status-green: #00922c;
  --status-yellow: #d08400;      /* amber: distinct from the brand yellow */
  --status-red: #e21b1b;
  --display: "Poppins", -apple-system, "Segoe UI", sans-serif;
  --sans: "Roboto", -apple-system, "Segoe UI", sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root { --bg: #1b1a18; --card: #242320; --text: #f1efe9; --muted: #a8a59d; --border: #3a3833; --accent: #f3c300; }
}
body { padding: 0; font-family: var(--sans); font-size: 14px; }
a { color: var(--text); text-decoration: underline; text-decoration-color: var(--border); text-underline-offset: 2px; }
a:hover { text-decoration-color: var(--brand); }

/* --- header band --- */
.topband { background: var(--charcoal); color: #fff; position: sticky; top: 0; z-index: 30; }
.topband-in { display: flex; align-items: center; gap: 28px; max-width: 1440px; margin: 0 auto; padding: 0 28px; min-height: 58px; }
.tb-brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: #fff; flex: none; }
.tb-brand img { height: 26px; width: auto; display: block; }
.tb-brand span { font: 600 15px var(--display); padding-left: 12px; border-left: 1px solid rgba(255,255,255,.22); letter-spacing: .01em; }
.topband .tabnav { margin: 0; border: 0; gap: 4px; align-self: stretch; }
.topband .tabnav a { display: flex; align-items: center; color: rgba(255,255,255,.72); font: 500 14px var(--display);
  padding: 0 12px; border-bottom: 3px solid transparent; margin: 0; text-decoration: none; }
.topband .tabnav a:hover { color: #fff; }
.topband .tabnav a.active { color: #fff; border-bottom-color: var(--brand); }
.tb-meta { margin-left: auto; font-size: 12px; color: rgba(255,255,255,.6); white-space: nowrap; }
.page { max-width: 1440px; margin: 0 auto; padding: 24px 28px 40px; }
.page-intro { color: var(--muted); margin: 0 0 16px; max-width: 80ch; }
.page-foot { max-width: 1440px; margin: 0 auto; padding: 0 28px 28px; text-align: left; }

/* --- type --- */
.card h2, .section-head h2 { font-family: var(--display); letter-spacing: -.005em; }
.card h2 { font-size: 16px; font-weight: 600; }
.section-head h2 { font-size: 13px; font-weight: 600; letter-spacing: .06em; }
.stat-row > span strong, .funnel-row strong { font-family: var(--display); font-weight: 600; letter-spacing: -.01em; }
table { font-size: 13px; }
th { font-weight: 500; font-size: 12px; }

/* --- surfaces --- */
.card { border-radius: 10px; border-color: var(--border); box-shadow: 0 1px 0 rgba(0,0,0,.02); }
.stat-row > span { border-radius: 8px; }

/* --- buttons: brand yellow with charcoal text, like the website --- */
button, .btn { background: var(--brand); color: var(--brand-ink); font-weight: 600; font-family: var(--display); border: 0; }
button:hover, .btn:hover { opacity: 1; background: var(--brand-hover); }
button.btn-secondary { background: var(--card); color: var(--text); border: 1px solid var(--border); }
button.btn-secondary:hover { background: var(--bg); }
.segmented input:checked + label { background: var(--charcoal); color: #fff; }

/* --- jump nav + the global range bar: sticky under the header --- */
.jump-nav a { text-decoration: none; }
.jump-nav a:hover { border-color: var(--brand); }

/* --- goal status: bigger dots with a legend --- */
.goal-dot { width: 9px; height: 9px; }
.status-legend { display: inline-flex; gap: 14px; align-items: center; font-size: 12px; color: var(--muted); }
.status-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; vertical-align: -1px; }

@media (max-width: 900px) {
  .topband-in { gap: 12px; padding: 0 14px; overflow-x: auto; }
  .tb-meta { display: none; }
  .page { padding: 16px 14px 32px; }
}
/* folded report filters: one line saying what is applied */
details.fbox { margin: 2px 0 12px; }
.fbox-sum { list-style: none; display: inline-flex; align-items: center; gap: 8px; cursor: pointer; user-select: none;
  font-size: 12.5px; color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: 4px 12px 4px 10px; }
.fbox-sum::-webkit-details-marker { display: none; }
.fbox-sum:hover { border-color: var(--brand); }
.fbox-ic { color: var(--muted); font-size: 13px; transform: rotate(-45deg); display: inline-block; }
.fbox-edit { color: var(--muted); font-size: 12px; border-left: 1px solid var(--border); padding-left: 8px; }
details.fbox[open] .fbox-sum { border-color: var(--brand); background: var(--card); }
details.fbox[open] .fbox-edit { visibility: hidden; }
details.fbox > form.filters { margin-top: 8px; }
/* the range bar + section links stay pinned under the header while a long report scrolls */
.card.stickybar { position: sticky; top: 58px; z-index: 20; display: flex; flex-direction: column; gap: 8px;
  padding: 10px 16px; border-radius: 10px; box-shadow: 0 6px 16px -12px rgba(0,0,0,.25); }
.stickybar .jump-nav { margin: 0; }
.stickybar .filters { flex-wrap: wrap; row-gap: 6px; }
.stickybar .status-legend { margin-left: auto; }
.stickybar .status-legend a { font-size: 12px; }
/* long explanations: two lines, tap to read the rest */
.card-sub.clamp { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; cursor: pointer; }
.card-sub.clamp:hover { color: var(--text); }
.card-sub.clamp.open { display: block; -webkit-line-clamp: unset; }
@media (max-width: 900px) { .card.stickybar { position: static; } .stickybar .status-legend { margin-left: 0; } }
/* channel tables: campaigns as rows, statuses as columns */
.camp-table td { vertical-align: top; }
.camp-name a { font-weight: 500; }
.camp-sub { display: block; font-size: 11.5px; color: var(--muted); margin-top: 2px; }
.camp-table td.dim { color: var(--muted); }
/* goals: the internal metric key is for debugging, not for reading */
.goals-table .row-key { display: none; }
/* phones: the 420px card minimum forced a sideways scroll on a 390px screen */
@media (max-width: 600px) { .grid { grid-template-columns: minmax(0, 1fr); } }
.grid { margin-top: 0; }
.page > .grid:first-child { margin-top: 0; }
/* goals: let the list be as tall as it is — the page has the room */
#configured-goals .table-scroll { max-height: none; }
/* legend: a ring means the status changed since the last reading */
.status-legend .ring { width: 9px; height: 9px; border-radius: 50%; display: inline-block; margin-right: 5px; vertical-align: -1px;
  background: var(--muted); box-shadow: 0 0 0 2px var(--card), 0 0 0 3px var(--muted); }
#configured-goals .table-scroll { overflow-x: auto; }
@media (max-width: 600px) {
  .wide-select { min-width: 0; width: 100%; }
  .filters label { flex-wrap: wrap; max-width: 100%; }
  .filters select { max-width: 100%; }
}
.segmented { position: relative; }   /* keeps its hidden radios inside it (they stretched the page on phones) */
.status-legend { flex-wrap: wrap; }
.status-legend > span, .status-legend a, .topband .tabnav a { white-space: nowrap; }
