/* Motherlode — one stylesheet for every section.
 *
 * Every section used to carry its own copy of the same 120 lines: the same
 * palette, the same nav, the same panel/table/button/toast rules, drifting
 * apart one paste at a time across eighteen files. That core lives here once.
 * A section's own <style> block is now only what is genuinely unique to it.
 *
 * Greyscale for the interface, hue for severity, and nothing else. The chrome
 * — nav, panels, tables, labels — carries no colour at all, so the three
 * places that do are impossible to miss:
 *
 *     ok      green    "this is fine"
 *     warn    yellow   "worth a look"
 *     bad     red      "this is the finding"
 *
 * That split is the whole point: colour spent on everything is colour that
 * signals nothing. Severity is still carried by contrast as well as hue —
 * a red pill is also a filled pill — so nothing depends on colour alone, and
 * the page still reads for anyone who cannot separate red from green.
 *
 * Every hue is checked against its own page colour: all six clear WCAG AA
 * (paper 5.2-5.7:1, mono 7.6-13.7:1), as does white on each filled surface.
 *
 * Type: system sans for the interface, monospace for data — ids, sizes, hashes,
 * timestamps, commands. That split is the only visual grammar the pages need.
 */

:root {
  /* Paper, the default since 2026-09-15. Warm rather than pure white: #ffffff
   * under a full-screen panel grid is glary, and a hint of yellow makes the
   * hairlines read as paper rather than as a bug. Greys are picked for contrast
   * against that page colour, not against white: --fg-1 14.8:1, --fg-2 6.1:1,
   * --fg-3 3.1:1 — all clear WCAG AA for the sizes they are used at. */
  --black:   #fbfbf9;   /* page */
  --ink:     #f4f3ef;   /* one step off page: inset bars, table stripes */
  --ink-2:   #ecebe5;
  --hair:    #e2e0d9;   /* the hairline every box is drawn with */
  --hair-2:  #c7c4ba;   /* when a box has to separate itself from another */
  --white:   #14151a;   /* the most emphatic ink */
  --fg-1:    #23252b;   /* primary text */
  --fg-2:    #5c6068;   /* secondary: labels, metadata */
  --fg-3:    #8b8f97;   /* tertiary: placeholders, disabled */

  /* the names the sections already use, kept so nothing had to be rewritten */
  --bg:      var(--black);
  --panel:   var(--black);
  --panel-2: var(--ink);
  --panel-3: var(--ink-2);
  --panel2:  var(--ink);
  --hover:   var(--ink);
  --border:  var(--hair);
  --line:    var(--hair);
  --line-soft: var(--ink-2);
  --line-strong: var(--hair-2);
  --text:    var(--fg-1);
  --fg:      var(--fg-1);
  --fg-bright: var(--white);
  --muted:   var(--fg-2);
  --muted-2: var(--fg-3);
  --dim:     var(--fg-2);
  --accent:  var(--white);
  --accent-hover: var(--white);
  --accent-soft: var(--ink-2);
  --accent-dim:  var(--ink-2);

  /* Severity. Three tokens each: the hue itself for text and borders, a soft
   * surface for a tinted background, a line for its edge, and the text colour
   * to use once the hue becomes the fill. */
  --ok:        #1c7a43;   --ok-soft:   #e9f6ee;  --ok-line:   #b2ddc2;  --on-ok:   #ffffff;
  --warn:      #8a5a00;   --warn-soft: #fff6e2;  --warn-line: #f0d89e;  --on-warn: #ffffff;
  --bad:       #bf3328;   --bad-soft:  #fdeceb;  --bad-line:  #f1b7b2;  --on-bad:  #ffffff;

  --danger:  var(--bad);
  /* soft surfaces by their other names, for sections that ask this way */
  --success-soft: var(--ok-soft);
  --warning-soft: var(--warn-soft);
  --danger-soft:  var(--bad-soft);
  --info-soft:    var(--ink-2);
  --danger-dim: var(--bad-soft);
  --info:    var(--fg-1);
  --success: var(--ok);
  --warning: var(--warn);

  /* aliases sections ask for by name, all resolving to the three above */
  --up: var(--ok);        --down: var(--bad);      --idle: var(--fg-3);
  --pending: var(--fg-2); --progress: var(--fg-1); --doing: var(--fg-1);
  --done: var(--fg-2);    --high: var(--white);    --med: var(--fg-1);
  --low: var(--fg-3);     --term-bg: var(--black);
  /* providers carry their own text label, so the badge does not need a hue */
  --do: var(--fg-2); --ovh: var(--fg-2); --wasabi: var(--fg-2);

  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
          Arial, "Helvetica Neue", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
          "DejaVu Sans Mono", monospace;

  --nav-h: 48px;         /* .mnav height; sections offset their own sticky chrome by it */
  --r: 3px;              /* one radius, small enough to read as a square corner */
  --radius: var(--r); --radius-sm: 2px; --radius-pill: 999px;
  --modal-backdrop: rgba(24, 24, 20, .38);
  --scroll: #cfccc2;
  --scroll-hover: #b0ada2;

  /* Depth is available on paper in a way it is not on black, where a shadow is
   * invisible. Kept to two hairline-soft steps so panels lift off the page
   * without the interface looking like it has physics. */
  --shadow-sm: 0 1px 1px rgba(20, 21, 26, .04);
  --shadow: 0 1px 2px rgba(20, 21, 26, .05), 0 2px 8px rgba(20, 21, 26, .04);
  --shadow-md: 0 2px 4px rgba(20, 21, 26, .06), 0 8px 24px rgba(20, 21, 26, .07);
  --ctl: #ffffff;       /* control surface: inputs and buttons sit above the page */
  --r-ctl: 5px;         /* controls get a touch more radius than boxes */
  color-scheme: light;
}

