@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 500; font-display: swap; src: url("fonts/space-grotesk-500.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/space-grotesk-600.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "Space Grotesk"; font-style: normal; font-weight: 700; font-display: swap; src: url("fonts/space-grotesk-700.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/ibm-plex-sans-400.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 500; font-display: swap; src: url("fonts/ibm-plex-sans-500.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Sans"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/ibm-plex-sans-600.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 400; font-display: swap; src: url("fonts/ibm-plex-mono-400.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 500; font-display: swap; src: url("fonts/ibm-plex-mono-500.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
@font-face { font-family: "IBM Plex Mono"; font-style: normal; font-weight: 600; font-display: swap; src: url("fonts/ibm-plex-mono-600.woff2?v=f4c567d21c6069a7b8c1b0f82c4e7d5d82764ee7ef03d5adfe35c6a07d42d36a") format("woff2"); }
:root {
  color-scheme: dark;
  --page: #101316;
  --side: #0d1013;
  --surface: #171b1e;
  --raised: #1d2226;
  --inset: #121518;
  --line: #262b2f;
  --line-strong: #343b40;
  --ink: #f0eee9;
  /* ALIASES, not new colours. These three were used and never defined, so every rule
     referencing them was invalid at computed-value time and silently did nothing — a
     destructive Delete rendered as an ordinary link, and mandate refusals painted in the
     success family. Nothing throws and nothing logs when a var() does not resolve, which
     is why this survived; test/css_selftest.mjs now fails on an undefined token. */
  --ink-1: #f0eee9;
  --bad: #d5504a;
  --bg: #1d2226;
  --ink-2: #a6adb0;
  --ink-3: #7f8789;
  --ink-th: #8b9395;
  --accent: #5aa9ff;
  --accent-soft: rgba(90, 169, 255, 0.14);
  --accent-ink: #10233c;
  --good: #46c2b0;
  --warn: #e0a45c;
  --warn-soft: rgba(224, 164, 92, 0.14);
  --serious: #e0776b;
  --crit: #d5504a;
  --s1: #5aa9ff;
  --s5: #d5504a;
  --radius: 6px;
  --radius-s: 4px;
  --font: "IBM Plex Sans", "Segoe UI", system-ui, Arial, sans-serif;
  --display: "Space Grotesk", "Segoe UI", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, Menlo, monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
/* `hidden` MEANS HIDDEN, and no later rule may out-specify it. This is not tidiness: the shell
   hides the sign-in link for a signed-in member with this attribute, and one responsive rule
   setting `display: inline-flex` on the sign-in link — with no guard, and for a good reason of
   its own (tap-target height) — put a DEAD "Sign in" beside "Signed in" at every width ≤700px,
   which is every width a UI change must be driven at. `href="#"`, so pressing it did nothing.
   The invariant: a control that cannot act must never look like one that can.
   `!important` is deliberate. The invariant is the HTML contract, it has no legitimate
   exception, and the alternative — auditing every present and future `display` rule for
   collisions with an attribute set from JavaScript — is what already failed.
   `test/shell_a11y_selftest.mjs` asserts this rule is here and that nothing carries `!important`
   past it. */
[hidden] { display: none !important; }
/* The skip link. Off-screen until focused, then a real, visible control — one that appears
   only on focus and is never drawn is the same trap as one that is drawn and cannot act. */
.skip-link {
  position: absolute; left: 8px; top: -60px; z-index: 400;
  padding: 9px 14px; border-radius: var(--radius-s);
  background: var(--accent); color: var(--accent-ink);
  font-size: 13px; font-weight: 600; text-decoration: none;
  transition: top 0.12s ease-out;
}
.skip-link:focus { top: 8px; }
/* The second one sits INSIDE the flow, so it cannot borrow the first's trick of hiding above
   the viewport: `bottom: -60px` against its own section puts it 60px BELOW that section, which
   is on screen — it rendered as a permanently visible blue button under the front door, found
   by looking at the page rather than at the rule. It hides the way everything else in this
   file hides, and comes back into FLOW when focused so it displaces content instead of
   covering it. */
.skip-inline {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
  top: auto; left: auto; bottom: auto;
}
.skip-inline:focus {
  position: static; width: auto; height: auto; margin: 8px 0 0; padding: 9px 14px;
  overflow: visible; clip-path: none; white-space: normal;
}
@media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } }
html, body { height: 100%; }
body {
  font-family: var(--font);
  background: var(--page);
  color: var(--ink);
  font-size: 13.5px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
/* Text-field chrome only: padding on a range insets the thumb's travel from both track ends. */
input:where(:not([type="range"])), select { font: inherit; color: var(--ink); background: var(--inset); border: 1px solid var(--line-strong); border-radius: var(--radius-s); padding: 6px 10px; }
input:where(:not([type="range"])):focus, select:focus { border-color: var(--accent); outline: none; }
::selection { background: rgba(90, 169, 255, 0.3); }
/* Heard, not seen. `#routeStatus` carries the route change and the outcome of a candidate
   write to assistive tech; both are already on screen for everyone else, so the region must
   take no space and must never become a focus stop. `display:none` would silence it. */
.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
/* visible keyboard focus everywhere (mouse clicks stay clean via :focus-visible) */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
a:focus-visible, .nav a:focus-visible, table.data tbody tr:focus-visible,
.checkrow:focus-visible, .presult:focus-visible, .org:focus-visible,
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
input:focus-visible, select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------- shell ---------- */
.shell { display: grid; grid-template-columns: 224px 1fr; min-height: 100vh; }
.side {
  background: var(--side);
  border-right: 1px solid var(--line);
  padding: 18px 14px;
  display: flex; flex-direction: column; gap: 18px;
  position: sticky; top: 0; height: 100vh;
}
.side-head { display: flex; align-items: center; gap: 4px; }
.brand { display: flex; align-items: center; gap: 8px; padding: 2px 0; flex: 1; min-width: 0; }
.side-head .brand-mark { width: 30px; height: 30px; }
.side-head .brand-name, .side-head .brand-sub { white-space: nowrap; }
.side-head .brand-sub { letter-spacing: 0.04em; }
.brand-mark {
  width: 36px; height: 36px; flex: none;
}
.brand-name { font-family: var(--display); font-weight: 600; font-size: 15px; letter-spacing: -0.01em; }
.brand-sub { font-size: 11px; color: var(--ink-3); letter-spacing: 0.08em; text-transform: uppercase; }

.org-wrap { position: relative; }
.org {
  border: 1px solid var(--line-strong); border-radius: var(--radius-s);
  background: var(--inset); padding: 8px 10px; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.org:hover { border-color: var(--accent); }
.org-name { font-weight: 600; font-size: 13px; }
.org-kind { font-size: 11px; color: var(--ink-3); margin-top: 1px; }
.org-caret { color: var(--ink-3); font-size: 11px; }
.org-menu {
  position: absolute; z-index: 60; left: 0; right: 0; top: calc(100% + 4px);
  background: var(--raised); border: 1px solid var(--line-strong);
  border-radius: var(--radius-s); overflow: hidden;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
.org-menu button { display: block; width: 100%; text-align: left; padding: 10px 12px; }
.org-menu button:hover { background: rgba(255, 255, 255, 0.05); }

.nav { display: flex; flex-direction: column; gap: 2px; }
.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: var(--radius-s);
  color: var(--ink-2); font-weight: 500; font-size: 13.5px;
}
.nav a svg { width: 16px; height: 16px; opacity: 0.75; }
.nav a:hover { background: rgba(255, 255, 255, 0.04); color: var(--ink); }
.nav a.active { background: rgba(90, 169, 255, 0.13); color: var(--accent); }
.nav a.active svg { opacity: 1; }

.side-foot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; font-size: 11px; color: var(--ink-3); padding: 0 8px; }
/* The account state sits with the nav it gates. Sized as a nav row rather than a call to
   action: an allocator can use this console without an account, and the link is what they
   reach for when they want to keep what they built. */
.account-state { display: flex; flex-direction: column; gap: 2px; margin: 0 -8px; }
.side-link {
  display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: var(--radius-s);
  color: var(--ink-2); font-size: 12.5px; text-decoration: none; white-space: nowrap;
}
.side-link svg { width: 16px; height: 16px; flex: none; opacity: 0.75; }
.side-link:hover { background: rgba(255, 255, 255, 0.04); color: var(--ink); }
.side-toggle {
  flex: none; display: grid; place-items: center; width: 32px; height: 32px;
  border: 0; border-radius: var(--radius-s); background: none; color: var(--ink-3); cursor: pointer;
}
.side-toggle:hover { background: rgba(255, 255, 255, 0.06); color: var(--ink); }

/* COLLAPSED: an icon rail, not nothing. The toggle, the nav and the account stay in reach;
   labels stay in the accessibility tree and show beside the icon on hover or focus. */
@media (min-width: 901px) {
  .shell.side-collapsed { grid-template-columns: 52px 1fr; }
  .side-collapsed .side { padding: 12px 8px; gap: 12px; align-items: center; }
  .side-collapsed .side-head { flex-direction: column; }
  .side-collapsed .brand, .side-collapsed .org-wrap { display: none; }
  .side-collapsed .side-foot { padding: 0; align-items: center; }
  .side-collapsed .account-state { margin: 0; }
  .side-collapsed .nav a, .side-collapsed .side-link { position: relative; padding: 8px; gap: 0; }
  .side-collapsed .nav-label {
    position: absolute; left: calc(100% + 12px); top: 50%; transform: translateY(-50%); z-index: 70;
    padding: 4px 8px; border: 1px solid var(--line-strong); border-radius: var(--radius-s);
    background: var(--raised); color: var(--ink); font-size: 12px; white-space: nowrap; pointer-events: none;
    clip-path: inset(50%);
  }
  .side-collapsed .nav a:hover .nav-label, .side-collapsed .nav a:focus-visible .nav-label,
  .side-collapsed .side-link:hover .nav-label, .side-collapsed .side-link:focus-visible .nav-label { clip-path: none; }
}

.main { min-width: 0; display: flex; flex-direction: column; }
.kbd {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
  border: 1px solid var(--line-strong); border-radius: 4px; padding: 1px 5px;
  margin-left: auto;
}
.btn {
  border: 1px solid var(--line-strong); border-radius: var(--radius-s);
  padding: 6px 12px; font-size: 12.5px; font-weight: 550; color: var(--ink-2);
  background: var(--inset);
}
.btn:hover { border-color: var(--accent); color: var(--ink); }
.btn.primary { background: var(--accent); color: var(--accent-ink); border-color: transparent; font-weight: 650; }
.btn.primary:hover { filter: brightness(1.08); }
.btn[disabled] { opacity: 0.45; cursor: not-allowed; }

.view { padding: 22px 24px 60px; max-width: 1320px; width: 100%; margin: 0 auto; }

/* ---------- cards & grids ---------- */
.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px;
}
.card h3 { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2); margin-bottom: 11px; }
.card .sub { font-size: 11.5px; color: var(--ink-3); margin-top: -8px; margin-bottom: 12px; }
/* The pull-up closes the gap under a CARD HEADING, which is the only thing it was ever written
   to sit beneath. When real content lands between the two it pulls the note 8px INTO that
   content instead: #dsCreditsSlot put the credit line there, and the Score-runs card printed
   two sentences on top of each other on first paint, at both viewports, with no interaction.
   An EMPTY slot must keep the pull — the credit line is absent far more often than it is
   present, and the heading is still what the note follows on screen. `:empty` is exactly that
   distinction, and it is why this is not simply `h3 + .sub`. */
.card :not(h3):not(:empty) + .sub { margin-top: 4px; }
.grid { display: grid; gap: 12px; }
.cols-2 { grid-template-columns: 1fr 1fr; }
.cols-3 { grid-template-columns: repeat(3, 1fr); }
.cols-4 { grid-template-columns: repeat(4, 1fr); }
.span-2 { grid-column: span 2; }
@media (max-width: 1100px) { .cols-4 { grid-template-columns: 1fr 1fr; } .cols-3 { grid-template-columns: 1fr; } .cols-2 { grid-template-columns: 1fr; } .span-2 { grid-column: span 1; } }

/* stat tiles */
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }
.tile { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 14px 16px; }
.tile .label { font-size: 11.5px; color: var(--ink-2); margin-bottom: 6px; }
.tile .value { font-size: 23px; font-weight: 650; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.tile .value small { font-size: 14px; color: var(--ink-2); font-weight: 500; }
.tile .delta { font-size: 11.5px; margin-top: 4px; color: var(--ink-3); }
.tile .delta.up { color: var(--good); }
.tile .delta.down { color: var(--s5); }

/* chips */
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 650; letter-spacing: 0.04em;
  border-radius: 999px; padding: 2px 9px; text-transform: uppercase;
  border: 1px solid transparent;
}
.chip.grade-A { background: rgba(70, 194, 176, 0.14); color: #63c98a; }
.chip.grade-B { background: rgba(70, 194, 176, 0.10); color: #8fc98a; }
.chip.grade-C { background: rgba(224, 164, 92, 0.13); color: var(--warn); }
.chip.grade-D { background: rgba(224, 119, 107, 0.14); color: var(--serious); }
.chip.grade-F { background: rgba(213, 80, 74, 0.16); color: #e57d78; }
.chip.ok { background: rgba(70, 194, 176, 0.12); color: #63c98a; }
.chip.breach { background: rgba(213, 80, 74, 0.16); color: #e57d78; }
.chip.info { background: rgba(90, 169, 255, 0.13); color: var(--accent); }
.chip.neutral { background: rgba(255, 255, 255, 0.06); color: var(--ink-2); }
.chip.cls { background: rgba(255, 255, 255, 0.05); color: var(--ink-2); border-color: var(--line); }

/* ---------- tables ---------- */
.tablewrap { overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
/* No header in this console sorts. There is no th listener, no closest("th") branch, no
   aria-sort anywhere — so a pointer cursor and a hover brightening were an affordance for a
   control that does not exist, on 53 headers across two routes. A control that cannot act
   must not look like one that can, and the answer is not to fake the sort. Static headers
   are static; the only hover affordance kept is on a header that really does carry a
   tooltip, where `help` describes exactly what hovering does.
   --ink-th, not --ink-3: this band sits on --raised, where --ink-3 measures 4.38:1 —
   the one genuine contrast failure on either route. */
table.data th {
  text-align: right; font-size: 11px; font-weight: 600; letter-spacing: 0.065em;
  text-transform: uppercase; color: var(--ink-th); padding: 9px 12px;
  border-bottom: 1px solid var(--line-strong); white-space: nowrap; cursor: default;
  position: sticky; top: 0; background: var(--raised); z-index: 2;
}
table.data th.l, table.data td.l { text-align: left; }
table.data th[title] { cursor: help; }

table.data td {
  padding: 9px 12px; text-align: right; border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
table.data tr:last-child td { border-bottom: none; }
table.data tbody tr { cursor: pointer; }
table.data tbody tr:hover { background: rgba(255, 255, 255, 0.03); }
.sym { font-weight: 600; }
.sym .meta { font-weight: 400; color: var(--ink-3); font-size: 11.5px; margin-left: 6px; }
.dim { color: var(--ink-2); }
.dim2 { color: var(--ink-3); }
.pos { color: #63c98a; }
.neg, .yv-detail-metrics dd.neg { color: #e57d78; }
.num-strong { font-weight: 650; }

/* filter row */
.filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 14px; }

.filters input[type="search"] { min-width: 220px; }

/* ---------- charts ---------- */
.chart { position: relative; }
.chart svg { display: block; width: 100%; height: auto; }
/* Below the width where the natural aspect keeps axis text legible, scroll rather than
   deform. The alternative was preserveAspectRatio="none" + a min-height, which stretched
   the drawing ~1.5x at 390px (#979). Same pattern as .tablewrap. */
.chart-scroll { overflow-x: auto; }

/* Pairwise correlation grid (#982). Shade carries magnitude; the NUMBER carries the value,
   so colour is never the sole encoding — the same rule the cause bars follow. */
.corr-grid td, .corr-grid th { text-align: center; font-variant-numeric: tabular-nums; }
.corr-grid .corr-h { font-size: 11px; color: var(--ink-3); font-weight: 600; white-space: nowrap; }
.corr-grid .corr-self { color: var(--ink-3); }
.chart .axis text, .chart text.axis { fill: var(--ink-3); font-size: 11px; font-family: var(--mono); font-variant-numeric: tabular-nums; }
/* theme-aware chart primitives (so charts survive print / light) */
.chart .gridline { stroke: var(--line); }
.chart .endlabel { fill: var(--ink); font-weight: 600; }
.chart .enddot { stroke: var(--surface); }
.tooltip {
  position: fixed; z-index: 100; pointer-events: none;
  background: var(--raised); border: 1px solid var(--line-strong);
  border-radius: var(--radius-s); padding: 8px 11px; font-size: 12px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5);
  display: none; max-width: 280px;
}
.tooltip .tt-title { font-weight: 600; margin-bottom: 3px; }
.tooltip .tt-row { display: flex; justify-content: space-between; gap: 16px; color: var(--ink-2); }
.tooltip .tt-row b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* bar rows */
.brow { display: grid; grid-template-columns: 150px 1fr 64px; align-items: center; gap: 10px; margin: 7px 0; font-size: 12.5px; }
.brow .lbl { color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.brow .track { height: 12px; background: var(--inset); border-radius: 3px; overflow: hidden; }
.brow .fill { height: 100%; border-radius: 3px 3px 3px 3px; }
.brow .val { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); }

/* legend */
.legend { display: flex; flex-wrap: wrap; gap: 14px; font-size: 11.5px; color: var(--ink-2); margin-top: 10px; }
.legend .key { display: inline-flex; align-items: center; gap: 6px; }
.legend .swatch { width: 10px; height: 10px; border-radius: 3px; }

/* ---------- instrument detail ---------- */
.inst-top { display: grid; gap: 14px; margin-bottom: 16px; }
.inst-head .back { display: inline-block; color: var(--ink-3); font-size: 12.5px; margin-bottom: 6px; }
.inst-head .back:hover { color: var(--ink); }
.inst-title { font-family: var(--display); font-size: 28px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.1; overflow-wrap: anywhere; }
.inst-sub { color: var(--ink-2); font-size: 13px; margin-top: 8px; display: flex; gap: 6px 14px; flex-wrap: wrap; align-items: center; }
/* The headline is the net's own equation; every term is readable and the net is the largest. */
.inst-bridge { display: flex; align-items: flex-start; padding: 14px 20px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); }
.ib-cell { min-width: 0; }
.ib-op { align-self: center; padding: 0 20px; font-size: 22px; line-height: 1; color: var(--ink-3); }
.ib-k { color: var(--ink-2); font-size: 12px; }
.ib-v { font-size: 26px; font-weight: 500; line-height: 1.2; margin-top: 2px; font-variant-numeric: tabular-nums; letter-spacing: -0.6px; }
.ib-s { color: var(--ink-3); font-size: 12px; margin-top: 4px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.ib-net .ib-v { font-size: 30px; font-weight: 500; line-height: 1.05; letter-spacing: -0.9px; }
/* The one estimates footnote's mark; a pseudo-element, so the number's own text stays the number. */
.inst .inst-est::after { content: "*"; color: var(--ink-3); font-size: .5em; font-weight: 400; vertical-align: super; margin-left: 1px; letter-spacing: 0; }
.inst-foot { margin: 16px 0 0; font-size: 11px; color: var(--ink-3); }
/* Above phone width the equation is header type, not a card: labels, numbers and notes each share one row. */
@media (min-width: 701px) {
  .inst-bridge { display: grid; grid-auto-flow: column; grid-template-rows: auto auto auto; justify-content: start; padding: 0; background: none; border: 0; border-radius: 0; }
  .ib-cell { display: grid; grid-row: 1 / span 3; grid-template-rows: subgrid; }
  /* Each sign at its neighbour's size, on the shared baseline, so the font centres it on the digits. */
  .ib-op { grid-row: 2; align-self: baseline; font-size: 26px; padding: 0 16px; transform: translateY(-0.05em); }
  .ib-eq { font-size: 34px; }
  .ib-k, .ib-v { align-self: baseline; }
  .ib-s { margin-top: 8px; }
}
/* Wide: the equation sits beside the name on the name's own three rows. */
@media (min-width: 1200px) {
  .inst-top { grid-template-columns: minmax(0, 1fr) auto; grid-template-rows: auto auto auto; column-gap: 40px; row-gap: 0; }
  .inst-head, .inst-bridge { grid-row: 1 / span 3; display: grid; grid-template-rows: subgrid; }
  .inst-head > .back, .inst-title { align-self: baseline; }
}
/* The instrument page on the Designer's type scale: card names are its eyebrow, labels 12px, sentences 13px. */
.inst .card h3 { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; font: 400 11px/1.4 var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); margin-bottom: 12px; }
.inst #leverPanel h3 { font: 600 14px var(--font); letter-spacing: 0; text-transform: none; color: var(--ink); }
.inst .card h3 .dim2 { font-weight: 400; }
.inst-tag { font: 400 12px var(--font); color: var(--ink-3); letter-spacing: 0; text-transform: none; }
.inst .chip, .inst .legend, .inst .muted, .inst .chip-btn, .inst .tile .delta,
.inst .evidence-source, .inst .footnote, .inst .fine, .inst .brow, .inst-quality .kv { font-size: 12px; }
.inst .ec-compare, .inst .evidence-copy, #instFit .dim { font-size: 13px; }
.inst-quality .kv .v { font-weight: 500; }
.inst .footnote { line-height: 1.55; }
.inst .brow { grid-template-columns: minmax(96px, 160px) minmax(32px, 1fr) 56px; }
.inst .brow .lbl { white-space: normal; }
.inst .ec-compare { background: none; border: 0; padding: 0; margin-top: 14px; }
.inst .ec-compare:empty { display: none; }
/* At your size: the yield at that size leads; entry cost, breakeven and capacity follow once each. */
.inst #ecTiles { display: block; margin-top: 18px; }
.ec-yield { display: flex; flex-direction: column; gap: 4px; margin-bottom: 16px; }
.ec-yield .label { font: 400 11px var(--mono); letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); }
.ec-yield .value { font-size: 30px; font-weight: 500; letter-spacing: -0.9px; line-height: 1.15; font-variant-numeric: tabular-nums; }
.inst .ec-yield .delta { font: 400 11px var(--mono); color: var(--ink-3); }
.ec-facts { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 0; padding-top: 14px; border-top: 1px solid var(--line); }
.ec-facts .tile { background: none; border: 0; border-radius: 0; padding: 0; min-width: 0; }
.ec-facts .label { font-size: 12px; color: var(--ink-2); margin: 0; }
.ec-facts .value { margin: 3px 0 0; font-size: 15px; font-weight: 500; letter-spacing: -0.3px; font-variant-numeric: tabular-nums; color: var(--ink); }
.inst .ec-facts .delta { margin: 3px 0 0; font-size: 11px; line-height: 1.45; color: var(--ink-3); }
.inst-cols { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 12px; align-items: start; }
.inst-main, .inst-side { display: grid; gap: 12px; align-content: start; min-width: 0; }
.inst-cols .span-2 { grid-column: auto; }
.inst .brow + .kv { margin-top: 14px; }
.inst-basis { margin-top: 10px; }
.inst-basis summary { color: var(--ink-3); font-size: 12px; cursor: pointer; width: fit-content; }
.inst-basis summary:hover { color: var(--ink-2); }
.inst-basis[open] summary { margin-bottom: 4px; }
.inst-basis .footnote, .inst-basis .evidence-source { margin-top: 6px; border-top: 0; padding-top: 0; }
.inst-basis .basis-calc { margin-top: 6px; font-size: 12px; column-gap: 0; row-gap: 4px; }
.inst-basis .basis-calc .v { padding-left: 14px; }
.inst-basis .basis-calc .k span { display: block; color: var(--ink-3); font-size: 11px; }
.inst-basis .basis-calc .basis-sum { border-top: 1px solid var(--line); padding-top: 4px; color: var(--ink); font-weight: 600; }
.inst-basis .basis-calc.footnote { grid-template-columns: auto 1fr; }
.inst-basis .basis-calc.footnote .v { text-align: left; font-weight: 400; color: var(--ink-2); }
.inst-basis .basis-notes { margin-top: 8px; padding-left: 14px; display: grid; gap: 3px; }
.inst-peers .peer-row { grid-template-columns: minmax(0, 1fr) auto; }
.peer-row .sym { color: var(--ink); font-weight: 600; }
.peer-venue { color: var(--ink-3); font-size: 12px; margin-top: 2px; overflow-wrap: anywhere; }
.peer-row.is-self { background: var(--raised); border-radius: var(--radius-s); padding-left: 8px; padding-right: 8px; }
/* One column: the cards interleave so the risk stays next to the numbers it judges. */
@media (max-width: 1100px) {
  .inst-cols { grid-template-columns: minmax(0, 1fr); }
  .inst-main, .inst-side { display: contents; }
  .inst-main > *, .inst-side > * { order: 8; }
  #instHistory { order: 1; } .inst-risk { order: 2; } .inst-cost { order: 3; } .inst-quality { order: 4; }
  #instFit { order: 5; } #leverPanel { order: 6; } .inst-peers { order: 7; }
}
/* Too narrow for the equation on one line: it becomes a ledger, net under a rule. */
@media (max-width: 700px) {
  .inst-title { font-size: 24px; }
  .inst-bridge { flex-direction: column; align-items: stretch; padding: 10px 14px; }
  .ib-op { display: none; }
  .ib-cell { display: grid; grid-template-columns: minmax(0, 1fr) auto; column-gap: 12px; align-items: baseline; padding: 6px 0; }
  .ib-k { grid-area: 1 / 1; }
  .ib-s { grid-area: 2 / 1; }
  .ib-v { grid-area: 1 / 2 / 3 / 3; font-size: 20px; text-align: right; margin-top: 0; }
  .ib-cell[data-op="+"] .ib-v::before { content: "+\2009"; color: var(--ink-3); }
  .ib-cell[data-op="\2212"] .ib-v::before { content: "\2212\2009"; color: var(--ink-3); }
  .ib-net { margin-top: 4px; padding-top: 10px; border-top: 1px solid var(--line-strong); }
  .ib-net .ib-v { font-size: 28px; }
  .ec-facts { grid-template-columns: minmax(0, 1fr); }
}

.slider-row { display: flex; align-items: center; gap: 14px; margin: 10px 0 16px; }
.slider-row input[type="range"] { flex: 1; accent-color: var(--accent); }
.slider-row:has(#sizeVal) input[type="range"] { min-width:0; }
/* The size track is drawn here so the capacity tick sits where the thumb's centre would: the
   thumb travels from --thumb/2 to 100% - --thumb/2, and the tick and fill use the same span. */
.size-track { --thumb:16px; --fill:0; position:relative; flex:1; min-width:0; display:flex; align-items:center; }
.size-track input[type="range"] { -webkit-appearance:none; appearance:none; position:relative; z-index:1; width:100%; height:24px; margin:0; background:transparent; cursor:pointer; }
.size-track input[type="range"]::-webkit-slider-runnable-track { height:4px; border-radius:2px; background:linear-gradient(var(--accent),var(--accent)) 0 0 / calc(var(--thumb) / 2 + var(--fill) * (100% - var(--thumb))) 100% no-repeat, var(--line-strong); }
.size-track input[type="range"]::-moz-range-track { height:4px; border-radius:2px; background:var(--line-strong); }
.size-track input[type="range"]::-moz-range-progress { height:4px; border-radius:2px; background:var(--accent); }
.size-track input[type="range"]::-webkit-slider-thumb { -webkit-appearance:none; appearance:none; width:var(--thumb); height:var(--thumb); margin-top:calc((4px - var(--thumb)) / 2); border-radius:50%; background:var(--accent); border:2px solid var(--surface); box-shadow:0 0 0 1px var(--line-strong); }
.size-track input[type="range"]::-moz-range-thumb { width:var(--thumb); height:var(--thumb); border-radius:50%; background:var(--accent); border:2px solid var(--surface); box-shadow:0 0 0 1px var(--line-strong); }
.size-track input[type="range"]:focus-visible { outline:2px solid var(--accent); outline-offset:2px; border-radius:2px; }
.size-cap { --at:0; position:absolute; top:50%; left:calc(var(--thumb) / 2 + var(--at) * (100% - var(--thumb))); width:2px; height:14px; border-radius:1px; background:var(--warn); transform:translate(-50%, -50%); pointer-events:none; }
.slider-row .size-fixed { font:700 16px var(--font); font-variant-numeric:tabular-nums; }
.slider-row input.size-val { font:700 16px var(--font); font-variant-numeric:tabular-nums; width:8ch; min-width:0; min-height:44px; flex:0 0 8ch; text-align:right; padding:8px 6px; border:1px solid var(--line-strong); background:transparent; cursor:text; }
.slider-row input.size-val:hover { border-color:var(--line-strong); }
.slider-row input.size-val:focus { flex-basis:12ch; width:12ch; background:var(--inset); border-color:var(--accent); }
.slider-row input.size-val:invalid { border-color:var(--bad); }
.kv { display: grid; grid-template-columns: 1fr auto; gap: 6px 18px; font-size: 13px; }
.kv .k { color: var(--ink-2); }
.kv .v { text-align: right; font-variant-numeric: tabular-nums; font-weight: 600; }
.kv .v.muted { color: var(--ink-3); font-weight: 400; }
.hr { border: none; border-top: 1px solid var(--line); margin: 12px 0; }

/* reviewed protocol facts — evidence/provenance only; score math stays separate */
.protocol-evidence { grid-column: 1 / -1; }
.compact-evidence { padding-top: 13px; padding-bottom: 13px; }
.compact-evidence .evidence-head { margin-bottom: 7px; }
.evidence-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.inst .evidence-head h3 { margin: 0; }
.evidence-head .yv-ev-open { margin-left: auto; }
/* One label column and one sentence per finding, aligned under the header. */
.evidence-lines { margin: 0; display: grid; }
.evidence-lines > div { display: grid; grid-template-columns: 132px minmax(0, 1fr); column-gap: 16px; padding: 9px 0; border-top: 1px solid var(--line); align-items: baseline; }
.evidence-lines > div:first-child { border-top: 0; padding-top: 0; }
.evidence-lines dt { font-size: 12px; color: var(--ink-2); }
.evidence-lines dd { margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink); }
.evidence-lines + .evidence-source { margin-top: 10px; }
/* After the base rule: on a phone the label sits above its phrase, so the phrase gets the full width. */
@media (max-width: 700px) { .evidence-lines > div { grid-template-columns: minmax(0, 1fr); row-gap: 2px; } }
.evidence-copy { color: var(--ink-2); font-size: 12.5px; line-height: 1.55; overflow-wrap: anywhere; }
.contract-list { list-style: none; display: flex; flex-direction: column; gap: 7px; color: var(--ink-2); font-size: 12px; }
.contract-list li { padding-left: 11px; border-left: 2px solid var(--line-strong); overflow-wrap: anywhere; }
.contract-list strong { color: var(--ink); }
.mono { font-family: var(--mono); font-size: 11px; }
.ext { color: var(--accent); text-decoration: underline; text-decoration-color: rgba(90, 169, 255, 0.35); text-underline-offset: 2px; }
.ext:hover { color: var(--ink); }
.unknown { color: var(--ink-3); font-style: italic; }
.evidence-source { border-top: 1px solid var(--line); padding-top: 10px; color: var(--ink-3); font-size: 11px; overflow-wrap: anywhere; }
.protocol-evidence:not(.compact-evidence) .evidence-source { font: 400 11px var(--mono); }
.evidence-source strong { color: var(--ink-2); }


/* mandate check rows */
.checks { display: flex; flex-direction: column; }
.checkrow {
  display: grid; grid-template-columns: 1fr auto auto; gap: 14px; align-items: center;
  padding: 9px 2px; border-bottom: 1px solid var(--line); font-size: 13px;
}
.checkrow:last-child { border-bottom: none; }
.checkrow .rule { color: var(--ink-2); }
.checkrow .reading { font-variant-numeric: tabular-nums; text-align: right; }
/* A row that navigates is a link, and a link is reachable. `.checkrow:focus-visible` and
   the document's Enter/Space delegation for `[data-nav]` both already existed and were both
   dead here, because the element was never focusable — the pointer cursor was the only
   thing that said it could be activated at all. */
.checkrow.nav-row { cursor: pointer; }
.checkrow.nav-row:hover .rule { color: var(--ink); }

/* strategies */
.strat { display: flex; flex-direction: column; gap: 11px; }
.strat .shead { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.strat .sname { font-size: 16px; font-weight: 650; letter-spacing: -0.01em; }
.strat .sdesc { color: var(--ink-2); font-size: 13px; }
.strat .slegs { display: flex; gap: 6px; flex-wrap: wrap; }
.strat .syield { font-size: 26px; font-weight: 700; font-variant-numeric: tabular-nums; }
.strat .syield.sm { font-size: 18px; }
.strat .syield small { font-size: 13px; color: var(--ink-2); font-weight: 500; }

/* Candidate progression track (replaced the assurance ladder, 2026-08-26). Four states,
   each drawn from a real designer row. Crisp shapes, no glow: a filled sky disc is proven,
   a sky ring is in flight, a hollow hairline is pending, and a dotted hairline is unread.
   State classes are namespaced `st-*` on purpose: `.strat .pending` already exists on this
   card and would otherwise capture a bare `.pending` label and resize it to 14px. */
.stage-track { margin-top: 2px; padding: 10px 12px; background: var(--inset); border: 1px solid var(--line); border-radius: var(--radius-s); }
.stage-dots { display: flex; align-items: center; }
.stage-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; background: transparent; border: 1px solid var(--line-strong); }
.stage-dot.st-done { background: var(--accent); border-color: var(--accent); }
.stage-dot.st-active { background: transparent; border: 2px solid var(--accent); }
.stage-dot.st-unknown { border-style: dotted; }
.stage-link { flex: 1; height: 1px; background: var(--line-strong); }
.stage-link.st-done { background: var(--accent); }
/* 11px is the product's legibility floor. These labels shipped at 9.5px — the smallest type
   anywhere in the console — and 9.5px uppercase at 0.03em is below what an allocator can read
   at a glance however good the contrast is. `min-width:0` + `overflow-wrap` keep the wider
   labels ("Deploy proposed") wrapping inside their own column instead of pushing the track
   past the card edge, which is what a bare size bump would have done. */
.stage-names { display: flex; justify-content: space-between; font-size: 11px; letter-spacing: 0.03em; text-transform: uppercase; color: var(--ink-3); margin-top: 7px; gap: 4px; }
.stage-names span { flex: 1; min-width: 0; overflow-wrap: break-word; text-align: center; font-size: 11px; font-weight: 500; padding: 0; }
.stage-names span:first-child { text-align: left; }
.stage-names span:last-child { text-align: right; }
.stage-names span.st-done { color: var(--ink-2); }
.stage-names span.st-active { color: var(--accent); font-weight: 700; }
/* `pending` (nothing happened) and `unknown` (nothing was read) are different claims and must
   not look alike: the dot is dotted rather than solid, and the label is italic. The caption
   names the unread stage and prints its reason, so the difference is stated, not just drawn. */
.stage-names span.st-unknown { font-style: italic; }
/* `stale` is a third claim again: the row IS in hand and was read, it simply describes
   CONTENT that is no longer saved (the candidate was edited, or its portfolio was rewritten).
   Neither `done` nor `pending` nor `unknown` may stand in for it, so it gets its own mark —
   a dashed caution ring, and a struck label. */
.stage-dot.st-stale { border-color: var(--serious); border-style: dashed; }
.stage-names span.st-stale { color: var(--serious); text-decoration: line-through; }
/* `blocked` is a fourth: not undone, not unread, not out of date — UNREACHABLE. Nothing this
   allocator does to the design turns it into `pending`, so it must not wear pending's plain
   grey dot, which reads as one more step still to come. The dot is barred through; the label
   is struck with a DOTTED rule so it cannot be mistaken for `stale`'s solid one, which means
   something else entirely. The caption states the reason in words — this is the mark, not the
   message.
   The label's colour has now failed a judge TWICE, in opposite directions, and this is where it
   landed. A first version set it to `--ink-3`, which `.stage-names` already sets — a dead rule,
   caught by computing the two. The fix dimmed it to `#5c6365`, which was not dead but measured
   **2.99:1** on `--inset` (2.83 on `--surface`, 2.62 on `--raised`) against a 4.5:1 floor, so
   the state was marked by making its own words hard to read. `#82898b` clears AA on all three
   grounds (4.87 / 5.15 / 4.51) and is still not `--ink-3`, so the rule does something.
   THE DISTINCTION DOES NOT REST ON BRIGHTNESS, which is why giving that up costs nothing: the
   dot is barred, the strike is DOTTED where `stale`'s is solid, and the caption says the reason
   in words. Italic is not available here — `st-unknown` already means something by it. */
.stage-dot.st-blocked { border-color: var(--ink-3); position: relative; }
.stage-dot.st-blocked::after { content: ""; position: absolute; left: 0; right: 0; top: 3px; height: 1px; background: var(--ink-3); }
.stage-names span.st-blocked { color: #82898b; text-decoration: line-through; text-decoration-style: dotted; }
.stage-cap { font-size: 11px; color: var(--ink); margin-top: 8px; font-weight: 600; }
.stage-cap .dim2 { font-weight: 400; }
.stage-cap .stage-dot { display: inline-block; vertical-align: middle; margin-right: 6px; }

.strat-foot { display: flex; align-items: flex-end; gap: 20px; margin-top: auto; padding-top: 4px; }
.strat-foot .metric .muted { margin-bottom: 1px; }
.strat-foot .cta { margin-left: auto; }
.strat .pending { font-size: 14px; color: var(--ink-3); font-weight: 500; padding-bottom: 5px; }

/* Saved designs: one card's simulation, price shock and price range (#1260). An open panel
   takes the full row, because the result tables do not fit half of it. */
.strat.strat-wide { grid-column: 1 / -1; }
.saved-analysis { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--line); padding-top: 12px; min-width: 0; }
.saved-analysis-fields, .saved-analysis-presets, .saved-analysis-run { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.saved-analysis { gap: 16px; }
/* #2342: one tab per type; each keeps its own latest result, so none is ever out of reach. */
.saved-analysis-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--line); min-width: 0; overflow-x: auto; }
.saved-analysis-tab { flex: 0 0 auto; padding: 10px 18px; margin-bottom: -1px; border: 0; border-bottom: 3px solid transparent; background: none;
  color: var(--ink-2); font: inherit; font-size: 16px; font-weight: 600; cursor: pointer; }
.saved-analysis-tab:hover { color: var(--ink); }
.saved-analysis-tab[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }
.saved-analysis-tab:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (max-width: 520px) { .saved-analysis-tab { flex: 1 1 0; padding: 10px 4px; font-size: 15px; } }
.saved-analysis-panel { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.saved-analysis-panel > .saved-analysis-desc { font-size: 15px; }
.saved-analysis [data-sa-result]:empty { display: none; }
.saved-analysis-prev { padding-top: 12px; border-top: 1px dashed var(--line); }
.saved-analysis-scenario { margin: 0 0 4px; font-size: 15px; color: var(--ink-2); }
.saved-analysis-scenario b { color: var(--ink); font-weight: 600; }
.saved-analysis-bars { margin: 16px 0 4px; display: flex; flex-direction: column; gap: 10px; max-width: 760px; min-width: 0; }
.saved-analysis-bars figcaption { display: flex; flex-direction: column; gap: 2px; }
.saved-analysis-bars-title { font-size: 15px; font-weight: 600; color: var(--ink); }
.saved-analysis-bars-sub { font-size: 13.5px; color: var(--ink-2); }
/* Rows are divs, not li: the saved-designs card list styles every li inside its cards. */
.saved-analysis-bar-list { display: flex; flex-direction: column; gap: 8px; }
.saved-analysis-bar { display: grid; grid-template-columns: minmax(0, 2fr) minmax(60px, 3fr) auto; align-items: center; gap: 12px; font-size: 13.5px; }
.saved-analysis-bar-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.saved-analysis-bar-track { height: 12px; border-radius: 6px; background: var(--inset); overflow: hidden; }
.saved-analysis-bar-fill { display: block; height: 100%; border-radius: 6px; background: var(--accent); }
.saved-analysis-bar-value { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); min-width: 60px; text-align: right; }
@media (max-width: 520px) { .saved-analysis-bar { grid-template-columns: minmax(0, 1fr) auto; } .saved-analysis-bar-track { grid-column: 1 / -1; grid-row: 2; } }
/* The inputs sit under the answer, and read at the size of the answer's labels. */
.saved-analysis-setup { display: flex; flex-direction: column; gap: 14px; padding-top: 16px; border-top: 1px solid var(--line); min-width: 0; }
.saved-analysis-setup, .saved-analysis-setup :is(.fine, .muted, .saved-analysis-run, label, legend, input, select, .btn, dt, dd) { font-size: 15px; }
.saved-analysis-setup input[type="checkbox"] { width: 16px; height: 16px; }
.saved-analysis-setup .saved-analysis-foot .btn.primary { padding: 10px 22px; }
.saved-analysis-setup .saved-analysis-foot { padding-top: 0; border-top: 0; }
.saved-analysis-presets .btn[aria-pressed="true"] { border-color: var(--accent); color: var(--ink); background: var(--accent-soft); }
.saved-analysis-fields input[type="number"] { width: 110px; }
.saved-analysis-pct { display: inline-flex; align-items: center; gap: 4px; color: var(--ink-2); }
.saved-analysis-pct input[type="number"] { width: 84px; }
.saved-analysis-assets { display: flex; flex-wrap: wrap; gap: 6px 14px; margin: 0; padding: 0; border: 0; min-width: 0; }
.saved-analysis-assets legend { padding: 0; margin-bottom: 6px; width: 100%; }
.saved-analysis-assets label { display: inline-flex; align-items: center; gap: 5px; min-height: 28px; }
.saved-analysis-run { font-size: 12px; color: var(--ink-2); }
.saved-analysis [data-sa-msg]:empty { display: none; }
.saved-analysis-bad { color: var(--crit); }
/* #2304: the Analyze window reads at the page's body size, and secondary detail waits behind a summary. */
.saved-analysis .fine, .saved-analysis .muted, .saved-analysis-run,
.saved-analysis .footnote, .saved-analysis .chip, .saved-analysis .legend, .saved-analysis table.data, .saved-analysis table.data th { font-size: 13.5px; }
.saved-analysis-desc { margin: 0; color: var(--ink-2); }
.metric-label, .metric-gloss { color: var(--ink-3); font-size: 13.5px; }
.saved-analysis-more > summary { cursor: pointer; color: var(--ink-2); padding: 4px 0; }
.saved-analysis-more[open] > summary { margin-bottom: 8px; }
/* Assumptions on the Simulation tab (#1960). */
.saved-analysis-assumptions, .saved-analysis-editor { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.saved-analysis-editor { border-left: 2px solid var(--line); padding-left: 10px; }
.saved-analysis-editor .tablewrap input:not([type]) { width: 100%; min-width: 120px; }
.saved-analysis-editor .tablewrap select { width: 100%; min-width: 160px; max-width: 320px; }
.saved-analysis-editor .saved-analysis-intro { margin: 10px 0 8px; max-width: 72ch; line-height: 1.5; }
.saved-analysis-settings th[scope="row"] { font-weight: 500; color: var(--ink); white-space: nowrap; text-transform: none; letter-spacing: normal; font-size: 13.5px; }
.saved-analysis-settings .saved-analysis-why { min-width: 260px; white-space: normal; color: var(--ink-2); line-height: 1.45; }
/* On a phone the explanation drops under its setting instead of scrolling off the side. */
@media (max-width: 640px) {
  .saved-analysis-settings thead { display: none; }
  .saved-analysis-settings tr { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; column-gap: 8px; }
  .saved-analysis-settings th[scope="row"] { white-space: normal; }
  .saved-analysis-settings td input[type="number"] { width: 88px; }
  .saved-analysis-settings .saved-analysis-why { grid-column: 1 / -1; min-width: 0; padding-top: 0; }
}
.saved-analysis-editor label, .saved-analysis-assumptions > .saved-analysis-fields label { display: inline-flex; align-items: center; gap: 6px; }
/* A select is as wide as its longest option; on a phone it shrinks to the row instead (#2005). */
.saved-analysis-assumptions > .saved-analysis-fields label { min-width: 0; max-width: 100%; }
.saved-analysis-assumptions select { min-width: 0; max-width: 100%; text-overflow: ellipsis; }
.saved-analysis-foot { display: flex; justify-content: flex-end; gap: 8px; padding-top: 12px; border-top: 1px solid var(--line); }
.saved-analysis-runwith { margin: 0; display: flex; flex-direction: column; gap: 8px; }
.saved-analysis-runwith > div { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 16px; row-gap: 4px; }
.saved-analysis-runwith dt { min-width: 140px; color: var(--ink-2); }
/* Results: each figure a tile whose number reads first. */
.saved-analysis [data-sa-result] .strat-foot { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px; margin: 12px 0; }
.saved-analysis [data-sa-result] .metric { display: flex; flex-direction: column; gap: 4px; padding: 14px 16px; border: 1px solid var(--line); border-radius: var(--radius); }
.saved-analysis [data-sa-result] .metric .syield { order: -1; font-size: 26px; font-weight: 700; line-height: 1.15; color: var(--ink); font-variant-numeric: tabular-nums; }
.saved-analysis [data-sa-result] .metric-label { font-size: 15px; color: var(--ink); }
.saved-analysis-more > summary { font-size: 15px; color: var(--ink); padding: 6px 0; }
.saved-analysis-runwith dd { margin: 0; min-width: 0; }
.saved-analysis .saved-analysis-link { display: inline; min-height: 0; padding: 0; border: 0; border-radius: 3px; background: none; font: inherit;
  color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.saved-analysis .saved-analysis-link:hover:not(:disabled) { background: none; border: 0; color: var(--accent); text-decoration-thickness: 2px; }
.saved-analysis-modal { margin: auto; box-sizing: border-box; width: min(420px, calc(100vw - 32px)); max-height: 85vh; overflow: auto;
  padding: 16px 20px 20px; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--surface); color: var(--ink);
  font: inherit; box-shadow: 0 24px 60px rgba(0,0,0,.55); }
.saved-analysis-modal.is-wide { width: min(760px, calc(100vw - 32px)); }
.saved-analysis-modal::backdrop { background: rgba(8,10,12,.6); }
.saved-analysis-modal > header { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 0 0 12px; }
.saved-analysis-modal > header h2 { margin: 0; font-size: 16px; }
.saved-analysis-json { width: 100%; min-height: 200px; box-sizing: border-box; background: var(--inset); color: var(--ink); border: 1px solid var(--line-strong); border-radius: var(--radius-s); font-family: var(--mono); font-size: 12px; padding: 8px; }
.saved-analysis [data-sa-ov-status]:empty { display: none; }
/* A design's score history (#2000). */
.saved-analysis-history { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--line); padding-top: 10px; min-width: 0; }
.saved-analysis-history h4 { margin: 0; }
.saved-analysis-history > details[open] { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.saved-analysis [data-sa-history]:empty { display: none; }
.saved-analysis-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 12px; color: var(--ink-2); }
.saved-analysis-legend span, .saved-analysis-history td { align-items: center; }
.saved-analysis-swatch { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; box-shadow: 0 0 0 2px var(--surface); }
.saved-analysis-history .tablewrap { max-height: 320px; overflow-y: auto; }
.saved-analysis .tablewrap { overflow-x: auto; }
.saved-analysis [data-sa-result] svg { max-width: 720px; }
.saved-analysis-book { display: flex; flex-direction: column; gap: 8px; border-top: 1px solid var(--line); padding-top: 10px; min-width: 0; }
.saved-analysis-book h4 { margin: 0; }
.saved-analysis-verdict { display: flex; flex-wrap: wrap; gap: 6px 24px; margin: 0; }
.saved-analysis-verdict dt { font-size: 13.5px; color: var(--ink-2); }
.saved-analysis-verdict dd { margin: 0; font-variant-numeric: tabular-nums; }
.saved-analysis-unpriced { margin: 0; padding-left: 18px; }
.saved-analysis-preset select { margin-left: 6px; max-width: 100%; }
.saved-analysis-mandate { border-collapse: collapse; width: 100%; max-width: 720px; font-size: 13.5px; }
.saved-analysis-mandate th, .saved-analysis-mandate td { text-align: left; padding: 4px 8px 4px 0; border-top: 1px solid var(--line); vertical-align: top; font-weight: normal; }
.saved-analysis-mandate td:last-child { white-space: nowrap; }
.saved-analysis-mandate tr[data-mandate-ok="false"] td:last-child { color: var(--crit); }
.saved-analysis-mandate tr[data-mandate-ok="null"] td:last-child, .saved-analysis-mandate tr[data-mandate-ok="withheld"] td:last-child { color: var(--ink-2); }

/* strategy designer — hero metric row, calm leg table, whispered fine print.
   Hierarchy is the point: the numbers an allocator reads first are the largest thing
   on the surface, the instrument (the table) is quiet, and caveats are one hover or
   one click away instead of paragraphs between them. */
.hero-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden; margin: 14px 0 12px;
}
.hero-row .htile { background: var(--surface); padding: 15px 18px 16px; min-width: 0; }
.hero-row .htile.lead { background: linear-gradient(180deg, rgba(90, 169, 255, 0.06), rgba(90, 169, 255, 0)); }
.hero-row .label { font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); }
.hero-row .label .dim2 { font-weight: 400; letter-spacing: 0.02em; text-transform: none; }
.hero-row .value {
  font-size: 30px; font-weight: 700; letter-spacing: -0.03em; line-height: 1.12;
  font-variant-numeric: tabular-nums; margin-top: 9px; white-space: nowrap;
}
.hero-row .htile.lead .value { font-size: 40px; }
.hero-row .value.small { font-size: 19px; letter-spacing: -0.01em; overflow: hidden; text-overflow: ellipsis; }
.hero-row .value .chip { vertical-align: middle; }
/* two lines, then the rest is on hover — the row stays a row, never a paragraph */
.hero-row .sub {
  font-size: 11.5px; color: var(--ink-3); margin-top: 7px; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* The clamp's escape hatch is `title=`, and that is a hover — which does not exist on
   touch and is not a reliable screen-reader path. The clamped string here is the RISK
   BASIS ("risk drag · rubric · agent-only · not human-approved + heuristic · modeled APY
   drag"): the honesty qualifier this product requires to ride with the number on every
   surface. At 430px it rendered as "…· agent-only · not…". Where there is no hover to
   recover it, or no width to hold it in two lines, it is not clamped at all. */
@media (max-width: 900px), (hover: none) {
  .hero-row .sub { display: block; -webkit-line-clamp: none; overflow: visible; }
}
@keyframes valpulse { 0% { opacity: 0.25; transform: translateY(-3px); } 70% { opacity: 1; } 100% { transform: none; } }
.hero-row .htile.chg .value { animation: valpulse 0.42s cubic-bezier(0.2, 0.75, 0.3, 1); }
@media (max-width: 1100px) { .hero-row .htile.lead .value { font-size: 32px; } }
@media (prefers-reduced-motion: reduce) { .hero-row .htile.chg .value { animation: none; } }

/* an honesty qualifier on a section heading is a whisper, not a shout — the heading
   stays uppercase, the qualifier does not */
h3 .hnote { text-transform: none; letter-spacing: 0; font-weight: 400; color: var(--ink-3); font-size: 11.5px; }

/* capacity marker — truthful, quiet; the full sentence is on hover */
.capmk { margin-left: 7px; font-size: 11px; font-weight: 550; color: var(--warn); cursor: help; border-bottom: 1px dotted rgba(224, 164, 92, 0.5); }
.warnink { color: var(--warn); }

/* fine print — the whisper tier: one short line per section, never a paragraph */
.fine { color: var(--ink-3); font-size: 11px; line-height: 1.5; margin-top: 9px; }
.lnk { color: var(--ink-2); font-size: inherit; padding: 0; text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--line-strong); }
.lnk:hover { color: var(--accent); }

/* action row — one green CTA, everything else recedes */

.btn.quiet { background: none; border-color: var(--line); color: var(--ink-3); font-weight: 500; }
/* A control holding a change that is not in the design yet. The two constraints beside it do
   nothing until it is pressed, while the market list's filters re-grade as you type — same
   visual register, opposite behaviour, and nothing said so. Drawn, not only labelled: the word
   on the button changes too, so the disclosure survives a reader who does not parse colour. */
.btn.needs-apply { border-color: var(--warn); color: var(--warn); background: var(--warn-soft); }
.btn.quiet:hover { border-color: var(--line-strong); color: var(--ink-2); }

/* command palette */
.palette-backdrop { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.55); z-index: 200; display: grid; place-items: start center; padding-top: 12vh; }
.palette {
  width: min(560px, 92vw); background: var(--raised); border: 1px solid var(--line-strong);
  border-radius: 12px; overflow: hidden; box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
}
.palette input { width: 100%; border: none; background: none; padding: 14px 16px; font-size: 15px; border-bottom: 1px solid var(--line); border-radius: 0; }
.palette .results { max-height: 320px; overflow-y: auto; }
/* Notices sit beside the listbox, not in it: a listbox may contain options only, and a
   prose row inside one is read out as if it were pickable. */
.palette .pnotices:empty { display: none; }
.palette .presult { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; font-size: 13.5px; }
.palette .presult:hover, .palette .presult.sel { background: rgba(90, 169, 255, 0.10); }
.palette .presult .pk { color: var(--ink-3); font-size: 11px; margin-left: auto; }

/* candidate resolver — palette notices + Markets resolve card */
.pnotice { padding: 10px 14px; font-size: 12.5px; line-height: 1.5; color: var(--ink-2); border-bottom: 1px solid var(--line); }
.pnotice.ok { color: var(--ink-2); border-left: 3px solid var(--accent); }
.pnotice.warn { color: var(--warn); border-left: 3px solid var(--warn); }
.pnotice.info { color: var(--ink-2); border-left: 3px solid var(--s1); padding-bottom: 6px; }
.pnotice strong { color: var(--ink); }
.pnotice .pn2 { color: var(--ink-3); font-size: 11.5px; margin-top: 3px; }

/* size presets + comparison on instrument */
.size-presets { display: flex; align-items: center; gap: 6px; margin: -6px 0 14px; flex-wrap: wrap; }
.chip-btn { border: 1px solid var(--line-strong); border-radius: 999px; padding: 3px 11px; font-size: 11.5px; color: var(--ink-2); background: var(--inset); }
.chip-btn:hover { border-color: var(--accent); color: var(--ink); }
.chip-btn.active { background: rgba(90, 169, 255, 0.15); color: var(--accent); border-color: transparent; }
.ec-compare { font-size: 12px; color: var(--ink-2); margin-top: 12px; padding: 10px 12px; background: var(--inset); border-radius: var(--radius-s); border: 1px solid var(--line); }
.ec-compare b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* lever panel: the pressed debt leg reads like the active size preset */
.chip-btn[aria-pressed="true"] { background: var(--accent-soft); color: var(--accent); border-color: transparent; }
#leverPanel[aria-busy="true"] #leverTiles { opacity: 0.55; transition: opacity 0.15s; }
#leverRange:disabled { opacity: 0.5; }
#leverPanel { align-self: start; }

/* misc */
.muted { color: var(--ink-3); font-size: 11.5px; }
.footnote { color: var(--ink-3); font-size: 11px; margin-top: 10px; line-height: 1.5; }
.pagehead { display: flex; align-items: baseline; gap: 12px; margin-bottom: 16px; flex-wrap: wrap; }
.pagehead h2 { font-family: var(--display); font-size: 21px; font-weight: 600; letter-spacing: -0.01em; }
.pagehead .sub { color: var(--ink-2); font-size: 13px; }
.pagehead .right { margin-left: auto; display: flex; gap: 8px; align-items: center; }

@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  /* The sidebar becomes a header: brand, org and account on the first row, the nav on the
     second. Placed by grid areas rather than wrapped, because a
     wrapped row left the account links on a line of their own at tablet widths,
     pushed right under a nav that ended on the left. */
  .side {
    position: static; height: auto; display: grid; gap: 8px 16px; align-items: center; padding: 10px 14px;
    border-right: none; border-bottom: 1px solid var(--line);
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: "head org account" "nav nav nav";
  }
  .side-toggle { display: none; }
  .side-head { grid-area: head; }
  .side > .org-wrap { grid-area: org; justify-self: start; min-width: 0; max-width: 100%; }
  .nav { grid-area: nav; min-width: 0; flex-direction: row; flex-wrap: nowrap; overflow-x: auto; }
  .side-foot { display: contents; }
  .account-state { grid-area: account; flex-direction: row; margin: 0; }
  .side-link:not([hidden]) { min-height: 40px; }
  .view { padding: 16px 14px 60px; }
}
@media (max-width: 700px) {
  .side { gap: 8px 12px; }
  .brand { padding: 0; gap: 8px; }
  .brand-mark { width: 28px; height: 28px; }
  .brand-sub { display: none; }
  .brand-name { font-size: 14px; }
  .org { min-height: 44px; padding: 5px 10px; }
  .org-name, .org-kind { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .nav { gap: 4px; }
  .nav a { flex: none; min-height: 40px; padding: 8px 12px; white-space: nowrap; }
  .universe-load { padding: 5px 14px; }
  /* This is the one control the whole public funnel goes through. Scoped to `:not([hidden])`
     as well as the backstop at the top of this file, so the intent is readable HERE — this rule
     is about a link that is on screen, and it must never be the reason one comes back. */
  .side-link:not([hidden]) { min-height: 40px; }
  .btn, .chip-btn { min-height: 40px; }
  input:not([type="checkbox"]), select { min-height: 40px; }
  .view { padding: 14px 12px 48px; }
  table.data th, table.data td { padding: 11px 10px; }
  .hero-row { grid-template-columns: minmax(0, 1fr); }
  .filters input[type="search"] { flex: 1 1 100%; min-width: 0; }
  .brow { grid-template-columns: 110px 1fr 56px; }
  .org > div { min-width: 0; }
  .designer-advanced .filters label { flex: 1 1 100%; min-width: 0; }
  .designer-advanced .filters select, .designer-advanced .filters input { width: 100% !important; max-width: 100%; min-width: 0; }
  .designer-advanced .filters .btn { flex: 1 1 100%; }
  button.flow-remove { width: 40px; height: 40px; }
  .mini-help::before { content: ""; position: absolute; inset: -12px; }
}
@media (max-width: 520px) {
  /* Too narrow for the org beside the brand: it takes a row of its own, and Invite members and
     Signers keep their icons and accessible names but not their visible labels. */
  .side {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: "head account" "org org" "nav nav";
  }
  .org-wrap, .org, .nav { width: 100%; }
  #inviteLink .nav-label, #signersLink .nav-label {
    position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  /* The brand gives way to the account links rather than running under them. */
  .side-head, .brand > div { min-width: 0; }
  .side-head .brand-name { overflow: hidden; text-overflow: ellipsis; }
}
/* PRINT — a printed sheet is a RECORD, and this block used to remap only the neutral ramp.
   Every token that carries MEANING kept its dark-theme value against the printer's white
   ground, so the contrast direction was reversed for exactly the elements a reader cares most
   about: measured at 816px, 82 AA failures, 80 of them below 3:1, chips at 1.00:1 (invisible),
   and 186 interactive controls printed. See smart-trade#788.
   Three rules now, in the order they pay:
     1. invert the SEMANTIC tokens too, not just the neutrals;
     2. hide controls by ROLE, not by container — `.side` missed `#dMarketPicker`,
        which is an <aside class="discover"> and matched neither;
     3. give the page margins and stop cards splitting across a boundary. */
@page { margin: 14mm 12mm; }
@media print {
  :root {
    color-scheme: light;
    --page: #fff; --side: #fff; --surface: #fff; --raised: #fff; --inset: #fff;
    --line: #d7dbe2; --line-strong: #c2c8d2;
    --ink: #111418; --ink-2: #3a4250; --ink-3: #6b7280;
    /* On paper the header band is white, where the light --ink-3 already clears AA (4.83:1);
       the dark-theme lightening would go the wrong way here (3.13:1). */
    --ink-th: #6b7280;
    /* The semantic ramp, darkened until each clears 4.5:1 on white. The HUES are kept — a
       reader who knows blue means "this console", amber means caution and red means breach
       must not have to relearn the sheet — only the lightness moves. */
    --accent: #14539e; --accent-soft: #e8f0fb; --accent-ink: #ffffff;
    --good: #0f6f62; --warn: #8a5210; --warn-soft: #fbf1e4;
    --serious: #a3372a; --crit: #a3170f;
    --ink-1: #111418; --bad: #a3170f; --bg: #ffffff;
    --s1: #14539e; --s5: #a3170f;
  }
  /* A control on paper is a dead affordance printed onto a record — but HALF of this console's
     record lives inside one: a route's name is the text of `button.flow-leg-link` and its
     weight is the value of `input.flow-weight-num`. A first version hid controls by role and
     produced a sheet of empty boxes with a lone "%" in each, which is worse than the dead
     buttons it removed. So the rule is: drop the AFFORDANCE, keep the CONTENT.
     Hidden — purely an action, or a widget with nothing printable in it: */
  .btn, .chip-btn, [role="button"], .flow-remove, .flow-equal,
  input[type="range"], input[type="checkbox"], input[type="radio"], select, textarea,
  .side, .filters .btn { display: none !important; }
  /* The market picker is a BROWSING tool, not part of the record — and hiding its controls one
     by one leaves the labels and units behind, which is a filter row with the filter missing.
     It goes whole. This is the panel `.side` never matched: it is an
     <aside class="discover">. */
  .discover, #dMarketPicker { display: none !important; }
  /* The last affordances that survive as glyphs: a "?" that opens nothing and a caret that
     drops no menu. They read as ink smudges on a sheet. */
  .mini-help, .src-caret, .org-caret { display: none !important; }
  /* The canvas pan/zoom chrome — buttons that are not `.btn`, so the list above missed them.
     A zoom control on paper is the definition of a dead affordance. */
  .canvas-controls { display: none !important; }
  /* Kept, stripped to text: a button whose label IS the fact, and a field whose value is. */
  button { border: 0 !important; background: none !important; padding: 0 !important;
    color: inherit !important; font: inherit !important; text-align: left; }
  input { border: 0 !important; background: none !important; padding: 0 !important;
    color: var(--ink) !important; font: inherit !important; width: auto !important;
    appearance: textfield; -moz-appearance: textfield; }
  input::-webkit-outer-spin-button, input::-webkit-inner-spin-button { display: none !important; }
  /* A COLLAPSED <details> IS STILL PART OF THE RECORD, and getting this half-right printed a
     746x1 sliver: the summary was hidden with the other controls, while the content stayed
     clipped by `::details-content`, whose `content-visibility: hidden` a `display` rule cannot
     touch. Eight sections vanished, `Constraints & evidence` among them — the two limits the
     design was built under. So: the summary is KEPT (on a sheet it is the section heading, not
     an affordance) minus its marker, and the content box is un-clipped. */
  summary { display: block !important; list-style: none; font-weight: 650; }
  summary::marker, summary::-webkit-details-marker { content: none !important; display: none !important; }
  details::details-content { content-visibility: visible !important; }
  details > *:not(summary) { display: revert !important; }
  /* Chips carried a translucent tint over a dark surface; on white that resolved to near-white
     ink on white — the 1.00:1 measurement. Opaque ground, ink dark enough to read. */
  .chip { background: #f1f3f7 !important; border: 1px solid var(--line); color: var(--ink) !important; }
  .chip.grade-A, .chip.grade-B, .chip.ok { background: #e7f4f1 !important; color: var(--good) !important; }
  .chip.grade-C { background: var(--warn-soft) !important; color: var(--warn) !important; }
  .chip.grade-D, .chip.grade-F, .chip.breach { background: #fbeceb !important; color: var(--crit) !important; }
  .chip.info { background: var(--accent-soft) !important; color: var(--accent) !important; }
  .chip.neutral, .chip.cls { background: #f1f3f7 !important; color: var(--ink-2) !important; }
  /* `.pos` / `.neg` are LITERAL hex, not tokens, so the ramp above does not reach them — and
     `.pos` is what every yield number on the sheet is painted with (2.05:1 on white, the single
     worst reading in the measurement). Same hues, darkened. */
  .pos { color: var(--good) !important; }
  .neg { color: var(--crit) !important; }
  /* A record should not break mid-thought. */
  .card, .tile, .tablewrap, .strat, .stage-track, .deploy-note, tr { break-inside: avoid; }
  thead { display: table-header-group; }
  body { background: #fff; color: #111; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .shell { grid-template-columns: 1fr; }
  .view { max-width: 100%; padding: 0; }
  .card, .tile, .tablewrap { border-color: #d7dbe2 !important; background: #fff !important; break-inside: avoid; box-shadow: none; }
  .grid, .tiles { gap: 10px; }
  .chart .gridline { stroke: #e2e6ec; }
  .chart .endlabel { fill: #111418; }
  .chart .enddot { stroke: #fff; }
  .chart .axis text, .chart text.axis { fill: #6b7280; }
  a[href^="#/"] { color: inherit; }
  h2, h3 { break-after: avoid; }
  .inst-basis > * { display: block !important; }
  .inst-basis summary { display: none !important; }
  .protocol-evidence .yv-ev-open { display: none !important; }
}

/* Connection entry and shared provenance dialog layout. */
.org-connect { border-top: 1px solid var(--line); }
.org-row { display: flex; align-items: stretch; }
.org-menu .org-row [data-book] { flex: 1; min-width: 0; }
.org-menu .org-disconnect { width: auto; flex: none; padding: 10px; font-size: 12px; color: var(--ink-3); }
.org-menu .org-disconnect:hover, .org-menu .org-disconnect:focus-visible { color: var(--serious); }
.org-connect .org-name { color: var(--accent); }
.stale { color: var(--warn); }

/* ---------- shell states ----------
   index.html ships the shell INERT and boot.js either activates it or marks it degraded.
   An un-drawn disabled state is the same dead affordance with extra attributes on it, so
   both states are drawn: a control that cannot act must not look like one that can. */
[aria-disabled="true"] { opacity: 0.42; filter: grayscale(0.6); cursor: not-allowed; }
/* Loading is not failing. While boot is still reading, the chrome is inert for the same
   reason but only dimmed for it — the hard treatment is reserved for a shell that will
   never come up. */
.shell[data-shell="loading"] [aria-disabled="true"]:not(#navConsole) { opacity: 0.72; filter: none; }
/* boot.js's stand-in for the wallet box: shown only while the real one is hidden, never degraded */
.org-ghost { display: none; }
.org[hidden] + .org-ghost { display: flex; }
.shell[data-shell="degraded"] .org-ghost { display: none; }
.org-ghost[aria-busy="true"], .start-doors[data-prepaint] [aria-busy="true"] { cursor: progress; }
.nav a[aria-disabled="true"]:hover { background: none; color: var(--ink-2); }
.org[aria-disabled="true"]:hover { border-color: var(--line-strong); }

/* ---- degraded chrome: switched off, still READABLE ----
   The disabled treatment above is drawn with `opacity`, and opacity composites a label
   toward its own background: measured on the degraded shell, `Designer` landed at 2.35:1 and `data-collector unavailable` — the chrome's only naming
   of the service that failed — at 2.41:1. WCAG 1.4.3 exempts inactive controls, so none of
   that is a violation, and none of it is the point: boot.js writes this copy to be read
   ("labeled, not merely greyed — say which service failed"). So the degraded state stops
   paying for "off" in legibility and pays for it in colour instead. Every other signal is
   untouched: grayscale, `cursor: not-allowed`, `aria-disabled`/`disabled`, `tabindex="-1"`,
   and boot.js's capture-phase guard that prevents click, Enter and Space alike. The failure
   card and its Retry button keep their full emphasis — they are the loud part of this
   screen and are not dimmed at all. */
.shell[data-shell="degraded"] [aria-disabled="true"] {
  opacity: 1; filter: grayscale(1); color: var(--ink-th);
}
/* The children set their own colour, so the inherited one above never reaches them. */
.shell[data-shell="degraded"] .brand-name,
.shell[data-shell="degraded"] .brand-sub,
.shell[data-shell="degraded"] .org-name,
.shell[data-shell="degraded"] .org-kind,
.shell[data-shell="degraded"] .org-caret,
.shell[data-shell="degraded"] .nav a[aria-disabled="true"] { color: var(--ink-th); }

/* boot.js's visible-failure card: what failed, in the server's own words, then what the
   console is NOT doing about it, then the one control that still works. */
.boot-fail { max-width: 640px; margin: 48px auto; }
.boot-fail h3 { margin: 0 0 8px; }
.boot-fail-lede { color: var(--ink-2); margin: 0 0 10px; line-height: 1.5; }
.boot-fail-note { color: var(--ink-3); font-size: 12px; margin: 0 0 6px; line-height: 1.5; }
.boot-fail-act { margin: 14px 0 0; }
.boot-wait { max-width: 640px; margin: 48px auto; }
.boot-wait h3 { margin: 0 0 8px; }
.universe-load { padding: 6px 24px; font-size: 12px; color: var(--ink-2); background: var(--surface); border-bottom: 1px solid var(--line); }
.universe-load[hidden] { display: none; }
.seed-note {
  margin-top: 10px; border: 1px solid rgba(224, 164, 92, 0.45); border-radius: var(--radius-s);
  background: rgba(224, 164, 92, 0.10); color: var(--warn);
  padding: 9px 13px; font-size: 12px; line-height: 1.45;
}
/* ---------- capital-flow strategy designer ----------
   Ported from codex/strategy-designer-v1. Every value goes through the console's
   existing tokens, so this inherits whatever palette is in :root. */

/* strategy designer */
.designer-shell {
  background: var(--surface); border: 1px solid var(--line); border-radius: 12px;
  overflow: hidden;
}
.designer-intro {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  padding: 16px 20px;
}
.designer-intro h2 { font-size: 20px; line-height: 1.15; letter-spacing: -0.025em; }

/* ---- what the executor can run (read from the served capability) ----
   A list, not tiles: each line is a sentence with a subject, a chain and a venue, and a tile
   would cut it to a number that means nothing on its own. */
/* ---- the deployability verdict, wherever a design is on screen ----
   A note, not a tile: the reader needs the reason and what would clear it, and a tile would
   cut that to a word. The left rule is the state at a glance; the text carries the claim. */
.deploy-note {
  margin-top: 10px; padding: 10px 12px; font-size: 12.5px; line-height: 1.5;
  border: 1px solid var(--line); border-left: 3px solid var(--ink-3); border-radius: 8px;
  background: var(--inset); color: var(--ink);
}
.deploy-note.ok { border-left-color: var(--good); }
.deploy-note.warn { border-left-color: var(--serious); }
.deploy-note .chip { margin-right: 6px; vertical-align: baseline; }
.deploy-needs { list-style: none; margin: 7px 0 0; display: grid; gap: 4px; }
.deploy-needs li { font-size: 12px; color: var(--ink-2); padding-left: 12px; position: relative; }
.deploy-needs li::before { content: "→"; position: absolute; left: 0; color: var(--ink-3); }
.deploy-detail { margin-top: 6px; font-size: 11.5px; line-height: 1.45; color: var(--ink-3); }
/* On a card the note sits inside an already-dense column, so it loses the panel treatment and
   keeps only the left rule that carries the state. */
.deploy-note.compact { margin-top: 8px; padding: 7px 10px; font-size: 12px; }
.deploy-note.compact .deploy-needs { margin-top: 5px; }

.cap-list { list-style: none; margin-top: 12px; display: grid; gap: 7px; }
.cap-list li {
  font-size: 12.5px; line-height: 1.5; color: var(--ink);
  padding: 9px 12px; border-radius: 8px; background: var(--inset); border: 1px solid var(--line);
}
/* The key hangs beside the sentence, and the sentence indents under itself rather than under
   the key — a wrapped line starting beneath "LEVERED" reads as a second entry. */
.cap-list li { display: grid; grid-template-columns: 74px 1fr; gap: 8px; align-items: baseline; }
.cap-k { font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3); }
.cap-today .sub strong { color: var(--ink); font-weight: 600; }
@media (max-width: 640px) {
  .cap-list li { grid-template-columns: 1fr; gap: 2px; }
}

.strategy-flow {
  position: relative; min-height: 298px; padding: 24px;
  background: var(--inset); border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
}
/* ---- canvas viewport (M0): the designer flow on a pannable, zoomable slice of the map.
   Default view (no pan, no zoom, no offsets) is layout-identical to the previous fixed flow. */
/* The flow world has a floor width of ~896px and the viewport is roughly the window minus
   the sidebar, so between ~901px (where the stacked mobile layout stops taking over) and
   ~1180px the DESIGNED STRATEGY node — the page's primary output, the modeled net yield —
   was cut off by `overflow: hidden` with no scrollbar and nothing on screen saying the
   number continued past the edge. A 1024 or 1152 laptop, or any half-screen window, landed
   in that band by default. Hiding it is the one thing this console must not do with a
   number, so the viewport scrolls: a real scrollbar when (and only when) the world does not
   fit, on top of the drag-pan that was always there. touch-action follows — `none` also
   blocked the page's own vertical scroll on touch, which is why it is stated per axis. */
.canvas-viewport { overflow-x: auto; overflow-y: hidden; touch-action: pan-x pan-y; -webkit-user-select: none; user-select: none; scrollbar-width: thin; }
.canvas-viewport::-webkit-scrollbar { height: 8px; }
.canvas-viewport::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }
.canvas-viewport::-webkit-scrollbar-track { background: transparent; }
.canvas-viewport input, .canvas-viewport textarea { -webkit-user-select: auto; user-select: auto; }
.canvas-world {
  position: relative; display: grid;
  grid-template-columns: 170px minmax(340px, 1fr) 190px;
  align-items: center; gap: 86px; min-height: 250px; padding-bottom: 32px;
  transform-origin: 0 0; will-change: transform;
}
.canvas-world > [data-canvas-node] { cursor: grab; }
.canvas-viewport:active { cursor: grabbing; }

/* Screen-fixed HUD: the section head lives OUTSIDE .canvas-world so it never rides the
   pan/zoom transform. pointer-events pass through its empty space so the canvas still pans;
   only the Equal-weight button captures the pointer. */
.canvas-viewport > .flow-section-head {
  position: absolute; left: 24px; right: 170px; top: 15px; z-index: 3;
  margin: 0; pointer-events: none;
}
.canvas-viewport > .flow-section-head .flow-equal { pointer-events: auto; }
.canvas-controls { position: absolute; right: 10px; top: 10px; z-index: 3; display: flex; gap: 6px; }
.canvas-controls button {
  padding: 4px 9px; border: 1px solid var(--line); border-radius: 6px;
  background: color-mix(in srgb, var(--surface) 85%, transparent);
  color: var(--ink-3); font-size: 11px; font-variant-numeric: tabular-nums;
}
.canvas-controls button:hover { color: var(--ink); border-color: var(--line-strong); }
/* `print` rides with 900px in both of these blocks on purpose: paper cannot scroll or pan, which
   is the same constraint a narrow viewport has, and this console already solved it once. A
   second print-only canvas layout would be a second thing to keep true. */
@media (max-width: 900px), print {
  .canvas-world { display: contents; }
  [data-canvas-node] { transform: none !important; cursor: default; }
  .canvas-controls { display: none; }
  /* Both axes, not just overflow-x: a computed `visible` on one axis becomes `auto` while
     the other is `hidden`, which would leave a scroll container around a stacked list. */
  .canvas-viewport { overflow: visible; touch-action: auto; }
}
/* Between the mobile stack and the width where the flow world already fits, the world is
   squeezed to its legible floor FIRST and the scrollbar carries only what is left. Type is
   not part of the squeeze: the headline stays a headline. */
@media (min-width: 901px) and (max-width: 1180px) {
  .canvas-world { grid-template-columns: 148px minmax(300px, 1fr) 168px; gap: 34px; }
  .flow-node { padding: 14px; }
  .flow-node strong { font-size: 26px; }
  .flow-leg-link span { max-width: 168px; }
}

.flow-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; overflow: visible; }
.flow-lines path { fill: none; stroke: rgba(90, 169, 255, 0.5); stroke-width: 2px; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.flow-lines marker path { fill: var(--accent); stroke: none; }
.flow-node, .flow-routes { position: relative; z-index: 2; }
.flow-node {
  min-height: 116px; display: flex; flex-direction: column; justify-content: center;
  padding: 17px; border: 1px solid var(--line-strong); border-radius: 10px;
  background: var(--surface);
}
/* The DESIGNED STRATEGY headline was the ONE numeric leaf on this page without tabular figures
   — 165 of 166 had them — so the page's primary output was the one number that shifted width as
   it changed, which is exactly where a reader is watching a digit move. */
.flow-node strong { display: block; margin: 4px 0 1px; font-size: 31px; line-height: 1.1; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.flow-node span:not(.flow-eyebrow) { color: var(--ink-2); font-size: 11.5px; }
.flow-node em { margin-top: 13px; color: var(--ink-3); font-size: 11px; font-style: normal; }
/* The source node is a <button>: it opens the starting-asset menu on a plain click and
   still drags with the canvas, so it keeps the node look plus a switcher affordance. */
button.flow-source { font: inherit; color: inherit; text-align: left; width: auto; }
button.flow-source:hover, button.flow-source[aria-expanded="true"] { border-color: var(--accent); }
.src-caret {
  width: 14px; height: 14px; margin-left: 9px;
  stroke: var(--accent); stroke-width: 2.4; fill: none;
  stroke-linecap: round; stroke-linejoin: round;
  vertical-align: 3px; transition: transform 120ms ease;
}
button.flow-source:hover .src-caret { transform: translateY(1px); }
button.flow-source[aria-expanded="true"] .src-caret { transform: rotate(180deg); }
.asset-menu {
  position: fixed; z-index: 70;
  background: var(--raised); border: 1px solid var(--line-strong);
  border-radius: var(--radius-s); overflow: hidden;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
}
.asset-menu button { display: block; width: 100%; text-align: left; padding: 9px 13px; font-size: 12.5px; }
.asset-menu button strong { display: block; font-size: 13.5px; letter-spacing: -0.01em; }
.asset-menu button span { color: var(--ink-3); font-size: 11px; }
.asset-menu button:hover { background: rgba(255, 255, 255, 0.05); }
.asset-menu button.on { background: rgba(90, 169, 255, 0.13); }
.asset-menu button.on strong { color: var(--accent); }
.flow-eyebrow, .flow-section-label {
  color: var(--ink-3); font-size: 11px; font-weight: 650; letter-spacing: 0.075em; text-transform: uppercase;
}
.flow-section-head { display: grid; grid-template-columns: auto auto 1fr; align-items: baseline; gap: 11px; margin: 0 2px 7px; }
.flow-equal { color: var(--accent); font-size: 11px; white-space: nowrap; }
.flow-equal:hover { color: var(--ink); }
.flow-equal:disabled { color: var(--ink-3); cursor: not-allowed; }
.flow-balance {
  min-width: 0; color: var(--ink-2); font-size: 11px; font-variant-numeric: tabular-nums;
  text-align: right; white-space: nowrap;
}
.flow-leg {
  --leg-weight: 20%; position: relative; min-height: 68px; margin: 7px 0; padding: 10px 12px;
  border: 1px solid var(--line); border-radius: 8px; background: var(--surface);
}
.flow-leg::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px;
  width: var(--leg-weight); max-width: 100%; background: var(--accent); border-radius: 0 2px 2px 7px;
}
.flow-leg-top { display: flex; align-items: center; gap: 12px; }
.flow-leg-link { min-width: 0; text-align: left; }
.flow-leg-link:hover strong { color: var(--accent); }
.flow-leg-top strong { display: block; font-size: 13px; line-height: 1.2; }
.flow-leg-link span { display: block; max-width: 210px; margin-top: 2px; color: var(--ink-3); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.flow-leg-top > b { margin-left: auto; font-size: 13px; font-variant-numeric: tabular-nums; }
.flow-remove {
  width: 28px; height: 28px; display: grid; place-items: center; flex: 0 0 auto;
  border-radius: 5px; color: var(--ink-3); font-size: 16px; line-height: 1;
}
.flow-remove:hover { color: var(--ink); background: var(--inset); }
.flow-remove:disabled { visibility: hidden; }
.flow-leg-controls { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center; margin-top: 8px; }
.flow-weight-range { width: 100%; height: 3px; padding: 0; border: 0; border-radius: 2px; accent-color: var(--accent); cursor: pointer; }
.flow-leg-controls label { display: flex; align-items: center; gap: 3px; color: var(--ink-3); font-size: 11px; }
.flow-weight-num {
  width: 54px; padding: 3px 6px; border: 1px solid var(--line); background: var(--inset); text-align: right;
  font-size: 11px; font-variant-numeric: tabular-nums; appearance: textfield; -moz-appearance: textfield; cursor: text;
}
.flow-weight-num:hover { border-color: var(--line-strong); }
.flow-weight-num::-webkit-inner-spin-button, .flow-weight-num::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.flow-empty { padding: 28px 14px; border: 1px dashed var(--line-strong); border-radius: 8px; color: var(--ink-3); text-align: center; }
.flow-empty-head { color: var(--ink-2); margin-bottom: 10px; }
/* Constraint attribution: which rule bound, and whether it could ever match. Left-aligned
   inside a centred empty state because it is a list of readings, not a headline. */
.why-empty { list-style: none; margin: 0 auto; padding: 0; max-width: 620px; text-align: left; font-size: 12px; }
.why-empty li { padding: 4px 0 4px 12px; border-left: 2px solid var(--line-strong); margin-bottom: 4px; color: var(--ink-3); }
.why-empty li b { color: var(--ink-2); font-weight: 600; }
.why-empty-note { max-width: 620px; margin: 8px auto 0; text-align: left; font-size: 11px; color: var(--ink-3); opacity: .85; }
.market-empty .why-empty { font-size: 11px; margin-top: 8px; }
.why-empty-act { max-width: 620px; margin: 12px auto 0; text-align: left; }
/* A caveat that changes what every number below it means sits WITH those numbers, amber,
   never folded into a disclosure. */
.waive-note { margin: 0 0 10px; padding: 8px 12px; border-left: 3px solid var(--warn);
  background: var(--warn-soft); border-radius: 4px; font-size: 12px; color: var(--ink-2); }
.waive-note b { color: var(--ink-1); }
.why-empty-act .btn { width: 100%; }
/* A disabled control must not read as the brightest affordance on the page. */
.btn[disabled], .btn[disabled]:hover { opacity: .38; filter: grayscale(.65); cursor: not-allowed; }
.flow-section-label em { margin-left: 6px; color: var(--ink-3); font-weight: 500; letter-spacing: 0; text-transform: none; font-style: normal; font-variant-numeric: tabular-nums; }

.designer-shell .btn.primary { background: var(--accent); color: var(--accent-ink); }
.designer-shell :focus-visible { outline-color: var(--accent); }
.designer-shell input:focus, .designer-shell select:focus { border-color: var(--accent); }
.tooltip .tt-copy { color: var(--ink-2); line-height: 1.4; }
/* 15x15px at 9px type was the smallest control in the product and well under the 24x24
   target floor. The circle grows to 17px so the glyph can be 11px, and a transparent
   ::after extends the POINTER target to 24x24 without moving anything around it — the row
   it sits in is a dense label line and a 24px box in flow would reflow every one of them. */
.mini-help {
  position: relative;
  display: inline-grid; place-items: center; width: 17px; height: 17px; margin-left: 3px;
  border: 1px solid var(--line-strong); border-radius: 50%; color: var(--ink-3);
  font-size: 11px; font-weight: 700; line-height: 1; cursor: help; vertical-align: -2px;
}
.mini-help::after { content: ""; position: absolute; left: 50%; top: 50%; width: 24px; height: 24px; transform: translate(-50%, -50%); }
.designer-shell .mini-help:hover, .designer-shell .mini-help:focus { color: var(--accent); border-color: var(--accent); }

.designer-actions {
  display: flex; align-items: center; justify-content: flex-end; flex-wrap: wrap; gap: 9px;
  padding: 12px 16px; border-top: 1px solid var(--line);
}
.designer-actions .btn { flex: none; white-space: nowrap; }
.designer-actions #dMsg { flex: 1 1 100%; min-width: 0; text-align: right; }
.designer-actions #dMsg:empty { display: none; }
/* The market list is the designer's primary surface: beside the strategy from 1180px up,
   stacked above the routes below that, never behind a toggle (smart-trade#453). */
.designer-work { display: grid; grid-template-columns: minmax(0, 1fr); }
.discover { display: flex; flex-direction: column; min-width: 0; border-top: 1px solid var(--line); background: var(--surface); }
.discover-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; padding: 12px 16px 0; }
.discover-presets { flex: 1 1 100%; min-width: 0; }
.mandate-preset-bar { display: flex; align-items: center; gap: 7px; min-width: 0; flex-wrap: wrap; }
.mandate-select { display: flex; align-items: center; gap: 6px; min-width: 0; color: var(--ink-3); font-size: 11.5px; font-weight: 650; text-transform: uppercase; letter-spacing: .06em; }
.mandate-select select { min-width: 112px; max-width: 190px; min-height: 40px; padding: 4px 24px 4px 7px; color: var(--ink); font-size: 12px; text-transform: none; letter-spacing: 0; }
.mandate-preset-chips { display: flex; gap: 4px; min-width: 0; flex: 1 1 220px; flex-wrap: wrap; }
.mandate-chip { max-width: 190px; padding: 3px 7px; overflow: hidden; border: 1px solid var(--line); border-radius: 999px; color: var(--ink-2); background: var(--inset); font-size: 11.5px; line-height: 1.35; text-overflow: ellipsis; white-space: nowrap; }
.mandate-preset-actions { display: flex; align-items: center; gap: 8px; }
.mandate-preset-actions .lnk { min-height: 40px; }
.lnk.danger { color: var(--bad); }
.mandate-preset-note { margin-top: 5px; color: var(--ink-3); font-size: 11.5px; }
.mandate-preset-note.bad, .mandate-unknown { color: var(--bad); }
.mandate-preset-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 8px; padding: 10px; border: 1px solid var(--line-strong); border-radius: var(--radius-s); background: var(--inset); }
.mandate-preset-form[hidden] { display: none; }
.mandate-preset-form > label { display: grid; align-content: start; gap: 4px; min-width: 0; color: var(--ink-2); font-size: 11.5px; }
.mandate-preset-form input, .mandate-preset-form select { width: 100%; min-width: 0; min-height: 40px; font-size: 12px; }
.mandate-preset-form fieldset { grid-column: 1 / -1; min-width: 0; margin: 0; padding: 0; border: 0; }
.mandate-preset-form legend { margin-bottom: 5px; color: var(--ink-2); font-size: 11.5px; }
.mandate-chain-list { display: flex; gap: 5px 10px; min-width: 0; flex-wrap: wrap; }
.mandate-chain-list label { display: flex; align-items: center; gap: 4px; min-height: 40px; color: var(--ink-2); font-size: 11.5px; }
.mandate-chain-list input { width: 15px; min-height: 15px; }
.mandate-form-actions { grid-column: 1 / -1; display: flex; gap: 7px; }
/* Wraps at EVERY width, not only under 520px (#721). The switch's buttons are
   `white-space: nowrap`, and in the unavailable state its own labels grow
   ("Added · unavailable"), so on a nowrap row the dates absorb the entire
   shortfall — `flex: 1; min-width: 0` collapsed them to an 11px column and
   `overflow-wrap: anywhere` then broke the text at every character. The MARKETS
   column is ~420px, so this bit at desktop widths, not just on a phone. */
.market-recency { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-width: 0; padding: 9px 16px 0; }
.market-recency-switch { display: inline-flex; min-width: 0; padding: 2px; border: 1px solid var(--line); border-radius: 7px; background: var(--inset); }
.market-recency-switch button { min-height: 30px; padding: 4px 8px; border: 0; border-radius: 5px; color: var(--ink-3); background: transparent; font-size: 11px; white-space: nowrap; }
.market-recency-switch button.on { color: var(--ink); background: var(--raised); box-shadow: 0 0 0 1px var(--line-strong); }
.market-recency-switch button:disabled { cursor: not-allowed; opacity: .65; }
/* A floor as well as the wrap: `min-width: 0` alone lets a flex sibling starve
   this to nothing, and text that has room to be read is the whole point of it. */
.market-recency-dates { min-width: 14ch; flex: 1; color: var(--ink-3); font-size: 11px; line-height: 1.35; overflow-wrap: anywhere; }
.market-recency-dates time { display: block; }
.market-recency-dates time > span { color: var(--ink-2); font-weight: 600; }
.market-recency-dates i { display: none; }
.market-added, .market-removed { display: inline-block; margin-left: 6px; padding: 1px 5px; border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line)); border-radius: 999px; color: var(--accent); background: var(--accent-soft); font-size: 11px; font-style: normal; font-weight: 600; line-height: 1.3; text-transform: uppercase; letter-spacing: .04em; vertical-align: 1px; }
.market-removed { color: var(--ink-2); border-color: var(--line-strong); background: var(--raised); }
.market-name-static { cursor: default; }
.market-name-static:hover strong { color: var(--ink); }
.market-prior-only { grid-area: btn; color: var(--ink-3); font-size: 11px; line-height: 1.3; text-align: right; }
.market-full-id { display: block; margin-top: 3px; color: var(--ink-3); font: 11px/1.35 var(--mono); overflow-wrap: anywhere; word-break: break-word; }
.market-removed-row { box-shadow: inset 2px 0 0 var(--line-strong); }
.discover-filters { padding: 10px 16px 0; }
.discover-filter-bar { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; align-items: start; }
.discover-q input { width: 100%; min-width: 0; min-height: 34px; padding: 6px 9px; font-size: 12px; }
.discover-filter-drawer { min-width: 96px; }
.discover-filter-drawer > summary {
  display: flex; min-height: 34px; align-items: center; justify-content: space-between; gap: 7px;
  padding: 6px 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-s);
  color: var(--ink-2); font-size: 12px; font-weight: 600; cursor: pointer; list-style: none;
}
.discover-filter-drawer > summary::-webkit-details-marker, .discover-filter-choice > summary::-webkit-details-marker { display: none; }
.discover-filter-drawer > summary::after, .discover-filter-choice > summary::after { content: "⌄"; color: var(--ink-3); font-size: 11px; }
.discover-filter-drawer[open] > summary { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 55%, var(--line-strong)); background: var(--accent-soft); }
.discover-filter-drawer > summary b {
  min-width: 24px; padding: 1px 5px; border-radius: 999px; background: var(--inset);
  color: var(--ink-2); font-size: 11px; font-weight: 600; line-height: 1.45; text-align: center;
}
.discover-filter-panel { grid-column: 1 / -1; margin-top: 8px; padding: 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--inset); }
.discover-filter-panel-head { display: flex; min-height: 24px; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; color: var(--ink-th); font-size: 11px; font-weight: 600; letter-spacing: .045em; text-transform: uppercase; }
.discover-filter-panel-head .lnk { min-height: 28px; color: var(--accent); font-size: 11px; letter-spacing: 0; text-transform: none; }
.discover-filter-multis { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.discover-filter-choice { min-width: 0; }
.discover-filter-choice > summary {
  display: grid; min-height: 40px; grid-template-columns: minmax(0, 1fr) auto auto; align-items: center; gap: 5px;
  padding: 6px 7px; border: 1px solid var(--line); border-radius: 6px; background: var(--surface);
  color: var(--ink-2); font-size: 11px; cursor: pointer; list-style: none;
}
.discover-filter-choice > summary span, .discover-filter-choice > summary b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.discover-filter-choice > summary b { color: var(--accent); font-size: 11px; font-weight: 500; }
.discover-filter-choice[open] { grid-column: 1 / -1; }
.discover-filter-choice[open] > summary { border-color: var(--line-strong); }
.discover-filter-checks { max-height: 156px; margin-top: 4px; padding: 4px; overflow-y: auto; border: 1px solid var(--line); border-radius: 6px; background: var(--surface); scrollbar-width: thin; }
.discover-filter-checks label { display: flex; min-height: 30px; align-items: center; gap: 6px; padding: 3px 4px; color: var(--ink-2); font-size: 11px; cursor: pointer; }
.discover-filter-checks label:hover { background: var(--raised); }
.discover-filter-checks input { width: 14px; height: 14px; flex: 0 0 auto; accent-color: var(--accent); }
.discover-filter-checks span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.discover-filter-ranges, .discover-filter-selects { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 7px; margin-top: 9px; }
.discover-filter-ranges label, .discover-filter-selects label { display: grid; min-width: 0; gap: 4px; color: var(--ink-3); font-size: 11px; }
.discover-filter-selects label:last-child { grid-column: 1 / -1; }
.discover-filter-ranges input, .discover-filter-selects select { width: 100%; min-width: 0; min-height: 34px; padding: 6px 7px; font-size: 12px; }
.filter-input { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; border: 1px solid var(--line-strong); border-radius: 6px; background: rgba(0, 0, 0, 0.12); }
.filter-input:focus-within { border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 16%, transparent); }
.filter-input input { min-height: 32px; padding: 5px; border: 0; background: transparent; box-shadow: none; }
.filter-input i { padding: 0 7px; color: var(--ink-3); font-size: 11px; font-style: normal; }
.filter-range-error { margin-top: 8px; color: var(--crit); font-size: 11px; line-height: 1.4; }
.market-filter-exception { display: inline; margin-left: 6px; color: var(--warn); font-size: 11px; font-style: normal; }
.market-outside-filter { box-shadow: inset 2px 0 0 var(--warn); }
.market-result-count { margin: 0; padding: 9px 16px 7px; color: var(--ink-3); font-size: 11px; line-height: 1.5; }
.market-result-count b { color: var(--ink-2); font-weight: 600; font-variant-numeric: tabular-nums; }
.discover-list { min-height: 0; padding: 0 16px 14px; }
.discover-more { width: 100%; margin-top: 8px; color: var(--ink-2); }
.market-in-strategy td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.market-in-strategy td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.market-in-strategy .market-remove { color: var(--ink-2); border-color: var(--line-strong); }
.market-in-strategy .market-remove:hover { color: var(--serious); border-color: var(--serious); }
.market-picker-table { border: 1px solid var(--line); border-top: 0; border-radius: 0 0 8px 8px; background: var(--surface); }
.drow-head {
  display: flex; justify-content: space-between; gap: 8px; padding: 7px 12px;
  border: 1px solid var(--line); border-radius: 8px 8px 0 0; background: var(--raised);
  color: var(--ink-th); font-size: 11px; font-weight: 600; letter-spacing: 0.065em; text-transform: uppercase;
}
.drow-head span:last-child { margin-right: 74px; }
/* The action column has to hold its button, not merely most of it: 66px + 8px gap. */
.drow {
  display: grid; grid-template-columns: minmax(0, 1fr) auto 66px; grid-template-areas: "name side btn" "risk risk btn";
  align-items: center; gap: 2px 10px; padding: 8px 12px; border-top: 1px solid var(--line);
}
.drow .market-name { grid-area: name; }
.drow-side { grid-area: side; }
.drow-risk { grid-area: risk; }
.drow .market-add { grid-area: btn; }
.drow:first-child { border-top: 0; }
.drow-main { display: contents; }
.drow-side { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-variant-numeric: tabular-nums; }
.drow-side b { font-size: 13px; }
.drow-side span { font-size: 11px; }
.drow-risk { margin-top: 1px; color: var(--ink-3); font-size: 11px; line-height: 1.3; overflow-wrap: anywhere; }
.drow-risk > span { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.drow .risk-point-label { display: inline; max-width: none; margin: 0; }
.drow .risk-point-label::before { content: " · "; }
.market-name { display: block; width: 100%; min-width: 0; text-align: left; overflow: hidden; }
.market-name:hover strong { color: var(--accent); }
.market-name strong { display: block; overflow: hidden; text-overflow: ellipsis; font-size: 12.5px; }
.market-name span { display: block; margin-top: 2px; color: var(--ink-3); font-size: 11px; overflow-wrap: anywhere; }
.risk-point-label { max-width: min(106px, 100%); margin-left: auto; font-size: 11px; line-height: 1.25; white-space: normal; overflow-wrap: break-word; }
.discover .btn.market-add { width: 66px; min-height: 32px; padding: 5px 8px; color: var(--accent); border-color: var(--line-strong); }
.discover .btn.market-add:hover { color: var(--ink); border-color: var(--accent); }
.market-empty { padding: 18px 12px; border: 1px dashed var(--line); border-radius: 8px; color: var(--ink-3); font-size: 12px; text-align: center; }
.designer-advanced { border-top: 1px solid var(--line); }
.designer-advanced > summary { padding: 12px 17px; color: var(--ink-2); font-size: 12px; font-weight: 600; cursor: pointer; list-style-position: inside; }
.designer-advanced[open] > summary { border-bottom: 1px solid var(--line); }
.designer-advanced > :not(summary) { margin-left: 16px; margin-right: 16px; }
.designer-filters { padding-top: 14px; }
.designer-filters input[type="number"] { width: 64px; }
/* A constraint without its unit is a number nobody can check. */
.designer-filters .unit { color: var(--ink-3); font-size: 11px; }
.designer-table { margin-top: 12px; }
.designer-advanced > .btn { margin-top: 10px; margin-bottom: 15px; }
.strategy { min-width: 0; }
@media (min-width: 1280px) {
  .designer-work { grid-template-columns: 380px minmax(0, 1fr); }
  .discover { position: sticky; top: 59px; height: calc(100vh - 59px); max-height: calc(100vh - 59px); border-right: 1px solid var(--line); }
  .discover-head, .market-recency, .market-result-count { flex-shrink: 0; }
  .discover-filters { min-height: 44px; flex: 0 1 auto; overflow-y: auto; scrollbar-width: thin; }
  .discover-list { min-height: 120px; flex: 1 0 120px; overflow-y: auto; scrollbar-width: thin; }
  .designer-shell { overflow: clip; }
  .strategy .canvas-world { grid-template-columns: 126px minmax(240px, 1fr) 164px; gap: 24px; }
  .strategy .flow-node { padding: 13px; min-height: 100px; }
  .strategy .flow-node strong { font-size: 24px; }
  .strategy .flow-leg-link span { max-width: 168px; }
  .strategy .canvas-viewport > .flow-section-head { right: 130px; }
}
@media (max-width: 1279px) {
  .designer-work { display: flex; flex-direction: column; }
  .strategy { display: contents; }
  .strategy-flow { order: 0; }
  .discover { order: 1; }
  .discover-list { max-height: 70vh; overflow-y: auto; scrollbar-width: thin; }
  #dSeedNote, #dWaiveNote, #dMetric, #dDeploy { order: 2; }
  .designer-actions { order: 3; }
  .designer-advanced { order: 4; }
}
@media (max-width: 900px), print {
  .designer-shell { display: flex; flex-direction: column; }
  .designer-intro { align-items: stretch; flex-direction: column; padding: 14px 16px; }
  .designer-intro h1, .designer-intro h2 { font-size: 19px; }
  /* At 390 the page's own gutter is the one that matters; the cards are already one column. */
  .start-doors { padding: 22px 16px 32px; }
  .start-title-h { font-size: 21px; }
  .strategy-flow { display: contents; }
  .flow-lines { display: none; }
  .flow-source { order: 0; min-height: 0; padding: 11px 16px; border-width: 1px 0 0; border-radius: 0; background: var(--inset); }
  .flow-source strong { font-size: 22px; }
  /* RESULT AFTER CAUSE. At order 1 this sat 1,116px ABOVE the routes that produce it, with the
     whole market list wedged between them — so editing a weight moved a number the allocator
     could not see without scrolling back past everything. Order 4 puts it directly beneath the
     legs and immediately above the metric row it belongs with; the market picker keeps its
     place near the top, where a visitor with an empty design still finds it. Within order 4 the
     DOM decides, and `.flow-proof` precedes `#dSeedNote`/`#dMetric`/`#dDeploy`. */
  .flow-proof {
    order: 4; min-height: 70px; display: grid; grid-template-columns: 1fr auto;
    align-items: center; padding: 11px 16px; border-width: 1px 0 0; border-radius: 0;
    background: var(--inset);
  }
  .flow-proof .flow-eyebrow { grid-column: 1; }
  .flow-proof strong { grid-column: 1; margin-top: 1px; font-size: 27px; }
  .flow-proof span:not(.flow-eyebrow) { grid-column: 1; font-size: 11.5px; }
  .flow-proof em { grid-column: 2; grid-row: 1 / 4; margin: 0; font-size: 11.5px; text-align: right; }
  .flow-routes { order: 3; padding: 0 16px 8px; background: var(--inset); }
  /* head precedes .flow-routes in the DOM; same order slots it directly above the legs,
     recreating the old stacked layout where it lived inside the routes card */
  .canvas-viewport > .flow-section-head {
    position: static; order: 3; pointer-events: auto; margin: 0 0 8px;
    padding: 11px 16px 0; background: var(--inset); border-top: 1px solid var(--line);
  }
  .flow-section-head { grid-template-columns: 1fr auto; align-items: center; margin-bottom: 8px; }
  .flow-balance { grid-column: 1 / -1; font-size: 11.5px; text-align: left; }
  .flow-leg { min-height: 60px; margin: 5px 0; padding: 8px 10px; }
  .flow-leg-link span { font-size: 11.5px; }
  .flow-leg-controls { margin-top: 5px; }
  .flow-weight-num, .flow-leg-controls label { font-size: 12px; }
  .designer-work, .strategy { display: contents; }
  .discover { order: 2; }
  .discover-list { max-height: 62vh; }
  #dSeedNote, #dWaiveNote, #dMetric, #dDeploy { order: 4; }
  .market-picker-table th:nth-child(4), .market-picker-table td:nth-child(4) { display: none; }
  .designer-actions {
    order: 5; position: static; display: block; padding: 12px 16px;
    border-width: 1px 0 0; border-radius: 0; background: var(--surface);
  }
  .designer-actions .btn.primary { width: 100%; }
  .designer-actions .btn.primary { min-height: 44px; }
  
  .designer-advanced { order: 6; }
  .designer-filters { align-items: flex-end; }
}

@media (max-width: 520px) {
  .discover-head { display: block; padding: 11px 12px 0; }
  .discover-head > .flow-section-label { margin-bottom: 8px; }
  .mandate-preset-bar { align-items: flex-start; }
  .mandate-select { width: 100%; }
  .mandate-select select { flex: 1; max-width: none; }
  .mandate-preset-chips { flex-basis: 100%; }
  .mandate-chip { max-width: 100%; }
  .mandate-preset-actions { width: 100%; justify-content: flex-end; }
  .mandate-preset-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .mandate-preset-form > label:first-child { grid-column: 1 / -1; }
  .market-recency { flex-wrap: wrap; padding: 9px 12px 0; }
  .market-recency-switch { width: 100%; }
  .market-recency-switch button { flex: 1; }
  .market-recency-dates { flex-basis: calc(100% - 28px); }
}

@media (max-width: 350px) {
  .flow-balance { margin-top: 2px; }
}

.start-doors { margin: 0 auto; padding: 48px 24px 64px; max-width: 820px; }
.start-doors .start-title-h {
  font-size: 26px; line-height: 1.2; letter-spacing: -0.025em; margin: 0;
}
.start-list {
  list-style: none; display: grid; gap: 20px; margin: 28px 0 0; padding: 0;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.start-door.is-open {
  padding: 24px; border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); display: flex; flex-direction: column; min-width: 0;
}
.start-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.start-title { font-weight: 650; font-size: 17px; color: var(--ink); }
.start-why { margin-top: 12px; font-size: 13px; line-height: 1.6; color: var(--ink-2); overflow-wrap: anywhere; }
.start-go { margin-top: auto; padding-top: 28px; }
.start-cta { width: 100%; min-height: 44px; }
@media (max-width: 760px) {
  .start-doors { padding: 32px 16px 48px; }
  .start-doors .start-title-h { font-size: 23px; }
  .start-list { grid-template-columns: minmax(0, 1fr); gap: 16px; margin-top: 24px; }
  .start-door.is-open { padding: 20px; }
  .start-go { padding-top: 20px; }
}
/* What the designer keeps of the doors: which one it is standing behind, and the way back. */
.start-note { margin: 6px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-3); max-width: 70ch; }
.start-note-k { font-weight: 650; color: var(--ink-2); }
.start-note .lnk { font-size: 12px; margin-left: 4px; }

/* WHERE THE BASELINE LANDS. A one-time, irreversible choice, so the options are radios in a
   list rather than a dropdown: every organization the reader could pick is visible at once,
   which is what makes it a comparison instead of a guess. The id is `code` and full-length —
   these organizations have no names, and a truncated id could match two of them. */
.baseline-opts { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.baseline-opt { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--bg); cursor: pointer; }
.baseline-opt:hover { border-color: var(--accent); }
.baseline-opt input { margin-top: 2px; flex: none; }
.baseline-opt-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.baseline-opt-body b { font-size: 12.5px; color: var(--ink); }
.baseline-opt-body .dim2 { font-size: 11.5px; }
.baseline-opt-id { font-size: 11px; color: var(--ink-3); word-break: break-all; }

/* The literal request. Reads as a row of facts rather than prose, because it is one — and it
   is built from the same rule set the design is, so it cannot drift from what was applied. */
.design-request { margin: 8px 0 0; font-size: 11.5px; color: var(--ink-3); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.design-request .req-bit { padding: 2px 8px; border: 1px solid var(--line); border-radius: 999px; background: var(--inset); }
.design-request .req-waived { border-color: var(--warn); color: var(--warn); }

/* A card whose data this build does not receive. It keeps its heading and states the absence —
   the refusal is information — but it does not claim a panel's worth of the page to do it. The
   grid row is still as tall as its tallest real card; this one just stops being stretched to
   match, which is where the 370px empty box came from. */
#instHistory { min-width: 0; }
.card.is-unserved { align-self: start; }
.card.is-unserved .dim { padding: 2px 0 4px; line-height: 1.55; }
@media print { .card.is-unserved { align-self: start; } }

/* A modelled number whose question has moved on. Dimmed, never blanked: the last real answer is
   still the best information on screen, and a reader mid-drag watching values vanish learns less
   than one watching them lag. The transition is what makes the lag legible rather than a flicker. */
#leverTwoRisks { transition: opacity 120ms ease; }
#leverTwoRisks.is-stale, #leverPanel[aria-busy="true"] #leverNote, .lever-hf.is-stale { opacity: 0.55; }
/* One slider row: fixed-width figures so the track never resizes as digits change, and one
   reserved status line under it so pending and clamp notes never push the card around. */
.lever-row { margin-bottom: 0; }
.lever-row #leverVal { flex: 0 0 6ch; text-align: right; font-variant-numeric: tabular-nums; }
.lever-hf { flex: 0 0 8ch; white-space: nowrap; font-variant-numeric: tabular-nums; transition: opacity 120ms ease; }
.lever-ask { height: 1.5em; line-height: 1.5em; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* THE MANDATE EDITOR. Sits with the checks it grades, because a limit read in one place and set
   in another is how two of them stayed at 100% unnoticed. Opens by default while any limit is
   unset — the state a reader most needs to act on is the one they cannot see is there. */
.mandate-editor { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.mandate-editor > summary { cursor: pointer; font-size: 12px; color: var(--ink-2); }
.mandate-fields { display: flex; flex-direction: column; gap: 6px; }
.mandate-field { display: grid; grid-template-columns: minmax(140px, 1.2fr) 88px auto minmax(0, 2fr);
  align-items: center; gap: 8px; font-size: 12px; }
.mandate-field-label { color: var(--ink-2); }
.mandate-field input { width: 100%; font-variant-numeric: tabular-nums; }
.mandate-field-hint { font-size: 11px; }

/* The saved-strategy shelf's heading. It is ~75% of this page and had no heading at all, so a
   reader navigating by heading walked 23 cards without being told what they were. Styled as the
   page's other section labels are: this adds a landmark, not a new visual language. */
.shelf-heading {
  margin: 18px 2px 0; color: var(--ink-3);
  font-size: 11px; font-weight: 650; letter-spacing: 0.075em; text-transform: uppercase;
}
.shelf-heading .dim2 {
  margin-left: 6px; color: var(--ink-3); font-weight: 500;
  letter-spacing: 0; text-transform: none; font-variant-numeric: tabular-nums;
}
/* The page's own name. It reads as the page title it now is, rather than inheriting the browser
   default for an h1, which would tower over a console organised around density. */
h1[data-route-focus] { font-size: 19px; font-weight: 650; letter-spacing: -0.01em; }

/* ---------------- THE PAGE INDEX ----------------
   One page by product decision (the SPA is designer-only, AGENTS.md), and at 23,545px / 441 controls at 390 there was
   no way to move inside it: the four sections an allocator returns to begin past 21,000px. */
.page-index {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 2px;
  margin: -22px -24px 14px; padding: 6px 24px;
  border-bottom: 1px solid var(--line); background: var(--page);
  overflow-x: auto; scrollbar-width: none;
}
.page-index::-webkit-scrollbar { display: none; }
.page-index-label {
  flex: none; margin-right: 8px; color: var(--ink-th);
  font-size: 11px; font-weight: 600; letter-spacing: .045em; text-transform: uppercase;
}
.page-index a {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: var(--radius-s);
  color: var(--ink-2); font-size: 12px; text-decoration: none; white-space: nowrap;
}
.page-index a:hover { color: var(--ink); background: var(--raised); }
.page-index a.is-here { color: var(--ink); background: var(--accent-soft); }
.page-index-n { color: var(--ink-3); font-size: 11px; font-variant-numeric: tabular-nums; }
.page-index a.is-here .page-index-n { color: var(--ink-2); }
/* The jumped-to section must not land UNDER the two sticky bars that sit above it. */
#dFlowShell, #stratGrid, #stratGridTitle, #dsCapCard, #dsRunsCard, #dsOverlaysCard, #dsDeployCard {
  scroll-margin-top: 46px;
}
/* Navigation is not part of the record. */
@media print { .page-index { display: none; } }

/* ---------- sign in / sign out ---------- */
/* One narrow column, centred, because this page asks exactly one question and the
   designer behind it is the widest surface in the product — a full-bleed form here
   reads as a second application rather than a door into this one. */
.si-card {
  max-width: 460px; margin: 48px auto; display: flex; flex-direction: column; gap: 14px;
}
.si-card h1 {
  font-family: var(--display); font-size: 20px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ink);
}
.si-lede { font-size: 13px; color: var(--ink-2); line-height: 1.5; }
.si-methods { display: flex; flex-direction: column; gap: 8px; }
/* 44px, not the 6px-padding the shared .btn carries. This is the one control the whole
   public funnel goes through, it is pressed on phones, and the sign-in control beside it
   is already held to a 40px floor by a spec after shipping at 29px. A 19px tap target is
   how that happens again. */
.si-methods button {
  min-height: 44px; padding: 10px 16px; border-radius: var(--radius-s);
  border: 1px solid var(--line-strong); background: var(--inset);
  font-size: 13.5px; font-weight: 550; color: var(--ink);
  text-align: center; transition: border-color 120ms ease, background 120ms ease;
}
.si-methods button:hover:not(:disabled) { border-color: var(--accent); background: var(--raised); }
.si-methods button.si-primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600;
}
.si-methods button.si-primary:hover:not(:disabled) { background: var(--accent); border-color: var(--ink-2); }
/* Disabled means "a ceremony is running", so it must read as waiting rather than broken. */
.si-methods button:disabled, .si-enroll button:disabled { opacity: 0.55; cursor: progress; }
/* The note is empty most of the time. It keeps NO height when empty so the buttons do not
   sit above a permanent gap, and it never collapses the layout when it fills. */
.si-note { font-size: 12.5px; color: var(--ink-2); line-height: 1.5; min-height: 0; }
.si-note:empty { display: none; }
.si-note.bad { color: var(--bad); }
.si-note.good { color: var(--good); }
.si-alt { font-size: 12px; color: var(--ink-3); line-height: 1.5; }
.si-alt a { color: var(--accent); }
.si-enroll {
  display: flex; flex-direction: column; gap: 8px;
  border-top: 1px solid var(--line); padding-top: 14px; margin-top: 2px;
}
.si-enroll button {
  min-height: 44px; padding: 10px 16px; border-radius: var(--radius-s);
  border: 1px solid var(--line-strong); background: var(--inset);
  font-size: 13.5px; font-weight: 550; color: var(--ink);
}
.si-enroll button:hover:not(:disabled) { border-color: var(--accent); background: var(--raised); }
.si-enroll[hidden] { display: none; }
.si-signup { border-top: 1px solid var(--line); padding-top: 14px; margin-top: 2px; }
/* Links that navigate, dressed as the buttons beside them (org.js). */
.si-methods a.si-button {
  display: flex; align-items: center; justify-content: center; text-decoration: none;
  min-height: 44px; padding: 10px 16px; border-radius: var(--radius-s);
  border: 1px solid var(--line-strong); background: var(--inset);
  font-size: 13.5px; font-weight: 550; color: var(--ink);
}
.si-methods a.si-button:hover { border-color: var(--accent); background: var(--raised); }
.si-methods a.si-button.si-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); font-weight: 600; }
.si-form { display: flex; flex-direction: column; gap: 12px; }
.si-form[hidden] { display: none; }
.si-field { display: flex; flex-direction: column; gap: 4px; font-size: 12.5px; color: var(--ink-2); }
.si-field input, .si-field select {
  min-height: 40px; padding: 8px 10px; border-radius: var(--radius-s);
  border: 1px solid var(--line-strong); background: var(--inset); color: var(--ink); font-size: 13.5px;
}
@media (max-width: 560px) {
  .si-card { margin: 24px 12px; }
}
/* ---------- security (security.js) ---------- */
.sec-section { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--line); padding-top: 14px; }
.sec-section[hidden], .sec-confirm[hidden] { display: none; }
.sec-section h2 { font-size: 14px; font-weight: 600; color: var(--ink); }
.sec-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.sec-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 10px 12px; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--inset); }
.sec-meta { display: flex; flex-direction: column; gap: 2px; flex: 1 1 200px; min-width: 0; }
.sec-name { font-size: 13px; font-weight: 550; color: var(--ink); }
.sec-when, .sec-empty { font-size: 12px; color: var(--ink-2); }
.sec-reason { flex-basis: 100%; font-size: 12px; color: var(--ink-2); margin: 0; }
.sec-confirm { display: flex; flex-direction: column; gap: 10px; }
.sec-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.sec-row button, .sec-actions button {
  min-height: 44px; padding: 8px 14px; border-radius: var(--radius-s);
  border: 1px solid var(--line-strong); background: var(--raised);
  font-size: 13px; font-weight: 550; color: var(--ink);
}
.sec-row button:hover:not(:disabled), .sec-actions button:hover:not(:disabled) { border-color: var(--accent); }
.sec-row button:disabled { opacity: 0.55; cursor: not-allowed; }
.sec-actions button.si-danger { border-color: var(--bad); color: var(--bad); }
/* ---------- signers (signers.js) ---------- */
.si-card.sg-card { max-width: 760px; }
.sg-invite { display: flex; flex-wrap: wrap; gap: 16px; align-items: flex-start; }
.sg-qr { margin: 0; flex: 0 0 220px; display: flex; flex-direction: column; gap: 6px; }
.sg-qr svg { width: 220px; height: 220px; display: block; border-radius: var(--radius-s); }
.sg-qr figcaption { font-size: 12.5px; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.sg-facts { flex: 1 1 280px; min-width: 0; margin: 0; display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 4px 12px; font-size: 12.5px; }
.sg-facts dt { color: var(--ink-2); }
.sg-facts dd { margin: 0; color: var(--ink); overflow-wrap: anywhere; }
.sg-card code { font-family: var(--mono); font-size: 12px; }
.sg-keys { list-style: none; margin: 4px 0; padding: 0; display: flex; flex-direction: column; gap: 2px; font-size: 12.5px; }
.sg-key { display: flex; flex-wrap: wrap; gap: 4px 10px; }
.sg-key-src { color: var(--ink-2); min-width: 92px; }
.sg-device .si-field { margin-top: 6px; }
.sg-ok { font-size: 12.5px; color: var(--good); }
.sg-pending { font-size: 12.5px; color: var(--ink-th); max-width: 60ch; }
.sg-set { display: flex; flex-direction: column; gap: 8px; }
.sg-set h3 { font-size: 13px; font-weight: 600; color: var(--ink); margin: 0; text-transform: none; letter-spacing: normal; }
.sg-set .si-primary, .sg-card .sec-actions .si-primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.sg-alarm { border: 1px solid var(--bad); border-radius: var(--radius-s); padding: 10px 12px; color: var(--bad); font-size: 13px; }
@media (max-width: 560px) {
  .sg-qr { flex-basis: 100%; align-items: center; }
  .sg-facts { grid-template-columns: minmax(0, 1fr); }
  .sg-facts dd { margin-bottom: 4px; }
}


/* Start and inspection stay inside Designer's existing entry route. */
.onboarding-start { max-width: none; min-height: 70vh; display: grid; place-items: center; padding: 60px 22px; }
.onboarding-welcome { text-align: center; width: 100%; max-width: 460px; }
.onboarding-welcome img { display: block; margin: 0 auto 18px; }
.onboarding-welcome h1 { margin: 0; font-size: 30px; line-height: 1.1; letter-spacing: -.025em; }
.onboarding-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
.onboarding-pagination { margin-top: 16px; align-items: center; }
.onboarding-without-logo::before { content: ""; display: block; height: 41px; }
.onboarding-empty-description { margin: 12px 0 0; color: var(--ink-2); line-height: 21px; }
.onboarding-welcome .onboarding-actions { margin: 26px auto 0; max-width: 340px; }
.onboarding-welcome .onboarding-actions .btn { flex: 1 1 0; min-width: 0; }
.onboarding-actions .btn { min-height: 44px; padding: 10px 20px; }
.onboarding-address-link { margin-top: 18px; min-height: 28px; font-size: 12px; }
#startAddressForm:not([hidden]) { display: flex; gap: 8px; padding: 16px; margin-top: 16px; background: var(--raised); border: 1px solid var(--line); border-radius: 14px; }
#startAddress { min-width: 0; flex: 1; }
#startStatus { margin-top: 16px; color: var(--ink-2); overflow-wrap: anywhere; }
.onboarding-portfolio { max-width: none; padding: 20px 22px 40px; }
.onboarding-heading { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.onboarding-heading h1 { margin: 0; font-size: 21px; }
.onboarding-heading .onboarding-actions { margin-left: auto; }
.onboarding-account { color: var(--accent); font-size: 11px; overflow-wrap: anywhere; }
.onboarding-metrics { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-bottom: 14px; }
.onboarding-metrics > div { background: var(--raised); border: 1px solid var(--line); border-radius: 10px; padding: 14px 16px; }
.onboarding-metrics span { display: block; color: var(--ink-2); font-size: 13px; }
.onboarding-metrics strong { display: block; font-family: var(--mono); font-size: 26px; margin-top: 4px; overflow-wrap: anywhere; }
.onboarding-holdings { width: 100%; min-width: 760px; table-layout: fixed; }
.onboarding-col-position { width: 36%; }
.onboarding-col-qty { width: 22%; }
.onboarding-col-price { width: 14%; }
.onboarding-col-value { width: 18%; }
.onboarding-col-yield { width: 10%; }
.onboarding-holdings td { overflow: hidden; text-overflow: ellipsis; }
.onboarding-holdings td:first-child { overflow-wrap: anywhere; }
.onboarding-small-toggle { display: flex; align-items: center; gap: 8px; width: fit-content; min-height: 44px; margin-top: 8px; color: var(--ink-2); font-size: 12px; cursor: pointer; }
.onboarding-small-toggle input { appearance: none; position: relative; flex: 0 0 auto; width: 30px; height: 18px; margin: 0; padding: 0; border: 1px solid var(--line-strong); border-radius: 999px; background: var(--raised); cursor: pointer; }
.onboarding-small-toggle input::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px; border-radius: 50%; background: var(--ink-2); }
.onboarding-small-toggle input:checked { background: var(--accent); border-color: var(--accent); }
.onboarding-small-toggle input:checked::after { left: 14px; background: var(--ink); }
.onboarding-small-toggle input:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.onboarding-holdings td:first-child, .onboarding-holdings th:first-child { text-align: left; }
.onboarding-holdings td:not(:first-child), .onboarding-holdings th:not(:first-child) { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.onboarding-holdings small { display: block; color: var(--ink-2); font-size: 11px; margin-top: 4px; }
.onboarding-source { font-size: 11px; color: var(--ink-2); }
@media (max-width: 600px) { .onboarding-metrics { grid-template-columns: 1fr; } .onboarding-heading .onboarding-actions { margin-left: 0; } .onboarding-portfolio { padding: 20px 12px; } }

/* ---------------- MONITORING ----------------
   Ported from the supplied design (Smart Strategies Monitoring.dc.html), which used inline
   styles and raw hexes. Those hexes were ALREADY this palette — #101316/#171b1e/#262b2f/
   #f0eee9/#5aa9ff/#46c2b0/#e0a45c/#e0776b are --page/--surface/--line/--ink/--accent/--good/
   --warn/--serious verbatim — so the port is a translation, not a re-theme.

   THE ONE COLOUR THAT CHANGED. The design's dimmest grey (#5d6467) measures 2.87:1 against
   --surface, and shell_a11y_selftest.mjs enforces 4.5:1. It carried timestamps, axis labels
   and captions — small text, where the ratio matters most, and where "it is only a caption"
   is exactly backwards. Those take --ink-3 (#7f8789, 4.72:1). Secondary copy takes --ink-th
   (#8b9395, 5.40:1). Nothing else moved.

   ABOVE THE TOUCH-TARGET BLOCK, which must stay last (shell_a11y_selftest.mjs:1214). */

.mon { max-width: 1180px; display: flex; flex-direction: column; gap: 14px; }

.mon-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.mon-title { margin: 0; font-family: var(--display); font-size: 21px; font-weight: 600; letter-spacing: -0.015em; color: var(--ink); }
.mon-pill {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  border-radius: 999px; padding: 4px 11px;
  background: rgba(70, 194, 176, 0.14); color: var(--good);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.mon-pill-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; display: block; }
/* A refused read must not wear the live badge. */
.mon-pill-bad { background: rgba(213, 80, 74, 0.16); color: var(--crit); }

.mon-tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: 14px; overflow: hidden;
}
.mon-tile { background: var(--surface); padding: 15px 17px; }
.mon-tile-k { font-size: 12.5px; color: var(--ink-th); }
.mon-tile-v {
  font-family: var(--mono); font-size: 24px; font-weight: 600;
  font-variant-numeric: tabular-nums; margin-top: 4px; color: var(--ink);
}
.mon-tile-good { color: var(--good); }
.mon-tile-bad { color: var(--crit); }
.mon-tile-d { font-size: 12px; color: var(--ink-3); margin-top: 4px; }
.mon-tile-v small { display: inline-block; white-space: nowrap; font: 400 12.5px var(--font); color: var(--ink-3); margin-left: 8px; }

/* STRETCH, not start. The two panels below the chart hold different numbers of rows, and
   left to themselves one card ended half the height of the other with its bottom edge
   floating mid-page. They are a pair and they are read as a pair, so they share an edge. */
.mon-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(310px, 1fr)); gap: 14px; align-items: stretch; }
.mon-card { background: var(--surface); border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; display: flex; flex-direction: column; }
.mon-card-h {
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-3);
}
.mon-card-h-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.mon-card-sub { margin-left: auto; font-family: var(--font); font-size: 12px; text-transform: none; letter-spacing: normal; color: var(--ink-th); }

