/* The console. One stylesheet, no framework, no build step. Ported from
   mbp-data (Bathsight), which ported wap-data's console: same tokens, same
   vocabulary, so a person who knows one console knows the others. What
   changed is the PALETTE: stone ink and the Stonepath mint. The menu opens
   without JavaScript, and the theme follows the system until someone
   chooses otherwise. */

/* ── the faces ─────────────────────────────────────────────────────────────
   Saira 300–700 for headings; Bricolage Grotesque 800 for the Stonepath
   wordmark and IBM Plex Mono 600 for its tagline. All SIL OFL (fonts/*-OFL.txt),
   latin subsets, served by this app. 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")}
@font-face{font-family:"Bricolage Grotesque";font-style:normal;font-weight:800;
  font-display:swap;src:url("fonts/bricolage-latin-800.woff2") format("woff2")}
@font-face{font-family:"IBM Plex Mono";font-style:normal;font-weight:600;
  font-display:swap;src:url("fonts/plexmono-latin-600.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:#1d2430; --muted:#5c6676; --faint:#8a93a1;
  --line:#dee2e8; --line-soft:#eaedf1;
  --accent:#0b7f72; --accent-ink:#fff; --brand:#0b7f72; --link:#0a7468;
  --bad:#b3261e; --amber:#a66a00; --good:#0f7a34;
  --display:Saira,ui-sans-serif,system-ui,sans-serif;
  --logo-face:"Bricolage Grotesque",ui-sans-serif,system-ui,sans-serif;
  --logo-tag-face:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --logo-tile:#0d9488; --logo-drop:#fff; --logo-centre:#fff;
  --logo-path:#0d9488; --logo-tag:#0a7468;
  --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:#14b8a6; --accent-ink:#10161f; --brand:#14b8a6; --link:#2dd4bf;
  --bad:#ff8a80; --amber:#e0a33e; --good:#57c98a;
  --logo-tile:#0d9488; --logo-drop:#fff; --logo-centre:#fff;
  --logo-path:#0d9488; --logo-tag:#0d9488;
  --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:#14b8a6; --accent-ink:#10161f; --brand:#14b8a6; --link:#2dd4bf;
  --bad:#ff8a80; --amber:#e0a33e; --good:#57c98a;
  --logo-tile:#0d9488; --logo-drop:#fff; --logo-centre:#fff;
  --logo-path:#0d9488; --logo-tag:#0d9488;
  --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 ────────────────────────────────────────────────────────────
   🔴 Stonepath: lowercase "stone" in the ink, "path" in the logo mint, both
   Bricolage 800. The mark is the same mint tile in BOTH themes; only the
   type's colours flip, through --logo-* tokens, so there is no second,
   reversed artwork to keep in step. */
.wordmark{font-family:var(--logo-face);font-weight:800;letter-spacing:-.03em;
  line-height:.9;white-space:nowrap}
.wordmark > span{color:var(--logo-path)}
.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:21px}
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 a.me{text-decoration:none}
header.top a.me:hover{color:var(--ink)}
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)}
/* A multi-pick dropdown: a <details> whose summary looks like a select and
   whose panel is a list of checkboxes. No script needed to open it. */
details.picker{position:relative}
details.picker > summary{list-style:none;display:flex;align-items:center;
  justify-content:space-between;gap:8px;height:var(--control-h);padding:0 11px;
  border:1px solid var(--line);border-radius:var(--radius-sm);background:var(--card);
  font-size:14px;cursor:pointer;white-space:nowrap;overflow:hidden}
details.picker > summary::-webkit-details-marker{display:none}
details.picker > summary::after{content:"▾";color:var(--muted)}
details.picker[open] > summary{border-color:var(--accent)}
details.picker .picker-panel{position:absolute;z-index:20;top:calc(100% + 4px);left:0;
  min-width:100%;max-height:260px;overflow:auto;padding:6px 12px;background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  box-shadow:0 6px 20px rgba(16,24,40,.12)}