/* basic · paper — the default, restated so the picker can select it back */
[data-theme="paper"] { }

/* basic · mono — black and white, the original: severity by contrast only */
[data-theme="mono"] {
  --black:   #000000;
  --ink:     #0b0b0b;
  --ink-2:   #141414;
  --hair:    #242424;
  --hair-2:  #3a3a3a;
  --white:   #ffffff;
  --fg-1:    #ededed;
  --fg-2:    #9a9a9a;
  --fg-3:    #6a6a6a;
  --modal-backdrop: rgba(0, 0, 0, .72);
  --scroll: #262626;
  --scroll-hover: #3c3c3c;
  --shadow-sm: none; --shadow: none; --shadow-md: none;
  --ctl: transparent;
  /* Lifted and desaturated for a black page; the soft surfaces are near-black
   * tints rather than pastels, or they would glow. */
  --ok:        #57d68a;   --ok-soft:   #0c1a12;  --ok-line:   #24512f;  --on-ok:   #000000;
  --warn:      #ffc857;   --warn-soft: #1c1608;  --warn-line: #4f3c14;  --on-warn: #000000;
  --bad:       #ff6b6b;   --bad-soft:  #1e0d0d;  --bad-line:  #5e2626;  --on-bad:  #000000;
  color-scheme: dark;
}

/* ── themes ───────────────────────────────────────────────────────────────
 * Selected with data-theme on <html>; shared/motherlode.js sets it before
 * first paint and remembers the choice. No attribute means the default above.
 *
 * A theme only redefines the primitives at the top of :root — everything else
 * in this file, and every section's own <style>, derives from those, so a theme
 * is a dozen lines rather than a second stylesheet.
 *
 * One wart to know about: --black means "page" and --white means "the most
 * emphatic ink", which stops being literal the moment a theme is light. The
 * names are kept because ~300 rules and eighteen sections already reference
 * them; renaming would be a large diff for no visual change.
 *
 * Both themes carry the same severity hues — see the severity block in :root.
 */

