/* The admin UI. One stylesheet, no framework, no build step — this is an
   operator surface on a droplet, and a toolchain would be more to keep alive
   than the pages are worth.

   🔴 THIS IS wap-data's CONSOLE SYSTEM, ported (2026-10-08): the same tokens,
   the same header, the same .card / .stat / .pill / table.data / .field
   vocabulary, so the two consoles are one product and a person who knows one
   knows the other. What changed is the PALETTE — Bathsight's teal and the
   Milestone ink in place of partsight's orange and navy — and two things
   mbp-data does differently on purpose, each marked below: the menu opens
   without JavaScript, and the theme follows the system until someone
   chooses otherwise. */

/* ── the wordmark's face ───────────────────────────────────────────────────
   Saira 300–700 (SIL OFL, fonts/Saira-OFL.txt), latin subset, served by this
   app — the face partsight's lockup is set in. NOT a Google Fonts <link>: the
   admin must not phone a third party to render its own name. */
@font-face{font-family:Saira;font-style:normal;font-weight:300 700;
  font-display:swap;src:url("fonts/saira-latin-300-700.woff2") format("woff2")}

/* ── the palette ───────────────────────────────────────────────────────────
   Light by default, dark when the system asks, and EITHER when the person
   asks: a data-theme on <html> that outranks the media query, which is why
   the dark block is guarded by :not([data-theme="light"]).

   🔴 wap-data is dark-by-default. This one follows the SYSTEM, because an
   admin that is already the right theme when you open it at 9am beats one
   that is always dark. The switch is the same; only the default differs.

   🔴 The dark values are written TWICE on purpose. A media query and an
   attribute selector cannot share one selector list. Keep the two blocks in
   step — a test compares them declaration for declaration. */
:root{
  --bg:#f5f5f7; --card:#fff; --sunken:#eef0f3;
  --ink:#17202e; --muted:#5c6676; --faint:#8a93a1;
  --line:#dee2e8; --line-soft:#eaedf1;
  --accent:#3c6e71; --accent-ink:#fff; --brand:#3c6e71; --link:#2e595c;
  --bad:#b3261e; --amber:#a66a00; --good:#0f7a34;
  --display:Saira,ui-sans-serif,system-ui,sans-serif;
  --logo-tile:#17202e; --logo-drop:#fff; --logo-centre:#3c6e71;
  --mono:ui-monospace,SFMono-Regular,Menlo,monospace;
  --radius:10px; --radius-sm:7px; --control-h:38px; --header-h:56px;
  --shadow:0 1px 2px rgba(16,24,40,.05);
  color-scheme:light;
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#10161f; --card:#17202e; --sunken:#131b27;
  --ink:#e7ebf1; --muted:#9aa7b8; --faint:#6f7c8d;
  --line:#2a3443; --line-soft:#212a37;
  --accent:#7fc6c9; --accent-ink:#10161f; --brand:#7fc6c9; --link:#8fd2d5;
  --bad:#ff8a80; --amber:#e0a33e; --good:#57c98a;
  --logo-tile:#7fc6c9; --logo-drop:#fff; --logo-centre:#17202e;
  --shadow:none;
  color-scheme:dark;}}
:root[data-theme="dark"]{
  --bg:#10161f; --card:#17202e; --sunken:#131b27;
  --ink:#e7ebf1; --muted:#9aa7b8; --faint:#6f7c8d;
  --line:#2a3443; --line-soft:#212a37;
  --accent:#7fc6c9; --accent-ink:#10161f; --brand:#7fc6c9; --link:#8fd2d5;
  --bad:#ff8a80; --amber:#e0a33e; --good:#57c98a;
  --logo-tile:#7fc6c9; --logo-drop:#fff; --logo-centre:#17202e;
  --shadow:none;
  color-scheme:dark;
}

*{box-sizing:border-box} [hidden]{display:none !important}
body{margin:0;font:14.5px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif;
  background:var(--bg);color:var(--ink)}
a{color:var(--link);text-decoration:none} a:hover{text-decoration:underline}
code,.mono{font-family:var(--mono);font-size:12.5px}
h1{font-family:var(--display);font-weight:600;font-size:24px;line-height:1.2;margin:0}
h2{font-family:var(--display);font-weight:600;font-size:17px;margin:0}
h3{font-size:14.5px;margin:0 0 6px}
p{margin:0 0 10px}
.muted{color:var(--muted)} .faint{color:var(--faint)} .small{font-size:12.5px}
.error{color:var(--bad)} .ok-text{color:var(--good)} .warn-text{color:var(--amber)}
pre{white-space:pre-wrap;font-size:12px;margin:0}