details.picker .picker-panel .check{min-height:30px;white-space:nowrap}
details.picker .picker-panel .check[hidden]{display:none}
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 a.off{opacity:.35}
.guide-search{margin:0 0 6px}
.guide-search input{width:100%;height:32px;font-size:13px}
.guide-search span{display:block;min-height:1.4em;margin-top:4px;font-size:11.5px}
.guide mark.gq{background:color-mix(in srgb, var(--amber) 35%, transparent);color:inherit;
  border-radius:2px;padding:0 1px}
.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 STACKED: the 88px mark centred over a 60px wordmark, and
   the tagline 10px under the wordmark, one letter per span, spread to the
   wordmark's width exactly. */
body.auth{background:var(--bg)}
.authlogo{display:flex;flex-direction:column;align-items:center;gap:16px;
  margin-bottom:32px}
.authlogo .mark{width:88px;height:88px}
.authlogo .lockup{display:inline-flex;flex-direction:column;align-items:stretch;gap:10px}
.authlogo .wordmark{font-size:60px}
.authlogo .tagline{display:flex;justify-content:space-between;margin:0;
  font-family:var(--logo-tag-face);font-weight:600;font-size:13px;line-height:1;
  color:var(--logo-tag)}

.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:13px}
  .authlogo .mark{width:76px;height:76px}
  .authlogo .wordmark{font-size:51px}
  .authlogo .tagline{font-size:11px}
  .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)}
/* A setting saved but not yet built into the stored tables. */
.set-stale{margin:8px 0 0;padding:7px 10px;font-size:12px;line-height:1.5}
/* A setting's long form: what it does to the numbers, with worked examples. */
/* Opened, the row is tall: keep the value and Save beside the key, not mid-text. */
.set-row:has(.set-more[open]){align-items:flex-start}
.set-more{margin-top:8px;font-size:12.5px;line-height:1.55;color:var(--ink)}
.set-more > summary{cursor:pointer;color:var(--link);font-size:12px;font-weight:600}
.set-more p{margin:10px 0 0;max-width:78ch}
.set-more pre{margin:8px 0 0;padding:10px 12px;overflow-x:auto;font-family:var(--mono);
  font-size:11.5px;line-height:1.5;background:var(--sunken);
  border:1px solid var(--line-soft);border-radius:var(--radius-sm);white-space:pre}
.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}
}


/* ── the bar's drop-downs (web.NAV_GROUPS) ───────────────────────────── */
/* The summary looks like a link; the panel hangs below the header. Below
   960px the panel is inline under its summary, so the CSS-only menu keeps
   working without nav.js. */
details.navgroup{position:relative;display:block;height:100%}
details.navgroup > summary{display:flex;align-items:center;gap:5px;height:100%;
  box-sizing:border-box;padding:0 9px;color:var(--muted);font-size:13.5px;
  white-space:nowrap;border-bottom:2px solid transparent;cursor:pointer;
  list-style:none;user-select:none}
details.navgroup > summary::-webkit-details-marker{display:none}
details.navgroup > summary::after{content:"";width:5px;height:5px;
  border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;
  transform:translateY(-2px) rotate(45deg);opacity:.7}
details.navgroup[open] > summary::after{transform:translateY(1px) rotate(-135deg)}
details.navgroup > summary:hover,details.navgroup[open] > summary{color:var(--ink)}
details.navgroup.on > summary{color:var(--ink);border-bottom-color:var(--brand);font-weight:600}
details.navgroup > summary:focus-visible{outline:2px solid var(--brand);outline-offset:-2px}
.navmenu{position:absolute;top:100%;left:0;min-width:170px;display:grid;
  padding:6px;margin-top:1px;background:var(--card);border:1px solid var(--line);
  border-radius:8px;box-shadow:0 8px 24px rgb(0 0 0 / .18);z-index:30}
nav.app .navmenu a{padding:8px 10px;border-bottom:0;border-radius:6px}
nav.app .navmenu a:hover{background:var(--line)}
nav.app .navmenu a.on{color:var(--brand)}
/* 🔴 The bar scrolls sideways when it is short of room, and a scrolling box
   clips anything that hangs out of it — the drop-downs included. Wide enough
   for the grouped bar, it does not need to scroll. */