/* ── the picker, injected into .mnav by shared/motherlode.js ───────────── */
.mnav-theme { margin-left: auto; display: flex; align-items: center; }
.mnav-theme select {
  appearance: none; -webkit-appearance: none;
  background: var(--ctl); color: var(--fg-2);
  border: 1px solid var(--hair); border-radius: var(--radius-pill);
  font-family: var(--sans); font-size: 11.5px; font-weight: 600;
  letter-spacing: .04em; padding: 4px 24px 4px 11px; cursor: pointer;
  /* the caret, drawn rather than shipped as an asset */
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
                    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 13px) 52%, calc(100% - 9px) 52%;
  background-size: 4px 4px, 4px 4px;
  background-repeat: no-repeat;
  transition: color .12s, border-color .12s, box-shadow .12s;
}
.mnav-theme select:hover { color: var(--white); border-color: var(--hair-2); }
.mnav-theme select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

* { box-sizing: border-box; }

html { background: var(--black); }

body {
  margin: 0;
  background: var(--black);
  color: var(--fg-1);
  font-family: var(--sans);
  font-size: 13.5px;
  line-height: 1.55;
  text-rendering: optimizeLegibility;
  /* Lining, equal-width figures everywhere. Sizes, counts and timestamps are
   * most of what these pages show, and proportional digits make a column of
   * them jitter. */
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1, "cv05" 1;
}

/* Greyscale antialiasing thins glyphs, which reads as crisp on a black page
 * and as anaemic on a light one. So it is applied to the dark themes only —
 * paper keeps the platform's subpixel rendering and its normal stem weight. */
[data-theme="mono"] body { -webkit-font-smoothing: antialiased; }

::selection { background: var(--white); color: var(--black); }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--black); }
::-webkit-scrollbar-thumb { background: var(--scroll); border: 2px solid var(--black); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--scroll-hover); }
::-webkit-scrollbar-corner { background: var(--black); }

a { color: var(--fg-1); text-decoration: none; border-bottom: 1px solid var(--hair-2); }
a:hover { color: var(--white); border-bottom-color: var(--white); }
a.plain, a:has(> img), .mnav a, nav a { border-bottom: 0; }

hr { border: 0; border-top: 1px solid var(--hair); margin: 16px 0; }

/* ── the shared section nav ───────────────────────────────────────────────
 * A tab strip, not a set of buttons: where you are is marked by a rule under
 * the word, which is the quietest marker that still cannot be missed. */
.mnav {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 20px;
  height: var(--nav-h); padding: 0 18px;
  /* Translucent + blurred so content scrolling under it stays legible as
   * motion without bleeding through as text. color-mix keeps this one rule
   * correct in all four themes instead of needing a per-theme override. */
  background: var(--black);
  background: color-mix(in srgb, var(--black) 82%, transparent);
  backdrop-filter: saturate(160%) blur(12px);
  -webkit-backdrop-filter: saturate(160%) blur(12px);
  border-bottom: 1px solid var(--hair);
}
@supports not (backdrop-filter: blur(1px)) {
  .mnav { background: var(--black); }
}
.mnav-brand {
  display: flex; align-items: center; gap: 8px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  color: var(--white); text-decoration: none; border-bottom: 0; white-space: nowrap;
  padding-right: 20px; margin-right: -4px;
  border-right: 1px solid var(--hair);   /* separates identity from navigation */
}
.mnav-brand:hover { color: var(--white); }
.mnav-brand:hover .mnav-logo { color: var(--white); }
.mnav-logo { font-size: 9px; color: var(--fg-2); transition: color .12s; }

.mnav-tabs { display: flex; gap: 1px; flex-wrap: wrap; align-items: center; }

/* The active marker stays a rule under the word — the quietest thing that
 * cannot be missed, and the grammar the rest of the sections were built
 * around. What is new is a hover surface, so the strip responds to the
 * pointer instead of only changing text colour. */
.mnav-tab {
  position: relative;
  padding: 5px 10px; font-size: 12.5px; color: var(--fg-2); white-space: nowrap;
  text-decoration: none; border: 0; border-radius: var(--r-ctl);
  transition: color .12s, background .12s;
}
.mnav-tab::after {
  content: ""; position: absolute; left: 10px; right: 10px; bottom: -13px;
  height: 2px; background: transparent; transition: background .12s;
}
.mnav-tab:hover { color: var(--white); background: var(--ink); }
.mnav-tab.active { color: var(--white); font-weight: 650; }
.mnav-tab.active::after { background: var(--white); }