/* ── the lockup ────────────────────────────────────────────────────────────
   🔴 Bath at 600 in the ink, sight at 300 in the accent — partsight's split
   exactly, so the family reads as one. Every colour is a token, so the logo
   flips with the theme on its own and there is no second, reversed artwork
   to keep in step. */
.wordmark{font-family:var(--display);letter-spacing:-.01em;line-height:1;
  white-space:nowrap}
.wordmark b{font-weight:600}
.wordmark > span{font-weight:300;color:var(--accent)}
.mark{display:block;flex:none}

/* ── the header ────────────────────────────────────────────────────────────
   🔴 ONE BAR, the nav CENTRED ON THE PAGE'S MIDLINE by equal outer columns.
   Centring it in whatever gap the brand and the email leave moves it every
   time someone with a longer address signs in. The middle column is
   minmax(0,auto) and the nav scrolls, so ten tabs shrink rather than pushing
   the brand and the account off the page. */
header.top{position:sticky;top:0;z-index:20;height:var(--header-h);
  display:flex;align-items:center;gap:14px;padding:0 18px;
  background:var(--card);border-bottom:1px solid var(--line)}
header.top .side{display:flex;align-items:center;gap:12px;min-width:0}
a.brand{display:inline-flex;align-items:center;gap:8px;color:var(--ink);
  text-decoration:none;white-space:nowrap}
a.brand:hover{text-decoration:none}
a.brand .mark{width:30px;height:30px}
a.brand .wordmark{font-size:19px}
nav.app{display:flex;gap:2px;height:100%;align-items:stretch;min-width:0;
  overflow-x:auto;scrollbar-width:none}
nav.app::-webkit-scrollbar{display:none}
nav.app a{display:flex;align-items:center;padding:0 9px;color:var(--muted);
  font-size:13.5px;white-space:nowrap;border-bottom:2px solid transparent;
  text-decoration:none}
nav.app a:hover{color:var(--ink);text-decoration:none}
nav.app a.on{color:var(--ink);border-bottom-color:var(--brand);font-weight:600}
header.top .who{display:flex;gap:10px;align-items:center;font-size:13px;
  white-space:nowrap}
header.top .me{color:var(--muted);line-height:1.25;text-align:right;
  overflow:hidden;text-overflow:ellipsis}
header.top .me small{display:block;color:var(--faint);font-size:11.5px}
header.top form{display:inline}
header.top button{white-space:nowrap}

/* The theme switch: the sun to go light, the moon to go dark. Ships hidden
   and theme.js unhides it — the choice is only KEPT by script, so a button
   that cannot keep it is worse than no button at all. */
.theme-toggle{display:inline-grid;place-items:center;width:32px;height:32px;
  padding:0;flex:none;border-radius:var(--radius-sm);
  border:1px solid var(--line);background:var(--card);color:var(--muted);
  font-size:15px;line-height:1;font-variant-emoji:text;cursor:pointer}
.theme-toggle:hover{color:var(--ink);border-color:var(--faint);filter:none}

/* 🔴 The menu is CSS-ONLY — a checkbox and a label. wap-data uses a script
   for this; the admin should not need JavaScript to show its own menu, and
   the only script on these pages is the theme switch. */
.menu-check,.menu-toggle{display:none}

@media (min-width:961px){
  header.top{display:grid;
    grid-template-columns:minmax(max-content,1fr) minmax(0,auto) minmax(max-content,1fr)}
  nav.app{justify-self:center;max-width:100%}
  header.top .who{justify-self:end}
}
@media (max-width:1100px){ header.top .me{display:none} }
@media (max-width:960px){
  /* 🔴 FLEX, not grid, below the fold. Ordering grid items into rows left
     the toggle invisible and pushed Sign out off a 390px screen — a bar you
     cannot reach the menu from. A wrapping flex row cannot do that. */
  header.top{height:auto;min-height:var(--header-h);flex-wrap:wrap;
    padding:8px 14px;gap:10px}
  header.top .side{flex:0 1 auto}
  .menu-toggle{display:block;order:-1;font-size:21px;line-height:1;
    padding:10px 4px;cursor:pointer;color:var(--muted);user-select:none}
  header.top .who{margin-left:auto}
  nav.app{flex-basis:100%;order:9;flex-direction:column;height:auto;
    display:none;border-top:1px solid var(--line);padding-bottom:4px}
  .menu-check:checked ~ nav.app{display:flex}
  nav.app a{padding:9px 4px;border-bottom:0}
  nav.app a.on{color:var(--brand)}
}