@media (min-width:961px){ nav.app{overflow:visible} }
@media (max-width:960px){
  details.navgroup{height:auto}
  details.navgroup > summary{height:auto;padding:9px 4px;border-bottom:0}
  details.navgroup.on > summary{color:var(--brand)}
  .navmenu{position:static;min-width:0;padding:0 0 4px 14px;margin:0;border:0;
    box-shadow:none;background:none}
}

/* A number and its unit on one line: "3 days". */
.inline-unit{display:flex;align-items:center;gap:8px}
.inline-unit input{flex:1;min-width:0}

/* ── segmented choice (wap-data's): radios drawn as one joined control ── */
.segmented{display:inline-flex;align-self:flex-start;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;font-weight:400;
  border-right:1px solid var(--line);white-space:nowrap}
.segmented label:last-child{border-right:0}
.segmented label:has(input:checked){color:var(--accent);font-weight:600;
  background:color-mix(in srgb,var(--accent) 13%,transparent)}
.segmented label:has(input:focus-visible){outline:2px solid var(--brand);outline-offset:-2px}
.segmented input{position:absolute;opacity:0;pointer-events:none}

/* The digest form's When: the fields that apply to the Repeat choice. */
.when-default{margin:8px 0 0;font-size:15px}
.when-own{display:flex;gap:12px}
.when-own > .field{flex:1}
.when:has(input[name=schedule_kind][value=default]:checked) [data-when-kind]:not([data-when-kind~=default]),
.when:has(input[name=schedule_kind][value=daily]:checked) [data-when-kind]:not([data-when-kind~=daily]),
.when:has(input[name=schedule_kind][value=weekdays]:checked) [data-when-kind]:not([data-when-kind~=weekdays]),
.when:has(input[name=schedule_kind][value=weekly]:checked) [data-when-kind]:not([data-when-kind~=weekly]){display:none}

/* The "Using it" block on Key added: commands, not a secret, so solid. */
pre.token-use{border-style:solid;font-size:12.5px;white-space:pre-wrap;margin:0}

/* Two cards side by side at one height: the grid's default stretch, with
   each card a column so a footer sits at the bottom of the taller one. */
.grid.pair{align-items:stretch}
.grid.pair > .card{display:flex;flex-direction:column}
.grid.pair > .card > form{display:flex;flex-direction:column;flex:1}
.grid.pair .card-body{flex:1}
/* Sync: one card per mode, the default first and marked. */
.sync-modes .check-confirm{display:flex;align-items:center;gap:6px;color:var(--muted)}
.sync-modes .mode-what{margin:0 0 12px;font-weight:550}
.sync-modes dl.kv{grid-template-columns:72px minmax(0,1fr)}
.sync-modes .mode-waiting{margin:12px 0 0;font-size:12.5px}
.sync-note{margin:10px 0 24px}