/* ── page frame ───────────────────────────────────────────────────────── */
.wrap { max-width: min(1400px, 99vw); margin: 0 auto; padding: 22px 18px 80px; }

header {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: 12px; margin-bottom: 18px;
}
h1 { margin: 0; font-size: 18.5px; font-weight: 650; letter-spacing: -.017em; color: var(--white); }
h2 { margin: 0; font-size: 13.5px; font-weight: 620; letter-spacing: -.005em; color: var(--fg-1); }
h3 { margin: 0; font-size: 12.5px; font-weight: 620; color: var(--fg-1); }

/* ── panels ───────────────────────────────────────────────────────────── */
.panel {
  background: var(--panel); border: 1px solid var(--hair); border-radius: var(--r);
  margin-bottom: 16px; overflow: hidden; box-shadow: var(--shadow-sm);
}
.panel-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 13px; border-bottom: 1px solid var(--hair);
}
.panel-head h2, .panel-head h3 { font-size: 12px; font-weight: 600; color: var(--white); }
.panel-head .count, .panel-head .sub { font-size: 12px; color: var(--fg-2); }
.panel-head .spacer, .spacer { margin-left: auto; }

.row, .toolbar, .bar {
  display: flex; gap: 8px; align-items: center; flex-wrap: wrap; padding: 10px 13px;
}
.row label, .toolbar label, label.cap {
  font-size: 10.5px; color: var(--fg-2); text-transform: uppercase;
  letter-spacing: .1em; font-weight: 600;
}
.note { padding: 10px 13px; font-size: 12px; color: var(--fg-2); border-top: 1px solid var(--hair); }
.danger-note {
  padding: 10px 13px; font-size: 12px; color: var(--fg-1);
  border-top: 1px solid var(--bad-line); background: var(--bad-soft);
}

/* ── controls ─────────────────────────────────────────────────────────── */
button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; font-family: var(--sans); font-size: 12px; font-weight: 550;
  color: var(--fg-1); background: var(--ctl); border: 1px solid var(--hair-2);
  border-radius: var(--r-ctl); padding: 5px 12px; line-height: 1.5;
  box-shadow: var(--shadow-sm);
  transition: color .12s, border-color .12s, background .12s, box-shadow .12s;
}
/* On paper a hover has somewhere to go — a tint plus a hairline darkening.
 * On the dark themes --ctl is transparent and --shadow-sm is none, so this
 * collapses back to the original border-and-text-colour behaviour. */
button:hover:not(:disabled), .btn:hover {
  color: var(--white); border-color: var(--hair-2); background: var(--ink);
  box-shadow: var(--shadow);
}
button:active:not(:disabled), .btn:active {
  background: var(--ink-2); box-shadow: none; transform: translateY(.5px);
}
button:disabled {
  color: var(--fg-3); border-color: var(--hair); cursor: not-allowed;
  background: transparent; box-shadow: none;
}
button:focus-visible, .btn:focus-visible, a:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 1px solid var(--white); outline-offset: 2px;
}
/* the one filled control on a page: the thing it is for */
button.alt, button.primary {
  background: var(--white); color: var(--black); border-color: var(--white);
  font-weight: 650; box-shadow: var(--shadow-sm);
}
button.alt:hover:not(:disabled), button.primary:hover:not(:disabled) {
  background: var(--fg-1); border-color: var(--fg-1); box-shadow: var(--shadow);
}
/* Severity buttons. Tinted at rest so the colour is a property of the button
 * rather than a surprise on hover, then filled on hover — the point of no
 * return gets the loudest treatment available. Shape and weight are identical
 * to a neutral button, so hue is the only thing that changes. */
button.danger, .btn.danger {
  color: var(--bad); border-color: var(--bad-line); background: var(--bad-soft);
}
button.danger:hover:not(:disabled), .btn.danger:hover {
  background: var(--bad); color: var(--on-bad); border-color: var(--bad);
}
button.danger:active:not(:disabled) { background: var(--bad); filter: brightness(.92); }