/* ── the page ──────────────────────────────────────────────────────────── */
main{max-width:1180px;margin:0 auto;padding:24px 20px 40px}
main.narrow{max-width:440px;padding:84px 20px 32px}
.page-head{display:flex;align-items:flex-end;justify-content:space-between;
  gap:16px;flex-wrap:wrap;margin-bottom:18px}
.page-head .sub{color:var(--muted);margin:4px 0 0}
.page-head .actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
nav.tabs{display:flex;gap:4px;border-bottom:1px solid var(--line);
  margin:-4px 0 20px;overflow-x:auto;scrollbar-width:none}
nav.tabs::-webkit-scrollbar{display:none}
nav.tabs a{padding:9px 12px;color:var(--muted);font-size:13.5px;
  white-space:nowrap;border-bottom:2px solid transparent;margin-bottom:-1px;
  text-decoration:none}
nav.tabs a:hover{color:var(--ink);text-decoration:none}
nav.tabs a.on{color:var(--ink);border-bottom-color:var(--brand);font-weight:600}
.stack > * + *{margin-top:16px}
.grid{display:grid;gap:16px}
.grid.two{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid.three{grid-template-columns:repeat(3,minmax(0,1fr))}
.grid.side{grid-template-columns:minmax(0,1fr) 360px}
.grid.pick{grid-template-columns:290px minmax(0,1fr);align-items:start}
@media (max-width:960px){.grid.side,.grid.pick{grid-template-columns:minmax(0,1fr)}}
@media (max-width:1000px){.grid.three{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:820px){.grid.two,.grid.three{grid-template-columns:minmax(0,1fr)}}
@media (max-width:720px){table.data{min-width:640px}
  .guide table.data,.card-body table.data{min-width:0}}
.section-title{font-size:12px;font-weight:700;text-transform:uppercase;
  letter-spacing:.06em;color:var(--faint);margin:22px 0 10px}
.section-title:first-child{margin-top:0}
.meta{display:flex;flex-wrap:wrap;gap:4px 16px;font-size:12.5px;color:var(--muted)}
footer.foot{max-width:1180px;margin:0 auto;padding:0 20px 28px;
  font-size:12px;color:var(--faint)}

/* ── cards ─────────────────────────────────────────────────────────────── */
.card{background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);box-shadow:var(--shadow);min-width:0}
.card-head{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:14px 18px;border-bottom:1px solid var(--line-soft);
  flex-wrap:wrap}
.card-head h2{display:flex;align-items:center;gap:8px}
.card-head .actions{display:flex;gap:8px;align-items:center}
.card-body{padding:16px 18px} .card-body > :last-child{margin-bottom:0}
.card-foot{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:12px 18px;border-top:1px solid var(--line-soft);
  background:var(--sunken);border-radius:0 0 var(--radius) var(--radius);
  flex-wrap:wrap}
.card-foot .actions{display:flex;gap:8px;margin-left:auto}
.card.flush .card-body{padding:0}
.grid > .card,.grid > .card > form{display:flex;flex-direction:column}
.grid > .card > form{flex:1} .grid > .card .card-body{flex:1}
.card.status{border-left:4px solid var(--line)}
.card.status.s-ok{border-left-color:var(--good)}
.card.status.s-warn{border-left-color:var(--amber)}
.card.status.s-fail{border-left-color:var(--bad)}
.card.danger{border-color:color-mix(in srgb,var(--bad) 45%,var(--line))}
.card.danger .card-head h2{color:var(--bad)}
a.card{display:block;color:inherit;text-decoration:none}
a.card:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--line))}
.card-link{font-size:13px}

/* ── stats ─────────────────────────────────────────────────────────────── */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:12px}
.stat{background:var(--card);border:1px solid var(--line);
  border-radius:var(--radius);padding:14px 16px;color:inherit;
  text-decoration:none;display:block;box-shadow:var(--shadow)}
