/* Critical Components board — Material (MUI v5) design system.
 *
 * MUI ships as a React runtime; this board is dependency-free vanilla JS behind a
 * `default-src 'self'` CSP, so what is adopted here is MUI's *stable design system* rather than its
 * bundle: theme.spacing (8px grid), the type ramp, Paper elevations, and the documented metrics for
 * Chip / ToggleButton / Button / OutlinedInput / Table-dense. Colours stay on the existing theme
 * tokens so legacy, black and light all keep working.
 */

:root {
  /* theme.spacing(n) === n * 8px */
  --sp-05: 4px;
  --sp-1: 8px;
  --sp-15: 12px;
  --sp-2: 16px;
  --sp-3: 24px;
  --sp-4: 32px;

  /* Grid spacing={2} gutter, Card padding, gap between CardHeader and CardContent blocks */
  --dash-gutter: var(--sp-2);
  --card-pad: var(--sp-2);
  --card-gap: var(--sp-2);

  /* shape.borderRadius = 4; Card 8; Chip is fully rounded at half its height */
  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-chip: 12px;

  /* size="small" control height (Button/ToggleButton 32, OutlinedInput 36) */
  --control-h: 32px;
  --field-h: 36px;

  /* theme.shadows[1] / [2] / [4] */
  --elev-1: 0 2px 1px -1px rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .14), 0 1px 3px 0 rgba(0, 0, 0, .12);
  --elev-2: 0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12);
  --elev-4: 0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12);

  /* action.hover / action.selected / action.focus opacities */
  --state-hover: rgba(var(--accent-rgb), .08);
  --state-selected: rgba(var(--accent-rgb), .14);

  --success-fg: var(--src-ok-fg);
  --success-bg: var(--src-ok-bg);
  --success-border: var(--src-ok-border);
  --warning-fg: var(--src-warn-fg);
  --warning-bg: var(--src-warn-bg);
  --warning-border: var(--src-warn-border);
}

/* MUI "dense"/compact: tighten the gutters, never the type ramp. */
html[data-density="compact"] {
  --dash-gutter: var(--sp-1);
  --card-pad: var(--sp-15);
  --card-gap: var(--sp-15);
  --control-h: 28px;
  --field-h: 32px;
}

/* ---------------------------------------------------------------- layout */

.dash-main {
  max-width: 1440px;
  margin: 0 auto;
  padding: var(--sp-3) var(--sp-3) 64px;
  width: 100%;
  box-sizing: border-box;
}

/* body2 */
.dash-intro {
  color: var(--muted);
  font-size: .875rem;
  line-height: 1.43;
  letter-spacing: .01071em;
  margin: 0 0 var(--sp-2);
  max-width: 90ch;
}

.dash-loading {
  padding: var(--sp-4) 0;
  text-align: center;
  font-size: .875rem;
  line-height: 1.43;
}

/* Grid container — 12 columns, one gutter everywhere. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--dash-gutter);
  align-items: stretch;
}

/* Paper elevation={1} + Card */
/* One vertical rhythm for every card body: the gap owns the spacing, children never add margins. */
.gadget {
  grid-column: span 12;
  display: flex;
  flex-direction: column;
  gap: var(--card-gap);
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  padding: var(--card-pad);
}
.gadget.col-8 { grid-column: span 8; }
.gadget.col-6 { grid-column: span 6; }
.gadget.col-4 { grid-column: span 4; }
.gadget.flat {
  background: transparent;
  border: 0;
  box-shadow: none;
  padding: 0;
  border-radius: 0;
}
/* Three columns to one. `col-4` goes the whole way rather than to a half: once `col-8` has taken the
   full width there is nothing left to sit beside it, and a band heading cannot fill the other half, so
   `span 6` here left a hole exactly the size of the card. */
@media (max-width: 1100px) {
  .gadget.col-8 { grid-column: span 12; }
  .gadget.col-6 { grid-column: span 12; }
  .gadget.col-4 { grid-column: span 12; }
}
@media (max-width: 760px) {
  .dash-main { padding: var(--sp-2) var(--sp-2) 56px; }
  /* The action slot drops under the title instead of squeezing it to two words per line. */
  .gadget-head { flex-wrap: wrap; }
  .gadget-actions { width: 100%; justify-content: flex-start; }
}

/* Section heading — full-width row inside the same 12-column grid.
   A band is not a container: making it one would have meant a grid per band and re-deriving every
   column span and breakpoint below, to gain a line of text. */
