/* ============================================================================
   Rinforza design system — see app/DESIGN.md.
   Tenant UI: gold, black and white. Paper (light) and Night (dark) share one token set;
   the reader picks between them on Settings. Daniel chose both on 2026-09-17.
   ========================================================================== */
:root {
  /* Legacy component names share the same live palette as the shell. */
  --ink:var(--h2-side); --text:var(--h2-ink); --muted:var(--h2-ink2); --faint:var(--h2-ink3);
  --bg:var(--h2-bg); --card:var(--h2-card); --border:var(--h2-line);
  --accent:var(--h2-accent); --accent-ink:var(--h2-accent-deep);
  --accent-soft:var(--h2-accent-soft); --accent-dark:var(--h2-ink2);
  --good:var(--h2-good); --good-soft:var(--h2-good-soft);
  --warn:var(--h2-warn); --warn-soft:var(--h2-warn-soft);
  --bad:var(--h2-bad); --bad-soft:var(--h2-bad-soft);
  /* shape + elevation */
  --r-sm: 0px;
  --r-md: 0px;   /* square corners are part of the identity */
  --shadow-xs: 0 1px 2px rgba(23,26,33,.05);
  --shadow-sm: 0 4px 12px rgba(23,26,33,.07);
  --ring: 0 0 0 3px var(--accent-soft);
  /* spacing scale: 4 8 12 16 20 24 32 40 */
  --gutter: 28px;

  /* ---- type ------------------------------------------------------------------------------
     Lifted from control/static/control.css so the operator console and the tenant app read as
     one product. Same three faces as before — the difference was never WHICH font, it was how
     they were used:

       figures   were IBM Plex Mono, now Space Grotesk Medium. A monospace forces even spacing
                 around every digit and comma, so "$121,339" reads as a terminal readout. This
                 is the change that alters the character of every screen.
       headings  were weight 700 with negative tracking, now weight 500 with slightly positive
                 tracking — Space Grotesk's own proportions rather than a squeezed bold.
       body      was 14px/1.55, now 15px/1.6.
       captions  gain Barlow 300, which this app did not previously even load.

     Mono is still loaded and still used for identifiers, tokens and code — places where
     character alignment is the point. It is no longer used for money. */
  --font-display: 'Space Grotesk', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    Barlow, 'Helvetica Neue', Arial, sans-serif;
  --font-mono:    'IBM Plex Mono', ui-monospace, monospace;
  --track-eyebrow: .18em;
}

* { box-sizing: border-box; margin: 0; }
html { -webkit-font-smoothing: antialiased; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}
body {
  font: 400 16px/1.6 var(--font-body);
  color: var(--text); background: var(--bg); min-height: 100vh;
}

/* ------------------------------------------------------------ a11y helpers */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100; background: var(--card);
  color: var(--accent-ink); padding: 10px 16px; border-radius: 0 0 var(--r-sm) 0;
  font-weight: 600; text-decoration: none;
}
.skip-link:focus { left: 0; }
:focus-visible { outline: none; box-shadow: var(--ring); border-radius: var(--r-sm); }

/* ------------------------------------------------------------ top nav */
.topnav {
  background: var(--ink); color: #fff; min-height: 56px; display: flex; align-items: center;
  padding: 0 20px; gap: 8px; position: sticky; top: 0; z-index: 50;
}
.topnav .brand {
  display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 16px;
  color: #fff; margin-right: 16px; text-decoration: none; white-space: nowrap;
}
.topnav .brand .mark {
  width: 26px; height: 26px; border-radius:0; overflow: hidden;
  display: block; flex: none;
}
.topnav nav { display: flex; align-items: center; gap: 2px; flex: 1; min-width: 0; }
.topnav a.item {
  color: #c9ccd5; text-decoration: none; font-size: 13.5px; font-weight: 600;
  padding: 7px 12px; border-radius: var(--r-sm); position: relative; white-space: nowrap;
  transition: color .12s, background .12s;
}
.topnav a.item:hover { color: #fff; background: rgba(255,255,255,.08); }
.topnav a.item[aria-current="page"] { color: #fff; }
.topnav a.item[aria-current="page"]::after {
  content: ''; position: absolute; left: 12px; right: 12px; bottom: -8px;
  height: 3px; border-radius:0 3px 0 0; background: var(--h2-sel-rule);
}
.topnav .side { display: flex; align-items: center; gap: 4px; }

/* "More" overflow dropdown — keeps the bar from crowding as sections grow */
.nav-more { position: relative; display: flex; align-items: center; }
.nav-more .more-btn {
  color: #c9ccd5; background: transparent; border: none; font: inherit; font-size: 13.5px;
  font-weight: 600; padding: 7px 12px; border-radius: var(--r-sm); cursor: pointer;
  white-space: nowrap; position: relative;
}
.nav-more .more-btn:hover { color: #fff; background: rgba(255,255,255,.08); }
.nav-more.active-child .more-btn { color: #fff; }
.nav-more.active-child .more-btn::after {
  content: ''; position: absolute; left: 12px; right: 24px; bottom: -8px;
  height: 3px; border-radius:0 3px 0 0; background: var(--accent);
}
.nav-more .menu {
  position: absolute; top: calc(100% + 6px); left: 0; background: var(--ink);
  border: 1px solid rgba(255,255,255,.12); border-radius: var(--r-md); padding: 6px;
  min-width: 190px; display: none; flex-direction: column; gap: 1px;
  box-shadow: var(--shadow-sm); z-index: 60;
}
.nav-more.open .menu { display: flex; }
.nav-more .menu a.item[aria-current="page"]::after { display: none; }
.nav-more .menu a.item[aria-current="page"] { background: rgba(255,255,255,.1); }
.topnav .side .whoami {
  color: #c9ccd5; font-size: 12.5px; font-weight: 600; padding: 0 8px 0 12px;
  white-space: nowrap; border-left: 1px solid rgba(255,255,255,.14); margin-left: 4px;
}
.nav-burger {
  display: none; color: #fff; font-size: 20px; padding: 6px 12px; cursor: pointer;
  border-radius: var(--r-sm); user-select: none; background: transparent; border: none;
  margin-left: auto;
}
.nav-burger:hover { background: rgba(255,255,255,.1); }

@media (max-width: 900px) {
  .nav-burger { display: block; }
  .topnav { flex-wrap: wrap; padding: 10px 16px; align-items: flex-start; }
  .topnav .brand { padding-top: 3px; }
  .topnav nav, .topnav .side {
    display: none; width: 100%; flex-direction: column; align-items: stretch; gap: 2px;
    padding: 8px 0 4px;
  }
  .topnav.nav-open nav, .topnav.nav-open .side { display: flex; }
  .topnav a.item { padding: 10px 12px; }
  .topnav a.item[aria-current="page"] { background: rgba(255,255,255,.1); }
  .topnav a.item[aria-current="page"]::after { display: none; }
  /* stacked menu: "More" items show inline, no dropdown button */
  .nav-more { display: block; width: 100%; }
  .nav-more .more-btn { display: none; }
  .nav-more .menu {
    display: flex !important; position: static; background: transparent; border: none;
    box-shadow: none; padding: 0; min-width: 0;
  }
  .nav-more.active-child .more-btn::after { display: none; }
}

main { max-width: 1180px; margin: 0 auto; padding: 26px var(--gutter) 64px; }

/* ------------------------------------------------------------ typography */
h1 { font-size: 26px; font-weight: 500; letter-spacing: .01em; line-height: 1.08;
     margin-bottom: 4px; }
h2 {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--muted); margin: 28px 0 12px;
}
.panel > h2:first-child { margin-top: 0; }
.sub { color: var(--muted); font-size: 13.5px; margin-bottom: 20px; max-width: 70ch; }
.page-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }
.page-head .actions { display: flex; gap: 8px; flex-shrink: 0; }
.topbar { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }

/* ------------------------------------------------------------ stat cards */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(176px, 1fr)); gap: 12px; margin-bottom: 12px; }
.card {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 16px 18px; box-shadow: var(--shadow-xs); display: flex; flex-direction: column;
  min-width: 0;                 /* let the card shrink in its grid track instead of forcing a wider one */
  container-type: inline-size;  /* size the big number relative to THIS card's width (see .num) */
}
.card .lbl {
  order: 1; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted); margin-bottom: 6px;
}
/* Number scales with the card: full 24px on wide cards, shrinks to fit long values
   (e.g. "$101,559,475") on narrow cards so it never spills past the card edge. */