a.stat:hover{border-color:color-mix(in srgb,var(--accent) 45%,var(--line));
  text-decoration:none}
.stat .v{display:block;font-family:var(--display);font-size:26px;
  font-weight:600;font-variant-numeric:tabular-nums;line-height:1.2}
.stat .l{display:block;color:var(--muted);font-size:12.5px;margin-top:2px}
.stat .v.bad{color:var(--bad)} .stat .v.warn{color:var(--amber)}
.stat .v small{display:block;font:400 12px/1.4 system-ui,sans-serif;
  color:var(--faint);margin-top:4px}

/* ── pills, tags, dots ─────────────────────────────────────────────────── */
.pill{display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  padding:2px 9px;border-radius:999px;font-size:12px;font-weight:600;
  background:color-mix(in srgb,var(--muted) 14%,transparent);color:var(--muted)}
.pill::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor}
.pill.plain::before{display:none}
.pill.ok,.pill.live,.pill.success,.pill.active,.pill.sent,.pill.healthy,
.pill.on,.pill.current{color:var(--good);
  background:color-mix(in srgb,var(--good) 13%,transparent)}
.pill.warn,.pill.paused,.pill.running,.pill.invited,.pill.skipped,
.pill.stale,.pill.partial{color:var(--amber);
  background:color-mix(in srgb,var(--amber) 14%,transparent)}
.pill.fail,.pill.failed,.pill.error,.pill.failure,.pill.bad{color:var(--bad);
  background:color-mix(in srgb,var(--bad) 13%,transparent)}
.pill.expired,.pill.revoked,.pill.skip,.pill.disabled,.pill.off{color:var(--faint)}
.tag{display:inline-block;padding:0 7px;border-radius:6px;font-size:11.5px;
  border:1px solid var(--line);color:var(--muted);white-space:nowrap}
.tag.env{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 50%,var(--line))}
.tag.db{color:var(--good);border-color:color-mix(in srgb,var(--good) 50%,var(--line))}
.dot{width:8px;height:8px;border-radius:50%;display:inline-block;
  background:var(--faint);flex:none}
.dot.ok{background:var(--good)} .dot.warn{background:var(--amber)}
.dot.fail{background:var(--bad)}
ul.checklist{list-style:none;padding:0;margin:0;display:grid;gap:7px;font-size:13.5px}
ul.checklist li{display:flex;gap:9px;align-items:baseline}
ul.checklist .dot{position:relative;top:-1px}

/* ── messages ──────────────────────────────────────────────────────────── */
.msg{padding:10px 14px;border-radius:var(--radius-sm);margin:0 0 16px;
  font-size:14px;border:1px solid}
.msg.ok{border-color:color-mix(in srgb,var(--good) 40%,transparent);
  background:color-mix(in srgb,var(--good) 8%,var(--card))}
.msg.bad{border-color:color-mix(in srgb,var(--bad) 40%,transparent);
  background:color-mix(in srgb,var(--bad) 8%,var(--card))}
.msg.info{border-color:color-mix(in srgb,var(--accent) 35%,transparent);
  background:color-mix(in srgb,var(--accent) 7%,var(--card))}
.msg.warn{border-color:color-mix(in srgb,var(--amber) 40%,transparent);
  background:color-mix(in srgb,var(--amber) 8%,var(--card))}
.msg > :last-child{margin-bottom:0}
.empty-state{text-align:center;padding:28px 16px;color:var(--muted)}

/* ── forms ─────────────────────────────────────────────────────────────── */
.fields{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));
  gap:14px 16px;align-items:start}
.fields.cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}
.fields.cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}
.fields.cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}
@media (max-width:960px){.fields.cols-4{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:720px){.fields.cols-2,.fields.cols-3,.fields.cols-4{
  grid-template-columns:minmax(0,1fr)}}
.fields .wide{grid-column:1 / -1}
.field{display:flex;flex-direction:column;gap:5px;min-width:0}
.field > label,.label{font-size:12.5px;font-weight:600;color:var(--ink);
  display:flex;align-items:center;gap:6px}
.field .help{font-size:12px;color:var(--muted)}
input,select,textarea{width:100%;height:var(--control-h);padding:0 11px;
  border:1px solid var(--line);border-radius:var(--radius-sm);
  background:var(--card);color:var(--ink);font:inherit;font-size:14px}
textarea{height:auto;min-height:88px;padding:9px 11px;font-family:var(--mono);
  font-size:13px}
select[multiple]{height:auto;min-height:110px;padding:6px}
/* The UA focus ring is blue, which on a teal brand is the one piece of
   colour nobody chose. Replaced, never removed. */
input:focus,select:focus,textarea:focus{
  outline:2px solid color-mix(in srgb,var(--accent) 45%,transparent);
  outline-offset:0;border-color:var(--accent)}
a:focus-visible,button:focus-visible,.menu-toggle:focus-visible,
summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px;
  border-radius:3px}