/* ── Planning rules (Purchasing → Planning rules) ─────────────────────── */
.inv-jump{margin:0 0 16px;flex-wrap:wrap}
.card.inv{margin-bottom:16px;scroll-margin-top:calc(var(--header-h) + 16px)}
.inv-intro{margin:0 0 14px;max-width:80ch;color:var(--muted);font-size:13.5px}
.vendor{padding:14px 0;border-top:1px solid var(--line-soft);scroll-margin-top:calc(var(--header-h) + 16px)}
.vendor:first-of-type{border-top:0;padding-top:0}
.vendor-head{display:flex;flex-wrap:wrap;gap:10px 28px;align-items:flex-end;justify-content:space-between}
.vendor-head h3{margin:0 0 2px;font-size:16px}
.vendor-stats{display:flex;flex-wrap:wrap;gap:6px 22px;margin:0}
.vendor-stats div{display:flex;flex-direction:column}
.vendor-stats dt{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.vendor-stats dd{margin:0;font-weight:600}
.vendor-stats .planned dd{color:var(--link)}
.po-list{margin-top:10px}
.po-list > summary{cursor:pointer;color:var(--link);font-size:13px;font-weight:600;margin-bottom:8px}
table.data.compact td,table.data.compact th{padding-top:6px;padding-bottom:6px}
table.data tr.off td{opacity:.55}
table.data tr.off td.act{opacity:1}
.bar-col{min-width:160px;width:28%}
.leadbar{position:relative;height:8px;border-radius:4px;background:var(--sunken)}
.leadbar span{position:absolute;inset:0 auto 0 0;border-radius:4px;background:var(--accent)}
.leadbar span.over{background:var(--amber)}
.leadbar i{position:absolute;top:-3px;bottom:-3px;width:2px;background:var(--ink);opacity:.6}
td.act{text-align:right;white-space:nowrap}
details.reveal{display:inline-block;text-align:left}
details.reveal > summary{list-style:none}
details.reveal > summary::-webkit-details-marker{display:none}
details.reveal[open] > summary{display:none}
details.reveal form,.row-form{display:flex;flex-wrap:wrap;gap:6px 8px;align-items:center}
details.reveal form input[name=reason],.row-form input[name=reason]{min-width:200px;flex:1}
.pr-quote .row-form{flex-wrap:wrap}
.pr-quote .row-form input[name=reason]{min-width:220px}
table.data tr.more{display:none}
tr.more-row td{text-align:center}
.row-form input.num{width:64px;text-align:right}
.status-legend{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:8px 18px;margin:0 0 14px}
.status-legend dt{font-weight:650;font-size:13px}
.status-legend dd{margin:0;font-size:12.5px;color:var(--muted)}
.add-form{margin-top:14px}
.add-form > summary{list-style:none}
.add-form > summary::-webkit-details-marker{display:none}
.grid-form{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px 12px;margin-top:12px;align-items:end}
.grid-form .field.wide{grid-column:span 3}
@media (max-width:820px){.grid-form{grid-template-columns:minmax(0,1fr)}.grid-form .field.wide{grid-column:auto}}
ul.chips{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:10px}
ul.chips li{display:flex;align-items:center;gap:6px}
.chip{display:inline-flex;align-items:center;height:28px;padding:0 12px;border-radius:14px;
  background:var(--sunken);border:1px solid var(--line);font-size:13px;font-weight:600}
.chip-act{cursor:pointer;color:var(--link);font-size:12px;list-style:none}
.chip-act::-webkit-details-marker{display:none}
.row-form input.colour-in{width:200px;flex:0 0 auto}

/* ── Planning rules: the summary, the why line, the colour lanes ───────── */
.pr-summary{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px;margin:0 0 12px}
.pr-sum{display:flex;flex-direction:column;gap:3px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;
  background:var(--card);color:inherit;text-decoration:none}
.pr-sum:hover,.pr-sum:focus-visible{border-color:var(--link)}
.pr-sum-h{font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.pr-sum-v{font-size:14px}
.pr-sum-s{font-size:12px;color:var(--faint)}
.pr-why{margin:-4px 0 10px;font-size:13.5px}
.pr-quote{margin:0 0 10px}
.pr-quote form{margin-top:8px}
.pr-bar-key{display:flex;flex-wrap:wrap;align-items:center;gap:4px 16px;margin:8px 0 2px}
.pr-bar-key>span{display:inline-flex;align-items:center;gap:6px}
.pr-key-bar{display:inline-block;width:22px;height:6px;border-radius:3px;background:var(--accent)}
.pr-key-bar.over{background:var(--amber)}
.pr-key-tick{display:inline-block;width:2px;height:12px;background:var(--ink)}
.pr-lanes{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:10px}
.pr-lane{border:1px solid var(--line);border-radius:8px;padding:10px 12px;background:var(--sunken)}
.pr-lane.counts{border-color:color-mix(in srgb,var(--good) 45%,var(--line))}
.pr-lane-h{margin:0 0 8px}
.pr-lane-s{display:block;font-size:12px;color:var(--muted);margin-top:2px}
.pr-lane ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.pr-colour summary{cursor:pointer;list-style:none;padding:4px 8px;border:1px solid var(--line);border-radius:6px;background:var(--card);font-weight:600;font-size:13.5px}
.pr-colour summary::-webkit-details-marker{display:none}
details.reveal.pr-colour[open] > summary{display:block;border-color:var(--link)}
details.reveal.pr-colour{display:block}
details.reveal .pr-colour-form{display:flex;flex-direction:column;align-items:stretch}
details.reveal .pr-colour-form select,details.reveal .pr-colour-form input[name=reason]{width:100%;min-width:0;min-height:36px;flex:none}
details.reveal .pr-colour-form button{align-self:flex-start}
.pr-colour-form{display:flex;flex-direction:column;gap:6px;margin:6px 0 4px}

/* ── Restock plan (Purchasing → Restock plan) ───────────────────────── */
.rs-night{display:flex;flex-wrap:wrap;align-items:center;gap:8px 12px;margin:0 0 16px}
.rs-night label{font-weight:600}
.rs-night select{width:auto;min-width:200px}
.rs-orders{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:12px;margin:0 0 20px}
.rs-order{display:flex;flex-direction:column;gap:4px;padding:14px;border:1px solid var(--line);border-radius:10px;
  background:var(--card);color:inherit;text-decoration:none}
.rs-order:hover{border-color:var(--link)}
.rs-order.late{border-left:4px solid var(--bad)}
.rs-order.due{border-left:4px solid var(--amber)}
.rs-order.not_due{opacity:.75}
.rs-order .pill{align-self:flex-start}
.rs-order-top{display:flex;justify-content:space-between;align-items:center;gap:8px}
.rs-vendor{font-weight:700;font-size:15px}
.rs-when,.rs-size{font-size:13px}
.rs-money{font-weight:650}
.card.rs{margin-bottom:16px;scroll-margin-top:calc(var(--header-h) + 16px)}
.rs-stats{margin:0 0 16px}
.rs-h{font-size:13px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted);margin:16px 0 8px}
table.data td.num,table.data th.num{text-align:right}
.rs-callout{margin:0 0 14px;padding:10px 12px;border-radius:8px;border:1px solid var(--line);background:var(--sunken)}
.rs-callout.late{border-color:color-mix(in srgb,var(--bad) 45%,var(--line))}
.rs-callout.due{border-color:color-mix(in srgb,var(--amber) 45%,var(--line))}
.rs-mins{list-style:none;margin:0 0 4px;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:10px}
.rs-minbox{border:1px solid var(--line);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:6px}
.rs-minbox.short{border-color:color-mix(in srgb,var(--bad) 50%,var(--line))}
.rs-min-top{display:flex;justify-content:space-between;align-items:flex-start;gap:8px;font-size:13.5px;font-weight:600}
.rs-kind{display:block;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.rs-meter{height:6px;border-radius:3px;background:var(--line-soft);overflow:hidden}
.rs-meter span{display:block;height:100%;background:var(--good)}
.rs-minbox.short .rs-meter span{background:var(--bad)}
.rs-legend{margin:0 0 10px;font-size:13px}
.rs-legend summary{cursor:pointer;color:var(--link)}
.rs-legend dl{display:grid;grid-template-columns:max-content 1fr;gap:6px 16px;margin:10px 0 0;max-width:110ch}
.rs-legend dt{font-weight:600}
.rs-legend dd{margin:0;color:var(--muted)}
@media (max-width:640px){ .rs-legend dl{grid-template-columns:1fr} .rs-legend dd{margin-bottom:6px} }
.rs-tag{margin:0 4px 4px 0;white-space:nowrap}
table.rs-lines{min-width:900px}
table.rs-lines td:first-child{min-width:250px}
table.rs-lines th .th-sub{display:block;font-weight:400;text-transform:none;letter-spacing:0;color:var(--faint);font-size:11px}
table.rs-lines td .sub.error{color:var(--bad)}
table.rs-lines td .sub.warn-text{color:var(--amber)}
table.rs-lines td{vertical-align:top}
tbody.rs-gauge th{text-align:left;font-size:13px;font-weight:650;background:var(--sunken);padding:8px 12px;text-transform:none;letter-spacing:0;color:var(--ink)}
tbody.rs-gauge th .muted{font-weight:400}
.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.rs-tag.min{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 50%,var(--line))}
tbody.rs-line + tbody.rs-line tr:first-child td{border-top:1px solid var(--line-soft)}
tr.rs-work td{background:var(--sunken);padding:12px 14px}
.rs-text{margin:0 0 10px;max-width:100ch;line-height:1.5}
.rs-kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:6px 18px;margin:0}
.rs-kv dt{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--muted)}
.rs-kv dd{margin:0;font-size:13px}
.rs-hist{display:inline-block;margin:0 14px 2px 0}
.rs-hist.late{color:var(--bad)}
.rs-hist.due{color:var(--amber)}
.rs-hist.not_due{color:var(--muted)}
.card.rs tr.on td{background:var(--sunken)}