button.warn, button.warning, .btn.warn, .btn.warning {
  color: var(--warn); border-color: var(--warn-line); background: var(--warn-soft);
}
button.warn:hover:not(:disabled), button.warning:hover:not(:disabled),
.btn.warn:hover, .btn.warning:hover {
  background: var(--warn); color: var(--on-warn); border-color: var(--warn);
}
button.warn:active:not(:disabled) { background: var(--warn); filter: brightness(.92); }

button.ok, button.success, .btn.ok, .btn.success {
  color: var(--ok); border-color: var(--ok-line); background: var(--ok-soft);
}
button.ok:hover:not(:disabled), button.success:hover:not(:disabled),
.btn.ok:hover, .btn.success:hover {
  background: var(--ok); color: var(--on-ok); border-color: var(--ok);
}
button.ok:active:not(:disabled) { background: var(--ok); filter: brightness(.92); }

/* Disabled has to beat all three, or a greyed-out destructive button still
 * reads as armed. */
button.danger:disabled, button.warn:disabled, button.warning:disabled,
button.ok:disabled, button.success:disabled {
  color: var(--fg-3); background: transparent; border-color: var(--hair);
}
button.mini { padding: 3px 8px; font-size: 11px; }
button.on { background: var(--white); color: var(--black); border-color: var(--white); }
button.ghost, button.icon-btn {
  border-color: transparent; color: var(--fg-2);
  background: transparent; box-shadow: none;
}
button.ghost:hover, button.icon-btn:hover {
  color: var(--white); border-color: transparent; background: var(--ink); box-shadow: none;
}

input, select, textarea {
  background: var(--ctl); color: var(--fg-1); border: 1px solid var(--hair-2);
  border-radius: var(--r-ctl); padding: 5px 10px; font-size: 13px; font-family: var(--sans);
  outline: none;
  /* was hardcoded to dark, which gave paper a black native date picker,
   * black dropdown menus and a dark checkbox on a white page */
  color-scheme: inherit;
  box-shadow: var(--shadow-sm);
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--white);
  box-shadow: var(--shadow-sm);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--white) 12%, transparent);
}
input::placeholder, textarea::placeholder { color: var(--fg-3); }
input[type="checkbox"], input[type="radio"] { accent-color: var(--white); }
input[type="range"] { accent-color: var(--white); padding: 0; border: 0; }

/* ── tables ───────────────────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  color: var(--fg-2); text-align: left; font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; font-weight: 600; padding: 7px 11px;
  border-bottom: 1px solid var(--hair); white-space: nowrap;
}
tbody td { padding: 7px 11px; border-bottom: 1px solid var(--ink-2); vertical-align: middle; }
tbody tr:hover td { background: var(--ink); }
tbody tr.chosen td, tbody tr.selected td { background: var(--white); color: var(--black); }
tbody tr.chosen td *, tbody tr.selected td * { color: inherit; }
td.num, .num { font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
caption { text-align: left; color: var(--fg-2); font-size: 11px; padding: 6px 11px; }

/* A row that is the finding rather than the data. White bar, white text, and
 * the rest of the table left grey around it. */
tbody tr.stale td, tbody tr.bad td, tbody tr.error td {
  color: var(--white); background: var(--bad-soft);
}
tbody tr.stale td:first-child, tbody tr.bad td:first-child, tbody tr.error td:first-child {
  box-shadow: inset 2px 0 0 var(--bad);
}
tbody tr.stale:hover td, tbody tr.bad:hover td, tbody tr.error:hover td {
  background: color-mix(in srgb, var(--bad-soft) 80%, var(--bad));
}