input:disabled,select:disabled{background:var(--sunken);color:var(--muted);
  cursor:not-allowed}
input[type=checkbox],input[type=radio]{width:16px;height:16px;margin:0;
  accent-color:var(--accent);flex:none}
.check{display:flex;align-items:center;gap:8px;font-size:14px;cursor:pointer;
  min-height:var(--control-h)}
.checks{display:flex;flex-wrap:wrap;gap:4px 20px}
.inline-form{display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap}
.inline-form .field{flex:1;min-width:180px}
.form-actions{display:flex;gap:8px;align-items:center;justify-content:flex-end;
  flex-wrap:wrap;margin-top:16px}
.form-actions .note{margin-right:auto;font-size:12.5px;color:var(--muted)}

/* ── buttons ───────────────────────────────────────────────────────────── */
button,.btn{display:inline-flex;align-items:center;justify-content:center;
  gap:6px;height:var(--control-h);padding:0 15px;border:1px solid var(--accent);
  border-radius:var(--radius-sm);background:var(--accent);color:var(--accent-ink);
  font:inherit;font-size:14px;font-weight:600;cursor:pointer;white-space:nowrap;
  text-decoration:none}
button:hover,.btn:hover{filter:brightness(1.07);text-decoration:none}
button.secondary,.btn.secondary,button.quiet{background:var(--card);
  color:var(--ink);border-color:var(--line)}
button.secondary:hover,.btn.secondary:hover,button.quiet:hover{
  border-color:var(--faint);filter:none}
button.danger,.btn.danger{background:var(--bad);border-color:var(--bad);color:#fff}
button.sm,.btn.sm{height:30px;padding:0 11px;font-size:13px}
button.link{background:none;border:0;color:var(--link);padding:0;height:auto;
  font-weight:500}
button:disabled{opacity:.45;cursor:not-allowed;filter:none}
form.inline{display:inline}

/* ── segmented / choice lists ──────────────────────────────────────────── */
.segmented{display:inline-flex;border:1px solid var(--line);
  border-radius:var(--radius-sm);overflow:hidden;background:var(--card)}
.segmented label{display:flex;align-items:center;gap:7px;padding:0 14px;
  height:var(--control-h);cursor:pointer;font-size:14px;
  border-right:1px solid var(--line);white-space:nowrap}
.segmented label:last-child,.segmented a:last-child{border-right:0}
.segmented label:has(input:checked){
  background:color-mix(in srgb,var(--accent) 13%,transparent);
  color:var(--accent);font-weight:600}
.segmented input{position:absolute;opacity:0;pointer-events:none}
.segmented a{display:flex;align-items:center;gap:6px;padding:0 13px;
  height:var(--control-h);color:var(--ink);font-size:13.5px;
  border-right:1px solid var(--line);white-space:nowrap;text-decoration:none}
.segmented a:hover{background:var(--sunken);text-decoration:none}
.segmented a.on{background:color-mix(in srgb,var(--accent) 13%,transparent);
  color:var(--accent);font-weight:600}
.segmented.sm a,.segmented.sm label{height:30px;font-size:13px;padding:0 11px}
/* A row's rarer actions, behind "More" in a row of their own (wap-data's
   keys table). Opening the menu shows the next row; no script. */
details.row-menu{display:inline-block;margin-left:6px}
details.row-menu > summary{list-style:none}
details.row-menu > summary::-webkit-details-marker{display:none}
details.row-menu[open] > summary{color:var(--accent);border-color:var(--accent)}
tr.row-actions{display:none}
tr:has(details.row-menu[open]) + tr.row-actions{display:table-row}
tr.row-actions > td{background:color-mix(in srgb,var(--faint) 5%,transparent);
  padding:14px 16px 16px}
.segmented .seg-label{display:flex;align-items:center;padding:0 12px;
  color:var(--muted);font-size:12.5px;border-right:1px solid var(--line);
  white-space:nowrap}
.choices{display:flex;flex-direction:column}
.choices a{display:block;padding:11px 16px;border-left:3px solid transparent;
  color:var(--ink);text-decoration:none;border-bottom:1px solid var(--line-soft)}
.choices a:last-child{border-bottom:0}
.choices a:hover{background:var(--sunken);text-decoration:none}
.choices a.on{background:color-mix(in srgb,var(--brand) 9%,transparent);
  border-left-color:var(--brand)}
.choices a .t{display:block;font-weight:600;font-size:14px}
.choices a .d{display:block;font-size:12.5px;color:var(--muted)}
.choices .group{padding:10px 16px 4px;font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--faint)}