.card .num {
  order: 2; font-size: clamp(16px, 15.5cqi, 24px); font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; white-space: nowrap; max-width: 100%;
}
.card.hero { border-color: var(--accent-soft); background: linear-gradient(180deg, var(--h2-hero-a), var(--h2-hero-b)); }
.card.hero .num { color: var(--accent-ink); }
/* dashboard KPI grid: fixed 4-up so 8 cards land as two clean rows (not a ragged 6+2) */
.cards-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 980px) { .cards-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .cards-4 { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------ tables */
.table-scroll { overflow-x: auto; border-radius: var(--r-md); }
table {
  width: 100%; border-collapse: separate; border-spacing: 0; background: var(--card);
  border: 1px solid var(--border); border-radius: var(--r-md); overflow: hidden;
  box-shadow: var(--shadow-xs);
}
th {
  text-align: left; padding: 10px 14px; background: var(--h2-surface-2); color: var(--muted);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  border-bottom: 1px solid var(--border); white-space: nowrap;
}
td { text-align: left; padding: 11px 14px; font-size: 13.5px; border-bottom: 1px solid var(--h2-line); vertical-align: middle; }
tr:last-child td { border-bottom: none; }
tbody tr:hover td, tr:hover td { background: var(--h2-surface-2); }
td a:not(.btn) { color: var(--accent-ink); text-decoration: none; font-weight: 600; }
td a:hover { text-decoration: underline; }
@media (max-width: 760px) {
  table { display: block; overflow-x: auto; }
}

/* ------------------------------------------------------------ avatars */
.av {
  display: inline-grid; place-items: center; width: 32px; height: 32px; border-radius:0;
  color: var(--av-ink); font-size: 12.5px; font-weight: 700; flex-shrink: 0; letter-spacing: .02em;
  background: var(--av0);
}
/* Seven tones, so two people side by side are told apart, all of them inside the palette.
   The ground comes from the theme; the initials colour is one token, and qa/test_theme_contrast
   checks it against all seven grounds in both themes. */
.av.t0{background:var(--av0)} .av.t1{background:var(--av1)} .av.t2{background:var(--av2)}
.av.t3{background:var(--av3)} .av.t4{background:var(--av4)} .av.t5{background:var(--av5)}
.av.t6{background:var(--av6)}
.av.lg { width: 46px; height: 46px; border-radius:0; font-size: 17px; }
.name-cell { display: flex; align-items: center; gap: 10px; min-width: 180px; }

/* ------------------------------------------------------------ buttons */
.btn {
  display: inline-block; background: var(--accent); color: var(--h2-on-accent); border: none;
  border-radius:0; padding: 8px 16px; font: inherit; font-size: 13.5px; font-weight: 600;
  cursor: pointer; text-decoration: none; transition: background .12s; text-align: center;
}
.btn:hover { background: var(--accent-dark); }
.btn:focus-visible { box-shadow: var(--ring), 0 0 0 1px var(--accent); }
.btn.secondary { background: var(--card); color: var(--text); border: 1px solid var(--border); }
.btn.secondary:hover { background: var(--h2-surface-2); border-color: var(--h2-line-2); }
.btn.danger { background: var(--bad); }
.btn.small { padding: 5px 11px; font-size: 12.5px; border-radius: var(--r-sm); }

/* ------------------------------------------------------------ pills / chips */
.pill {
  display: inline-block; padding: 2px 9px; border-radius:0; font-size: 11.5px;
  font-weight: 600; vertical-align: 1px; white-space: nowrap;
}
.pill.green { background: var(--good-soft); color: var(--good); }
.pill.amber { background: var(--warn-soft); color: var(--warn); }
.pill.red   { background: var(--bad-soft);  color: var(--bad); }
.pill.gray  { background: var(--h2-track); color: var(--muted); }
.pill.blue  { background: var(--accent-soft); color: var(--accent-ink); }

/* ------------------------------------------------------------ panels / notices */
form.panel, .panel {
  background: var(--card); border: 1px solid var(--border); border-radius: var(--r-md);
  padding: 20px; margin-bottom: 16px; box-shadow: var(--shadow-xs);
}
.notice { border-left: 4px solid var(--accent); }
.notice.warn { border-left-color: var(--warn); }
.notice.good { border-left-color: var(--good); }
.empty {
  text-align: center; color: var(--muted); padding: 36px 20px; background: var(--card);
  border: 1px dashed var(--border); border-radius: var(--r-md); font-size: 13.5px;
}

/* ------------------------------------------------------------ forms */
label {
  display: block; font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .07em; color: var(--muted); margin: 12px 0 5px;
}
input[type=text], input[type=number], input[type=email], input[type=password], select, textarea {
  width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius:0;
  font: inherit; font-size: 13.5px; background: var(--card); color: var(--text);
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: var(--ring);
}
textarea { min-height: 160px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12.5px; }
.row { display: flex; gap: 12px; }
.row > * { flex: 1; min-width: 0; }
@media (max-width: 640px) { .row { flex-direction: column; } }

/* ------------------------------------------------------------ misc */
.mt { margin-top: 16px; }
.muted { color: var(--muted); }
.right { text-align: right; }
.searchbar { display: flex; gap: 8px; margin-bottom: 16px; }
.searchbar input { flex: 1; border-radius:0; padding-left: 16px; }
.searchbar .btn { border-radius:0; }
.preview-box {
  border: 1px solid var(--border); border-radius: var(--r-sm); padding: 14px 16px;
  background: var(--h2-surface-2); font-size: 14px; overflow-x: auto;
}
.kv { display: grid; grid-template-columns: 168px 1fr; gap: 8px 14px; font-size: 13.5px; }
.kv dt {
  color: var(--muted); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; padding-top: 2px;
}
.kv dd { min-width: 0; overflow-wrap: anywhere; }
.kv dd a:not(.btn), .panel a:not(.btn) { color: var(--accent-ink); }
@media (max-width: 640px) {
  .kv { grid-template-columns: 1fr; gap: 2px 0; }
  .kv dt { margin-top: 10px; }
}
ul.plain { padding-left: 20px; }
ul.plain li { margin: 6px 0; }
code {
  background: var(--h2-surface-2); border-radius:0; padding: 1px 6px; font-size: 12.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; overflow-wrap: anywhere;
}
@media (max-width: 640px) {
  main { padding: 18px 16px 48px; }
  .cards { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 10px; }
  h1 { font-size: 19px; }
}

/* ---- insights dashboard: freshness strip, magnitude bars, stacked feed bar ---- */
.trunc { max-width: 340px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.freshbar { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 22px; }
.freshbar .chip { display: inline-flex; align-items: center; gap: 7px; background: var(--card);
  border: 1px solid var(--border); border-radius:0; padding: 5px 12px; font-size: 12px; }
.freshbar .chip .t { color: var(--muted); }
.freshbar .chip strong { color: var(--text); font-variant-numeric: tabular-nums; }
.freshbar .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--faint); flex: none; }
.freshbar .dot.on { background: var(--good); }

.bar { position: relative; height: 8px; border-radius:0; background: var(--accent-soft); min-width: 40px; }
.bar > i { position: absolute; left: 0; top: 0; bottom: 0; border-radius:0; background: var(--accent); }
.barcell { width: 34%; }
.barrow { display: flex; align-items: center; gap: 10px; }
.barrow .bv { min-width: 42px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }
.barrow .bar { flex: 1; }

.hbars { display: flex; flex-direction: column; gap: 9px; margin-top: 4px; }
.hbars .hb { display: grid; grid-template-columns: 128px 1fr 56px; align-items: center; gap: 12px; font-size: 13px; }
.hbars .hb .lab { color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbars .hb .val { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }

.stack { display: flex; height: 30px; border-radius: var(--r-sm); overflow: hidden; border: 1px solid var(--border); }
.stack > span { display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  color: #fff; min-width: 0; }
.stack .ok { background: var(--good); }
.stack .no { background: var(--bad); }
.stack .pend { background: var(--faint); }
.stack-key { display: flex; flex-wrap: wrap; gap: 16px; margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.stack-key .sw { display: inline-block; width: 11px; height: 11px; border-radius:0; margin-right: 6px; vertical-align: -1px; }
.stack-key .sw.ok { background: var(--good); }
.stack-key .sw.no { background: var(--bad); }
.stack-key .sw.pend { background: var(--faint); }

@media (max-width: 640px) {
  .hbars .hb { grid-template-columns: 96px 1fr 48px; gap: 8px; font-size: 12px; }
  .trunc { max-width: 200px; }
}

/* ============================================================ HUB v2 shell
   Sidebar platform layout + refined surfaces. Appended layer — later rules win. */
/* Two named themes, one token set. Gold, black and white only -- no cream, no cool greys.
   Daniel chose both on 2026-09-17 from three mock-ups; see brand/README.md.

     Paper (light)  white working area, black navigation rail, gold reserved for measurement.
     Night (dark)   black ground, white text, gold on the current page and the lead figure.

   Explicit choices override the OS; "Match my device" keeps its existing meaning. Gold is a
   ground, not body text: #cba453 carries black at 8.5:1, and the one place gold is TEXT is the
   lead figure at 30px, where #a8853d on white is 3.48:1 -- above the 3:1 WCAG asks of large
   text, below the 4.5:1 this file's other pairs are held to by qa/test_theme_contrast.py. */
:root{
  --h2-bg:#ffffff; --h2-card:#ffffff; --h2-line:#dedbd4; --h2-line-2:#a9a49a;
  --h2-ink:#070707; --h2-ink2:#3b3a36; --h2-ink3:#575550;
  --h2-accent:#070707; --h2-accent-deep:#070707; --h2-accent-soft:#f4f2ee;
  /* Paper keeps the 2026-08 ruling that the current page is a panel and a gold RULE, not a
     gold fill. Night reverses it, because that is what Daniel picked on 2026-09-17. */
  --h2-sel:#1b1b18; --h2-sel-ink:#ffffff; --h2-sel-rule:#cba453;
  --h2-fig:#a8853d; --h2-fig-lead:#a8853d; --h2-fig-mut:#b8b3a8; --h2-track:#e7e4dd;
  --h2-surface-2:#f4f2ee; --h2-scrim:rgba(255,255,255,.96); --h2-dot:#6b6860;
  --h2-notice:#f4f2ee; --h2-notice-line:#a9a49a; --h2-notice-ink:#3b3a36;
  --h2-hero-a:#ffffff; --h2-hero-b:#ffffff; --h2-hero-line:#070707;
  --h2-on-accent:#ffffff; --h2-side:#070707; --h2-side-ink:#a8a49b;
  --h2-good:#215c3b; --h2-good-soft:#f4f2ee;
  --h2-warn:#6f4300; --h2-warn-soft:#f4f2ee;
  --h2-bad:#9b2c22; --h2-bad-soft:#f4f2ee;
  --rf-action:#070707; --rf-action-hover:#3b3a36; --rf-action-ink:#ffffff;
  --av-ink:#ffffff;
  --av0:#2b2b27; --av1:#3b3a36; --av2:#6f5a28; --av3:#575550;
  --av4:#4a4943; --av5:#514b3c; --av6:#3f3a2e;
  --ring:0 0 0 2px var(--h2-card),0 0 0 4px var(--h2-ink);
  color-scheme:light;
}
@media(prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --h2-bg:#070707; --h2-card:#111110; --h2-line:#2b2b27; --h2-line-2:#4a4943;
  --h2-ink:#ffffff; --h2-ink2:#d7d4cc; --h2-ink3:#b4b1a8;
  --h2-accent:#ffffff; --h2-accent-deep:#ffffff; --h2-accent-soft:#1b1b18;
  --h2-sel:#cba453; --h2-sel-ink:#070707; --h2-sel-rule:#cba453;
  --h2-fig:#cba453; --h2-fig-lead:#cba453; --h2-fig-mut:#4a4943; --h2-track:#242420;
  --h2-surface-2:#171714; --h2-scrim:rgba(7,7,7,.96); --h2-dot:#8b887f;
  --h2-notice:#171714; --h2-notice-line:#4a4943; --h2-notice-ink:#d7d4cc;
  --h2-hero-a:#111110; --h2-hero-b:#111110; --h2-hero-line:#cba453;
  --h2-on-accent:#070707; --h2-side:#070707; --h2-side-ink:#a8a49b;
  --h2-good:#9fd9b4; --h2-good-soft:#171714;
  --h2-warn:#e8c073; --h2-warn-soft:#171714;
  --h2-bad:#f0a79b; --h2-bad-soft:#171714;
  --rf-action:#ffffff; --rf-action-hover:#d7d4cc; --rf-action-ink:#070707;
  --av-ink:#070707;
  --av0:#c9c6be; --av1:#b4b1a8; --av2:#cba453; --av3:#a8a49b;
  --av4:#dedbd4; --av5:#bfa478; --av6:#9c9890;
  color-scheme:dark;
}}
:root[data-theme="dark"]{
  --h2-bg:#070707; --h2-card:#111110; --h2-line:#2b2b27; --h2-line-2:#4a4943;
  --h2-ink:#ffffff; --h2-ink2:#d7d4cc; --h2-ink3:#b4b1a8;
  --h2-accent:#ffffff; --h2-accent-deep:#ffffff; --h2-accent-soft:#1b1b18;
  --h2-sel:#cba453; --h2-sel-ink:#070707; --h2-sel-rule:#cba453;
  --h2-fig:#cba453; --h2-fig-lead:#cba453; --h2-fig-mut:#4a4943; --h2-track:#242420;
  --h2-surface-2:#171714; --h2-scrim:rgba(7,7,7,.96); --h2-dot:#8b887f;
  --h2-notice:#171714; --h2-notice-line:#4a4943; --h2-notice-ink:#d7d4cc;
  --h2-hero-a:#111110; --h2-hero-b:#111110; --h2-hero-line:#cba453;
  --h2-on-accent:#070707; --h2-side:#070707; --h2-side-ink:#a8a49b;
  --h2-good:#9fd9b4; --h2-good-soft:#171714;
  --h2-warn:#e8c073; --h2-warn-soft:#171714;
  --h2-bad:#f0a79b; --h2-bad-soft:#171714;
  --rf-action:#ffffff; --rf-action-hover:#d7d4cc; --rf-action-ink:#070707;
  --av-ink:#070707;
  --av0:#c9c6be; --av1:#b4b1a8; --av2:#cba453; --av3:#a8a49b;
  --av4:#dedbd4; --av5:#bfa478; --av6:#9c9890;
  color-scheme:dark;
}

html,body{background:var(--h2-bg)}
body{color:var(--h2-ink)}

/* ---- shell ---- */
.shell{display:flex;min-height:100vh}
.sidebar{width:230px;flex:0 0 230px;background:var(--h2-side);display:flex;flex-direction:column;
  padding:18px 12px 14px;position:sticky;top:0;height:100vh;overflow-y:auto}
.sidebar .brand{display:flex;align-items:center;gap:10px;color:#fff;font-weight:800;font-size:18px;
  text-decoration:none;padding:8px 10px 20px;letter-spacing:-.01em}
.sidebar .brand .mark{height:28px;width:auto;border-radius:0}
.side-group{margin:10px 0 2px}
.side-title{font-size:12px;font-weight:600;letter-spacing:.1em;text-transform:uppercase;
  color:var(--h2-side-ink);padding:8px 12px 5px}
.sidebar .item{display:flex;align-items:center;gap:9px;color:var(--h2-side-ink);text-decoration:none;
  font-size:15px;font-weight:500;padding:9px 12px;border-radius:0;margin:1px 0}
.sidebar .item:hover{background:rgba(255,255,255,.06);color:#fff}
/* Active navigation follows the selected theme's neutral selection pair. The fixed white
   fill bypassed Dark (2026-09-15 full-gate correction); the gold edge remains the active marker. */
.sidebar .item[aria-current="page"]{background:var(--h2-sel);color:var(--h2-sel-ink);
  position:relative}
.sidebar .item[aria-current="page"]::before{content:'';position:absolute;left:0;top:0;bottom:0;
  width:3px;background:var(--h2-sel-rule)}
.side-bottom{margin-top:auto;padding-top:12px;border-top:1px solid rgba(255,255,255,.08);color:var(--h2-side-ink)}
.side-bottom button.item{color:var(--h2-side-ink)}
.side-bottom button.item:hover{color:#fff}
.side-bottom .whoami{font-size:14px;color:var(--h2-side-ink);padding:6px 12px;display:block;text-decoration:none;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.side-bottom .whoami:hover{color:#fff}

.content{flex:1;min-width:0;padding:28px 34px 60px}
.content > *{max-width:1140px}
main#main{display:block}

/* mobile drawer */
.topbar{display:none}
@media(max-width:920px){
  .sidebar{position:fixed;left:-250px;z-index:60;transition:left .22s ease;height:100vh}
  .shell.nav-open .sidebar{left:0;box-shadow:0 0 60px rgba(0,0,0,.5)}
  .shell.nav-open .scrim{position:fixed;inset:0;background:rgba(7,7,7,.5);z-index:55}
  .topbar{display:flex;align-items:center;gap:12px;background:var(--h2-side);color:#fff;
    padding:12px 16px;position:sticky;top:0;z-index:50}
  .topbar .brand{display:flex;align-items:center;gap:9px;color:#fff;font-weight:800;text-decoration:none}
  .topbar .brand img{height:28px;width:auto;border-radius:0}
  .topbar .burger{margin-left:auto;background:none;border:0;color:#fff;font-size:22px;cursor:pointer}
  .content{padding:18px 16px 50px}
}

/* ---- page head ---- */
.content h1{font-size:23px;font-weight:800;letter-spacing:-.02em;margin:0 0 4px}
.content .sub{color:var(--h2-ink2);font-size:14px;line-height:1.55;max-width:78ch}

/* ---- cards & stats ---- */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(168px,1fr));gap:12px;margin:16px 0}
.card{background:var(--h2-card);border:1px solid var(--h2-line);border-radius:0;
  padding:15px 17px;box-shadow:0 1px 2px rgba(16,20,34,.04)}
.card .num{font-size:23px;font-weight:800;letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  color:var(--h2-ink);line-height:1.15;white-space:nowrap}
.card .lbl{font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  color:var(--h2-ink3);margin-top:5px;line-height:1.35}
.card.hero{border-color:var(--h2-hero-line);background:linear-gradient(180deg,var(--h2-hero-a),var(--h2-hero-b))}
.card.hero .num{color:var(--h2-fig-lead)}

/* ---- sections ---- */
.sec{background:var(--h2-card);border:1px solid var(--h2-line);border-radius:0;
  padding:20px 22px;margin:16px 0;box-shadow:0 1px 2px rgba(16,20,34,.04)}
.sechead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 4px}
.sechead h2{font-size:16.5px;font-weight:800;margin:0;letter-spacing:-.01em}
.sechead .eyebrow{font-size:10.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--h2-accent-deep)}
.secnote{font-size:12.5px;color:var(--h2-ink3);margin:2px 0 10px}
.content h2{font-size:15px;font-weight:750;margin:18px 0 8px;letter-spacing:-.01em}
.sec h2{font-size:13.5px;color:var(--h2-ink2);text-transform:none}

/* trust chips */
.trust{font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  padding:3.5px 10px;border-radius:0;margin-left:auto;white-space:nowrap}
.trust.rec{background:var(--h2-good-soft);color:var(--h2-good)}
.trust.dir{background:var(--h2-warn-soft);color:var(--h2-warn)}
.trust.neu{background:var(--h2-track);color:var(--h2-ink2)}

/* ---- tab bar ---- */
.tabbar{position:sticky;top:0;z-index:20;display:flex;gap:6px;flex-wrap:wrap;
  background:var(--h2-scrim);backdrop-filter:blur(8px);
  padding:10px 2px;margin:10px 0 4px;border-bottom:1px solid var(--h2-line)}
.tabbar a{font-size:12.5px;font-weight:700;color:var(--h2-ink2);text-decoration:none;
  padding:6.5px 13px;border-radius:0;border:1px solid transparent}
.tabbar a:hover{background:var(--h2-surface-2);border-color:var(--h2-line)}
/* Gold marks ONE thing per screen: the current page in the rail. An active tab is position
   too, so it takes the inverse ink pair instead of a second gold block. */
.tabbar a.on{background:var(--h2-accent);color:var(--h2-on-accent)}

/* ---- freshness chips ---- */
.freshbar{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0 2px}
.freshbar .chip{display:inline-flex;align-items:center;gap:7px;background:var(--h2-card);
  border:1px solid var(--h2-line);border-radius:0;padding:5px 12px;font-size:11.5px;color:var(--h2-ink2)}
.freshbar .chip strong{font-weight:700;color:var(--h2-ink);font-variant-numeric:tabular-nums}
.freshbar .dot{width:7px;height:7px;border-radius:50%;background:var(--h2-dot)}
.freshbar .dot.on{background:var(--h2-good);box-shadow:0 0 0 3px rgba(78,112,80,.18)}

/* ---- tables ---- */
.table-scroll{overflow-x:auto}
table{width:100%;border-collapse:collapse;font-size:13.5px}
thead th{text-align:left;font-size:10.5px;font-weight:750;letter-spacing:.06em;text-transform:uppercase;
  color:var(--h2-ink3);padding:7px 9px;border-bottom:1px solid var(--h2-line-2)}
tbody td{padding:7.5px 9px;border-bottom:1px solid var(--h2-line);font-variant-numeric:tabular-nums}
tbody tr:last-child td{border-bottom:none}
tbody tr:hover td{background:var(--h2-surface-2)}
th.right,td.right{text-align:right}
td.trunc{max-width:340px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
td.muted{color:var(--h2-ink3)}

/* ---- bars ---- */
.hbars{display:flex;flex-direction:column;gap:7px;margin:6px 0 4px}
.hb{display:grid;grid-template-columns:118px 1fr 64px;align-items:center;gap:10px;font-size:12.5px}
.hb .lab{color:var(--h2-ink2);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hb .val{text-align:right;font-weight:700;font-variant-numeric:tabular-nums}
.bar{height:8px;background:var(--h2-track);border-radius:0;overflow:hidden}
.bar i{display:block;height:100%;background:linear-gradient(90deg,var(--h2-accent),var(--h2-accent-deep));border-radius:0}
.barcell{width:34%}
.barrow{display:flex;align-items:center;gap:8px}
.barrow .bv{min-width:44px;text-align:right;font-weight:700;font-variant-numeric:tabular-nums}
.barrow .bar{flex:1}

/* ---- panels ---- */
.panel{background:var(--h2-card);border:1px solid var(--h2-line);border-radius:0;padding:14px 16px}
.panel.notice{background:var(--h2-notice);border-color:var(--h2-notice-line);font-size:13.5px;color:var(--h2-ink2)}
.panel.notice.warn{background:var(--h2-warn-soft);border-color:var(--h2-notice-line);color:var(--h2-notice-ink)}
.empty{background:var(--h2-card);border:1px dashed var(--h2-line-2);border-radius:0;padding:16px;
  color:var(--h2-ink3);font-size:13.5px}
.row{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.mt{margin-top:14px}
@media(max-width:760px){.row{grid-template-columns:1fr}}

/* feed stacked bar */
.stack{display:flex;height:26px;border-radius:0;overflow:hidden;gap:2px}
.stack span{display:flex;align-items:center;justify-content:center;color:#fff;font-size:11.5px;font-weight:700}
.stack .ok{background:var(--h2-good);color:var(--rf-action-ink)}.stack .no{background:var(--h2-bad);color:var(--rf-action-ink)}.stack .pend{background:var(--h2-dot)}
.stack-key{display:flex;gap:16px;margin-top:9px;font-size:12.5px;color:var(--h2-ink2)}
.stack-key .sw{display:inline-block;width:10px;height:10px;border-radius:0;margin-right:6px}
.stack-key .sw.ok{background:var(--h2-good)}.stack-key .sw.no{background:var(--h2-bad)}.stack-key .sw.pend{background:var(--h2-dot)}
.pill{font-size:11px;font-weight:700;padding:2.5px 9px;border-radius:0}
.pill.red{background:var(--h2-bad-soft);color:var(--h2-bad)}
.pill.amber{background:var(--h2-warn-soft);color:var(--h2-warn)}
.pill.gray{background:var(--h2-track);color:var(--h2-ink2)}

/* ==================== DASHBOARD REDESIGN — scoped to #dash (2026-07-24) ==================== */
/* The dashboard carries its own local token block. It hardcoded two light values, so every
   meter track and chart gridline on this screen stayed cream on an ink ground — and the sweep
   that was supposed to catch that only inspected PROPERTY declarations, never custom-property
   DEFINITIONS. Derived from the theme tokens now, so there is nothing left here to forget. */
#dash{ --dline:var(--h2-line); --dgrid:var(--h2-track); --dtrack:var(--h2-track);
       --dfaint:var(--h2-ink3) }
#dash .dtop{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:20px}
#dash h1{font-size:23px;margin:0;color:var(--h2-ink);letter-spacing:-.2px}
#dash .dsub{color:var(--muted);font-size:13.5px;margin-top:3px}
#dash .dlink{color:var(--accent-ink);font-weight:600;text-decoration:none}
#dash .dlink:hover{text-decoration:underline}

#dash .freshrow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:-6px 0 16px}
#dash .fasof{font-size:11.5px;color:var(--muted);font-weight:600;margin-right:2px}
#dash .fchip{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;color:var(--muted);
  background:var(--card);border:1px solid var(--dline);border-radius:0;padding:3px 10px}
#dash .fchip .fd{width:7px;height:7px;border-radius:50%;background:var(--good);flex:0 0 auto}
#dash .fchip.warn{color:var(--warn)}
#dash .fchip.warn .fd{background:var(--warn)}
#dash .kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:16px}
#dash .kpi{position:relative;overflow:hidden;background:var(--card);border:1px solid var(--dline);border-radius:0;padding:16px 18px;box-shadow:var(--shadow-sm)}
#dash .kpi .lbl{font:500 11px var(--font-body);letter-spacing:var(--track-eyebrow);text-transform:uppercase;color:var(--muted)}
/* Gold marks the figure the page exists to show -- the tile that says so in the markup,
   not whichever one happens to come first. */
#dash .kpi.lead .big{color:var(--h2-fig-lead)}
#dash .kpi .big{font-size:30px;font-weight:500;color:var(--h2-ink);letter-spacing:-.01em;margin-top:6px;line-height:1.1;font-variant-numeric:tabular-nums}
#dash .kpi .foot{margin-top:8px;font:300 12.5px var(--font-body);color:var(--muted);display:flex;align-items:center;gap:7px;flex-wrap:wrap}
#dash .delta{display:inline-flex;align-items:center;gap:3px;font-weight:700;padding:2px 7px;border-radius:0;font-size:11.5px}
#dash .delta.up{color:var(--good);background:var(--good-soft)}
#dash .delta.down{color:var(--bad);background:var(--bad-soft)}
#dash .delta.flat{color:var(--muted);background:var(--h2-track)}
/* In flow, not floated over the card: absolute right/bottom put this on top of the .foot
   text whenever the line wrapped ("the little chart is over the words" — owner, 19 Aug).
   A reserved full-width row under the foot cannot collide with copy at any width, and the
   line gets three times the room. */
#dash .spark{display:block;width:100%;height:30px;margin-top:10px;opacity:.9}

#dash .dgrid{display:grid;grid-template-columns:1.35fr 1fr;gap:16px;margin-top:16px;align-items:start}
#dash .dcard{min-width:0;background:var(--card);border:1px solid var(--dline);border-radius:0;padding:18px;box-shadow:var(--shadow-sm)}
#dash .dcard.wide{grid-column:1 / -1}
#dash .eyebrow{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--dfaint);font-weight:700}
#dash .dcard h2{font-size:15.5px;margin:3px 0 0;color:var(--h2-ink)}
#dash .take{font-size:12.5px;color:var(--muted);margin-top:11px;line-height:1.5}
#dash .take b{color:var(--text)}
#dash .chead{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
#dash .chead-r{text-align:right;flex:0 0 auto}
#dash .chead-r .v{font-size:20px;font-weight:700;color:var(--h2-ink);letter-spacing:-.3px;font-variant-numeric:tabular-nums}
#dash .chead-r .k{font-size:11px;color:var(--muted)}
#dash .chead-r .dn{color:var(--bad);font-weight:700}
#dash .chead-r .up{color:var(--good);font-weight:700}

#dash .bars{margin-top:14px;display:flex;flex-direction:column;gap:12px}
/* .bar is also a generic 8px meter on stores/insights/map (lines ~301/~446); those rules
   leak height/background/overflow into these grid rows and collapse them into grey pills,
   so every property they set is reset here. */
#dash .bar{display:grid;grid-template-columns:148px 1fr auto;align-items:center;gap:12px;position:static;height:auto;min-width:0;background:none;border-radius:0;overflow:visible}
#dash .bar.act{grid-template-columns:148px 1fr auto auto}
#dash .bar .bl{font-size:13px;color:var(--text);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#dash .bar .bl a{color:var(--text);text-decoration:none}
#dash .bar .bl a:hover{color:var(--accent-ink)}
#dash .bar .track{height:9px;background:var(--dtrack);border-radius:0;overflow:hidden}
#dash .bar .fill{display:block;height:100%;background:var(--h2-fig);border-radius:0}
#dash .bar .fill.mut{background:var(--dfaint)}
#dash .bar .bv{font-size:12.5px;font-weight:700;color:var(--text);min-width:56px;text-align:right;font-variant-numeric:tabular-nums}
#dash .mini{font-size:11px;font-weight:600;color:var(--accent-ink);border:1px solid var(--dline);border-radius:0;padding:4px 9px;text-decoration:none;white-space:nowrap}
#dash .mini:hover{border-color:var(--accent);background:var(--accent-soft)}

/* share column for bar rows that carry a percentage (denominator stated in the take) */
#dash .bar.pct{grid-template-columns:148px 1fr auto auto}
#dash .bar .bp{font-size:11.5px;color:var(--muted);min-width:34px;text-align:right;font-variant-numeric:tabular-nums}

#dash .act-list{margin-top:12px;display:flex;flex-direction:column}
#dash .act-row{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 2px;border-top:1px solid var(--dline)}
#dash .act-row:first-child{border-top:0}
#dash .act-row .an{font-size:13px;color:var(--text);font-weight:600}
#dash .act-row .am{font-size:11.5px;color:var(--muted)}
#dash .pill.live{background:var(--good-soft);color:var(--good)}
#dash .pill.off{background:var(--h2-track);color:var(--muted)}
#dash .pill.test{background:var(--accent-soft);color:var(--accent-ink)}
#dash .pill.snap{background:var(--warn-soft);color:var(--warn)}

#dash .plot{width:100%;height:auto;display:block;margin-top:12px;overflow:visible}
#dash .plot .grid-l{stroke:var(--dgrid);stroke-width:1}
#dash .plot .axis-t{fill:var(--dfaint);font-size:10.5px}
#dash .plot .line{fill:none;stroke:var(--h2-fig);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
#dash .plot .dot{fill:var(--h2-fig);stroke:var(--card);stroke-width:2}
#dash .plot .cross{stroke:var(--h2-fig);stroke-width:1;stroke-dasharray:3 3;opacity:0;pointer-events:none}
#dash .plot .hdot{fill:var(--accent);stroke:var(--card);stroke-width:2;opacity:0;pointer-events:none}

/* ---- the Google page's bar chart (templates/google.html), 2026-09-18. Gold is the measurement:
   the bars take --h2-fig, as the dashboard's trend line does; a stretch no read has covered is a
   thin mark in --h2-fig-mut on the baseline rather than a gap that reads as zero; the baseline
   takes the track and the labels --muted. Tokens only, so both themes are right by construction
   and qa/test_theme_contrast.py has nothing local to check. */
.gchart-wrap{margin:14px 0 6px}
.gchart{width:100%;height:auto;display:block;overflow:visible}
.gchart .gbar{fill:var(--h2-fig)}
.gchart .gbar-unread,.gchart .gbar.gbar-part{fill:var(--h2-fig-mut)}
.gchart .gbase{stroke:var(--h2-track);stroke-width:1}
.gaxis{display:flex;justify-content:space-between;font-size:12px;color:var(--muted);
  font-variant-numeric:tabular-nums;margin-top:4px}

.dtip{position:fixed;pointer-events:none;background:var(--ink);color:#fff;padding:7px 10px;border-radius:0;font-size:12px;font-weight:500;opacity:0;transition:opacity .1s;box-shadow:0 6px 20px rgba(0,0,0,.25);z-index:9999;white-space:nowrap}
.dtip b{color:#fff}

/* ---- page header (was wrongly sharing .topbar with the mobile nav drawer, which is
   display:none on desktop — that hid the h1, the description AND the primary action button
   on 9 pages, e.g. "Run flows now" on /flows. Content pages now use .pagehead.) ---- */
.pagehead{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;
  flex-wrap:wrap;margin-bottom:18px}
.pagehead h1{font-size:23px;font-weight:800;letter-spacing:-.02em;margin:0 0 4px;color:var(--h2-ink)}
.pagehead .sub{color:var(--h2-ink2);font-size:14px;line-height:1.55;max-width:78ch;margin:0}
.pagehead form{flex:0 0 auto}

/* stores table */
#dash table.stbl{width:100%;border-collapse:collapse;margin-top:14px;font-size:13px}
#dash table.stbl th{text-align:left;font-size:11px;letter-spacing:.05em;text-transform:uppercase;
  color:var(--muted);font-weight:700;padding:0 10px 8px;border-bottom:1px solid var(--dline);white-space:nowrap}
#dash table.stbl th.right,#dash table.stbl td.right{text-align:right}
#dash table.stbl td{padding:11px 10px;border-bottom:1px solid var(--dline);vertical-align:middle;
  font-variant-numeric:tabular-nums;white-space:nowrap}
#dash table.stbl tr:last-child td{border-bottom:0}
#dash table.stbl tbody tr:hover{background:var(--accent-soft)}
#dash table.stbl .scode{display:inline-block;margin-left:7px;font-size:10.5px;font-weight:700;
  color:var(--muted);background:var(--dtrack);border-radius:0;padding:1px 6px}
#dash table.stbl .shr{font-size:11px;color:var(--muted);margin-left:2px}
#dash table.stbl .msp{width:90px;height:26px;display:block}
#dash tr.muted-row td{opacity:.55}

@media (max-width:1000px){ #dash .kpis{grid-template-columns:repeat(2,1fr)} #dash .dgrid{grid-template-columns:1fr} }
@media (max-width:520px){ #dash .kpis{grid-template-columns:1fr} #dash .bar{grid-template-columns:96px 1fr auto} }

/* ---------------------------------------------------------------- campaign results
   A funnel of four ratios against one limit: meters on a shared track, not a chart.
   Deliberately unscoped (no #dash prefix) because the same markup renders on the
   dashboard and on the campaign page, and a scoped rule would silently style only one.
   Colours come from the existing tokens — accent for the stages that carry the result,
   the muted grey for Delivered, which is only the denominator. */
.cres { border: 1px solid var(--border); border-radius: var(--r-md); padding: 14px 16px;
        background: var(--card); }
.cres + .cres { margin-top: 10px; }
.cres-head { display: flex; align-items: flex-start; justify-content: space-between;
             gap: 16px; margin-bottom: 12px; }
.cres-name { font-weight: 650; color: var(--text); line-height: 1.3; }
.cres-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.cres-open { color: var(--warn); font-weight: 600; }
/* NO nowrap HERE. It belongs on the figure, and this block holds sentences as well: the
   "Among customers who received this, N purchased $X within 14 days" line lives inside it
   (_campaign_results.html). With nowrap on the block, that sentence became one 538px line inside
   a 400px row, and the dashboard's Campaign results card cut 201, 231 and 190 pixels of text off
   three campaigns. MEASURED on production 2026-09-21, the owner's own screen; invisible in every
   local check because a fresh tenant has no campaign results to render. */
.cres-money { text-align: right; }
/* The one number a client looks for first, so it gets hero treatment, and it is the thing that
   must not break across lines. */
.cres-rev { font-size: 24px; font-weight: 700; color:var(--h2-ink); letter-spacing: -.02em;
            line-height: 1.1; white-space: nowrap; }

.cres-funnel { display: grid; gap: 7px; }
.cres-row { display: grid; grid-template-columns: 78px 1fr 62px 46px; align-items: center;
            gap: 10px; }
.cres-k { font-size: 12px; color: var(--muted); }
.cres-track { height: 9px; background: var(--h2-track); border-radius:0;
              overflow: hidden; }
.cres-fill { display: block; height: 100%; background: var(--h2-fig); border-radius:0; }
/* A floor so a real-but-tiny result is still a visible bar — applied ONLY when the value is
   above zero. Putting it on every fill drew a nub next to "Clicked 0", which reads as "a
   few" at a glance and is the exact opposite of what the number says. */
.cres-fill.nz { min-width: 3px; }
.cres-fill.mut { background: var(--faint); }
.cres-n { font-size: 13px; font-weight: 600; color: var(--text); text-align: right;
          font-variant-numeric: tabular-nums; }
.cres-r { font-size: 12px; color: var(--muted); text-align: right;
          font-variant-numeric: tabular-nums; }

.cres-note { margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--border);
             font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.cres-note b { color: var(--text); }
.cres-caveat { margin-top: 7px; font-size: 12px; color: var(--faint); line-height: 1.5; }

.cres.compact { padding: 11px 13px; }
.cres.compact .cres-rev { font-size: 19px; }
.cres.compact .cres-row { grid-template-columns: 66px 1fr 54px 42px; gap: 8px; }

@media (max-width: 560px) {
  .cres-row { grid-template-columns: 62px 1fr 50px 40px; gap: 7px; }
  .cres-head { flex-direction: column; gap: 6px; }
  .cres-money { text-align: left; }
}

/* The whole result card is the click target on the dashboard; it must not look like a link
   (no underline, no accent text) or the numbers inside stop reading as data. */
.cres-link { display: block; text-decoration: none; color: inherit; }
.cres-link:hover .cres { border-color: var(--accent); box-shadow: var(--shadow-xs); }
.cres-link:focus-visible { outline: none; }
.cres-link:focus-visible .cres { box-shadow: var(--ring); border-color: var(--accent); }
/* Figures in a results table line up only with tabular figures; proportional digits make a
   column of numbers ragged and hard to compare down the page. */
td.num, th.num { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- live ad campaigns
   Same meter vocabulary as campaign results, so paid and owned media read as one system. */
.adtot { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
         padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--border); }
.adtot-v { font-size: 26px; font-weight: 700; color:var(--h2-ink); letter-spacing: -.02em;
           line-height: 1.1; }
.adlist { display: grid; gap: 13px; }
.adrow-top { display: flex; align-items: center; justify-content: space-between; gap: 10px;
             margin-bottom: 5px; }
.adname { font-size: 13px; font-weight: 600; color: var(--text); line-height: 1.3;
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adbar { display: grid; grid-template-columns: 1fr 72px; align-items: center; gap: 10px; }
.adspend { font-size: 13px; font-weight: 600; color: var(--text); text-align: right;
           font-variant-numeric: tabular-nums; }
.admeta { font-size: 12px; color: var(--muted); margin-top: 4px; }
.admeta b { color: var(--text); }
/* Spend with nothing to show for it is the finding, not a blank — say it in words. */
.adnone { color: var(--warn); }
.adwarn { margin-top: 12px; font-size: 12.5px; color: var(--warn); line-height: 1.5; }

/* --- the expandable campaign row -------------------------------------------------------
   <details> rather than a click handler: keyboard-operable, opens under find-in-page, prints
   open, and survives the script never loading. The summary is the row that was already
   there, so the closed state is unchanged for anyone who never opens one.

   Disclosure controls use the surrounding neutral contrast. */
.adrow { border-bottom: 1px solid var(--border); padding-bottom: 12px; }
.adrow:last-child { border-bottom: 0; padding-bottom: 0; }
.adrow-sum { cursor: pointer; list-style: none; padding: 2px 0 0 18px; position: relative;
             border-radius: 0; }
.adrow-sum::-webkit-details-marker { display: none; }
/* The triangle is drawn rather than borrowed from the UA so it sits on the baseline of the
   campaign name at every zoom level. */
.adrow-sum::before { content: ''; position: absolute; left: 2px; top: 7px;
                     border: 4px solid transparent; border-left-color: var(--muted);
                     transition: transform 120ms linear; transform-origin: 25% 50%; }
.adrow[open] > .adrow-sum::before { transform: rotate(90deg); }
.adrow-sum:hover .adname { text-decoration: underline; text-underline-offset: 2px; }
.adrow-sum:focus-visible { outline: 2px solid var(--focus, var(--accent)); outline-offset: 2px; }

.addet { margin: 10px 0 2px 18px; padding: 12px 14px; background: var(--h2-surface-2);
         border: 1px solid var(--border); }
.addet-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
              gap: 10px 18px; margin: 0; }
.addet-grid dt { font-size: 11px; letter-spacing: .04em; text-transform: uppercase;
                 color: var(--muted); margin: 0 0 2px; }
.addet-grid dd { margin: 0; font-size: 14px; font-weight: 600; color: var(--text);
                 font-variant-numeric: tabular-nums; }
/* A finding, not decoration — it only appears when the number crosses the line. */
.adflag { display: inline-block; font-size: 11px; font-weight: 600; color: var(--warn);
          letter-spacing: .02em; }
.adbudget { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border);
            font-size: 12.5px; color: var(--muted); line-height: 1.55; }
.adbudget b { color: var(--text); }

@media (prefers-reduced-motion: reduce) {
  .adrow-sum::before { transition: none; }
}


/* ============================================================ Rinforza type
   Space Grotesk carries headings and the brand row; IBM Plex Mono carries the
   numerals (naturally tabular — Barlow's figures are not). Barlow does the rest. */
h1, .content h1, .sechead h2, .content h2, .sidebar .brand, .topbar .brand {
  font-family: var(--font-display);
}
/* Figures in the display face, not the mono. See the note beside --font-display. */
.card .num, #dash .kpi .big, .kpi .big {
  font-family: var(--font-display);
  font-weight: 500; letter-spacing: -0.01em;
}

/* device/bar values hold one line — '15,959 · 49%' must not wrap mid-figure */
.hb .val{white-space:nowrap}
.hb{grid-template-columns:118px 1fr auto}
.hbars .hb{grid-template-columns:128px 1fr auto}

/* deployed version — quiet, but always answerable in a support conversation */
.side-version{font-size:12px;letter-spacing:.04em;color:var(--h2-side-ink);padding:6px 12px 2px;
  font-family:'IBM Plex Mono',ui-monospace,monospace}

/* ---- Setup wizard --------------------------------------------------------
   Status is carried by a word and a mark, never by colour alone: the page is
   read by someone deciding what to chase next, and "red means you" fails for
   anyone who cannot separate red from green. */
.setup-bar{height:6px;background:var(--border);overflow:hidden}
.setup-bar span{display:block;height:100%;background:var(--accent)}
.setup-sum{margin-top:.6rem;font-size:.95rem}
.setup-step{display:flex;gap:.85rem;padding:.85rem 1rem;border:1px solid var(--border);
  border-top:0;background:var(--card)}
.setup-step:first-of-type{border-top:1px solid var(--border)}
.setup-mark{flex:0 0 1.4rem;text-align:center;font-weight:700;line-height:1.5}
.setup-step.done .setup-mark{color:var(--accent)}
.setup-step.skip{opacity:.55}
.setup-step.skip .setup-mark,.setup-step.todo .setup-mark{color:var(--muted)}
.setup-step.waiting .setup-mark,.setup-step.unknown .setup-mark{color:var(--warn)}
.setup-body{flex:1 1 auto;min-width:0}
.setup-title{font-weight:600;display:flex;flex-wrap:wrap;gap:.45rem;align-items:center}
.setup-why{color:var(--muted);font-size:.9rem;margin-top:.2rem}
.setup-detail{font-size:.9rem;margin-top:.35rem;overflow-wrap:anywhere}
/* What to do and who does it (2026-09-17). Not muted: on a step that is not done this is the
   sentence somebody acts on, while the detail above it is what was measured. */
.setup-how{font-size:.9rem;margin-top:.35rem}
/* Exact values to copy -- the records at a domain provider, the STOP test. One value per cell so
   a whole value can be selected without picking it out of a sentence. */
.setup-records{font-size:.85rem;border-collapse:collapse;margin-top:.5rem}
.setup-records th{text-align:left;color:var(--muted);font-weight:600;padding:.15rem .8rem .15rem 0}
.setup-records td{padding:.15rem .8rem .15rem 0;overflow-wrap:anywhere}
.setup-records code{user-select:all}
/* One line per channel, under the headline on Setup and on Help. */
.setup-channels{margin:.5rem 0 0;padding-left:1.1rem;font-size:.95rem}
.setup-channels li{margin-top:.2rem}
/* The wizard listed twenty-four things and linked to none of them (2026-08-22). */
.setup-action{margin-top:.45rem;font-size:.9rem}
/* Explicit colour, not the browser default. An unstyled <a> renders #0000ee, which on the
   ink background is about 1.1:1 and effectively invisible -- the link was there and could
   not be read. */
.setup-action a{color:var(--text);font-weight:600;text-decoration:none;
                border-bottom:1px solid var(--accent)}
.setup-action a:hover{border-bottom-color:var(--text)}

/* Neutral action controls leave the active navigation edge as the single gold accent. */
.btn{ background:var(--rf-action); color:var(--rf-action-ink); }
.btn:hover{ background:var(--rf-action-hover); }
.btn:focus-visible{ box-shadow:var(--ring), 0 0 0 1px var(--rf-action); }
.btn.secondary{ background:var(--card); color:var(--text); }
.btn.danger{ background:var(--bad); color:var(--rf-action-ink); }

/* Focus has an opaque high-contrast edge in both palettes. */
input:focus, select:focus, textarea:focus{ border-color:var(--rf-action); }
:where(a, button, input, select, textarea):focus-visible{ outline-color:var(--rf-action); }

/* Visible to screen readers, not to the eye. Added 2026-08-24 for the Flows table's action
   column, whose header was empty — a screen reader announced nothing for the column holding the
   Enable/Disable button. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Flows table. Nine columns in one row, two of them holding <select> controls that decide how
   often a person is emailed and which email goes out. At the default auto layout those cells
   collapsed to 120px and the browser clipped the labels to "After eacl" and "Built-in c" — a
   setting you cannot read without opening it. Give the control columns room and let the prose
   columns wrap instead. Added 2026-08-24 after reading the rendered table, not the markup. */
.flows-table select { width: 100%; }
.flows-table th:nth-child(4), .flows-table td:nth-child(4),
.flows-table th:nth-child(5), .flows-table td:nth-child(5) { min-width: 175px; }
.flows-table th:nth-child(2), .flows-table td:nth-child(2),
.flows-table th:nth-child(3), .flows-table td:nth-child(3) { min-width: 120px; }

/* Option A shared controls and type: change presentation, never hide status or actions. */
.content h1,.pagehead h1,#dash h1{font-size:30px;font-weight:500;letter-spacing:-.025em;line-height:1.2}
.content h2{font-weight:500;text-transform:none}
.content .sub,.secnote{font-size:14px;color:var(--h2-ink2)}
.card .lbl,.card .foot,.freshbar .chip{font-size:13px;font-weight:400;letter-spacing:0;text-transform:none}
thead th{font-size:13px;letter-spacing:.015em;text-transform:none;color:var(--h2-ink2);font-weight:600;background:var(--h2-surface-2)}
tbody td{font-size:14px;padding:11px 12px}
.content label{font-size:14px;letter-spacing:0;text-transform:none;font-weight:500;color:var(--h2-ink2)}
.content input,.content select,.content textarea{font-size:16px;border-radius:0!important;max-width:100%}
select option{background:var(--h2-card);color:var(--h2-ink)}
input::placeholder,textarea::placeholder{color:var(--h2-ink3);opacity:1}
:where(button,input,select,textarea):disabled{opacity:1;color:var(--h2-ink3);background:var(--h2-surface-2);cursor:not-allowed}
.btn.danger{background:var(--h2-bad-soft);color:var(--h2-bad);border:1px solid var(--h2-bad)}
.content a:not(.btn){text-underline-offset:3px}
.content :where(p,dd,li){overflow-wrap:anywhere}
.topbar .burger{min-width:44px;min-height:44px;font:500 16px var(--font-body)}
.sidebar :focus-visible,.topbar :focus-visible{outline:2px solid #ffffff;outline-offset:3px;box-shadow:none}
.sidebar .item[aria-current="page"]:focus-visible{outline-offset:-4px;outline-color:var(--h2-sel-ink)}
@media(max-width:700px){.content h1,.pagehead h1,#dash h1{font-size:26px}.pagehead{gap:14px;flex-wrap:wrap}.pagehead>div{min-width:0;max-width:100%}.content .sub{max-width:100%}}

/* The accepted campaign preview defines local colors after this stylesheet. Keep
   its presentation aligned with both Account themes without altering email HTML. */
:root .shell .content .campaign-detail{--preview-bg:var(--h2-card);--preview-ink:var(--h2-ink);--preview-muted:var(--h2-ink2);--preview-line:var(--h2-line-2);--preview-ground:var(--h2-surface-2);--preview-accent:var(--h2-ink)}