/* --- pattern library ------------------------------------------------------ */
.lib-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}
.lib-card{display:flex;flex-direction:column;color:inherit;text-decoration:none;overflow:hidden}
.lib-card .thumb{background:var(--sunken);display:flex;align-items:center;justify-content:center;
  height:190px;padding:10px;border-bottom:1px solid var(--line-soft)}
.lib-card .thumb img,.thumb-lg img{max-width:100%;max-height:100%;display:block;filter:var(--thumb-filter,none)}
.lib-body{padding:10px 12px 12px;display:flex;flex-direction:column;gap:5px}
.lib-title{font-weight:600}
.lib-meta{display:flex;gap:6px;flex-wrap:wrap}
.lib-filter .field{min-width:150px}
:root[data-theme="dark"]{--thumb-filter:invert(.86) sepia(.25) saturate(1.4) hue-rotate(345deg)}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]){--thumb-filter:invert(.86) sepia(.25) saturate(1.4) hue-rotate(345deg)}}
.doc-edit{font:12.5px/1.45 var(--mono,ui-monospace,monospace);width:100%;min-height:360px;tab-size:2}
.rev-table td{vertical-align:top}
.var-tabs a .sub{display:block;font-size:11px;opacity:.7}
@media (max-width:720px){.lib-grid{grid-template-columns:repeat(auto-fill,minmax(160px,1fr))}
  .lib-card .thumb{height:150px}}
