/* ==========================================================================
   Event Utilization Dashboard - visual system

   The chrome is deliberately achromatic. In an instrument, color means
   signal: a series hue (ER / Admissions / SNF) or a status. Navigation,
   selection and focus are carried by weight, rule and ink instead, so
   nothing competes with the data for the eye.

   Structure is a ruled ledger held on soft surfaces: each band is a panel
   with a generous radius, and inside it the ledger rules and the strict
   numeric column are untouched. Radius is a scale, not a value - the larger
   the surface the larger its corner, so a tile never reads as a button and a
   band never reads as a tile. It is set once in the tokens below and nothing
   hard-codes a corner.
   ========================================================================== */

:root {
  color-scheme: light;

  --ground:     #e8ecea;
  --panel:      #fbfcfc;
  --panel-2:    #f2f5f4;
  --ink:        #11171a;
  --ink-2:      #47545a;
  --ink-3:      #6d7b82;
  --muted:      #8b979d;
  --rule:       #d2d9d7;
  --rule-soft:  #e3e8e6;
  --rule-strong:#b3bdba;

  --series-er:  #2a78d6;
  --series-adm: #eb6834;
  --series-snf: #1baf7a;
  --series-carenet: #8257c9;

  --ord-1: #86b6ef;
  --ord-2: #3987e5;
  --ord-3: #1c5cab;

  --critical:   #b3261e;
  --critical-bg:#fbe9e7;
  --warning:    #8a6110;
  --warning-bg: #fbf0dc;
  --good:       #10683f;

  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --cond: "IBM Plex Sans Condensed", "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;

  --gut: 22px;

  /* Corners, by the size of the thing they belong to. */
  --r-xs:   4px;   /* marks, swatches, inline badges */
  --r-sm:   8px;   /* buttons, inputs, chips */
  --r-md:  12px;   /* tiles and inner surfaces */
  --r-lg:  16px;   /* bands - the largest surface on the page */
  --r-pill: 999px;

  /* Lift, not decoration: a band sits on the ground, a tile sits in a band.
     Both are tinted toward the ink so they hold in either theme. */
  --lift-1: 0 1px 2px rgb(16 24 28 / .05);
  --lift-2: 0 2px 10px rgb(16 24 28 / .07);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --ground:     #0e1213;
    --panel:      #171c1e;
    --panel-2:    #1e2426;
    --ink:        #eef3f2;
    --ink-2:      #b0bcbc;
    --ink-3:      #8a9797;
    --muted:      #74827f;
    --rule:       #2a3234;
    --rule-soft:  #222a2b;
    --rule-strong:#3c4749;
    --series-er:  #3987e5;
    --series-adm: #d95926;
    --series-snf: #199e70;
    --series-carenet: #9b74e0;
    --ord-1: #3987e5;
    --ord-2: #256abf;
    --ord-3: #184f95;
    --critical:   #ef8b83;
    --critical-bg:#2e1614;
    --warning:    #d9a63c;
    --warning-bg: #2b2210;
    --good:       #4cc189;
    /* Dark grounds swallow a tinted shadow, so the lift comes from black. */
    --lift-1: 0 1px 2px rgb(0 0 0 / .30);
    --lift-2: 0 2px 12px rgb(0 0 0 / .38);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --ground:     #0e1213;
  --panel:      #171c1e;
  --panel-2:    #1e2426;
  --ink:        #eef3f2;
  --ink-2:      #b0bcbc;
  --ink-3:      #8a9797;
  --muted:      #74827f;
  --rule:       #2a3234;
  --rule-soft:  #222a2b;
  --rule-strong:#3c4749;
  --series-er:  #3987e5;
  --series-adm: #d95926;
  --series-snf: #199e70;
  --series-carenet: #9b74e0;
  --ord-1: #3987e5;
  --ord-2: #256abf;
  --ord-3: #184f95;
  --critical:   #ef8b83;
  --critical-bg:#2e1614;
  --warning:    #d9a63c;
  --warning-bg: #2b2210;
  --good:       #4cc189;
  --lift-1: 0 1px 2px rgb(0 0 0 / .30);
  --lift-2: 0 2px 12px rgb(0 0 0 / .38);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14.5px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

.masthead { background: var(--panel); border-bottom: 1px solid var(--rule); }
.masthead-in {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  padding: 13px var(--gut);
}
.wordmark { display: flex; align-items: baseline; gap: 9px; min-width: 0; }
.wordmark h1 { font-size: 15px; font-weight: 600; margin: 0; letter-spacing: -.008em; white-space: nowrap; }
.wordmark .src {
  font-family: var(--mono); font-size: 11px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Which organization's data is under this page (development's session sets
   data-source). Synthetic data stays quiet. The moment real participants are behind the figures the badge
   says so and keeps saying so, because the expensive mistake is demoing, or
   editing config, against live care records by accident. Status colors are used
   here and never for a data series. */
.wordmark .src[data-source="real"] {
  padding: 2px 8px; border-radius: var(--r-pill); font-weight: 600; letter-spacing: .02em;
  color: var(--critical); background: var(--critical-bg); border: 1px solid var(--critical);
}
.masthead-tools { margin-left: auto; display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: 8px; }
/* Three roles and two tools do not fit beside the wordmark on a phone. They
   wrap under it rather than push the page sideways. */
@media (max-width: 520px) {
  .masthead-tools { margin-left: 0; justify-content: flex-start; }
  .masthead-tools .seg button { padding-inline: 8px; }
}

/* How old the figures are. Quiet at first; it only asks for attention once the
   data is old enough that somebody might act on a stale number. */
.asof {
  font-family: var(--mono); font-size: 11px; color: var(--muted);
  white-space: nowrap;
}
.asof[data-stale="true"] { color: var(--warning); font-weight: 600; }

/* ============================================================ controls */
.seg { display: inline-flex; border: 1px solid var(--rule); border-radius: var(--r-sm); overflow: hidden; }
.seg button {
  font: inherit; font-size: 12.5px; line-height: 1;
  padding: 6px 11px; border: 0; cursor: pointer;
  background: var(--panel); color: var(--ink-2); border-left: 1px solid var(--rule);
}
.seg button:first-child { border-left: 0; }
.seg button:hover { background: var(--panel-2); color: var(--ink); }
.seg button[aria-pressed="true"] { background: var(--ink); color: var(--panel); font-weight: 500; }

.btn {
  font: inherit; font-size: 12.5px; line-height: 1;
  padding: 7px 13px; border-radius: var(--r-sm); cursor: pointer;
  border: 1px solid var(--rule); background: var(--panel); color: var(--ink-2);
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.btn:hover { background: var(--panel-2); color: var(--ink); border-color: var(--rule-strong); }
.btn:active { transform: translateY(1px); }
.btn-solid { background: var(--ink); color: var(--panel); border-color: var(--ink); font-weight: 500; }
.btn-solid:hover { background: var(--ink-2); color: var(--panel); }
.btn-icon { width: 32px; padding: 7px 0; text-align: center; }

/* A masthead tool: a labelled button that reads as chrome, not as an action
   on the data. The Errors button is the only one, and it carries its status
   mark so the thing it is about is legible before you click it. */
.btn-tool { display: inline-flex; align-items: center; gap: 7px; }
.btn-tool .mark { width: 8px; height: 8px; border-radius: var(--r-pill); flex: none; }
.btn-tool[aria-pressed="true"] {
  background: var(--ink); color: var(--panel); border-color: var(--ink); font-weight: 500;
}

select, input[type="number"], input[type="text"] {
  font: inherit; font-size: 13px; padding: 6px 9px; border-radius: var(--r-sm);
  border: 1px solid var(--rule); background: var(--panel); color: var(--ink);
  transition: border-color .12s ease;
}
select:hover, input[type="number"]:hover, input[type="text"]:hover { border-color: var(--rule-strong); }
input[type="number"] { font-family: var(--mono); font-variant-numeric: tabular-nums; }

/* ============================================================ period bar */
.periodbar {
  background: var(--panel); border-bottom: 1px solid var(--rule);
  display: flex; align-items: flex-end; gap: 14px; flex-wrap: wrap;
  padding: 11px var(--gut);
}
.field { display: flex; flex-direction: column; gap: 3px; }
.field > span {
  font-family: var(--cond); font-size: 11px; font-weight: 500; color: var(--muted);
}
.periodbar .spacer { flex: 1 1 auto; }

.ticker { display: flex; align-items: baseline; gap: 20px; flex-wrap: wrap; }
.tick { display: flex; align-items: baseline; gap: 7px; }
.tick .lab { font-family: var(--cond); font-size: 11.5px; color: var(--muted); }
.tick .val {
  font-family: var(--mono); font-size: 15px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tick .mark { width: 9px; height: 9px; flex: none; border-radius: var(--r-pill); align-self: center; }
.mark.er { background: var(--series-er); }
.mark.adm { background: var(--series-adm); }
.mark.snf { background: var(--series-snf); }

/* ============================================================ tabs */
.tabs {
  display: flex; padding: 0 var(--gut); background: var(--panel);
  border-bottom: 1px solid var(--rule); overflow-x: auto; scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button {
  font: inherit; font-size: 13.5px; cursor: pointer; white-space: nowrap;
  padding: 10px 16px; border: 0; background: transparent; color: var(--ink-3);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  transition: color .12s ease, background .12s ease;
}
.tabs button:hover { color: var(--ink); background: var(--panel-2); }
.tabs button[aria-selected="true"] { color: var(--ink); font-weight: 600; border-bottom-color: var(--ink); }

main { padding: 0 var(--gut) 56px; max-width: 1360px; margin: 0 auto; }

/* ============================================================ ledger bands */
.band { border-bottom: 1px solid var(--rule); padding: 20px 0; }
.band:last-child { border-bottom: 0; }
.band-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.band-head h2 { font-size: 16.5px; font-weight: 600; margin: 0; letter-spacing: -.012em; }
.band-head .sub { font-size: 12.5px; color: var(--ink-3); max-width: 68ch; margin: 0; }
.band-head .tools { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

.note { font-size: 12.5px; color: var(--ink-3); margin: 8px 0 0; max-width: 72ch; }
.note.pending { color: var(--warning); }

.cols { display: grid; gap: 26px; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
.cols-tight { display: grid; gap: 18px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.stack { display: flex; flex-direction: column; gap: 12px; min-width: 0; }

/* ============================================================ figures */
/* Figures are the thing people come to read, so they are tiles with air
   around them rather than cells divided by hairlines. The number gets the
   room: a larger size, tabular figures, and a label small enough that it
   never competes with it. */
.figs { display: grid; gap: 10px; background: transparent; border: 0; }
.figs.n3 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }
.figs.n4 { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.figs.n5 { grid-template-columns: repeat(auto-fit, minmax(174px, 1fr)); }
.fig {
  background: var(--panel-2); padding: 14px 16px;
  border: 1px solid var(--rule-soft); border-radius: var(--r-md);
  display: flex; flex-direction: column; gap: 3px; min-width: 0;
  position: relative; overflow: hidden;
}
/* The flag is a rail inside the rounded edge, so the corner stays whole. */
.fig.flagged { box-shadow: inset 3px 0 0 var(--critical); border-color: var(--critical); }
.fig .lab {
  font-family: var(--cond); font-size: 11.5px; font-weight: 600; color: var(--muted);
  letter-spacing: .02em; text-transform: uppercase;
}
.fig .val {
  font-family: var(--mono); font-size: 28px; font-weight: 500;
  letter-spacing: -.022em; font-variant-numeric: tabular-nums; line-height: 1.12;
  color: var(--ink);
}
.fig .val.sm { font-size: 22px; }
.fig .sub { font-size: 12px; color: var(--ink-3); line-height: 1.4; }

.delta { font-family: var(--mono); font-size: 12px; font-weight: 500; }
.delta.up { color: var(--critical); }
.delta.down { color: var(--good); }
.delta.flat { color: var(--muted); }

/* ============================================================ tables */
.tablewrap { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: 13px; }
/* Numbers right, words left. The numeric column is the one that has to line
   up; forcing prose into it just makes names hard to scan. */
thead th {
  font-family: var(--cond); font-size: 11.5px; font-weight: 600; color: var(--muted);
  text-align: left; padding: 0 14px 6px 0; border-bottom: 1px solid var(--rule-strong);
  white-space: nowrap;
}
tbody td {
  text-align: left; padding: 6px 14px 6px 0;
  border-bottom: 1px solid var(--rule-soft); white-space: nowrap;
}
thead th.n, tbody td.n, tfoot td.n { text-align: right; padding-right: 0; padding-left: 14px; }
/* Every cell after the first keeps a left gutter. Without this a numeric
   column (padding-right: 0, so the digits align on the edge) runs straight
   into the text column after it - '#' + 'Participant' read as '#Participant'. */
thead th + th, tbody td + td, tfoot td + td { padding-left: 14px; }
thead th:first-child, tbody td:first-child, tfoot td:first-child { padding-left: 0; }
thead th:last-child, tbody td:last-child, tfoot td:last-child { padding-right: 0; }
tbody tr:hover td { background: var(--panel-2); }
tbody tr:hover td:first-child { border-top-left-radius: var(--r-xs); border-bottom-left-radius: var(--r-xs); }
tbody tr:hover td:last-child { border-top-right-radius: var(--r-xs); border-bottom-right-radius: var(--r-xs); }
tbody tr.clickable { cursor: pointer; }
tbody tr.flagged td:first-child { box-shadow: inset 2px 0 0 var(--critical); padding-left: 9px; }
td.n, th.n { font-family: var(--mono); font-variant-numeric: tabular-nums; }
tfoot td {
  text-align: left; padding: 8px 14px 0 0; font-weight: 600;
  border-top: 1px solid var(--rule-strong); font-family: var(--sans);
}
tfoot td.n { font-family: var(--mono); font-variant-numeric: tabular-nums; }
caption { caption-side: bottom; text-align: left; padding-top: 9px; font-size: 12px; color: var(--muted); }
/* The data-dependent half of a caption: what a column is currently missing.
   Carries the warning colour because it changes how a number should be read. */
.capnote:empty { display: none; }
/* A band whose subtitle only arrives with the data starts with an empty one. */
.band-head .sub:empty { display: none; }
.capnote.warn { color: var(--warning); }
/* Who you are signed in as, where the role toggle sits in the seed build. */
.whoami { font-size: 12px; color: var(--muted); white-space: nowrap; }
th .sort {
  font: inherit; font-family: var(--cond); font-size: 11.5px; font-weight: 600;
  background: none; border: 0; padding: 0; cursor: pointer; color: var(--muted);
}
th .sort:hover { color: var(--ink); }
th .sort[data-active="true"] { color: var(--ink); }

/* ============================================================ status */
.badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--mono); font-size: 11.5px; font-weight: 500;
  padding: 2px 8px; border-radius: var(--r-pill);
  background: var(--panel-2); color: var(--ink-2); border: 1px solid var(--rule);
}
.badge.critical { background: var(--critical-bg); color: var(--critical); border-color: transparent; }
.badge.warning { background: var(--warning-bg); color: var(--warning); border-color: transparent; }
.na { color: var(--muted); }
.chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  padding: 5px 11px; border-radius: var(--r-pill); background: var(--panel-2);
  border: 1px solid var(--rule); color: var(--ink-2);
}
.chip .n { font-family: var(--mono); color: var(--ink); font-variant-numeric: tabular-nums; }

/* ============================================================ charts */
.chart { display: block; width: 100%; height: auto; overflow: visible; }
.chart text { font-family: var(--sans); }
.chart .axis-label { fill: var(--muted); font-size: 11px; }
.chart .value-label {
  fill: var(--ink-2); font-size: 11px; font-weight: 500;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
.chart .gridline { stroke: var(--rule-soft); stroke-width: 1; }
.chart .baseline { stroke: var(--rule-strong); stroke-width: 1; }
.chart .mark { transition: opacity .12s ease; }
.chart .mark.dim { opacity: .2; }
.chart-empty { color: var(--muted); font-size: 12.5px; padding: 26px 0; }
.legend {
  display: flex; flex-wrap: wrap; gap: 6px 15px; margin: 9px 0 0; padding: 0;
  list-style: none; font-size: 12.5px; color: var(--ink-2);
}
.legend li { display: flex; align-items: center; gap: 6px; }
.swatch { width: 10px; height: 10px; border-radius: var(--r-xs); flex: none; }

/* Rate rows: label, bar, figure, status on one strict numeric column. */
.rates { display: flex; flex-direction: column; }
.raterow {
  display: grid; grid-template-columns: 118px 1fr 58px auto;
  align-items: center; gap: 12px;
  padding: 5px 0 5px 9px; border-left: 2px solid transparent;
}
.raterow.flagged { border-left-color: var(--critical); }
.raterow .nm { font-size: 12.5px; color: var(--ink-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.raterow .pc { font-family: var(--mono); font-size: 12.5px; text-align: right; font-variant-numeric: tabular-nums; }
.raterow .bar { height: 9px; background: var(--rule-soft); border-radius: var(--r-pill); overflow: hidden; }
.raterow .bar i { display: block; height: 100%; background: var(--series-er); border-radius: var(--r-pill); transition: width .18s ease; }
.raterow.flagged .bar i { background: var(--critical); }

/* Day-pattern grid */
.daygrid-wrap { display: inline-block; }
.daygrid { display: grid; grid-template-columns: repeat(7, 21px); gap: 2px; }
.dayhead { font-family: var(--cond); font-size: 10px; color: var(--muted); text-align: center; }
.daycell {
  font-family: var(--mono); font-size: 10.5px; text-align: center;
  padding: 3px 0; border-radius: var(--r-xs); color: var(--ink-3);
  background: var(--panel-2); border-bottom: 2px solid transparent;
}
.daycell.none { background: transparent; }
.daycell.repeat { background: var(--critical-bg); color: var(--critical); font-weight: 600; }
.daycell.centerday { border-bottom-color: var(--rule-strong); }

/* ============================================================ admin edit */
.editrow { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.editrow label { font-size: 12.5px; color: var(--ink-2); }
.editrow input { width: 86px; }
.err { color: var(--critical); font-size: 12.5px; margin: 6px 0 0; }
.readonly {
  display: inline-flex; gap: 7px; align-items: center; font-size: 12.5px;
  padding: 5px 11px; border-radius: var(--r-sm); background: var(--panel-2);
  border: 1px solid var(--rule); color: var(--ink-2);
}
.readonly b { font-family: var(--mono); font-weight: 500; color: var(--ink); }

/* ============================================================ detail view */
.backlink {
  font: inherit; font-size: 12.5px; background: none; border: 0; padding: 0;
  color: var(--ink-2); cursor: pointer; margin-bottom: 12px;
}
.backlink:hover { color: var(--ink); text-decoration: underline; }
.subject { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.subject h2 { font-size: 21px; font-weight: 600; margin: 0; letter-spacing: -.015em; }
.subject .meta { font-size: 12.5px; color: var(--ink-3); }
.pills { display: flex; gap: 7px; flex-wrap: wrap; margin-top: 9px; }

/* ============================================================ states */
.loading, .failure { font-size: 13px; padding: 30px 0; }
.loading { color: var(--muted); }
.failure { color: var(--critical); }

/* The one motion effect: a value that just changed says so, briefly. It
   exists to make partial updates legible. Nothing else moves on its own. */
@keyframes changed-flash {
  from { background-color: var(--panel-2); }
  to { background-color: transparent; }
}
.changed { animation: changed-flash .55s ease-out; border-radius: var(--r-xs); }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: var(--r-xs); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

@media (max-width: 620px) {
  :root { --gut: 16px; }
  .fig .val { font-size: 23px; }
  .fig .val.sm { font-size: 19px; }
  .band { padding: 16px 15px; border-radius: var(--r-md); }
  .raterow { grid-template-columns: 92px 1fr 54px; }
  .raterow .badge { display: none; }
  .ticker { gap: 14px; }
  .band-head .tools { margin-left: 0; width: 100%; }
}

/* Hidden tab panels stay mounted; only visibility changes. */
[hidden] { display: none !important; }

/* Hover readout on chart marks. */
.tooltip {
  position: fixed; z-index: 50; pointer-events: none; max-width: 250px;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--rule-strong); border-radius: var(--r-md);
  padding: 8px 11px; font-size: 12.5px;
  box-shadow: var(--lift-2);
}
.tooltip .t-title { font-weight: 600; margin-bottom: 3px; }
.tooltip .t-row { display: flex; align-items: center; gap: 7px; }
.tooltip .t-row .k { color: var(--ink-3); }
.tooltip .t-row .v {
  margin-left: auto; font-family: var(--mono); font-variant-numeric: tabular-nums;
}

/* The working area used to be one continuous sheet divided by hairlines.
   It is now a stack of surfaces: each band is its own panel on the ground,
   which is what lets a corner be rounded at all. The rules INSIDE a band -
   the tables, the ledger - are untouched; only the container changed. */
main {
  background: transparent;
  border-inline: 0;
  padding-inline: var(--gut);
  padding-block: 18px 56px;
}
.band {
  background: var(--panel);
  border: 1px solid var(--rule-soft);
  border-radius: var(--r-lg);
  box-shadow: var(--lift-1);
  padding: 20px 22px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--rule-soft);
}
.band:last-child { border-bottom: 1px solid var(--rule-soft); margin-bottom: 0; }
/* The unsaved rail follows the rounded edge instead of squaring it off. */
.band.previewing {
  box-shadow: inset 3px 0 0 var(--warning), var(--lift-1);
  border-color: var(--warning);
  padding-left: 22px;
}

/* A share reads as one figure beside its ranking, not two half-empty columns. */
.cols-share { display: grid; gap: 26px; grid-template-columns: 210px minmax(0, 1fr); align-items: start; }
@media (max-width: 620px) {
  main { padding-inline: 16px; }
  .cols-share { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Benchmark rate sliders (admin)

   A dragged rate is a what-if, and the one thing the page must never do is
   let an unsaved figure pass for the committed one. So "previewing" is a
   state with its own mark: the warning rail on every band the rates feed,
   and an explicit unsaved figure beside the slider. Warning ink, not
   critical - an exploration is not an error.
   ========================================================================== */

.rates-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px 26px;
}

.rate { border-left: 2px solid var(--rule-soft); padding-left: 11px; }
.rate.previewing { border-left-color: var(--warning); }

.rate-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.rate-lab { font-size: 12.5px; color: var(--ink-2); }
.rate-val {
  font-family: var(--mono); font-size: 16px; font-weight: 500;
  color: var(--ink); margin-left: auto; font-variant-numeric: tabular-nums;
}
.rate-diff { flex-basis: 100%; font-size: 11.5px; color: var(--muted); font-family: var(--mono); }
.rate-diff.off { color: var(--warning); }

.rate-ctl { display: flex; align-items: center; gap: 10px; margin-top: 9px; }
.rate-track { position: relative; flex: 1 1 auto; min-width: 0; }
.rate-num { width: 84px; flex: none; }

/* The saved value, marked on the track, so you can always find your way back. */
.rate-mark {
  position: absolute; bottom: -1px; width: 1px; height: 7px;
  background: var(--rule-strong); transform: translateX(-.5px); pointer-events: none;
}

.slider {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; height: 18px;
  background: transparent; cursor: ew-resize; padding: 0; border: 0;
}
.slider::-webkit-slider-runnable-track {
  height: 5px; background: var(--rule); border-radius: var(--r-pill);
}
.slider::-moz-range-track { height: 5px; background: var(--rule); border-radius: var(--r-pill); }
.slider::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 15px; height: 15px; margin-top: -5px;
  background: var(--ink); border: 2px solid var(--panel); border-radius: var(--r-pill);
  box-shadow: var(--lift-1);
}
.slider::-moz-range-thumb {
  width: 15px; height: 15px; background: var(--ink);
  border: 2px solid var(--panel); border-radius: var(--r-pill); box-shadow: var(--lift-1);
}
.rate.previewing .slider::-webkit-slider-thumb { background: var(--warning); }
.rate.previewing .slider::-moz-range-thumb { background: var(--warning); }
.slider:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }

.rate-note { font-size: 11.5px; color: var(--ink-3); margin: 8px 0 0; max-width: 34ch; }
.rate-actions { margin-top: 18px; }

/* Every band whose figures came from unsaved rates carries the rail (defined
   with the band itself, so it composes with the band's own lift). Only the
   band whose wording actually makes the unsaved claim takes the warning ink -
   coloring the standing explanatory copy too would make the ink meaningless. */
.band.preview-note .band-head .sub { color: var(--warning); }

/* ---- Scenarios -----------------------------------------------------------
   The current rates stay neutral - they are what is, not a proposal - and each
   entry beyond the saved one takes a hue from the ordinal ramp. Four rows is
   the cap: a fifth would have to repeat a hue that already means something
   else. Nothing here is added by hand - the working row appears when a rate
   moves, and saving pushes the rates it replaced onto the board.             */

/* One grid for the whole list, not one per row: with a grid per row the
   action column is 0px wide on the header and ~200px on a data row, so every
   column lands somewhere different. The rows are display:contents so their
   cells are laid out by the list's own column tracks and actually line up. */
.scenarios {
  display: grid;
  grid-template-columns: 12px minmax(140px, 1fr) auto auto auto auto;
  align-items: center;
}
.scn { display: contents; }
/* display:contents outranks the UA's [hidden] rule, so the working row would
   stay visible without this. It is hidden far more often than it is shown. */
.scn[hidden] { display: none; }
.scn > * {
  padding: 9px 0 9px 12px;
  border-bottom: 1px solid var(--rule-soft);
  min-width: 0;
}
.scn > *:first-child { padding-left: 0; }
.scn:last-of-type > * { border-bottom: 0; }
.scn > .swatch { width: 10px; height: 10px; border-radius: 2px; box-sizing: content-box; }
.scn > .swatch { border-radius: var(--r-xs); }
/* The name cell is a wrapper now (input + its refusal message). Pull its own
   padding back by what the input adds, so names line up with the swatches. */
.scn > .namewrap { padding-left: 5px; }
/* The CELL keeps its full width, so the ledger rule under it runs the length
   of the row like every other one. Only the field inside is capped - a name
   is a label, not a text box the width of the table. */
input.scn-name { max-width: 320px; }
.scn-head > * {
  font-family: var(--cond); font-size: 11px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
  padding-top: 0; padding-bottom: 7px; border-bottom: 1px solid var(--rule);
}
input.scn-name {
  width: 100%; min-width: 0; font: inherit; font-size: 13px;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-sm);
  padding: 4px 7px; color: var(--ink);
  transition: border-color .12s ease, background .12s ease;
}
.scn-name-ro { font-size: 13px; color: var(--ink); }
.scn-rates { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); text-align: right; }
.scn-total { font-family: var(--mono); font-size: 13.5px; color: var(--ink); text-align: right; }
.scn-diff { font-family: var(--mono); font-size: 11.5px; color: var(--muted); text-align: right; }
.scn-diff.up { color: var(--critical); }
.scn-diff.down { color: var(--good); }
/* The unsaved row carries the same warning language as the sliders and bands,
   so a proposal never reads as something the organization has committed to. */
.scn-working > * { background: var(--warning-bg); }
.scn-working > *:first-child { box-shadow: inset 2px 0 0 var(--warning); }
.scn-working .scn-name-ro { color: var(--warning); font-weight: 600; }
.scn-acts { display: flex; gap: 6px; justify-content: flex-end; }
.scn-note { grid-column: 1 / -1; }
.btn-xs { padding: 3px 8px; font-size: 11.5px; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn:disabled:hover { background: var(--panel); color: var(--ink-2); }

/* Narrow: the numeric block cannot hold six columns, so each rate set becomes
   a small stacked record and the shared header is dropped with it. */
@media (max-width: 760px) {
  .scenarios { display: block; }
  .scn {
    display: grid; align-items: center; gap: 2px 10px;
    grid-template-columns: 12px 1fr auto;
    grid-template-areas: "sw name total" ". rates diff" ". acts acts";
    padding: 10px 0; border-bottom: 1px solid var(--rule-soft);
  }
  .scn-head { display: none; }
  .scn > * { padding: 0; border-bottom: 0; }
  .scn > .swatch { grid-area: sw; }
  .namewrap, .scn-name-ro { grid-area: name; margin-left: 0; }
  .scn-rates { grid-area: rates; text-align: left; }
  .scn-total { grid-area: total; }
  .scn-diff { grid-area: diff; }
  .scn-acts { grid-area: acts; justify-content: flex-start; margin-top: 6px; }
}

/* Sub-bar labels in a multi-series ranked chart. */
.value-label.sm { font-size: 10.5px; }

@media (max-width: 720px) {
  .scn {
    grid-template-columns: 10px 1fr auto;
    grid-template-areas: "sw name total" ". rates diff" ". acts acts";
    font-size: 12.5px;
    row-gap: 4px;
  }
  .scn-head { display: none; }
  .scn > .swatch { grid-area: sw; }
  .namewrap, .scn-name-ro { grid-area: name; }
  .scn-rates { grid-area: rates; }
  .scn-total { grid-area: total; }
  .scn-diff { grid-area: diff; }
  .scn-acts { grid-area: acts; justify-content: flex-start; margin-top: 4px; }
}

/* ---- Schema guard --------------------------------------------------------
   Shown instead of the dashboard when the database no longer provides what the
   calculations need. Deliberately plain and full width: this is not a toast to
   be dismissed, it is the page.                                              */
.blocked {
  max-width: 62ch; margin: 56px auto; padding: 26px 30px;
  background: var(--panel); border: 1px solid var(--rule);
  border-left: 3px solid var(--critical); border-radius: var(--r-lg);
  box-shadow: var(--lift-1);
}
.blocked h2 { margin: 0 0 12px; font-size: 19px; letter-spacing: -.012em; }
.blocked p { margin: 0 0 12px; color: var(--ink-2); font-size: 14px; }
.blocked-action { color: var(--ink) !important; font-weight: 500; }
.blocked-list {
  font-family: var(--mono); font-size: 12.5px; color: var(--ink);
  background: var(--panel-2); border: 1px solid var(--rule-soft);
  border-radius: var(--r-md);
  margin: 0 0 16px; padding: 12px 14px 12px 30px; list-style: square;
}
.blocked-list li { margin: 3px 0; }
.blocked-meta { font-size: 12px; color: var(--muted) !important; }

/* ==========================================================================
   Month scrub

   One strip holding every month on offer, seen through a twelve-month
   window. At rest the window is January to December of the chosen year;
   dragging past either end slides the strip into the next or previous year.
   The highlight is a pill that rides the strip, so the chosen month is the
   one thing in the gadget with weight.
   ========================================================================== */

.field-scrub { flex: 1 1 460px; max-width: 680px; min-width: 0; }
.mscrub {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; align-items: center; gap: 6px;
  border-radius: var(--r-sm); outline: none;
  touch-action: none; user-select: none; -webkit-user-select: none;
}
.mscrub:focus-visible .ms-view { outline: 2px solid var(--ink); outline-offset: 2px; }
.ms-view {
  position: relative; overflow: hidden; container-type: inline-size;
  height: 34px; border-radius: var(--r-sm); background: var(--panel-2);
  border: 1px solid var(--rule); cursor: grab;
}
.mscrub.dragging .ms-view { cursor: grabbing; border-color: var(--rule-strong); }
.ms-strip {
  position: absolute; inset: 0 auto 0 0; display: flex;
  width: calc(var(--n) / 12 * 100%);
  transform: translateX(calc(var(--off, 0) * -100% / var(--n)));
  transition: transform .28s cubic-bezier(.2, .7, .2, 1);
}
.mscrub.dragging .ms-strip { transition: none; }
.ms-thumb {
  position: absolute; top: 4px; bottom: 4px;
  left: calc(var(--i, 0) * 100% / var(--n)); width: calc(100% / var(--n));
  padding-inline: 2px; box-sizing: border-box;
  transition: left .12s ease;
}
.ms-thumb::before {
  content: ""; position: absolute; inset: 0 2px; border-radius: var(--r-xs);
  background: var(--ink); box-shadow: var(--lift-1);
}
.mscrub.dragging .ms-thumb { transition: none; }
.ms-slot {
  position: relative; flex: 1 1 0; min-width: 0;
  display: grid; place-items: center;
  font-family: var(--cond); font-size: 11.5px; font-weight: 500; color: var(--ink-3);
}
/* A hairline at each January marks where one year hands over to the next. */
.ms-slot.jan { border-left: 1px solid var(--rule-strong); }
.ms-slot.jan:first-child { border-left: 0; }
.ms-slot.on { color: var(--panel); font-weight: 600; }
.ms-y {
  position: absolute; top: 1px; left: 3px;
  font-family: var(--mono); font-size: 8.5px; line-height: 1; color: var(--muted);
}
.ms-slot.on .ms-y { color: var(--panel); opacity: .8; }
.ms-m { position: relative; }
.ms-s { display: none; }
@container (max-width: 330px) {
  .ms-s { display: inline; }
  .ms-l { display: none; }
}
.ms-step {
  font: inherit; font-size: 16px; line-height: 1; width: 26px; height: 34px; padding: 0;
  border: 1px solid var(--rule); border-radius: var(--r-sm); background: var(--panel);
  color: var(--ink-2); cursor: pointer;
}
.ms-step:hover { background: var(--panel-2); color: var(--ink); border-color: var(--rule-strong); }
.ms-step:disabled { opacity: .4; cursor: default; }
.ms-out {
  font-family: var(--mono); font-size: 12.5px; font-weight: 500; color: var(--ink);
  white-space: nowrap; font-variant-numeric: tabular-nums; min-width: 14ch; padding-left: 4px;
}
@media (max-width: 520px) {
  .mscrub { grid-template-columns: auto minmax(0, 1fr) auto; }
  .ms-out { grid-column: 1 / -1; order: -1; padding-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .ms-strip, .ms-thumb { transition: none; }
}

/* ==========================================================================
   The picker (js/picker.js)

   Every pick-one control in the app. The trigger is the value; the list
   opens under it with the current value ticked and under the cursor. Every
   row reserves the tick's slot, so choosing never shifts the column.
   ========================================================================== */

.dd {
  font: inherit; font-size: 13px; line-height: 1.2; color: var(--ink);
  display: inline-flex; align-items: center; gap: 7px; min-width: 7.5rem; max-width: 100%;
  padding: 6px 9px; border-radius: var(--r-sm); cursor: pointer; text-align: left;
  border: 1px solid var(--rule); background: var(--panel);
  transition: border-color .12s ease;
}
.dd:hover { border-color: var(--rule-strong); }
.dd:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.dd[aria-expanded="true"] { border-color: var(--ink-3); }
.dd.empty .ddval { color: var(--muted); }
.ddval { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bcaret {
  flex: none; width: 7px; height: 7px; margin: -3px 1px 0 2px;
  border-right: 1.5px solid var(--ink-3); border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(45deg); transition: transform .15s ease;
}
.dd[aria-expanded="true"] .bcaret { transform: rotate(-135deg); margin-top: 3px; }
.ddicon { flex: none; display: inline-flex; align-items: center; }
.ddmark { display: inline-block; width: 9px; height: 9px; border-radius: var(--r-pill); }
.ddmark.src-synthetic { background: var(--muted); }
.ddmark.src-real { background: var(--critical); }

.ddpanel {
  position: fixed; z-index: 50; max-width: min(24rem, calc(100vw - 16px));
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--rule); border-radius: var(--r-md); box-shadow: var(--lift-2);
  overflow: hidden; font-size: 13px;
}
.ddsearch { padding: 6px; border-bottom: 1px solid var(--rule-soft); }
.ddq { width: 100%; box-sizing: border-box; font-size: 13px; }
.ddlist { max-height: 17rem; overflow-y: auto; padding: 4px; outline: none; }
.ddopt {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
  padding: 6px 8px; border-radius: var(--r-xs); cursor: pointer;
}
.ddopt.cursor { background: var(--panel-2); }
.ddopt .tick { width: 12px; flex: none; color: var(--ink); font-weight: 600; text-align: center; }
.ddlab { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ddhint { flex: none; font-family: var(--mono); font-size: 11px; color: var(--muted); }
.ddopt[aria-selected="true"] .ddlab { font-weight: 600; }
.ddopt.off { color: var(--muted); cursor: default; }
.ddwhy { flex-basis: 100%; padding-left: 19px; font-size: 11.5px; color: var(--muted); white-space: normal; }
.ddcreate { color: var(--ink); font-weight: 500; }
.ddempty, .ddnote { padding: 8px 10px; font-size: 12px; color: var(--muted); }
.ddnote { border-top: 1px solid var(--rule-soft); }

/* ==========================================================================
   Multi-select segmented control

   Same family as the single-pick control, one signal apart: a hairline gap
   between the options, because several can be on at once and a continuous bar
   of pressed buttons reads as one selection rather than four.
   ========================================================================== */

.seg-multi { flex-wrap: wrap; gap: 0; }
.seg-multi button[aria-pressed="true"] { background: var(--ink); color: var(--panel); }
.scope-hint { font-size: 11.5px; color: var(--muted); margin-left: 10px; white-space: nowrap; }

/* ==========================================================================
   A name you type in place

   Nothing here commits to a server, so there is no Save button and no saved
   state to show. The only feedback that matters is the refusal: an empty name
   is marked in place and not written, and leaving the field restores the last
   good one. Red is used because this is the one state where the field is
   holding something it will not keep.
   ========================================================================== */

.namewrap { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
input.scn-name:hover { border-color: var(--rule); background: var(--panel-2); }
input.scn-name:focus { border-color: var(--rule-strong); background: var(--panel); outline: none; }
input.scn-name.invalid,
input.scn-name.invalid:focus {
  border-color: transparent;
  border-bottom: 2px solid var(--critical);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  background: var(--critical-bg);
  color: var(--critical);
}
.name-err { font-size: 11px; color: var(--critical); font-weight: 600; padding-left: 7px; }
.name-err[hidden] { display: none; }
/* The working row already paints itself in warning ink; a name being edited
   there must still read as text, not as part of the warning. */
.scn-working .scn-name { color: var(--warning); font-weight: 600; }

/* ==========================================================================
   FIN-5 small multiples

   One donut says where a center's money goes. Several say which center's
   money goes somewhere different - and that only works if every donut is the
   same size, so a larger arc can only ever mean a larger share. The
   magnitudes live in the caption under each one and in the table beside them.
   ========================================================================== */

.splitbody {
  display: grid; gap: 26px;
  grid-template-columns: minmax(200px, auto) minmax(0, 1fr);
  align-items: start;
}
.splitbody.wide { grid-template-columns: minmax(0, 1fr); }

.donuts { display: flex; flex-wrap: wrap; gap: 18px 22px; align-items: flex-start; }
.donutcell { display: flex; flex-direction: column; align-items: center; gap: 3px; min-width: 0; }
.donutcap {
  font-family: var(--cond); font-size: 12px; font-weight: 600; color: var(--ink-2);
  text-align: center; max-width: 17ch; line-height: 1.25;
}
.donutsub {
  font-family: var(--mono); font-size: 11.5px; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.donutcell .chart-empty { padding: 30px 8px; text-align: center; }

@media (max-width: 760px) {
  .splitbody { grid-template-columns: minmax(0, 1fr); }
  .donuts { justify-content: flex-start; }
}


/* Session chrome and the Errors tab (from development). */

.orgfield .dd { min-width: 14rem; }
.rolebadge { font: 500 0.8rem/1 var(--mono); padding: 0.3rem 0.55rem; border: 1px solid var(--rule); border-radius: var(--r-sm); }
.usermenu { display: inline-flex; gap: 0.5rem; align-items: center; }
.username { font-size: 0.85rem; opacity: 0.8; }

.deploys details { border-top: 1px solid var(--rule); padding: 0.5rem 0; }
.deploys summary { cursor: pointer; font-family: var(--mono); font-size: 0.85rem; }
.deploys details.failed summary { color: var(--critical); }
.deploys pre { white-space: pre-wrap; font-size: 0.8rem; max-height: 24rem; overflow: auto; }