/* Both lists scroll in their own box rather than growing the page. Unbounded, the action
   ledger ran twice the height of the alerts beside it and pushed the chart off the fold —
   two panes that scroll independently beat one column that runs to 3,000px. */
.mon-alerts, .mon-ledger { flex: 1; min-height: 360px; max-height: 520px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
/* One column, so there is nothing to line up with and the floor is only dead space: an
   alert panel holding one row should be one row tall on a phone. */
@media (max-width: 700px) {
  .mon-alerts, .mon-ledger { min-height: 0; }
}

.mon-alert {
  display: grid; grid-template-columns: 8px 54px minmax(0, 1fr); gap: 10px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.mon-alert:last-child { border-bottom: 0; }
.mon-dot { width: 7px; height: 7px; border-radius: 50%; margin-top: 6px; background: var(--ink-3); }
/* The four dots are events.severity (info | warning | critical, per schema.ts) plus `act`
   for a kind that MOVED a position. Severity and consequence are different axes: a relever
   is logged `info` and is still the most consequential line on the page. */
.mon-alert-act .mon-dot { background: var(--accent); }
.mon-alert-warn .mon-dot { background: var(--warn); }
.mon-alert-serious .mon-dot { background: var(--crit); }
.mon-time { font-family: var(--mono); font-size: 12px; color: var(--ink-3); padding-top: 1px; }
.mon-alert-main { min-width: 0; }
.mon-alert-msg { font-size: 13px; color: var(--ink); line-height: 1.35; }
.mon-alert-market { font-size: 12px; color: var(--ink-th); margin-top: 3px; }
/* A middle dot between two readings on one quiet line. Cheaper than a second line and
   cheaper than a bordered chip, which is what a run count used to cost here. */
.mon-sep { color: var(--ink-3); margin: 0 6px; }
/* What the panel found, when what it found is nothing. Not an error state and not styled
   like one: an empty alert list after six weeks is the best sentence on the page. It takes
   the space left under the rows and centres in it, so a panel holding one alert reads as an
   all-clear rather than as a card someone forgot to fill. */
.mon-alerts { display: flex; flex-direction: column; }
.mon-quiet {
  flex: 1; display: grid; place-items: center; min-height: 56px;
  font-size: 12.5px; color: var(--ink-3); margin: 0; padding: 14px 0 4px; text-align: center;
}

/* The action, in words. events.kind itself — staking_lever, cbbtc_deadman — is on the row
   as a title attribute so it stays greppable, but the loop's internal vocabulary is not what
   goes on the screen. Set in the body face, not mono: it is a phrase now, not an identifier. */
.mon-kind {
  font-size: 12.5px; color: var(--ink-3); margin-right: 7px;
}
.mon-kind-deleverage, .mon-kind-staking_unwind { color: var(--serious); }
.mon-kind-relever, .mon-kind-staking_lever { color: var(--good); }
.mon-kind-sweep { color: var(--accent); }

/* Three FIXED columns — stamp, what it was, what it cost — laid out to the same rhythm as
   the alert row in the panel beside it. The four `auto` columns it replaces resized to
   their own longest word on every row, so no two stamps, kinds or amounts shared an edge. */
.mon-ledger { --mon-reb-cols: 54px minmax(0, 1fr) 84px; }
.mon-reb {
  display: grid; grid-template-columns: var(--mon-reb-cols); column-gap: 10px; row-gap: 3px; padding: 9px 0;
  border-bottom: 1px solid var(--line); font-size: 13px;
}
.mon-reb:last-child { border-bottom: 0; }
.mon-reb-name {
  grid-column: 2; color: var(--ink); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mon-reb-why { grid-column: 2; font-size: 12.5px; color: var(--ink-th); min-width: 0; }
/* Tabular figures and a fixed column: without both, "$1,204" and a lone em-dash sit at
   different x on consecutive rows. */
.mon-reb-cost {
  grid-column: 3; font-family: var(--mono); font-size: 12.5px; color: var(--ink-th);
  text-align: right; font-variant-numeric: tabular-nums;
}

.mon-reb-why .mon-tx { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); }

/* The column names, on the same grid as the rows they name. aria-hidden: each row already
   reads as date, name, amount in order, and a header repeated into every row is noise. */
.mon-reb-head {
  display: grid; grid-template-columns: var(--mon-reb-cols); column-gap: 10px;
  padding-bottom: 7px; border-bottom: 1px solid var(--line);
  font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-3);
}
.mon-reb-head span:last-child { text-align: right; }

/* A grouped row opens onto the events it stands for. The summary IS the row, so the grid
   lives on it and the native marker is replaced by one that sits in the date column. */
.mon-reb-g > summary { cursor: pointer; list-style: none; }
.mon-reb-g > summary::-webkit-details-marker { display: none; }
.mon-reb-g > summary .mon-reb-why::after { content: " ▸"; color: var(--ink-3); }
.mon-reb-g[open] > summary .mon-reb-why::after { content: " ▾"; }
.mon-reb-g > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.mon-reb-kids { padding: 2px 0 10px 64px; }
.mon-reb-kid {
  display: grid; grid-template-columns: 54px minmax(0, 1fr); column-gap: 10px;
  padding: 3px 0; font-size: 12.5px; color: var(--ink-th);
}
.mon-reb-g > summary.mon-reb { border-bottom: 0; }
.mon-reb-g { border-bottom: 1px solid var(--line); }
.mon-reb-g:last-child { border-bottom: 0; }

/* One cell per position. auto-fit rather than a fixed five: the fleet is five positions today and
   the strip must not need a rewrite at six, or collapse to a scrollbar at two. */
.mon-positions {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
  gap: 14px; margin-top: 12px;
}
.mon-position { display: flex; flex-direction: column; min-width: 0; }
.mon-position-h { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
/* The market names are long and the cell is narrow; the name yields, the reading never does. */
.mon-position-name {
  font-size: 12px; color: var(--ink-th); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mon-position-now { font-family: var(--mono); font-size: 13px; color: var(--ink-1); flex: none; }
/* Out of its own band is the whole point of the glance, so it is the only colour here. */
.mon-position-now-out { color: var(--serious); }
.mon-mini { width: 100%; height: 124px; display: block; margin-top: 6px; }
.mon-position-empty { justify-content: center; }

/* THE THIRD STATE. `.mon-empty` says a panel has nothing in it; `.mon-refused` says the read
   was refused and prints the server's own words. They are styled apart on purpose — the old
   monitoring UI rendered a refusal AS an empty panel, which read as a calm healthy position
   (the defect dashboard-fetch-contract.spec.ts was written for). */
.mon-empty { font-size: 13px; color: var(--ink-th); margin: 12px 0 2px; }
.mon-refused { font-size: 13px; color: var(--crit); margin: 12px 0 2px; }
.mon-refused-why { color: var(--ink); }

@media (max-width: 700px) {
  .mon-ledger { --mon-reb-cols: 46px minmax(0, 1fr) 70px; }
}

/* Opt-in selection interaction preview; default portfolio presentation is unchanged. */
.selection-preview-note { color: var(--warn); font-size: 12px; line-height: 1.5; margin: 0 0 16px; }
.selection-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; padding: 10px 14px; margin: 16px 0; border: 1px solid var(--line); border-radius: var(--radius-s); background: var(--raised); font-size: 12px; }
.selection-toolbar label, .selection-check label { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; cursor: pointer; }
.selection-toolbar input, .selection-check input { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; }
.selection-check label { justify-content: center; width: 32px; }
.selection-check input:disabled { cursor: not-allowed; }
.onboarding-holdings.is-selecting { min-width: 960px; }
.selection-col-check { width: 40px; }
.selection-col-reason { width: 155px; }
.is-selecting .onboarding-col-position { width: 29%; }
.is-selecting .onboarding-col-qty { width: 17%; }
.is-selecting .onboarding-col-price { width: 12%; }
.is-selecting .onboarding-col-value { width: 16%; }
.is-selecting .onboarding-col-yield { width: 8%; }
.onboarding-holdings.is-selecting td:nth-child(2), .onboarding-holdings.is-selecting th:nth-child(2), .onboarding-holdings.is-selecting td:last-child, .onboarding-holdings.is-selecting th:last-child { text-align: left; white-space: normal; }
.selection-chosen { background: var(--accent-soft); }
.selection-unavailable { color: var(--ink-3); }
.selection-ready { color: var(--good); font-size: 11px; }
.selection-reason { color: var(--ink-3); font-size: 11px; border: 1px solid var(--line-strong); border-radius: 4px; padding: 2px 5px; display: inline-block; }

/* #/book~<id> (book.js) */
.bk-card { max-width: 720px; }
.bk-step { border-top: 1px solid var(--line); padding-top: 12px; margin-top: 12px; }
.bk-step h2 { font-size: 14px; margin: 0 0 8px; }
.bk-form { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 8px 12px; }
.bk-form .si-methods { grid-column: 1 / -1; }
.bk-problem { color: var(--bad); }
.bk-problem:empty { display: none; }
.bk-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.bk-table th { text-align: left; font-weight: 500; color: var(--ink-2); padding: 3px 12px 3px 0; white-space: nowrap; }
.bk-table td { padding: 3px 0; overflow-wrap: anywhere; }
.bk-table small, .bk-problems, .bk-gates { color: var(--ink-2); font-size: 12.5px; }
.bk-problems li strong, .bk-gates li strong { color: var(--ink); font-weight: 500; }
.bk-gates { list-style: none; padding: 0; margin: 0; display: grid; gap: 4px; }
.bk-gate-state { display: inline-block; min-width: 64px; text-transform: capitalize; }
.bk-gates [data-state="passed"] .bk-gate-state { color: var(--good); }
.bk-gates [data-state="failed"] .bk-gate-state { color: var(--bad); }
.bk-problems { padding-left: 16px; margin: 8px 0 0; }
.bk-table .good { color: var(--good); }
.bk-table .bad { color: var(--bad); }
.bk-card button:disabled { opacity: 0.45; cursor: not-allowed; }

/* ---------------- TOUCH TARGETS ----------------
   LAST IN THE FILE ON PURPOSE. A media query adds no specificity, so these rules lost to the
   base declarations further down the stylesheet that set the very heights they are correcting
   (`.discover-filter-checks label { min-height: 30px }`, `.market-recency-switch button`) —
   written once in the responsive block above and silently overridden. Ordering is the fix that
   does not require inventing specificity.

   Measured at 390 before: 109 of 325 interactive targets under 32px. The shape of it was not
   "everything is small" — it was a handful of KINDS, so it is corrected as kinds rather than
   with a blanket rule that would inflate the dense screen this console is organised around.
   The largest group by far was 70 filter checkboxes at 14x14. A checkbox cannot carry a
   pseudo-element hit pad — it is a replaced element — so the LABEL becomes the target, which
   is what natively toggles it anyway. */

@media (max-width: 700px) {
  .discover-filters label, .designer-filters label, .filters label,
  .discover-filter-panel label, .discover-filter-checks label {
    min-height: 40px; display: flex; align-items: center; gap: 6px;
  }
  .market-recency-switch button { min-height: 40px; }
  /* A leg chip navigates to the instrument page — 149x22 was a link you had to aim at. */
  .chip.cls, a.chip { min-height: 32px; display: inline-flex; align-items: center; }
  /* The rest, each a real control that sat just under the line. */
  .flow-equal { min-height: 40px; }
  .lnk { position: relative; }
  .lnk::after { content: ""; position: absolute; inset: -11px; }
  .brand { min-height: 40px; }
  .chip-btn, .btn.quiet { min-height: 40px; }
  /* The mandate editor's four-column grid collapses rather than scrolling: a limit whose hint
     you cannot read is a limit you will set wrong. The input gets the tap height for the same
     reason every other control in this block does. */
  .mandate-field { grid-template-columns: 1fr auto; grid-template-areas: "label unit" "input input" "hint hint"; }
  .mandate-field-label { grid-area: label; }
  .mandate-field input { grid-area: input; min-height: 40px; }
  .mandate-field-hint { grid-area: hint; }
  /* The whole row is the target — a 14x14 radio is not one, and this is a decision that
     cannot be taken back. */
  .baseline-opt { min-height: 44px; }
  /* The page index is a row of jump targets; they get the same height as every other control.
     IT WRAPS HERE RATHER THAN SCROLLING. At 390 the row measured 542px inside a 394px box with
     `overflow-x: auto` and no fade, chevron or any other hint that it scrolled — so Assumptions
     and Deploy sat past the right edge, invisible, on a page 23,453px tall where this index is
     the only practical navigation (smart-trade#986). A scroll affordance would have been the
     smaller change; wrapping is the better one, because vertical space is the cheap axis at
     this width and a hidden control is not cheaper than a second line. */
  .page-index { top: 0; margin: -16px -14px 12px; padding: 5px 14px; flex-wrap: wrap; overflow-x: visible; }
  .page-index a { min-height: 40px; }
  /* An external link in prose measured 16px tall and got no pad, because the pad was written
     for `.lnk` alone. Same remedy, same reason it is a PAD and not a min-height: a 40px box
     around an inline link grows the line it sits in. */
  .ext { position: relative; }
  .ext::after { content: ""; position: absolute; inset: -12px 0; }
}