.dash-band {
  grid-column: span 12;
  margin: var(--sp-2) 0 0;
}
.dash-grid > .dash-band:first-child { margin-top: 0; }
/* h6 */
.dash-band h2 {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: .0075em;
  color: var(--text);
}
/* caption */
.dash-band p {
  margin: var(--sp-05) 0 0;
  font-size: .75rem;
  line-height: 1.66;
  letter-spacing: .03333em;
  color: var(--muted);
}

/* CardHeader: title (overline) + subheader (caption) */
.gadget-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-15);
  margin: 0;
}

/* CardHeader action slot. Sits on the baseline of the title, wraps under it when the card is narrow
   rather than squeezing the heading into two words. */
.gadget-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-05);
  flex-wrap: wrap;
  justify-content: flex-end;
  flex-shrink: 0;
}
.gadget-actions .ghost {
  min-height: var(--control-h);
  padding: 0 var(--sp-1);
  font-size: .75rem;
  white-space: nowrap;
}

/* A quiet reload returns no skeleton, so without this the button looks inert on an unchanged board. */
.gadget.is-reloading {
  animation: card-refreshed 600ms cubic-bezier(.4, 0, .2, 1);
}
@keyframes card-refreshed {
  0% { border-color: var(--accent); }
  100% { border-color: var(--border); }
}
@media (prefers-reduced-motion: reduce) {
  .gadget.is-reloading { animation: none; }
}
.gadget-head h2 {
  margin: 0;
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .08333em;
  text-transform: uppercase;
  color: var(--muted-strong);
}
.gadget-head .sub {
  margin-top: var(--sp-05);
  color: var(--muted);
  font-size: .75rem;
  font-weight: 400;
  line-height: 1.66;
  letter-spacing: .03333em;
  text-transform: none;
}

/* ---------------------------------------------------------------- toolbar */

/* AppBar-style sticky Toolbar (dense) */
.filterbar {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-2);
  padding: var(--sp-15) 0;
  background: var(--bg);
  border-bottom: 1px solid var(--border);
}

/* ToggleButtonGroup size="small" */
.filterbar .seg {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--panel);
}
.filterbar .seg button {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--muted);
  font: inherit;
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.75;
  letter-spacing: .02857em;
  text-transform: uppercase;
  padding: 0 var(--sp-15);
  height: var(--control-h);
  cursor: pointer;
  white-space: nowrap;
}
.filterbar .seg button + button { border-left: 1px solid var(--border); }
.filterbar .seg button:hover { background: var(--state-hover); color: var(--text); }
.filterbar .seg button.on {
  background: var(--state-selected);
  color: var(--text);
}
.filterbar .seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

/* FormControlLabel + Checkbox, size="small" */
.filterbar .toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: var(--control-h);
  padding: 0 var(--sp-15);
  font-size: .8125rem;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
}
.filterbar .toggle:hover { background: var(--state-hover); color: var(--text); }
.filterbar .toggle input { margin: 0; }

/* OutlinedInput size="small" */
.filterbar input[type="search"] {
  height: var(--field-h);
  box-sizing: border-box;
  min-width: 180px;
  flex: 1 1 180px;
  padding: 0 var(--sp-15);
  font-size: .875rem;
  color: var(--text);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.filterbar input[type="search"]::placeholder { color: var(--muted-strong); }
.filterbar input[type="search"]:hover { border-color: var(--muted-strong); }
.filterbar input[type="search"]:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}

/* Button size="small", variant="outlined" */
.filterbar .ghost,
.dash-main .ghost {
  height: var(--control-h);
  padding: 0 var(--sp-15);
  border-radius: var(--radius-sm);
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .02857em;
  text-transform: uppercase;
  white-space: nowrap;
}

.filterbar .fb-spacer { flex: 1 1 var(--sp-2); }

/* caption, tabular */
/* Stays right-aligned whether or not the toolbar wraps. */
.filterbar .live-clock {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  height: var(--control-h);
  font-size: .75rem;
  letter-spacing: .03333em;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.filterbar .live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--success-fg);
  animation: livepulse 2s ease infinite;
}
.filterbar.paused .live-dot { background: var(--warning-fg); animation: none; }
@keyframes livepulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .4); }
  70% { box-shadow: 0 0 0 7px rgba(var(--accent-rgb), 0); }
  100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0); }
}
@media (prefers-reduced-motion: reduce) {
  .filterbar .live-dot, .stat.just-updated, .sk { animation: none !important; }
}