/* ── tables ────────────────────────────────────────────────────────────── */
.table-wrap{overflow-x:auto}
.card > .table-wrap{border-radius:0 0 var(--radius) var(--radius)}
.card > .table-wrap:first-child{border-radius:var(--radius)}
.table-wrap.boxed{border:1px solid var(--line);border-radius:var(--radius);
  background:var(--card)}
table.data{width:100%;border-collapse:collapse;font-size:13.5px}
table.data th{text-align:left;padding:9px 14px;font-size:11.5px;font-weight:650;
  text-transform:uppercase;letter-spacing:.04em;color:var(--muted);
  background:var(--sunken);border-bottom:1px solid var(--line);white-space:nowrap}
table.data td{padding:10px 14px;border-bottom:1px solid var(--line-soft);
  vertical-align:top;overflow-wrap:anywhere}
table.data tr:last-child td{border-bottom:0}
table.data tbody tr:hover td{background:color-mix(in srgb,var(--accent) 3%,transparent)}
table.data .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
table.data .nowrap{white-space:nowrap}
table.data td.empty{color:var(--muted);text-align:center;padding:22px}
table.data td .sub{display:block;color:var(--muted);font-size:12px}
dl.kv{display:grid;grid-template-columns:minmax(120px,max-content) minmax(0,1fr);
  gap:9px 18px;margin:0;font-size:13.5px}
dl.kv dt{color:var(--muted)} dl.kv dd{margin:0;min-width:0;overflow-wrap:anywhere}
details summary{cursor:pointer;color:var(--muted);font-size:13px}
details[open] summary{margin-bottom:8px}

/* ── the live run: a hand-started sync, watched ────────────────────────── */
.bar{height:10px;border-radius:999px;
  background:color-mix(in srgb,var(--faint) 22%,transparent);overflow:hidden}
.bar > span{display:block;height:100%;width:0;background:var(--brand);
  border-radius:inherit;transition:width .6s ease}
.bar.running > span{background-image:linear-gradient(90deg,transparent 0,
  rgba(255,255,255,.35) 50%,transparent 100%);background-size:200% 100%;
  animation:bar-sheen 1.6s linear infinite;background-color:var(--brand)}
.bar.success > span{background:var(--good)}
.bar.failed > span{background:var(--bad)}
@keyframes bar-sheen{from{background-position:200% 0}to{background-position:-200% 0}}
@media (prefers-reduced-motion:reduce){.bar > span{transition:none;animation:none !important}}
.live-run{margin-bottom:16px}
.live-meta{display:flex;flex-wrap:wrap;justify-content:space-between;
  gap:4px 16px;margin-top:8px}
.run-log{list-style:none;margin:12px 0 0;padding:8px 0;max-height:320px;
  overflow:auto;border:1px solid var(--line);border-radius:8px;
  font:12px/1.55 var(--mono);
  background:color-mix(in srgb,var(--faint) 6%,transparent)}
.run-log li{display:flex;gap:10px;padding:0 12px}
.run-log time{color:var(--faint);flex:none;min-width:58px}
.run-log span{overflow-wrap:anywhere}
.run-log li.warn span{color:var(--amber)}
.run-log li.error span{color:var(--bad);font-weight:600}

/* ── the token, the help "?", little bars ──────────────────────────────── */
.token{font-family:var(--mono);font-size:14px;padding:12px 14px;
  border:1px dashed var(--accent);border-radius:var(--radius-sm);
  word-break:break-all;background:color-mix(in srgb,var(--accent) 5%,var(--card))}