.choices label{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;border:1px solid var(--line-soft);
  border-radius:8px;margin-bottom:6px;cursor:pointer}
.choices label:has(input:checked){border-color:var(--accent);background:color-mix(in srgb,var(--brand) 7%,transparent)}
.choices label input{margin-top:3px}
.choices label .t{display:block;font-weight:600;font-size:14px}
.choices label .d{display:block;font-size:12.5px;color:var(--muted)}
.choices label > span{display:block}
.var-tabs{flex-wrap:wrap;max-width:100%}

/* --- designer ------------------------------------------------------------- */
main:has(#dz){max-width:none}
.dz{display:grid;grid-template-columns:230px minmax(0,1fr) 320px;gap:14px;align-items:start}
.dz-left,.dz-right{position:sticky;top:12px;max-height:calc(100vh - 24px);overflow:auto}
.dz-sec{padding:12px 14px;border-bottom:1px solid var(--line-soft)}
.dz-sec:last-child{border-bottom:0}
.dz-sec .section-title{margin:0 0 8px}
.dz-tiles{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.dz-tile{border:1px solid var(--line);border-radius:8px;padding:6px;cursor:grab;background:var(--card);
  display:flex;flex-direction:column;gap:4px;font-size:11.5px;line-height:1.25;text-align:left;color:inherit}
.dz-tile:hover{border-color:var(--accent)}
.dz-tile.on{border-color:var(--accent);background:color-mix(in srgb,var(--brand) 8%,var(--card))}
.dz-tile svg{width:100%;aspect-ratio:1;color:var(--ink);background:var(--sunken);border-radius:5px}
.dz-toolbar{display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap;padding:8px 10px;margin-bottom:8px}
.dz-tools{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.dz-stage{position:relative;height:min(74vh,760px);min-height:420px;padding:10px;display:flex}
.dz-stage svg{flex:1;width:100%;height:100%;touch-action:none;user-select:none}
.dz-busy{position:absolute;top:12px;right:14px;font-size:12px;color:var(--muted)}
.dz-strip{display:flex;gap:10px;flex-wrap:wrap}
.dz-strip a{display:flex;flex-direction:column;align-items:center;gap:4px;font-size:11.5px;color:inherit;
  text-decoration:none;border:1px solid var(--line);border-radius:8px;padding:6px;background:var(--card)}
.dz-strip a.on{border-color:var(--accent)}
.dz-strip svg{height:120px;width:auto;color:var(--ink)}
.dz-param{display:grid;grid-template-columns:1fr 112px;gap:6px;align-items:center;margin:0 0 6px}
.dz-param label{font-size:12.5px}
.dz-param .help{grid-column:1/-1;margin:-2px 0 4px;font-size:11.5px;color:var(--faint)}
.dz-param input,.dz-param select{height:30px;font-size:12.5px;padding:0 8px}
.dz-param input[type=checkbox]{height:auto;justify-self:start}
.dz-anchor{display:flex;gap:6px;align-items:center;margin:0 0 6px;font-size:12.5px}
.dz-anchor .segmented a{padding:0 9px}
#dz-svg .groove{stroke:var(--ink);stroke-width:.32;fill:none;stroke-linecap:round}
#dz-svg .cut{stroke:var(--accent);stroke-width:.3;stroke-dasharray:1.2 .8;fill:none}
#dz-svg .sheet{fill:var(--card);stroke:var(--line);stroke-width:.35}
#dz-svg .zone{fill:transparent;stroke:color-mix(in srgb,var(--accent) 55%,transparent);stroke-width:.35;
  stroke-dasharray:2 1.2;cursor:pointer}
#dz-svg .zone.on{fill:color-mix(in srgb,var(--accent) 9%,transparent);stroke:var(--accent);stroke-width:.5;stroke-dasharray:none}
#dz-svg .zone.drop{fill:color-mix(in srgb,var(--accent) 22%,transparent)}
#dz-svg .zone-label{font:600 2.4px system-ui;fill:var(--accent);pointer-events:none}
#dz-svg .handle{stroke:var(--accent);stroke-width:1.6;stroke-opacity:.0;cursor:ns-resize}
#dz-svg .handle.x{cursor:ew-resize}
#dz-svg .handle:hover,#dz-svg .handle.dragging{stroke-opacity:.45}
#dz-svg .finding{fill:var(--bad);opacity:.85}
@media (max-width:1100px){.dz{grid-template-columns:1fr}.dz-left,.dz-right{position:static;max-height:none}}
.dz-tiles .dz-tile{height:auto;width:auto;min-width:0;min-height:0;white-space:normal;justify-content:flex-start;
  align-items:stretch;font-weight:500;padding:6px}

/* --- tile editor ---------------------------------------------------------- */
.te{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:14px;align-items:start}
.te-stage{padding:0;overflow:hidden}
.te-bar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;padding:8px 10px;border-bottom:1px solid var(--line-soft)}
.te-bar select{height:28px;width:auto}
#te-svg{display:block;width:100%;height:min(70vh,700px);background:var(--card);cursor:crosshair;touch-action:none}
#te-svg .grid{stroke:var(--line-soft);stroke-width:.02}
#te-svg .axis{stroke:var(--line);stroke-width:.03}
#te-svg .cell{fill:color-mix(in srgb,var(--accent) 7%,transparent);stroke:var(--accent);stroke-width:.04;stroke-dasharray:.2 .12}
#te-svg .rep{stroke:var(--muted);stroke-width:.06;stroke-opacity:.55;fill:none;stroke-linecap:round}
#te-svg .seg{stroke:var(--ink);stroke-width:.1;fill:none;stroke-linecap:round}
#te-svg .seg.hot{stroke:var(--bad)}
#te-svg .ghost{stroke:var(--accent);stroke-width:.08;stroke-dasharray:.15 .1}
#te-svg .pt{fill:var(--accent)}
.te-thumb{width:100%;height:100%;color:var(--ink)}
@media (max-width:1000px){.te{grid-template-columns:1fr}}