/* ---------------------------------------------------------------- KPI strip */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: var(--dash-gutter);
}
.stat {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-05);
  min-height: 84px;
  padding: var(--sp-15) var(--sp-2);
  text-decoration: none;
  color: inherit;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  transition: box-shadow 150ms cubic-bezier(.4, 0, .2, 1), border-color 150ms;
}
.stat:hover, .stat:focus-visible {
  border-color: var(--accent);
  box-shadow: var(--elev-4);
}
/* h5 */
.stat .stat-value {
  font-size: 1.5rem;
  font-weight: 500;
  line-height: 1.334;
  font-variant-numeric: tabular-nums;
}
/* caption */
.stat .stat-label {
  font-size: .75rem;
  line-height: 1.66;
  letter-spacing: .03333em;
  color: var(--muted);
}
.stat.warn .stat-value { color: var(--danger-fg); }
.stat.caution .stat-value { color: var(--warning-fg); }
.stat.ok .stat-value { color: var(--success-fg); }
.stat.just-updated { animation: pulse .9s ease; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), .35); }
  100% { box-shadow: 0 0 0 7px rgba(var(--accent-rgb), 0); }
}

/* ---------------------------------------------------------------- Chip */

/* Chip size="small", variant="outlined" */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-05);
  height: 24px;
  box-sizing: border-box;
  padding: 0 var(--sp-1);
  border-radius: var(--radius-chip);
  border: 1px solid var(--border);
  background: var(--chip);
  color: var(--muted);
  font-size: .75rem;
  line-height: 1;
  letter-spacing: .01em;
  white-space: nowrap;
  max-width: 100%;
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.chip.success { color: var(--success-fg); border-color: var(--success-border); background: var(--success-bg); }
.chip.warning { color: var(--warning-fg); border-color: var(--warning-border); background: var(--warning-bg); }
.chip.danger { color: var(--danger-fg); border-color: var(--danger-border); background: var(--danger-bg); font-weight: 500; }
.chip.neutral { color: var(--muted); }
.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-1);
  align-items: center;
  margin: 0;
}

/* ---------------------------------------------------------------- index rail */

/* List / ListItem (dense): status dot, primary+secondary text, trailing metadata.
   Every column is explicit, so the state chip can never overlap the title. */