/* ── text ─────────────────────────────────────────────────────────────── */
.mono, code, pre, kbd, samp { font-family: var(--mono); }
.sub, .muted, .dim { color: var(--fg-2); }
.ok { color: var(--ok); }
.warn { color: var(--warn); }
.bad, .err, .error-text { color: var(--bad); font-weight: 550; }
.cap { text-transform: uppercase; letter-spacing: .1em; font-size: 10.5px; color: var(--fg-2); }
b, strong { color: var(--white); font-weight: 600; }
pre { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
kbd {
  font-size: 11px; color: var(--fg-2); border: 1px solid var(--hair-2);
  border-radius: 2px; padding: 0 4px;
}

/* ── status chips ─────────────────────────────────────────────────────── */
/* Was inline-block with line-height doing the vertical spacing, which left
 * the text sitting high in the capsule. inline-flex with a min-height centres
 * it properly and lets a chip carry a leading .dot without extra markup. */
.tag, .pill, .badge, .chip {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 19px; padding: 0 9px;
  font-size: 10.5px; line-height: 1;
  white-space: nowrap; border-radius: var(--radius-pill);
  color: var(--fg-2);
  /* Surface and border derive from the pill's own text colour, not from a
     fixed grey. An inverted row (tr.chosen/.selected) forces `color: inherit`
     on everything inside it, so a pill with a fixed --ink background ended up
     light-on-light at 1.07:1 — unreadable in both themes. A currentColor tint
     follows whatever colour the pill inherits and cannot invert against it. */
  background: color-mix(in srgb, currentColor 11%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 24%, transparent);
  text-transform: uppercase; letter-spacing: .085em; font-weight: 650;
}
.tag.ok, .pill.ok, .badge.ok, .chip.ok {
  color: var(--ok); border-color: var(--ok-line); background: var(--ok-soft);
}
.tag.warn, .pill.warn, .badge.warn, .chip.warn {
  color: var(--warn); border-color: var(--warn-line); background: var(--warn-soft);
}
/* filled, because this is the one that has to be seen from across the room */
.tag.bad, .pill.bad, .badge.bad, .chip.bad {
  color: var(--on-bad); background: var(--bad); border-color: var(--bad);
}
.tag.muted, .pill.muted, .badge.muted {
  color: var(--fg-3); border-color: var(--hair); background: transparent;
}

.dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%;
       background: var(--fg-3); }
.dot.ok { background: var(--ok); }
.dot.warn { background: var(--warn); }
.dot.bad { background: var(--bad); box-shadow: 0 0 0 2px var(--bad-soft); }

/* ── messages, overlays ───────────────────────────────────────────────── */
.msg, .empty { padding: 26px 14px; text-align: center; color: var(--fg-2); font-size: 13px; }
.msg.error, .empty.error { color: var(--bad); }

.toast {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  background: var(--white); color: var(--black); border: 1px solid var(--white);
  border-radius: var(--radius-pill); padding: 8px 16px; font-size: 12px; font-weight: 550;
  box-shadow: var(--shadow-md);
  opacity: 0; transition: opacity .15s; pointer-events: none;
  max-width: 80vw; text-align: center; z-index: 100;
}
.toast.show { opacity: 1; }
/* On mono this inverts to black-on-white. On paper --black IS the page, so
 * inverting produced a toast identical to the normal one — hence an explicit
 * emphatic surface instead of a swap of the two primitives. */
.toast.bad { background: var(--bad); color: var(--black); border-color: var(--bad); }

/* The backdrop centres the dialog. Without this a modal stretches the full
 * width of the window and sits squashed at the top -- which is exactly what
 * happened when these rules were consolidated here: the centring and the
 * max-width lived in each section's own copy, and that copy was dropped.
 * Sections still set their own width; everything else is the same everywhere. */
.modal-bg, .modal-shim {
  position: fixed; inset: 0; z-index: 200; background: var(--modal-backdrop);
  display: flex; align-items: center; justify-content: center; padding: 24px;
}
.modal {
  background: var(--black); border: 1px solid var(--hair-2); border-radius: var(--r);
  z-index: 201; box-shadow: var(--shadow-md);
  padding: 22px; width: 100%; max-width: 480px;
  max-height: calc(100vh - 48px); overflow: auto;
}
.modal .actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

.spin { animation: ml-spin 1s linear infinite; display: inline-block; }
@keyframes ml-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .spin { animation: none; }
  * { transition: none !important; }
}

[hidden] { display: none !important; }