a.help-q{display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;border-radius:50%;border:1px solid var(--line);
  color:var(--faint);font-size:11px;font-weight:700;text-decoration:none;flex:none}
a.help-q:hover,a.help-q:focus{color:var(--brand);border-color:var(--brand);
  text-decoration:none}
.hbars{display:grid;gap:5px}
.hbar{display:grid;grid-template-columns:minmax(90px,40%) 1fr 56px;gap:10px;
  align-items:center;font-size:12.5px}
.hl{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted)}
.ht{background:var(--sunken);border-radius:4px;height:10px}
.ht i{display:block;height:10px;border-radius:4px;min-width:2px}
.hv{text-align:right;font-variant-numeric:tabular-nums}
/* Stacked day columns (charts.html `columns`). 🔴 These were never ported
   with the macro, so the Per day card drew bare <i> tags in a line. */
.cols{display:flex;align-items:flex-end;gap:2px;border-bottom:1px solid var(--line)}
.col{flex:1;display:flex;flex-direction:column-reverse;min-width:3px}
.col i{display:block} .col:hover i{opacity:.75}
.cols-axis{display:flex;justify-content:space-between;font-size:11px;
  color:var(--faint);margin-top:4px}
.legend{display:flex;gap:14px;font-size:12px;color:var(--muted);margin-top:6px}
.legend i{display:inline-block;width:10px;height:10px;border-radius:2px;
  margin-right:5px;vertical-align:-1px}
.c-accent{background:var(--accent)} .c-bad{background:var(--bad)}
.c-amber{background:var(--amber)} .c-good{background:var(--good)}
.c-muted{background:var(--faint)}

/* ── the guide ─────────────────────────────────────────────────────────── */
.guide{display:grid;grid-template-columns:220px minmax(0,1fr);gap:32px;
  align-items:start}
.guide nav.toc{position:sticky;top:calc(var(--header-h) + 16px);font-size:13.5px;
  max-height:calc(100vh - var(--header-h) - 32px);overflow:auto}
.guide nav.toc a{display:block;padding:3px 0;color:var(--muted)}
.guide nav.toc a:hover{color:var(--link)}
.guide nav.toc b{display:block;margin:14px 0 4px;font-size:11px;
  text-transform:uppercase;letter-spacing:.06em;color:var(--ink)}
.guide article{max-width:860px;min-width:0;line-height:1.6}
.guide article section{scroll-margin-top:calc(var(--header-h) + 16px);
  border-top:1px solid var(--line);padding-top:10px;margin-top:28px}
.guide article h2{font-size:20px;margin:10px 0 8px}
.guide article h3{font-size:15px;margin:18px 0 6px}
.guide dl.terms{display:grid;
  grid-template-columns:minmax(150px,max-content) minmax(0,1fr);gap:8px 18px;margin:10px 0}
.guide dl.terms dt{font-weight:600} .guide dl.terms dd{margin:0}
.guide ol li,.guide ul li{margin:4px 0} .guide .table-wrap{margin:10px 0}
.guide .rule{border-left:3px solid var(--line);padding:4px 0 4px 14px;margin:12px 0}
.guide .tip{background:color-mix(in srgb,var(--accent) 7%,transparent);
  border-radius:8px;padding:10px 14px;margin:12px 0}
.guide .danger{background:color-mix(in srgb,var(--bad) 8%,transparent);
  border-left:3px solid var(--bad);border-radius:6px;padding:10px 14px;margin:12px 0}
.guide .needs{display:inline-block;font-size:12px;color:var(--muted);
  border:1px solid var(--line);border-radius:10px;padding:1px 9px;margin-bottom:6px}
@media (max-width:860px){.guide{grid-template-columns:minmax(0,1fr)}
  .guide nav.toc{position:static;max-height:none}
  .guide dl.terms{grid-template-columns:minmax(0,1fr)}}

/* ── sign in, set a password ───────────────────────────────────────────────
   A 440px column: the lockup 84px from the top, a 400px card 32px below it.
   🔴 The lockup is partsight's large sign-in hero, measure for measure: the
   100px mark BESIDE a 60px wordmark, 13px apart, and the tagline 8px under
   the wordmark, one letter per span, spread to the wordmark's width. */
body.auth{background:var(--bg)}
.authlogo{display:flex;align-items:center;justify-content:center;gap:13px;
  margin-bottom:32px}