.fresh-rail {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.fresh-row {
  display: grid;
  grid-template-columns: 10px minmax(0, 1.4fr) minmax(0, 1fr) auto auto 64px;
  column-gap: var(--sp-15);
  align-items: center;
  min-height: 56px;
  padding: var(--sp-1) var(--sp-15);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--soft-surface);
  text-decoration: none;
  color: inherit;
  transition: background 150ms cubic-bezier(.4, 0, .2, 1), border-color 150ms;
}
.fresh-row:hover, .fresh-row:focus-within {
  border-color: var(--accent);
  background: var(--state-hover);
}
.fresh-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted-strong);
}
.fresh-dot.fresh { background: var(--success-fg); }
.fresh-dot.stale { background: var(--warning-fg); }
.fresh-dot.missing { background: var(--danger-fg); }
.fresh-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  text-decoration: none;
  color: inherit;
}
.fresh-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-05);
  flex-wrap: wrap;
  justify-content: flex-end;
}
.sync-btn {
  min-height: var(--control-h);
  padding: 0 var(--sp-1);
  font-size: .75rem;
}
.sync-status {
  font-size: .7rem;
  color: var(--muted);
  max-width: 9rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sync-status.ok { color: var(--success-fg); }
.sync-status.err { color: var(--danger-fg); }
.sync-status.syncing { color: var(--accent); }
.sync-note {
  font-size: .7rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* subtitle2 */
.fresh-row .name {
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.57;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* caption, text.secondary */
.fresh-row .meta,
.fresh-row .fresh-meta {
  font-size: .75rem;
  line-height: 1.5;
  letter-spacing: .03333em;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.fresh-row .fresh-meta { font-variant-numeric: tabular-nums; }
/* Why a target is not going to run, on its own line under the row. Allowed to wrap — an ellipsised
   "DefaultAzureCredential failed to retrieve a token" reads as noise rather than a cause. */
.fresh-row .fresh-why {
  grid-column: 2 / -1;
  margin-top: 2px;
  font-size: .75rem;
  line-height: 1.5;
  letter-spacing: .03333em;
  color: var(--muted);
  white-space: normal;
  overflow-wrap: anywhere;
}
.fresh-row[data-blocked="1"] {
  border-color: var(--danger-border);
  background: var(--danger-bg);
}
.fresh-row[data-blocked="1"] .fresh-why { color: var(--danger-fg); }
/* The freshness bar measures "how current"; for a target that has never run there is nothing to
   measure, and a bar sitting at 28% implies progress that does not exist. */
.fresh-row[data-blocked="1"] .fresh-bar { visibility: hidden; }
/* LinearProgress determinate */
.fresh-bar {
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}
.fresh-bar > i { display: block; height: 100%; background: var(--success-fg); }
.fresh-bar.stale > i { background: var(--warning-fg); }
.fresh-bar.missing > i { background: var(--danger-fg); }
@media (max-width: 900px) {
  .fresh-row {
    grid-template-columns: 10px minmax(0, 1fr) auto;
    row-gap: var(--sp-05);
  }
  /* Wraps rather than ellipsises once it owns a full row: on a phone "next in 27 min" fell off the end
     of "chunks 6532 · documents 4136 · 3 min ago", so the one forward-looking fact was the one lost.
     `.meta` above it stays clipped — that is prose, and prose belongs in the tooltip. */
  .fresh-row .fresh-meta {
    grid-column: 2 / -1;
    white-space: normal;
    overflow: visible;
  }
  .fresh-row .fresh-bar { grid-column: 2 / -1; }
}

/* ---------------------------------------------------------------- charts */

.chart-wrap { position: relative; height: 224px; }
.chart-wrap.tall { height: 264px; }
/* Keep the doughnut from ballooning in a wide card. */
.chart-wrap.dial { height: 200px; max-width: 220px; margin: 0 auto; }
.chart-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  text-align: center;
}
/* h5 + caption */
.chart-center .big { font-size: 1.5rem; font-weight: 500; line-height: 1.334; font-variant-numeric: tabular-nums; }
.chart-center .tiny { font-size: .75rem; line-height: 1.66; color: var(--muted); margin-top: 2px; }
.chart-note {
  margin: 0;
  font-size: .75rem;
  line-height: 1.66;
  letter-spacing: .03333em;
  color: var(--muted);
}

/* ---------------------------------------------------------------- assets */

.tier-lane { margin: 0; }
.tier-lane-head {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0 0 var(--sp-15);
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .08333em;
  text-transform: uppercase;
  color: var(--muted-strong);
}
.tier-lane-head .count {
  height: 20px;
  display: inline-flex;
  align-items: center;
  padding: 0 var(--sp-1);
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--chip);
  color: var(--muted);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  font-variant-numeric: tabular-nums;
}

/* Equal-height Cards in a responsive Grid. */
.asset-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--dash-gutter);
  align-items: stretch;
}
.asset-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  height: 100%;
  box-sizing: border-box;
  padding: var(--sp-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  background: var(--panel);
  box-shadow: var(--elev-1);
}
.asset-card.is-hidden { display: none !important; }
.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-1);
}
/* subtitle1 */
.asset-card h3 {
  margin: 0;
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: .00938em;
}
/* body2 */
.asset-card .card-sub {
  margin: 0;
  color: var(--muted);
  font-size: .875rem;
  line-height: 1.43;
  letter-spacing: .01071em;
}
.field {
  margin: 0;
  font-size: .8125rem;
  line-height: 1.54;
}
.field .f-label { color: var(--muted); }
.bind-list { display: flex; flex-wrap: wrap; gap: var(--sp-1); margin: 0; }
/* Chip clickable, size="small" */
.bind {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-05);
  height: 24px;
  box-sizing: border-box;
  padding: 0 var(--sp-1);
  font-size: .75rem;
  text-decoration: none;
  color: var(--text);
  border: 1px solid var(--border);
  background: var(--chip);
  border-radius: var(--radius-chip);
  max-width: 100%;
}
.bind:hover, .bind:focus-visible { border-color: var(--accent); background: var(--state-hover); }
.bind.unresolved { color: var(--danger-fg); border-color: var(--danger-border); background: var(--danger-bg); }
.bind .bind-count { color: var(--muted); font-variant-numeric: tabular-nums; }
.bind > .mono { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Alert severity="warning" */
.impact-note {
  margin: 0;
  padding: var(--sp-1) var(--sp-15);
  border-left: 4px solid var(--warning-border);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  background: var(--warning-bg);
  color: var(--warning-fg);
  font-size: .8125rem;
  line-height: 1.54;
}

details.radius { margin: 0; }
details.radius > summary {
  cursor: pointer;
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.75;
  color: var(--link-fg);
}
details.radius[open] > summary { margin-bottom: var(--sp-1); }
.radius-body { font-size: .8125rem; line-height: 1.54; }

/* Push per-card disclosures to the bottom so cards in a row line up. */
.asset-card > details.radius:last-child { margin-top: auto; }

/* ---------------------------------------------------------------- tables */

/* Table size="small" */
table.tbl {
  width: 100%;
  border-collapse: collapse;
  font-size: .8125rem;
}
table.tbl th,
table.tbl td {
  text-align: left;
  padding: var(--sp-1) var(--sp-2);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
  line-height: 1.54;
}
table.tbl th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--th-bg);
  color: var(--muted);
  font-size: .8125rem;
  font-weight: 500;
  line-height: 1.5;
  white-space: nowrap;
}
table.tbl tbody tr:last-child td { border-bottom: none; }
table.tbl tbody tr:hover td { background: var(--state-hover); }
table.tbl td.num, table.tbl th.num { text-align: right; font-variant-numeric: tabular-nums; }
.tbl-scroll {
  max-height: 380px;
  overflow: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
code, .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
td code {
  background: var(--code-bg);
  padding: 1px var(--sp-05);
  border-radius: var(--radius-sm);
  font-size: .75rem;
  word-break: break-all;
}

/* Button size="small", variant="text" */
.ask {
  display: inline-flex;
  align-items: center;
  height: 24px;
  box-sizing: border-box;
  padding: 0 var(--sp-1);
  font-size: .75rem;
  font-weight: 500;
  letter-spacing: .02857em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--link-fg);
  border: 1px solid var(--border);
  background: var(--panel);
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
.ask:hover, .ask:focus-visible { border-color: var(--accent); background: var(--state-hover); }
.ask.row-cta { opacity: .6; }
tr:hover .ask.row-cta, tr:focus-within .ask.row-cta { opacity: 1; }

/* ---------------------------------------------------------------- feedback */

/* Alert severity="error" */
.err-banner {
  margin-bottom: var(--sp-2);
  padding: var(--sp-15) var(--sp-2);
  background: var(--danger-bg);
  color: var(--danger-fg);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-sm);
  font-size: .875rem;
  line-height: 1.43;
}
/* Last-good / soft refresh failure (SWR) */
.warn-banner {
  margin-bottom: var(--sp-2);
  padding: var(--sp-15) var(--sp-2);
  background: var(--warning-bg);
  color: var(--warning-fg);
  border: 1px solid var(--warning-border);
  border-radius: var(--radius-sm);
  font-size: .875rem;
  line-height: 1.43;
}
.refresh-cue {
  color: var(--muted-strong);
  font-weight: 500;
}
.fresh-text .caveat {
  color: var(--warning-fg);
}
.trunc-caption {
  margin-top: var(--sp-1);
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  flex-wrap: wrap;
}
/* The cross-source map is a mounted component, not markup this sheet owns. It renders its own
   `.pa-react-flow-card` containing a header, a legend, a 470px canvas and a detail panel — roughly
   630px all told, and it measures itself to fit the view.

   The board used to put `.pa-react-flow-card` on the *mount point* as well and clamp it to a 280px
   host inside a 320px `overflow:hidden` card. So the component laid itself out for 630px, React Flow
   fitted eleven nodes to a 470px canvas, and the board then showed the top 320px of it: ten of the
   eleven nodes sat below the clip and the widget read as empty. Bound the canvas the component
   actually measures, and let its chrome lay out at its natural size. */
