/* ================================================================
   Dark dashboard theme — scoped to body.dash-dark
   Applies to all /admin/* and /promoter/* pages so the dashboards
   match the ambassador / public-site aesthetic (true near-black).
   Loaded after app.css so it overrides.

   2026-06-06 — Palette repulled from #0b1220/#0f172a slate-blue to
   #0a0a0a/#141414 near-black to match body.landing-dark (used on
   homepage, /services, /ambassador/*, /promoter/login, etc.). The
   slate-blue artifact came from an earlier dashboards-feel-like-Stripe
   moment; now everything flows on one palette. Tokens only — every
   downstream selector already references --dd-* so nothing else
   needed touching.
   ================================================================ */

body.dash-dark {
  /* Near-black palette — same family as body.landing-dark (#0a0a0a body,
     #141414 cards). Three surface tiers give us depth without leaving the
     near-black register. */
  --dd-bg:           #0a0a0a;   /* page background (was #0b1220 slate) */
  --dd-bg-alt:       #0a0a0a;   /* gradient endpoint — now flat */
  --dd-surface:      #141414;   /* primary card surface (was #1e293b) */
  --dd-surface-2:    #0f0f0f;   /* sunk / input field bg (was #0f172a) */
  --dd-surface-3:    #1a1a1a;   /* card header / hover lift (was #15233a) */
  --dd-border:       rgba(255,255,255,0.08);
  --dd-border-soft:  rgba(255,255,255,0.05);
  --dd-text:         #f8fafc;
  --dd-text-soft:    #cbd5e1;
  --dd-text-muted:   #94a3b8;
  --dd-text-faint:   #64748b;
  /* Inherit the tenant accent the header injects on partner domains; on native
     BuzzHive --accent is #ec4899, so the god-admin + BuzzHive promoter dash stay
     orange exactly as before. */
  --dd-accent:       var(--accent, #ec4899);
  --dd-accent-soft:  rgba(236,72,153, 0.15);
  --dd-accent-soft:  color-mix(in srgb, var(--accent, #ec4899) 15%, transparent);

  /* Override the light-theme tokens from app.css so any component that uses
     `var(--bg-sunk)` / `var(--fg)` etc. on a dash page picks a dark surface
     instead of the original `#f1f5f9`. Without these overrides the admin
     support inbox detail page renders inset boxes (Original message, AI
     draft, Claude review reason) as near-white panels on a dark page,
     making the white-on-white text unreadable. */
  --bg-sunk:    var(--dd-surface-3);
  --bg-soft:    var(--dd-surface-2);
  --bg-card:    var(--dd-surface);
  --bg-app:     var(--dd-bg);
  --fg:         var(--dd-text);
  --fg-muted:   var(--dd-text-muted);
  --border:     var(--dd-border);
  --border-soft: var(--dd-border-soft);

  /* 2026-07-19 whitebox-kill — COMPLETE the override set. app.css :root also
     defines --bg / --border-strong / --accent-soft / --success-soft /
     --warning-soft / --danger-soft in LIGHT values, and this block never
     flipped them. Any dash component reaching for one of those rendered a
     white/light box on the dark dashboard (outreach recipient picker
     2026-07-17, team invite credentials card 2026-07-19, admin/audience.php
     row-actions menu, promoter/events/edit.php .vibe-card). Overriding every
     surface token here makes that entire bug class impossible on dash pages.
     Public pages are unaffected (scoped to body.dash-dark); the studio apps
     (.vs2/.ws/.gs/#vbe) define their own local --bg and are likewise
     unaffected. HARD RULE: no light CSS on the dashboards, ever. */
  --bg:            var(--dd-bg);
  --border-strong: rgba(255, 255, 255, 0.16);
  --accent-soft:   rgba(236,72,153, 0.15);
  --accent-soft:   color-mix(in srgb, var(--accent, #ec4899) 15%, transparent);
  --success-soft:  rgba(5, 150, 105, 0.15);
  --warning-soft:  rgba(217, 119, 6, 0.15);
  --danger-soft:   rgba(220, 38, 38, 0.15);

  /* Flat near-black — no gradient. landing-dark is flat #0a0a0a; matching it. */
  background: var(--dd-bg);
  color: var(--dd-text);
  min-height: 100vh;
}

/* ---------- Header / nav ---------- */
body.dash-dark .site-header {
  background: rgba(10, 10, 10, 0.92);
  border-bottom: 1px solid var(--dd-border);
  backdrop-filter: blur(8px);
}
body.dash-dark .brand { color: var(--dd-text); }
body.dash-dark .brand-mark { background: var(--dd-accent); color: #0a0a0a; }
body.dash-dark .nav a { color: var(--dd-text-soft); }
body.dash-dark .nav a:hover { color: var(--dd-text); }
body.dash-dark .nav a.btn-secondary {
  border: 1px solid var(--dd-border);
  color: var(--dd-text-soft);
  background: transparent;
  border-radius: 999px;
}
body.dash-dark .nav a.btn-secondary:hover {
  border-color: var(--dd-accent);
  color: var(--dd-text);
}
body.dash-dark .nav a.btn-primary {
  background: var(--dd-accent);
  color: #0a0a0a;
  border-radius: 999px;
  font-weight: 700;
}
body.dash-dark .nav a.btn-primary:hover { filter: brightness(1.1); }

/* ---------- Dash shell + sidebar ---------- */
body.dash-dark .dash-shell {
  background: transparent;
}
body.dash-dark .dash-sidebar {
  background: var(--dd-bg);
  border-right: 1px solid var(--dd-border);
  color: var(--dd-text-soft);
}
body.dash-dark .dash-sidebar .eyebrow {
  color: var(--dd-accent);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
body.dash-dark .dash-sidebar > div:first-child {
  border-bottom-color: var(--dd-border) !important;
}
body.dash-dark .menu a {
  color: var(--dd-text-soft);
  padding: 8px 12px;
  border-radius: 8px;
  transition: background 0.15s, color 0.15s;
  display: block;
  text-decoration: none;
}
body.dash-dark .menu a:hover {
  background: rgba(255,255,255,0.04);
  color: var(--dd-text);
}
body.dash-dark .menu a.active {
  background: var(--dd-accent-soft);
  color: var(--dd-accent);
  font-weight: 600;
  box-shadow: inset 2px 0 0 var(--dd-accent);
}
body.dash-dark .menu .group-label {
  color: var(--dd-text-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 16px 12px 6px;
}

body.dash-dark .dash-main { color: var(--dd-text); }

/* ---------- Headings ---------- */
body.dash-dark h1,
body.dash-dark h2,
body.dash-dark h3,
body.dash-dark h4 { color: var(--dd-text); }
body.dash-dark h1 { font-weight: 800; letter-spacing: -0.02em; }

/* ---------- Eyebrow + utility text ---------- */
body.dash-dark .eyebrow {
  color: var(--dd-accent);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
body.dash-dark .muted { color: var(--dd-text-muted); }
body.dash-dark .mono-sm { color: var(--dd-text-muted); }
body.dash-dark p { color: var(--dd-text-soft); }
body.dash-dark a { color: var(--dd-accent); }
body.dash-dark a:hover { filter: brightness(1.15); }
body.dash-dark code {
  background: var(--dd-surface-2);
  color: var(--dd-text-soft);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.9em;
}
body.dash-dark hr {
  border: 0;
  border-top: 1px solid var(--dd-border);
}

/* ---------- Cards ---------- */
body.dash-dark .card,
body.dash-dark .card-flat,
body.dash-dark .card-padless {
  background: var(--dd-surface);
  border: 1px solid var(--dd-border);
  color: var(--dd-text-soft);
  border-radius: 14px;
  box-shadow: 0 20px 40px -20px rgba(0,0,0,0.4);
}
body.dash-dark .card-flat { box-shadow: none; background: var(--dd-surface-3); }
body.dash-dark .card-header {
  background: var(--dd-surface-3);
  border-bottom: 1px solid var(--dd-border);
  padding: var(--s-4, 16px) var(--s-5, 20px);
  border-radius: 14px 14px 0 0;
}
body.dash-dark .card-header h3 { margin: 0; color: var(--dd-text); }

/* ---------- Stat cards (overview metrics) ---------- */
body.dash-dark .stat-card {
  background: var(--dd-surface);
  border: 1px solid var(--dd-border);
  border-radius: 12px;
  padding: var(--s-4, 16px) var(--s-5, 20px);
}
body.dash-dark .stat-card .label {
  color: var(--dd-text-faint);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
body.dash-dark .stat-card .value {
  color: var(--dd-text);
  font-size: 32px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-top: 4px;
}

/* ---------- Tables ---------- */
body.dash-dark .table { color: var(--dd-text-soft); border-collapse: collapse; }
body.dash-dark .table thead th {
  background: var(--dd-surface-3);
  color: var(--dd-text-faint);
  border-bottom: 1px solid var(--dd-border);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 12px 16px;
}
body.dash-dark .table tbody td {
  border-bottom: 1px solid var(--dd-border-soft);
  padding: 14px 16px;
  color: var(--dd-text-soft);
}
body.dash-dark .table tbody tr:hover td { background: rgba(255,255,255,0.025); }
body.dash-dark .table tbody tr:last-child td { border-bottom: 0; }
body.dash-dark .table strong { color: var(--dd-text); }
body.dash-dark .table a { color: var(--dd-accent); }
/* Table-cell buttons need explicit text color because `.table a`
   (above) otherwise overrides to orange — invisible against the orange
   .btn-primary background. Caught 2026-06-08 on the cross-share
   recent-assets table. */
body.dash-dark .table a.btn-primary,
body.dash-dark .table a.btn-primary:hover { color: #0a0a0a; }
body.dash-dark .table a.btn-secondary,
body.dash-dark .table a.btn-ghost { color: var(--dd-text-soft); }

/* ---------- Liquid tables on mobile ----------
   On phones a wide data table would overflow, so every .table reflows into a
   stack of cards: one card per row, each cell on its own line with its column
   name as a label (the label is injected from <thead> by a small script in
   footer.php — see dash-table-stack). No horizontal scroll, fits any width. */
@media (max-width: 720px) {
  body.dash-dark .table,
  body.dash-dark .table tbody,
  body.dash-dark .table tr,
  body.dash-dark .table td { display: block; width: 100%; }
  body.dash-dark .table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  body.dash-dark .table tr {
    border: 1px solid var(--dd-border);
    border-radius: 10px;
    padding: 4px 13px;
    margin-bottom: 12px;
    background: var(--dd-surface-2);
  }
  body.dash-dark .table tbody td {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    text-align: right;
    border: 0;
    border-bottom: 1px solid var(--dd-border-soft);
    padding: 10px 0;
  }
  body.dash-dark .table tbody tr td:last-child { border-bottom: 0; }
  body.dash-dark .table tbody td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    text-align: left;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--dd-text-faint);
  }
  body.dash-dark .table tbody td[data-label=""]::before { content: none; }
}

/* ---------- Form inputs ---------- */
body.dash-dark .input,
body.dash-dark .select,
body.dash-dark .textarea,
body.dash-dark input[type=text],
body.dash-dark input[type=email],
body.dash-dark input[type=password],
body.dash-dark input[type=number],
body.dash-dark input[type=date],
body.dash-dark input[type=time],
body.dash-dark input[type=datetime-local],
body.dash-dark input[type=search],
body.dash-dark input[type=url],
body.dash-dark select,
body.dash-dark textarea {
  background: var(--dd-surface-2);
  border: 1px solid rgba(255,255,255,0.12);
  color: var(--dd-text);
  padding: 10px 13px;
  border-radius: 8px;
  font-size: 14px;
  transition: border-color 0.15s, box-shadow 0.15s;
  /* Render native widgets (number spinner, date/time pickers) in dark mode so the
     up/down arrows match the dark UI instead of showing grey browser boxes. */
  color-scheme: dark;
}
body.dash-dark .input::placeholder,
body.dash-dark textarea::placeholder,
body.dash-dark input::placeholder { color: var(--dd-text-faint); }
body.dash-dark .input:focus,
body.dash-dark .select:focus,
body.dash-dark .textarea:focus,
body.dash-dark input:focus,
body.dash-dark select:focus,
body.dash-dark textarea:focus {
  outline: none;
  border-color: var(--dd-accent);
  box-shadow: 0 0 0 3px rgba(236,72,153,0.18);
}
body.dash-dark .field label,
body.dash-dark label {
  color: var(--dd-text-soft);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
body.dash-dark .field .help,
body.dash-dark .help,
body.dash-dark span.help { color: var(--dd-text-muted); font-size: 12px; }

/* ---------- Buttons ---------- */
body.dash-dark .btn-primary {
  background: var(--dd-accent);
  color: #0a0a0a;
  border: 0;
  border-radius: 8px;
  font-weight: 700;
  box-shadow: 0 6px 16px -6px rgba(236,72,153,0.5);
}
body.dash-dark .btn-primary:hover { filter: brightness(1.1); }
body.dash-dark .btn-secondary {
  background: var(--dd-surface-3);
  border: 1px solid var(--dd-border);
  color: var(--dd-text-soft);
  border-radius: 8px;
}
body.dash-dark .btn-secondary:hover {
  border-color: var(--dd-accent);
  color: var(--dd-text);
}
body.dash-dark .btn-ghost {
  background: transparent;
  border: 1px solid transparent;
  color: var(--dd-text-soft);
  border-radius: 8px;
}
body.dash-dark .btn-ghost:hover {
  background: rgba(255,255,255,0.04);
  color: var(--dd-text);
}
body.dash-dark .btn-block { width: 100%; }
body.dash-dark .btn-lg { padding: 14px 22px; font-size: 16px; }

/* ---------- Badges ---------- */
body.dash-dark .badge {
  background: var(--dd-surface-3);
  color: var(--dd-text-soft);
  border: 1px solid var(--dd-border);
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.03em;
}
body.dash-dark .badge-success {
  background: rgba(34,197,94,0.12);
  color: #86efac;
  border-color: rgba(34,197,94,0.3);
}
body.dash-dark .badge-warning {
  background: rgba(217,119,6,0.12);
  color: #fcd34d;
  border-color: rgba(217,119,6,0.3);
}
body.dash-dark .badge-danger {
  background: rgba(220,38,38,0.12);
  color: #fca5a5;
  border-color: rgba(220,38,38,0.3);
}
body.dash-dark .badge-info {
  background: rgba(59,130,246,0.12);
  color: #93c5fd;
  border-color: rgba(59,130,246,0.3);
}
body.dash-dark .badge-neutral {
  background: var(--dd-surface-3);
  color: var(--dd-text-muted);
  border-color: var(--dd-border);
}

/* ---------- Alerts ---------- */
body.dash-dark .alert {
  border-radius: 10px;
  padding: 12px 16px;
  border: 1px solid;
}
body.dash-dark .alert-success {
  background: rgba(34,197,94,0.1);
  border-color: rgba(34,197,94,0.3);
  color: #d1fae5;
}
body.dash-dark .alert-warning {
  background: rgba(217,119,6,0.1);
  border-color: rgba(217,119,6,0.35);
  color: #fef3c7;
}
body.dash-dark .alert-danger {
  background: rgba(220,38,38,0.1);
  border-color: rgba(220,38,38,0.35);
  color: #fecaca;
}
body.dash-dark .alert-info {
  background: rgba(59,130,246,0.1);
  border-color: rgba(59,130,246,0.3);
  color: #bfdbfe;
}

/* ---------- Empty states ---------- */
body.dash-dark .empty-state {
  text-align: center;
  color: var(--dd-text-muted);
}
body.dash-dark .empty-state h3 { color: var(--dd-text); }

/* ---------- Misc ---------- */
body.dash-dark .checkfield label { text-transform: none; letter-spacing: 0; color: var(--dd-text-soft); }
body.dash-dark .row.between { color: inherit; }
body.dash-dark .activity-cell { color: var(--dd-text-muted); }
body.dash-dark .activity-cell .activity-money { color: var(--dd-text); }

/* ============ AUTH SHELL (login + signup pages) ============
   Applies whenever body has landing-dark + the page uses .auth-shell. */
body.landing-dark .auth-shell {
  min-height: calc(100vh - 80px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* No background — inherits the #0a0a0a from body.landing-dark so the auth
     pages flow visually with the rest of the public site (homepage, services,
     legal pages all use the same base). */
  padding: var(--s-10, 40px) var(--s-5, 20px);
}
/* [authv3-20260819] The v3 pass on the auth card lives HERE, not in app.css.
   app.css is loaded first (header.php:128) and dash-dark.css second (:129), and
   this block and the app.css one were written at the same (0,2,1) specificity —
   so anything written over there loses to what is written here. One block, in
   the winning file, styling all fourteen pages that use .auth-card:
   promoter/admin/ambassador/operator login + signup + forgot + reset.

   Radius -> notch, flat pink -> the magenta/violet gradient, and the labels onto
   the mono micro-caps the rest of v3 uses. */
body.landing-dark .auth-card {
  background: linear-gradient(180deg, rgba(255,255,255,.03), rgba(0,0,0,.28));
  border: 1px solid #23232a;
  border-radius: 0;
  clip-path: polygon(12px 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%, 0 12px);
  padding: clamp(28px, 4vw, 44px);
  max-width: 440px;
  width: 100%;
  box-shadow: none;
}
body.landing-dark .auth-card h1 {
  color: #ffffff;
  font-size: clamp(28px, 4vw, 36px);
  font-weight: 900;
  letter-spacing: -0.02em;
  margin: 0 0 var(--s-2, 8px);
}
body.landing-dark .auth-card .lead {
  color: #94a3b8;
  font-size: 15px;
  margin: 0 0 var(--s-6, 24px);
}
body.landing-dark .auth-card .field { margin-bottom: var(--s-4, 16px); }
/* [authv3-20260819] Mono micro-caps — the same label treatment the Launchpad
   and every rebuilt page uses, so a sign-in screen reads as the same product. */
body.landing-dark .auth-card label {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: #8d949d;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 6px;
}
body.landing-dark .auth-card .input,
body.landing-dark .auth-card input[type=text],
body.landing-dark .auth-card input[type=email],
body.landing-dark .auth-card input[type=password] {
  width: 100%;
  background: rgba(0,0,0,.34);
  border: 1px solid #23232a;
  color: #f2f3f5;
  padding: 12px 14px;
  border-radius: 0;
  /* 6px control notch. */
  clip-path: polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
  color-scheme: dark;
  font-size: 15px;
  box-sizing: border-box;
  transition: border-color 0.15s, background 0.15s;
}
body.landing-dark .auth-card .input::placeholder { color: #5e646c; }
body.landing-dark .auth-card input:focus {
  outline: none;
  border-color: rgba(236,72,153,.5);
  background: rgba(0,0,0,.5);
  /* Was a 3px pink glow ring. clip-path CLIPS box-shadow, so the ring would be
     sliced off at the notch corners — the focus state has to be carried by the
     border and the fill instead. */
  box-shadow: none;
}
body.landing-dark .auth-card .help {
  color: #64748b;
  font-size: 12px;
}
/* [authv3-20260819] Was a flat #ec4899 pill with black text and a pink drop
   glow. Now the magenta -> violet gradient and the 7px control notch, matching
   every primary button in v3. The !importants stay: .btn-primary in app.css
   sets background/color/border and this rule has to beat it on properties it
   already owns. Dropped the glow — box-shadow gets clipped by clip-path. */
body.landing-dark .auth-card .btn-primary {
  background: linear-gradient(135deg, #ec4899, #a855f7) !important;
  color: #ffffff !important;
  border: 0 !important;
  border-radius: 0;
  clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
  padding: 14px 28px;
  font-weight: 800;
  font-size: 16px;
  width: 100%;
  box-shadow: none;
  cursor: pointer;
  transition: filter 0.15s;
}
/* No translateY on hover — nothing else in v3 lifts, and the button moving out
   from under the cursor on a form you are about to submit reads as a glitch. */
body.landing-dark .auth-card .btn-primary:hover { filter: brightness(1.08); }
/* [authv3-20260819] Notch, not a 10px radius — a rounded alert inside a notched
   card is the kind of half-migrated detail that makes a page look unfinished.
   The RED stays red: this is the only thing a person reads when a sign-in fails
   and it must not be quietly restyled to brand magenta. */
body.landing-dark .auth-card .alert-danger {
  background: rgba(220,38,38,0.12);
  border: 1px solid rgba(220,38,38,0.4);
  color: #fecaca;
  padding: 10px 14px;
  border-radius: 0;
  clip-path: polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
  margin-bottom: var(--s-4, 16px);
  font-size: 14px;
}
/* [authv3-20260819] Same notch. Kept BLUE rather than folded into magenta:
   magenta is the primary-action colour here, and an informational note wearing
   the same colour as the Sign in button reads as something to click. */
body.landing-dark .auth-card .alert-info {
  background: rgba(59,130,246,0.12);
  border: 1px solid rgba(59,130,246,0.35);
  color: #bfdbfe;
  padding: 10px 14px;
  border-radius: 0;
  clip-path: polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
  margin-bottom: var(--s-4, 16px);
  font-size: 14px;
}
body.landing-dark .auth-card .muted { color: #64748b; }
body.landing-dark .auth-card a { color: #ec4899; }
body.landing-dark .auth-card a:hover { filter: brightness(1.15); }

/* Help page TOC sidebar */
body.dash-dark .help-toc a { color: var(--dd-text-muted); }
body.dash-dark .help-toc a:hover { background: rgba(255,255,255,0.04); color: var(--dd-text); }
body.dash-dark .help-toc .group-label { color: var(--dd-text-faint); }
body.dash-dark .help-content h2 {
  border-bottom-color: var(--dd-border);
}
body.dash-dark .help-content code { background: var(--dd-surface-2); }
body.dash-dark .help-content .callout {
  background: var(--dd-surface);
  border-left-color: var(--dd-accent);
}
body.dash-dark .help-content .callout.warn { background: rgba(217,119,6,0.06); border-left-color: #d97706; }
body.dash-dark .help-content table.steps td { border-bottom-color: var(--dd-border); color: var(--dd-text-soft); }
body.dash-dark .help-content table.steps td:first-child { color: var(--dd-accent); }

/* ===========================================================================
   Run Up / analytics components (.ru-*)
   These classes are used by admin/runup.php and other admin pages but were
   never given CSS, so those sections rendered as raw stacked text (and didn't
   reflow on mobile). Defined here once, globally, for the dark admin theme.

   LIQUID is applied ONLY to the hero strip (clamp-based fluid padding + number
   size) so it scales smoothly on phones; everything else uses conventional
   fixed sizing + a breakpoint, to avoid liquid distorting other elements.
   =========================================================================== */

/* --- Hero strip (LIQUID, hero only) --- */
body.dash-dark .ru-hero {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(8px, 1.6vw, 16px);
  margin: 20px 0 28px;
}
body.dash-dark .ru-hero-stat {
  flex: 1 1 clamp(130px, 22vw, 180px);
  border: 1px solid var(--dd-border);
  border-radius: 14px;
  padding: clamp(12px, 2.4vw, 20px);
  background: linear-gradient(180deg, rgba(255,255,255,0.035), rgba(255,255,255,0.01));
}
body.dash-dark .ru-hero-num {
  font-size: clamp(20px, 4.8vw, 30px);
  font-weight: 700;
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--dd-text);
}
body.dash-dark .ru-hero-lbl {
  font-size: clamp(10px, 1.4vw, 12px);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--dd-text-muted);
  margin-top: 6px;
}

/* --- Filter chips --- */
body.dash-dark .ru-filters { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 20px; }
body.dash-dark .ru-chip {
  display: inline-block;
  padding: 6px 14px;
  border: 1px solid var(--dd-border);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 600;
  color: var(--dd-text-soft);
  text-decoration: none;
  background: var(--dd-surface);
}
body.dash-dark .ru-chip:hover { border-color: var(--dd-accent); color: var(--dd-text); }
body.dash-dark .ru-chip-active { background: var(--dd-accent); border-color: var(--dd-accent); color: #fff; }

/* --- Table --- */
body.dash-dark .ru-table-wrap {
  overflow-x: auto;
  border: 1px solid var(--dd-border);
  border-radius: 14px;
  -webkit-overflow-scrolling: touch;
}
body.dash-dark .ru-table { width: 100%; min-width: 720px; border-collapse: collapse; font-size: 13px; }
body.dash-dark .ru-table th,
body.dash-dark .ru-table td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--dd-border);
  text-align: left;
  white-space: nowrap;
  color: var(--dd-text-soft);
}
body.dash-dark .ru-table tr:last-child td { border-bottom: none; }
body.dash-dark .ru-table thead th {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--dd-text-muted); background: rgba(255,255,255,0.02);
}
body.dash-dark .ru-table tbody tr:hover { background: rgba(255,255,255,0.025); }
body.dash-dark .ru-cell-sub { font-size: 11px; color: var(--dd-text-muted); margin-top: 2px; }

/* --- Post-count badges --- */
body.dash-dark .ru-post-counts { display: inline-flex; gap: 6px; align-items: center; }
body.dash-dark .ru-pc {
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
  background: rgba(148,163,184,0.15); color: var(--dd-text-muted);
}
body.dash-dark .ru-pc-live { background: rgba(52,211,153,0.15); color: #34d399; }
body.dash-dark .ru-pc-pending { background: rgba(251,191,36,0.15); color: #fbbf24; }
body.dash-dark .ru-pc-failed { background: rgba(248,113,113,0.15); color: #f87171; }
body.dash-dark .ru-status-badge {
  display: inline-block; font-size: 11px; font-weight: 700; padding: 3px 10px;
  border-radius: 999px; text-transform: uppercase; letter-spacing: 0.03em;
}

/* --- Mobile breakpoint (conventional, non-liquid) --- */
@media (max-width: 640px) {
  body.dash-dark .ru-hero-stat { flex: 1 1 calc(50% - 8px); }
}

/* ===========================================================================
   MOBILE ADMIN NAV — horizontal pill strip (no JS)
   app.css hides .dash-sidebar entirely below 960px with no replacement, so the
   full admin menu (Affiliates, Audience, Cross-share, Run Up, Social analytics,
   Support inbox, …) becomes unreachable on a phone. Instead of hiding it, we
   turn the sidebar into a compact horizontal, sideways-scrolling pill nav
   pinned above the content — every destination stays one tap away without
   widening the page. (A hamburger-toggle variant is available if a tighter
   footprint is ever wanted; it needs a small markup add to admin_sidebar.php.)
   =========================================================================== */
@media (max-width: 960px) {
  body.dash-dark .dash-shell { display: block; }
  body.dash-dark .dash-sidebar {
    display: block;
    width: 100%;
    position: static;
    border-right: none;
    border-bottom: 1px solid var(--dd-border);
    margin-bottom: 16px;
    padding-bottom: 8px;
  }
  /* Hide the "BuzzHive Admin / username" header block to save vertical space. */
  body.dash-dark .dash-sidebar > div:first-child { display: none; }
  /* Lay the menu out as a horizontal scrolling strip of pills. */
  body.dash-dark .dash-sidebar .menu {
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 8px;
    padding: 4px 2px 8px;
    -webkit-overflow-scrolling: touch;
  }
  body.dash-dark .dash-sidebar .menu a {
    flex: 0 0 auto;
    white-space: nowrap;
    padding: 8px 14px;
    border: 1px solid var(--dd-border);
    border-radius: 999px;
    font-size: 13px;
  }
  /* The inline "Account" group label doesn't make sense in a horizontal row. */
  body.dash-dark .dash-sidebar .menu .group-label { display: none; }
}

/* ================================================================
   [cockpit-v3-20260814] DASHBOARD V3 — THE COCKPIT LAYER
   ----------------------------------------------------------------
   Shock, 2026-08-14: the Copilot launchpad was rebuilt as an amber
   HUD ("the cockpit of a UFO") and it no longer matched the other 45
   dashboard pages. Rather than dress one page and orphan the rest,
   the treatment moves HERE, where every /promoter/* and /admin/*
   page already inherits .card / .table / .btn / .stat-card.

   Same discipline as the 2026-06-06 palette repull noted at the top
   of this file: downstream selectors already reference the shared
   primitives, so one layer restyles the whole backend.

   RULES THIS LAYER KEEPS:
     · The console is DARK, the controls are LIT. Light comes from
       inside the instruments, never a lamp above them.
     · ONE hue (BuzzHive amber) for chrome. Semantic colour is
       untouched — success stays green, danger stays red. A promoter
       must never have to decide whether amber means "warning".
     · Nothing here changes layout, spacing rhythm, or the mobile
       table reflow above. Skin only, so no page can break its grid.
   ================================================================ */

body.dash-dark {
  /* [hudmagenta-20260819] Was `236, 107, 28`. Stored as a BARE TRIPLET for
     rgba(var(--hud), a), which is why the site-wide orange sweep missed it —
     the pattern looked for `rgba(236,107,28,` and that string never appears.
     36 rules consume this one token, so the whole dashboard HUD turns with it. */
  --hud: 236, 72, 153;                      /* magenta, as an rgb triplet */
  --hud-line:     rgba(var(--hud), .26);
  --hud-line-hot: rgba(var(--hud), .7);
  --hud-ink:      rgba(252, 231, 243, .96);  /* was warm cream; now reads with magenta */
  --hud-dim:      rgba(249, 212, 232, .72);
  --hud-ease:     cubic-bezier(.22, .61, .24, 1);
}

/* ---------- Hull: the surface every panel is bolted to ----------
   Fixed, so it reads as a console you're seated at rather than
   wallpaper that scrolls past. Masked at the bottom so long pages
   don't end in a hard grid edge. */
body.dash-dark::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    radial-gradient(58% 42% at 14% 0%,  rgba(var(--hud), .10), transparent 66%),
    radial-gradient(48% 40% at 92% 10%, rgba(90, 140, 255, .06), transparent 62%),
    linear-gradient(rgba(255,255,255,.026) 1px, transparent 1px) 0 0 / 100% 44px,
    linear-gradient(90deg, rgba(255,255,255,.026) 1px, transparent 1px) 0 0 / 44px 100%;
  mask-image: radial-gradient(120% 90% at 50% 0%, #000 42%, transparent 88%);
}
/* Page content sits above the hull. Positioned so z-index applies. */
body.dash-dark .dash-shell,
body.dash-dark .nav,
body.dash-dark footer { position: relative; z-index: 1; }

/* [vs2zfix-20260817] THE Z-INDEX ABOVE MADE THE VIBE STUDIO'S TOP NAV
   UNCLICKABLE. Shock: "The Vibe Studio is actually messed up right now… I can't
   access any of the top nav."

   The cause is the line directly above, added with the cockpit skin on 08-14.
   `z-index: 1` does not merely lift .dash-shell over the hull — it makes the
   shell a STACKING CONTEXT, and every z-index inside it is then resolved
   relative to that context rather than the page. The Vibe Studio is a
   full-viewport takeover (`.vs2 { position:fixed; inset:0; z-index:10000 }`)
   and it lives inside the shell, so its 10000 never competes with the page: the
   whole studio arrives at the root as z-index 1 and loses to .site-header,
   which is `position:sticky; z-index:50`. The header is 61px tall, the studio's
   bead row is 0–44px and its toolbar row 44–80px — so the bead vanished
   entirely and the toolbar (File / Help / Manage / Event details / Ticket &
   sales / Merch) was sliced in half. Measured, not guessed:
   document.elementFromPoint at the bead's own coordinates returned
   header.site-header before this rule and span.vs2-brand after it.

   Fixing it HERE rather than in the studio, because the trap is here: any
   full-screen surface added inside the shell later would hit exactly this.

   z-index only — `position: relative` stays. Relative positioning with
   z-index:auto does NOT create a stacking context, so the shell still paints
   above the hull (z-index 0) exactly as it did, on all 45 dashboard pages. The
   studio covers the hull itself anyway.

   NOT a DOM portal (moving .vs2 to <body> would also have worked): .vs2 holds
   THREE iframes, and reparenting an iframe reloads it. This touches no markup.

   :has() is Chrome 105+ / Safari 15.4+ / Firefox 121+. On anything older the
   selector is invalid and the rule is dropped, which returns the studio to
   today's behaviour — degraded, never worse. */
/* [studiozfix-20260819] The 08-17 fix above named ONE studio, so it could only
   ever fix one. Shock, today: "website studio top nav is broken now", then
   "seat map studio is doing the same thing" — the identical symptom twice,
   because .ws and .smb are the same kind of surface as .vs2 and hit the same
   trap.

   Every full-screen studio is `position:fixed; inset:0; z-index:10000`. Any of
   them rendered inside .dash-shell has that 10000 resolved against the shell's
   stacking context instead of the page, arrives at the root as z-index 1, and
   loses to `.site-header` (position:sticky; z-index:50) — which covers the top
   ~61px, i.e. exactly where every studio puts its toolbars.

   So the exception is now a LIST, kept beside the rule that causes it:
     .vs2  Vibe Studio      _partials/vibe_v2_app.php
     .smb  Seat-Map Studio  promoter/seatmaps.php  (editor branch)
     .ws   Website Studio   _partials/website_studio_app.php
     .gs   Graphics Studio  _partials/graphics_studio_app.php

   .ws and .gs are listed even though those two currently render OUTSIDE the
   shell (no dash_sidebar include) — it costs nothing and means the trap cannot
   reopen if a sidebar is ever added back to either.

   >>> ADDING A NEW FULL-SCREEN STUDIO? ADD ITS ROOT CLASS TO THIS LIST. <<<

   Verified unambiguous: `class="smb"`, `class="ws"` and `class="gs"` each appear
   in exactly one file — their own studio — so no other page can match. A false
   positive would be harmless anyway: z-index:auto does not create a stacking
   context, so the shell still paints above the hull exactly as it does now.

   :has() is Chrome 105+ / Safari 15.4+ / Firefox 121+. On anything older the
   whole selector list is invalid and the rule is dropped, returning the studios
   to the broken-but-known behaviour — degraded, never worse. */
body.dash-dark .dash-shell:has(.vs2),
body.dash-dark .dash-shell:has(.smb),
body.dash-dark .dash-shell:has(.ws),
body.dash-dark .dash-shell:has(.gs) { z-index: auto; }

/* [studiochatz-20260819] …and the fix above would have BURIED THE HELP CHAT on
   the Seat-Map Studio, so it belongs in the same change.

   While a studio was wrongly flattened to z-index 1 the chat bubble sat on top
   of it by accident. Restoring the studio to a real 10000 overlay puts it above
   the bubble, whose default is `.chatw-bubble { z-index: 9998 }` — so the fix
   alone would have traded a covered toolbar for an unreachable help chat, in a
   studio where "needs an ai chat when they get stuck" was the reason it's there.

   /promoter/graphics and /studio.php already solve this per-page with
   `.chatw-bubble{z-index:10001 !important}`. The Seat-Map Studio sets no chat
   audience, so it never got one. Doing it here instead of editing seatmaps.php
   keeps the whole layering story in one place — and deliberately WITHOUT
   !important: chat_widget.php pins the bubble to z-index 2147483200 via
   `#chatw-bubble` for the vibestudio/webstudio audiences, and an ID (1,0,0)
   outranks this (0,2,1), so those two keep their own higher value instead of
   being silently dragged down to 10001. */
body.dash-dark:has(.vs2) .chatw-bubble, body.dash-dark:has(.vs2) .chatw-panel,
body.dash-dark:has(.smb) .chatw-bubble, body.dash-dark:has(.smb) .chatw-panel,
body.dash-dark:has(.ws)  .chatw-bubble, body.dash-dark:has(.ws)  .chatw-panel,
body.dash-dark:has(.gs)  .chatw-bubble, body.dash-dark:has(.gs)  .chatw-panel { z-index: 10001; }

/* ---------- Panels ---------- */
body.dash-dark .card,
body.dash-dark .card-flat,
body.dash-dark .card-padless {
  border-radius: 5px;
  border-color: var(--hud-line);
  background:
    linear-gradient(180deg, rgba(var(--hud), .045), rgba(0,0,0,.34)),
    rgba(9, 8, 7, .72);
  box-shadow:
    inset 0 1px 0 rgba(var(--hud), .22),
    inset 0 0 30px rgba(var(--hud), .04),
    0 22px 50px -30px rgba(0,0,0,.9);
}
body.dash-dark .card-flat { box-shadow: inset 0 0 24px rgba(var(--hud), .04); }
body.dash-dark .card-header {
  background: linear-gradient(180deg, rgba(var(--hud), .09), transparent);
  border-bottom-color: rgba(var(--hud), .2);
  border-radius: 5px 5px 0 0;
}
body.dash-dark .card-header h3 {
  color: var(--hud-dim);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .2em;
  text-transform: uppercase;
}

/* ---------- Instruments (stat cards) ----------
   Targeting corners are DRAWN, not images — they stay crisp at any
   zoom and cost nothing to load. */
body.dash-dark .stat-card {
  position: relative;
  overflow: hidden;
  border-radius: 4px;
  border-color: var(--hud-line);
  background:
    linear-gradient(180deg, rgba(var(--hud), .055), rgba(0,0,0,.28)),
    rgba(10, 9, 8, .72);
  box-shadow:
    inset 0 0 26px rgba(var(--hud), .09),
    inset 0 1px 0 rgba(var(--hud), .3),
    0 0 0 1px rgba(0,0,0,.5);
}
body.dash-dark .stat-card::before,
body.dash-dark .stat-card::after {
  content: "";
  position: absolute;
  width: 11px;
  height: 11px;
  pointer-events: none;
  border: 1.5px solid rgba(var(--hud), .85);
}
body.dash-dark .stat-card::before { top: 5px; left: 5px; border-right: 0; border-bottom: 0; }
body.dash-dark .stat-card::after { bottom: 5px; right: 5px; border-left: 0; border-top: 0; }
body.dash-dark .stat-card .label { color: var(--hud-dim); letter-spacing: .18em; }
body.dash-dark .stat-card .value {
  color: var(--hud-ink);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  text-shadow: 0 0 22px rgba(var(--hud), .5), 0 0 3px rgba(var(--hud), .35);
}

/* ---------- Readout tables ---------- */
body.dash-dark .table thead th {
  background: linear-gradient(180deg, rgba(var(--hud), .1), transparent);
  color: var(--hud-dim);
  border-bottom-color: rgba(var(--hud), .2);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: .18em;
}
body.dash-dark .table tbody td { border-bottom-color: rgba(var(--hud), .1); }
body.dash-dark .table tbody tr:hover td { background: rgba(var(--hud), .05); }
body.dash-dark .table a { color: rgba(255, 214, 178, .96); }

/* ---------- Controls: lit keys ---------- */
body.dash-dark .btn-primary {
  border-radius: 4px;
  letter-spacing: .04em;
  box-shadow: 0 6px 20px -8px rgba(var(--hud), .95), inset 0 1px 0 rgba(255,255,255,.22);
}
body.dash-dark .btn-secondary,
body.dash-dark .btn-ghost {
  border-radius: 4px;
  color: rgba(255, 214, 178, .9);
  border: 1px solid var(--hud-line);
  background: linear-gradient(180deg, rgba(var(--hud), .1), rgba(0,0,0,.28));
  transition: border-color .25s var(--hud-ease), box-shadow .25s var(--hud-ease), color .25s var(--hud-ease);
}
body.dash-dark .btn-secondary:hover,
body.dash-dark .btn-ghost:hover {
  color: var(--hud-ink);
  border-color: var(--hud-line-hot);
  background: linear-gradient(180deg, rgba(var(--hud), .16), rgba(0,0,0,.24));
  box-shadow: inset 0 0 18px rgba(var(--hud), .2), 0 0 18px -6px rgba(var(--hud), .7);
}

/* ---------- Sunk fields ----------
   Inputs read as recessed, so a promoter can tell at a glance what
   is a control (raised, lit) and what is a slot to type into. */
body.dash-dark .input,
body.dash-dark .select,
body.dash-dark .textarea,
body.dash-dark input[type=text],
body.dash-dark input[type=email],
body.dash-dark input[type=password],
body.dash-dark input[type=number],
body.dash-dark input[type=date],
body.dash-dark input[type=time],
body.dash-dark input[type=datetime-local],
body.dash-dark input[type=search],
body.dash-dark input[type=url],
body.dash-dark select,
body.dash-dark textarea {
  border-radius: 4px;
  border-color: rgba(var(--hud), .22);
  background: rgba(0,0,0,.42);
  box-shadow: inset 0 2px 8px rgba(0,0,0,.6);
}
body.dash-dark .input:focus,
body.dash-dark .select:focus,
body.dash-dark .textarea:focus,
body.dash-dark input:focus,
body.dash-dark select:focus,
body.dash-dark textarea:focus {
  border-color: var(--hud-line-hot);
  box-shadow: inset 0 2px 8px rgba(0,0,0,.55), 0 0 0 3px rgba(var(--hud), .22);
}
body.dash-dark label,
body.dash-dark .field label { color: var(--hud-dim); letter-spacing: .12em; }

/* ---------- The rail ----------
   The launchpad hides the sidebar; every other page keeps it, so it
   has to belong to the same console. */
body.dash-dark .dash-sidebar {
  background: linear-gradient(180deg, rgba(var(--hud), .04), transparent 40%), var(--dd-bg);
  border-right-color: var(--hud-line);
}
body.dash-dark .menu a { border-radius: 3px; }
body.dash-dark .menu a:hover { background: rgba(var(--hud), .07); }
body.dash-dark .menu a.active {
  color: var(--hud-ink);
  background: linear-gradient(90deg, rgba(var(--hud), .2), rgba(var(--hud), .04));
  box-shadow: inset 2px 0 0 rgba(var(--hud), 1), inset 0 0 20px rgba(var(--hud), .1);
}
body.dash-dark .menu .group-label,
body.dash-dark .dash-sidebar .eyebrow {
  color: rgba(var(--hud), .9);
  letter-spacing: .2em;
}

/* ---------- Chrome odds and ends ---------- */
body.dash-dark .eyebrow { color: rgba(var(--hud), .95); letter-spacing: .2em; }
body.dash-dark .alert { border-radius: 4px; }
body.dash-dark .badge { border-radius: 3px; letter-spacing: .1em; text-transform: uppercase; font-size: 10.5px; }
/* .badge-success / -warning / -danger / -info keep their own colour —
   status must never be readable as "just more amber". */
body.dash-dark .badge:not([class*="badge-"]),
body.dash-dark .badge-neutral {
  color: var(--hud-dim);
  background: rgba(var(--hud), .1);
  border-color: var(--hud-line);
}
body.dash-dark .empty-state h3 { color: var(--hud-ink); }
body.dash-dark .empty-state { color: var(--hud-dim); }
body.dash-dark hr { border-top-color: rgba(var(--hud), .16); }
body.dash-dark code { background: rgba(0,0,0,.45); border: 1px solid var(--hud-line); color: rgba(255,214,178,.92); }

@media (prefers-reduced-motion: reduce) {
  body.dash-dark .btn-secondary,
  body.dash-dark .btn-ghost { transition: none; }
}

/* ---------- [onehub-20260814] One hub, one way home ----------
   The left rail was removed from _partials/dash_sidebar.php: the launchpad is
   the only navigation surface, so every other page is a leaf with a single
   back link. The shell therefore collapses to one column on EVERY page, and
   .dash-sidebar rules above are left in place only for any view that still
   renders one (admin shells) — nothing here deletes them. */
body.dash-dark .dash-shell {
  grid-template-columns: 1fr !important;
  display: block;
}
/* [adminrail-20260819] ...but the rule above is UNSCOPED, and that is a bug.
   The comment says the .dash-sidebar rules are "left in place only for any view
   that still renders one (admin shells)" — and they are. What was not left in
   place is the GRID that positions them. So on all 32 admin pages the rail lost
   its column and rendered as a full-width block stacked above the content,
   pushing the dashboard far down the page. Shock hit it in the god admin; it has
   been broken since 08-14.

   Verified before writing this: _partials/dash_sidebar.php emits ZERO
   .dash-sidebar (the promoter rail really is gone, so nothing here brings it
   back), while _partials/admin_sidebar.php still emits one.

   Scoped with :has() so it can only fire where a rail actually exists.
   min-width:961px because below that the media query above deliberately turns
   the rail into a horizontal pill strip — that behaviour is correct and must not
   be overridden. Specificity: (0,3,1) !important beats the (0,2,1) !important
   above; `display` needs no !important because the rule above does not use it. */
@media (min-width: 961px) {
  body.dash-dark .dash-shell:has(.dash-sidebar) {
    display: grid;
    grid-template-columns: 240px 1fr !important;
  }
  body.dash-dark .dash-shell:has(.dash-sidebar) .dash-main { min-width: 0; }
}
/* The bar is a child of .dash-shell, not .dash-main, so it has to carry its own
   horizontal placement — otherwise its contents sit flush against the viewport
   edge while everything else on the page is indented.

   [topbaralign-20260815b] Shock: "put it directly under the BuzzHive site logo."

   MY FIRST ATTEMPT AT THIS MADE IT WORSE, and the reason is worth writing down.
   I gave the bar `max-width:1120px; margin-inline:auto`, which does align the text
   — and broke two other things at the same time:

     1. The bar stopped being full-bleed, so its border-bottom shrank to a 1120px
        line floating in the middle of the hero art instead of a band divider
        running edge to edge. That is the "orange line cutting through the hero
        background".
     2. I also carried over `padding-top:24px` and `margin-bottom:6px` from this
        file, not realising the SERVER was running `padding:0 0 14px` /
        `margin-bottom:22px`. The extra 24px pushed the bar's bottom edge from
        y=106 down to y=130, past the top of .lp-field at y=120 — so the divider
        landed INSIDE the hero. That is the "second top row is gone".

   One thing was asked for and three things moved. The lesson is the fix below:
   change the horizontal axis ONLY.

   The bar stays full width, so the border still spans the viewport and still
   reads as the band rule it has always been. Vertical values are exactly what the
   server was already running, untouched. The single change is the horizontal pad,
   which resolves to the header container's own inner edge:

     (100% - container-max)/2  = the auto margin .container would have taken
     + gutter                  = .container's own padding
     max(gutter, …)            = below the cap the term goes negative; fall back
                                 to the plain gutter, which is what .container
                                 does there too

   So the first child starts on the logo's left edge at every width, with no
   number here to keep in sync with app.css. Verified live at ten viewport widths
   from 320 to 1920: logo-left minus who-left = 0.00 at every one, bar spans the
   full viewport at every one, and the hero art clears the bar by 6px at every
   one.

   [topbarcentre-20260815] Shock: "the text is hugging the top line… having it
   smashed up to the top line looks bad."

   Correct, and measurable: this bar is a BAND between two rules — the header's
   bottom edge above it and its own border-bottom below — and the content was not
   centred in it. Measured live: 0px above the text, 15px below (14px padding plus
   the 1px border). It was sitting on the top rule.

   The two paddings are now equal, so the content row centres between the rules by
   construction rather than by a number that happens to look right. align-items is
   already `center`, so this holds whichever child is tallest — on inner pages the
   back button is taller than this two-line block and the band still centres on it.
   Verified after the change: 14.00 above / 14.00 below on the launchpad AND on
   /promoter/graphics.php, at 1440px and at 390px, and the hero art still clears
   the bar by exactly 6px. */
body.dash-dark .dash-topbar {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding-top: 14px;
  padding-bottom: 14px;
  padding-left:  max(var(--s-5, 20px), calc((100% - var(--container-max, 1120px)) / 2 + var(--s-5, 20px)));
  padding-right: max(var(--s-5, 20px), calc((100% - var(--container-max, 1120px)) / 2 + var(--s-5, 20px)));
  margin-bottom: 22px;
  border-bottom: 1px solid var(--hud-line);
}
body.dash-dark .dash-topbar + .dash-main { padding-top: var(--s-6, 24px); }
/* No horizontal override at any breakpoint: the max() above already collapses to
   the plain gutter below the cap, which is exactly what .container does. A media
   query here could only reintroduce the drift it is meant to prevent. */
@media (max-width: 980px) {
  /* Both, or the band stops being centred at the very width where the least
     vertical room makes it most obvious. */
  body.dash-dark .dash-topbar { padding-top: 12px; padding-bottom: 12px; }
}
body.dash-dark .dash-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  text-decoration: none;
  padding: 9px 15px 9px 12px;
  /* [backbutton-20260819] Shock: "it glows orange and I never really did like the
     way that button looked". Rebuilt in the one idiom he pointed at as right — the
     Captions tab pill: a notch instead of a 4px radius, and the active state is a
     magenta-to-violet FILL rather than a bloom. The old version leaned on two
     box-shadows (an inset wash plus a 20px outer glow); both are gone, because a
     glow is the thing he was reacting to and a fill says "you are here" without it. */
  clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: rgba(242, 243, 245, .82);
  border: 1px solid rgba(255, 255, 255, .10);
  background: rgba(255, 255, 255, .022);
  box-shadow: none;
  transition: color .16s var(--hud-ease), border-color .16s var(--hud-ease), background .16s var(--hud-ease);
}
body.dash-dark .dash-back:hover,
body.dash-dark .dash-back:focus-visible {
  outline: none;
  color: #fff;
  border-color: transparent;
  background: linear-gradient(135deg, #ec4899, #a855f7);
  box-shadow: none;
}
body.dash-dark .dash-back svg { flex: none; }
body.dash-dark .dash-back-admin { margin-left: auto; }
body.dash-dark .dash-who { display: flex; flex-direction: column; gap: 1px; line-height: 1.25; }
body.dash-dark .dash-who-l {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 9.5px;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: rgba(var(--hud), .9);
}
body.dash-dark .dash-who-n { font-size: 13.5px; font-weight: 650; color: var(--hud-dim); }
/* The launchpad is home — it must not offer a link back to itself. */
body.cop-onepage .dash-topbar { display: none; }