.authlogo .mark{width:100px;height:100px}
.authlogo .lockup{display:inline-flex;flex-direction:column;gap:8px}
.authlogo .wordmark{font-size:60px}
.authlogo .tagline{display:flex;justify-content:space-between;margin:0;
  font-family:var(--display);font-weight:500;font-size:14.3px;line-height:1;
  color:var(--muted);padding:0 1px 0 2px}

.card.auth-card{width:400px;max-width:100%;margin:0 auto;padding:24px 24px 0;
  overflow:hidden}
.card.auth-card h1{font-size:18px;margin:0 0 4px}
.card.auth-card p.sub{font-size:13.5px;color:var(--muted);margin:0 0 14px}
.card.auth-card label{display:block;font-weight:600;color:var(--ink);
  font-size:13px;margin:14px 0 5px}
.card.auth-card input{height:38px;width:100%}
.card.auth-card button[type=submit]{width:100%;height:38px;font-size:14px;
  font-weight:600;margin-top:18px}
/* The hint sits UNDER the box it describes, not above it. */
.card.auth-card .hint{font-size:12.5px;color:var(--faint);margin:5px 0 0}
/* Errors go ABOVE the fields: at the bottom they are below the fold on a
   phone, and the person has already pressed the button. */
.card.auth-card .err{margin:0 0 14px;padding:9px 11px;
  border-radius:var(--radius-sm);color:var(--bad);font-size:13.5px;
  background:color-mix(in srgb,var(--bad) 8%,transparent);
  border:1px solid color-mix(in srgb,var(--bad) 35%,transparent)}
.card.auth-card .strip{margin:22px -24px 0;padding:13px 24px;
  background:var(--sunken);border-top:1px solid var(--line);
  font-size:12.5px;color:var(--muted)}
body.auth footer.foot{text-align:center;padding-bottom:28px}

@media (max-width:460px){
  main.narrow{padding-top:48px}
  .authlogo{gap:11px}
  .authlogo .mark{width:85px;height:85px}
  .authlogo .wordmark{font-size:51px}
  .authlogo .tagline{font-size:12.2px}
  .card.auth-card{width:100%}
}

/* ── a setting row ─────────────────────────────────────────────────────────
   label and description on the left, the control in the middle, the save at
   the END OF ITS OWN ROW — so saving one thing cannot carry another along,
   and the eye travels the same way on every page that shows settings. */
/* align-content:start — the card body stretches to match its taller
   neighbour in a two-up grid, and without this the rows stretch with
   it and float in the middle of the gap. */
.set-list{display:grid;gap:2px;align-content:start}
/* 🔴 FLEX-WRAP, not a fixed 3-column grid. These cards sit two-up, so a row
   with a "why" box had about 150px left for the description and wrapped it
   three words to a line. Wrapping lets the control and the reason drop to
   their own line in a narrow card and sit inline in a wide one, and the
   description keeps a usable measure either way. */
.set-row{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;
  padding:11px 0;border-bottom:1px solid var(--line-soft)}
.set-row:last-child{border-bottom:0}
.set-row > .set-why{flex:1 1 100%;order:9}
.set-what{flex:1 1 240px;min-width:0}
/* 🔴 The KEY and its DESCRIPTION were 12.5px/600 against 12px/400 — half a
   pixel apart and both bright, so they read as one block of text and you
   had to parse the row to find where the name ended.
   Separated on three axes at once: size, weight, and the space between
   them. NOT on colour alone — the description stays --muted (7.2:1 on the
   dark card, 5.6:1 on the light) because the next step down, --faint, is
   4.16:1 and fails at this size. */
.set-what .label{font-family:var(--mono);font-size:13.5px;font-weight:650;
  color:var(--ink);letter-spacing:-.01em;line-height:1.3;flex-wrap:wrap}
.set-what .help{display:block;margin-top:5px;font-size:11.5px;line-height:1.5;
  color:var(--muted)}
.set-value{flex:0 1 160px;min-width:120px}
.set-value input,.set-value select{height:32px;font-size:13px}
.set-do{flex:0 0 auto;display:flex;gap:6px;align-items:center;margin-left:auto}
.set-why{height:32px;font-size:12.5px}
@media (max-width:720px){
  .set-value{flex:1 1 100%}
  .set-do{margin-left:0}
}