#crossFlowHost {
  margin-bottom: var(--sp-2);
  min-width: 0;
}
#crossFlowHost .pa-react-flow-card {
  margin: 0;
  border-radius: var(--radius-md);
}
#crossFlowHost .pa-react-flow-canvas {
  height: 300px;
}
/* A minimap is a navigation aid for a canvas too large to see at once. At preview size it covered
   roughly a third of the map it exists to help with, so it belongs to the expanded view only. */
#crossFlowHost .pa-react-flow-card:not(.is-expanded) .react-flow__minimap {
  display: none;
}
.empty {
  padding: var(--sp-3) var(--sp-2);
  border: 1px dashed var(--border);
  border-radius: var(--radius-md);
  color: var(--muted);
  font-size: .875rem;
  line-height: 1.43;
  text-align: center;
}
.muted { color: var(--muted); }
.nowrap { white-space: nowrap; }
.is-hidden { display: none !important; }
.dash-loading {
  padding: var(--sp-4) 0;
  text-align: center;
  font-size: .875rem;
  line-height: 1.43;
}

/* Skeleton */
.sk {
  background: linear-gradient(90deg, var(--panel) 25%, var(--hover-surface) 37%, var(--panel) 63%);
  background-size: 400% 100%;
  animation: sk 1.4s ease infinite;
  border-radius: var(--radius-sm);
}
.sk.line { height: 12px; margin: var(--sp-1) 0; }
.sk.title { height: 14px; width: 42%; }
.sk.tile { height: 84px; border-radius: var(--radius-md); }
.sk.block { height: 200px; border-radius: var(--radius-md); }
@keyframes sk {
  0% { background-position: 100% 0; }
  100% { background-position: 0 0; }
}

:where(a, button, summary, input, select):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
