@import url("https://fonts.googleapis.com/css?family=Montserrat:300,400,500,600");
@import url("https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap");

* { margin: 0; padding: 0; box-sizing: border-box; }

:root {
  --bg-primary: #f4f4f4;
  --bg-secondary: #fff;
  --bg-card: #fff;
  --border: rgba(33, 33, 33, 0.14);
  --text-primary: #212121;
  --text-secondary: #757575;
  --accent: #19AD79;
  --accent-hover: #14956a;
  --green: #19AD79;
  --yellow: #f5a623;
  --red: #D83C31;
  --blue: #0072EC;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  background: var(--bg-primary);
  color: var(--text-primary);
  height: 100vh;
  overflow: hidden;
}

#app { display: flex; flex-direction: column; height: 100vh; overflow: hidden; }

header {
  padding: 10px 20px;
  background: #2b303b;
  border-bottom: none;
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
  position: relative;
  z-index: 30;
  color: #929aac;
}

.header-logo { height: 28px; }
header h1 {
  font-size: 16px; font-weight: 500; white-space: nowrap; color: #929aac;
}
.header-center {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  text-align: center;
  pointer-events: none;
}

.controls {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
  flex: 1;
}

.header-metric-search {
  margin-left: auto;
  background: #21252e;
  border: 1px solid rgba(146,154,172,0.3);
  border-radius: 4px;
  color: #e7ebf2;
  font-size: 13px;
  padding: 6px 10px;
  width: 200px;
  outline: none;
  transition: border-color 0.15s, width 0.15s;
}
.header-metric-search::placeholder { color: #6f7889; }
.header-metric-search:focus { border-color: var(--accent); width: 240px; }

select, input[type="text"], button {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-primary);
  font-size: 13px;
  font-family: inherit;
}

button {
  cursor: pointer;
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
  font-weight: 600;
}
button:disabled { opacity: 0.4; cursor: default; }
button:hover:not(:disabled) { background: var(--accent-hover); }

input[type="text"] { width: 200px; }
input[type="text"]:focus, select:focus { outline: none; border-color: var(--accent); }

.layout { display: flex; flex: 1; overflow: hidden; border-top: 1px solid #2b303b; }

#tenant-list {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--bg-secondary);
}
.tenant-list-inner { padding: 8px; overflow-y: auto; flex: 1; }

.tenant-item {
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.tenant-item:hover { background: #f4f4f4; }
.tenant-item.active { background: rgba(25,173,121,0.08); border: 1px solid var(--accent); }
.tenant-item .name { font-weight: 500; }
.tenant-item .tenant-info { flex: 1; min-width: 0; }
/* Pinned "All Clients (Region)" aggregate row — bold, separated from real tenants. */
.tenant-item.tenant-aggregate {
  border-bottom: 1px solid var(--border, #e0e0e0);
  border-radius: 6px 6px 0 0;
  margin-bottom: 4px;
}
.tenant-item.tenant-aggregate .name { font-weight: 700; }
.tenant-item .badge {
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 10px;
  text-transform: uppercase;
  font-weight: 600;
}
.badge-standard { background: var(--green); color: #fff; }
.badge-test { background: var(--yellow); color: #fff; }
.badge-internal { background: var(--blue); color: #fff; }
.badge-region { background: #6c7a8d; color: #fff; }
.badge-bundle { background: #b06a2c; color: #fff; }

/* ─── Bundle-only rows (Show whole bundle diagnostic) ─── */
/* db keys in the comparison bundle but not the live tenant list: ex-tenants +
   test/internal dbs. Greyed and italic so they read as "not live". */
.tenant-item.tenant-bundle-only { opacity: 0.6; }
.tenant-item.tenant-bundle-only .name { font-style: italic; font-weight: 400; }
.tenant-item.tenant-bundle-only:hover { opacity: 0.85; }

/* ─── Ex-client greying, used across every tab (heatmap rows, Compare rows,
   Usage Health table rows / spider tiles / risk-quadrant dots + list, and the
   Client tab header). The "(ex)" name suffix itself is added by clientLabel().
   Greyed + italic so an ex-client reads as "not live" wherever it appears. */
.hm-row.ex-client,
.compare-row.ex-client,
.uh-row.ex-client,
.rq-list-item.ex-client { opacity: 0.6; font-style: italic; }
.hm-row.ex-client:hover,
.compare-row.ex-client:hover,
.uh-row.ex-client:hover,
.rq-list-item.ex-client:hover { opacity: 0.85; }
.sw-card.ex-client { opacity: 0.62; }
.sw-card.ex-client:hover { opacity: 0.9; }
.rq-pt.ex-client { opacity: 0.5; }
.tenant-header.ex-client .tenant-title-row h2 { opacity: 0.7; font-style: italic; }

/* ─── Favourite star ─── */
.fav-star {
  flex-shrink: 0;
  width: 18px;
  font-size: 14px;
  line-height: 1;
  color: #d0d0d0;
  cursor: pointer;
  transition: color 0.15s;
  margin-right: 4px;
}
.fav-star:hover { color: #f0c040; }
.fav-star.fav { color: #e6a817; }

.hide-client {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  border: 0;
  padding: 2px;
  margin-right: 4px;
  background: transparent;
  color: #9ca3af;
  cursor: pointer;
}
.hide-client svg { display: block; width: 100%; height: 100%; fill: none; stroke: currentColor; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.8; }
.hide-client:hover { color: #4b5563; }
.hide-client.hidden { color: #b45309; }

/* ─── Filter grid ───
   The three checkbox filters share compact first-row cells with their labels.
   Each customer-status label is paired with its dropdown immediately to the
   right, preventing either control from obscuring its label. */
.filter-grid {
  --filter-checkbox-size: 13px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  grid-template-rows: repeat(3, minmax(20px, auto));
  align-items: center;
  gap: 4px 8px;
  padding: 4px 2px 2px;
  font-size: 10px;
  color: #555;
}
.filter-grid .fg-corner,
.filter-grid .fg-rowlabel { display: none; }
.filter-grid .fg-col {
  align-self: center;
  justify-self: stretch;
  min-width: 0;
  padding-right: 18px;
  color: #6b7280;
  line-height: 1.1;
  text-align: right;
  white-space: normal;
  cursor: default;
}
.filter-grid .fg-col:nth-of-type(2),
.filter-grid .fg-cell:nth-of-type(1) { grid-area: 1 / 1; }
.filter-grid .fg-col:nth-of-type(3),
.filter-grid .fg-cell:nth-of-type(2) { grid-area: 1 / 2; }
.filter-grid .fg-col:nth-of-type(4),
.filter-grid .fg-cell:nth-of-type(3) { grid-area: 1 / 3; }
.filter-grid .fg-col:nth-of-type(5) { grid-area: 2 / 1; }
.filter-grid .fg-col:nth-of-type(6) { grid-area: 3 / 1; }
#usage-health-sidebar .filter-grid {
  grid-template-rows: repeat(5, minmax(20px, auto));
}
#usage-health-sidebar .filter-grid .fg-col:nth-of-type(7) { grid-area: 4 / 1; }
#usage-health-sidebar .filter-grid .fg-col:nth-of-type(8) { grid-area: 5 / 1; }
.filter-grid .fg-star { color: #bbb; font-size: 11px; }
.filter-grid .fg-cell {
  display: flex;
  align-items: center;
  justify-self: end;
  margin: 0;
  cursor: pointer;
}
.filter-grid .fg-cell input[type="checkbox"] {
  width: var(--filter-checkbox-size);
  height: var(--filter-checkbox-size);
  margin: 0;
  cursor: pointer;
  accent-color: var(--accent);
}
.filter-grid .customer-filter-mode {
  align-self: center;
  justify-self: start;
  width: 68px;
  min-width: 0;
  margin-left: calc(50% - 17px);
  padding: 1px 2px;
  font-size: 10px;
  cursor: pointer;
}
.filter-grid .customer-filter-mode:nth-of-type(1) { grid-area: 2 / 1 / 3 / 3; }
.filter-grid .customer-filter-mode:nth-of-type(2) { grid-area: 3 / 1 / 4 / 3; }
#usage-health-sidebar .filter-grid .customer-filter-mode:nth-of-type(3) { grid-area: 4 / 1 / 5 / 3; }
#usage-health-sidebar .filter-grid .customer-filter-mode:nth-of-type(4) { grid-area: 5 / 1 / 6 / 3; }

#metrics-panel { flex: 1; overflow-y: auto; padding: 20px; }

.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--text-secondary);
  font-size: 16px;
}
.loading { text-align: center; padding: 40px; color: var(--text-secondary); }
.loading-indicator { display: flex; align-items: center; justify-content: center; gap: 10px; height: 100%; }
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  border: 2px solid var(--text-secondary);
  border-top-color: transparent;
  border-radius: 50%;
  animation: spinner-rotate 0.7s linear infinite;
}
@keyframes spinner-rotate { to { transform: rotate(360deg); } }

/* Usage Health load progress. The spinner animates `transform`, so it is
   compositor-driven and keeps turning through the synchronous scoring blocks
   that dominate a cold load — which is why the step list below carries the
   information and the spinner carries only "still working". */
.uh-load { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; height: 100%; }
.uh-load-headline { display: flex; align-items: center; gap: 10px; }
.uh-load-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; min-width: 260px; }
.uh-load-step { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; opacity: 0.5; }
.uh-load-step-done { opacity: 1; }
.uh-load-tick { display: inline-block; width: 1em; text-align: center; }
.uh-load-step-done .uh-load-tick { color: var(--accent-green, #3fa66a); }
.uh-load-count { font-size: 0.78rem; opacity: 0.7; }

.metrics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.metric-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
  position: relative;
  transition: box-shadow 0.15s;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.metric-card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.1); border-color: var(--accent); }
.metric-card .label { font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; }
.metric-card .value { font-size: 26px; font-weight: 700; margin-top: 4px; }
.metric-card .sub { font-size: 11px; color: var(--text-secondary); margin-top: 4px; }
.metric-card .tile-qualifier { font-size: 10px; color: var(--text-secondary); opacity: 0.75; margin-top: 3px; font-style: italic; cursor: help; }

.spark-container { margin-top: 6px; line-height: 0; }
.sparkline { display: block; width: 100%; height: 28px; overflow: visible; }
.spark-wrap { position: relative; display: block; width: 100%; }
.spark-max { font-size: 8px; color: #94a3b8; font-family: system-ui, sans-serif; pointer-events: none; position: absolute; top: 0; right: 1px; line-height: 1; }
.spark-dot-vis { opacity: 0; transition: opacity 0.15s; }
.spark-dot:hover .spark-dot-vis { opacity: 1; }
.spark-hit { cursor: pointer; }
.spark-scale {
  position: relative;
  height: 12px;
  line-height: 12px;
  font-size: 8px;
  color: var(--text-secondary);
  opacity: 0.5;
}
.spark-scale span {
  position: absolute;
  transform: translateX(-50%);
}

.nps-positive { color: var(--green); }
.nps-negative { color: var(--red); }
.nps-neutral { color: var(--yellow); }

.section-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  cursor: default;
  user-select: none;
}

.trend-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  margin-bottom: 20px;
}
.trend-table th {
  text-align: left;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  font-weight: 700;
}
.trend-table td {
  padding: 6px 12px;
  border-bottom: 1px solid rgba(30,48,80,0.5);
}
/* In-row volume trend sparkline for Delivery Vector rows */
.trend-table .spark-cell { width: 55%; min-width: 80px; padding-top: 2px; padding-bottom: 2px; line-height: 0; }
.trend-table .spark-cell .sparkline { width: 100%; height: 22px; vertical-align: middle; }
/* Shrink the Vector label column so the sparkline gets most of the width */
.trend-table th:nth-child(1),
.trend-table td:nth-child(1) { width: 120px; white-space: nowrap; }
/* Pin numeric columns so sparkline cell gets the remaining space */
.trend-table th:nth-child(2),
.trend-table td:nth-child(2),
.trend-table th:nth-child(3),
.trend-table td:nth-child(3),
.trend-table th:nth-child(4),
.trend-table td:nth-child(4) { width: 90px; white-space: nowrap; }
/* API table: resource column (col 2) should stay wide, not pinned */
.api-table th:nth-child(2),
.api-table td:nth-child(2) { width: auto; white-space: normal; }
/* All-Time fallback: skipAllTime sections (Delivery Vectors, Touchpoints) showing
   the previous-365d breakdown. Grey the table slightly to signal it isn't the
   all-time figure. */
.fallback-365d .trend-table { opacity: 0.6; }
/* Same fallback in the Comparison heatmap: grey the whole heatmap table. */
.fallback-365d .heatmap-table { opacity: 0.6; }
.fallback-365d-note { margin-bottom: 6px; }

/* All-time-only tables (e.g. Repeat Responders): the figures are always all-time.
   When a time filter is active, grey the table to signal it isn't affected by it. */
.all-time-only-greyed .trend-table { opacity: 0.5; }

.trend-total td {
  font-weight: 600;
  border-top: 2px solid var(--border);
  padding-top: 8px;
}

/* APIs table (query 54): expand toggle + status colouring */
.api-row-extra { display: none; }
.api-expand-toggle:checked ~ .section-collapse .api-table .api-row-extra { display: table-row; }
.api-resource { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }
.api-status-ok { color: var(--green); }
.api-status-warn { color: var(--yellow); }
.api-status-err { color: var(--red); }
.api-expand-label {
  display: inline-block;
  font-size: 11px;
  color: var(--accent, #3b82f6);
  cursor: pointer;
  user-select: none;
  margin: -12px 0 12px;
  white-space: nowrap;
}
.api-expand-label::before { content: 'Show all (+' attr(data-more) ' more) ▾'; }
.api-expand-toggle:checked ~ .section-collapse .api-expand-label::before { content: 'Show top 10 ▴'; }
.api-expand-label:hover { text-decoration: underline; }

/* Countries table (query 61): expand toggle */
.country-row-extra { display: none; }
.country-expand-toggle:checked ~ .section-collapse .country-table .country-row-extra { display: table-row; }
.country-expand-label {
  display: inline-block;
  font-size: 11px;
  color: var(--accent, #3b82f6);
  cursor: pointer;
  user-select: none;
  margin: -12px 0 12px;
  white-space: nowrap;
}
.country-expand-label::before { content: 'Show all (+' attr(data-more) ' more) ▾'; }
.country-expand-toggle:checked ~ .section-collapse .country-expand-label::before { content: 'Show top 15 ▴'; }
.country-expand-label:hover { text-decoration: underline; }

/* Countries table: shrink the first (country) column so the Trend sparkline
   takes up most of the width. Overrides the generic .trend-table column sizing. */
.country-table th:nth-child(1),
.country-table td:nth-child(1) { width: 330px; max-width: 330px; white-space: normal; }
.country-table th:nth-child(2),
.country-table td:nth-child(2) { width: 70px; white-space: nowrap; }
.country-table th:nth-child(3),
.country-table td:nth-child(3),
.country-table .spark-cell { width: auto; }

/* Countries table: ISO-2 rollup + expandable raw-string breakdown */
.country-table .country-code { font-weight: 600; font-variant: tabular-nums; }
.country-table .country-name { color: var(--text-secondary, #6b7280); }
.country-table .country-null { font-style: italic; color: var(--text-secondary, #9ca3af); }
.country-table .country-unknown { font-style: italic; color: var(--text-secondary, #b45309); }
.country-variants { display: inline; }
.country-variants > summary {
  cursor: pointer;
  list-style: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.country-variants > summary::-webkit-details-marker { display: none; }
.country-variants > summary::before {
  content: '▸';
  font-size: 10px;
  color: var(--text-secondary, #9ca3af);
  transition: transform 0.12s ease;
}
.country-variants[open] > summary::before { transform: rotate(90deg); }
.cv-count {
  font-size: 10px;
  color: var(--text-secondary, #6b7280);
  background: var(--bg-hover, #f3f4f6);
  border-radius: 8px;
  padding: 0 6px;
  line-height: 16px;
}
.country-variant-list {
  list-style: none;
  margin: 6px 0 4px 16px;
  padding: 0;
  border-left: 2px solid var(--border, #e5e7eb);
}
.country-variant-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-size: 12px;
  padding: 2px 8px;
}
.country-variant-list .cv-raw { color: var(--text-primary, #374151); font-family: var(--mono, monospace); }
.country-variant-list .cv-val { color: var(--text-secondary, #6b7280); white-space: nowrap; font-variant: tabular-nums; }
.country-variant-list .cv-share { color: var(--text-tertiary, #9ca3af); }


.bar-container {
  background: var(--bg-card);
  border-radius: 4px;
  height: 20px;
  display: flex;
  overflow: hidden;
}
.bar-segment { height: 100%; transition: width 0.3s; }
.bar-promoters { background: var(--green); }
.bar-passives { background: var(--yellow); }
.bar-detractors { background: var(--red); }

.pipeline-legend {
  display: flex;
  gap: 16px;
  margin-top: 8px;
  font-size: 12px;
}

.tenant-header {
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 12px;
}
.tenant-header h2 { font-size: 20px; font-weight: 600; }
.tenant-header .db-name { color: var(--text-secondary); font-size: 13px; }

.error-msg {
  background: rgba(231,76,94,0.1);
  border: 1px solid var(--red);
  border-radius: 8px;
  padding: 12px 16px;
  color: var(--red);
}

.cache-info {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
}
.cache-date { font-size: 12px; color: var(--text-secondary); }

.tenant-header-left {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.tenant-title-row {
  display: flex;
  align-items: center;
  gap: 12px;
}
.arr-bin-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 10px;
  background: var(--bg-tertiary, #eef1f4);
  border: 1px solid var(--border-color, #d5dae0);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

.collapse-all-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  font-size: 15px;
  line-height: 1;
  background: #fff;
  border: 1px solid var(--border);
  color: var(--text-secondary);
  border-radius: 6px;
  cursor: pointer;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent); }

.section-cache-date {
  font-size: 11px;
  color: var(--text-secondary);
  font-weight: 400;
  margin-left: 8px;
}

.section-help-text {
  font-size: 10px;
  color: var(--text-secondary);
  font-weight: 500;
  margin-left: 8px;
  background: rgba(128, 128, 128, 0.12);
  padding: 1px 5px;
  border-radius: 3px;
  cursor: help;
}

.section-help-block {
  padding: 4px 12px 2px;
}
.section-help-block .section-help-text {
  margin-left: 0;
}

.heatmap-header {
  display: flex;
  justify-content: flex-end;
  padding: 8px 12px 4px;
}

.refresh-btn {
  padding: 4px 10px;
  font-size: 12px;
  background: #fff;
  border: 1px solid var(--border);
  color: var(--text-primary);
  border-radius: 6px;
  cursor: pointer;
}
.refresh-btn:hover { border-color: var(--accent); color: var(--accent); }
.refresh-light { border-color: #4caf50; color: #388e3c; }
.refresh-light:hover { background: #e8f5e9; border-color: #388e3c; }
.refresh-heavy { border-color: #f57c00; color: #e65100; }
.refresh-heavy:hover { background: #fff3e0; border-color: #e65100; }
/* Refresh All runs both tiers, so it takes neither tier's colour — its own
   deliberate-looking accent, and a heavier weight because it is the long one. */
.refresh-all { border-color: #5c6bc0; color: #3949ab; font-weight: 600; }
.refresh-all:hover { background: #e8eaf6; border-color: #3949ab; }

.time-period-select {
  padding: 3px 8px;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  cursor: pointer;
}
.time-period-select.time-filtered { border-color: var(--accent); color: var(--accent); font-weight: 500; }
.time-period-info { display: block; font-size: 11px; color: #929aac; margin: 2px 0 4px 0; }

/* Tile category shading (subtle solid tints) — distinguishes the tile types.
   Replaces the deprecated .rolling-tile thick border. See render.ts / app.js queryCategory.
     cat-additive       (green)  daily values sum: period total + sparkline; all-time = direct total
     cat-non-additive   (amber)  counts that don't sum (distinct users); a value per period, no sparkline
     cat-all-time-only  (grey)   current-state / absolute snapshot ("All Time Total Only:" prefix) */
.metric-card.cat-additive       { background: #eef9f3; }
.metric-card.cat-non-additive   { background: #fdf6ea; }
.metric-card.cat-all-time-only  { background: #f3f4f6; }

/* Tile category legend (tenant header) */
.tile-legend { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 11px; color: var(--text-secondary); }
.tile-legend .legend-item { display: flex; align-items: center; gap: 5px; white-space: nowrap; cursor: default; }
.tile-legend .legend-swatch { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--border); flex-shrink: 0; }
.tile-legend .legend-swatch.cat-additive       { background: #eef9f3; }
.tile-legend .legend-swatch.cat-non-additive   { background: #fdf6ea; }
.tile-legend .legend-swatch.cat-all-time-only  { background: #f3f4f6; }
th.no-time-filter { opacity: 0.5; color: var(--text-secondary); }
.hm-all-time-only { opacity: 0.45; }
.hm-na { color: #bbb; text-align: center !important; font-style: italic; opacity: 0.5; }
.heatmap-help { font-size: 11px; color: var(--text-secondary); padding: 8px 4px; font-style: italic; }
.heatmap-help-lg { font-size: 15px; }

/* Help text above the %/Absolute toggle (Repeat Responders heatmap) */
.heatmap-mode-help { font-size: 11px; color: var(--text-secondary); padding: 8px 4px 2px; font-style: italic; max-width: 720px; line-height: 1.5; }

/* Toolbar row above the heatmap table: the %/Absolute toggle (when the section has
   percentage columns) on the left, the column finder pinned right. It sits OUTSIDE
   `.heatmap-container`, so it never moves when the table scrolls horizontally. */
.heatmap-toolbar { display: flex; align-items: center; gap: 12px; padding: 0 4px; }
.heatmap-search { margin-left: auto; }   /* right-aligned with or without the toggle */
.hm-col-search {
  width: 190px;
  font-size: 12px;
  padding: 5px 9px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-primary);
  color: var(--text-primary);
}
.hm-col-search::placeholder { color: var(--text-secondary); }
.hm-col-search:focus { outline: none; border-color: var(--accent); }
/* No column matched the term — cleared on the next keystroke. */
.hm-col-search.hm-search-miss { border-color: var(--red, #e74c3c); background: rgba(231,76,60,0.06); }

/* %/Absolute hotswitch for share-of-table heatmaps (Repeat Responders, Flight Paths) */
.heatmap-mode-toggle { display: flex; align-items: center; gap: 8px; padding: 6px 4px 10px; }
.hm-toggle-label { font-size: 12px; color: var(--text-secondary); font-weight: 600; }
.hm-mode-switch { display: inline-flex; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.hm-mode-btn {
  border: none; background: var(--bg-secondary); color: var(--text-secondary);
  font-size: 12px; padding: 4px 12px; cursor: pointer; line-height: 1.4;
}
.hm-mode-btn + .hm-mode-btn { border-left: 1px solid var(--border); }
.hm-mode-btn:hover { background: var(--bg-primary); color: var(--text-primary); }
.hm-mode-btn.active { background: var(--accent); color: #fff; }

.query-icon {
  display: inline-block;
  width: 14px;
  height: 14px;
  line-height: 14px;
  text-align: center;
  font-size: 10px;
  background: var(--border);
  color: var(--text-secondary);
  border-radius: 50%;
  cursor: pointer;
  vertical-align: middle;
  margin-left: 4px;
  position: relative;
}
.query-tooltip {
  display: none;
  position: fixed;
  width: 280px;
  z-index: 20;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  font-size: 11px;
  font-family: 'Consolas', 'Monaco', monospace;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-all;
  box-shadow: rgba(15, 15, 15, 0.08) 0px 4px 12px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
}
.query-icon:hover .query-tooltip { display: block; }

.tenant-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.metric-card[draggable="true"] { cursor: grab; }
.metric-card.dragging { opacity: 0.3; cursor: grabbing; }
.metrics-grid.drag-over { outline: 2px dashed var(--accent); outline-offset: 4px; border-radius: 8px; }

.dashboard-section { margin-bottom: 4px; }

.section-title.editing {
  outline: 1px solid var(--accent);
  border-radius: 4px;
  padding: 2px 6px;
  cursor: text;
  user-select: text;
}
.metrics-grid:empty {
  min-height: 60px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.metrics-grid:empty::after { content: 'Drop cards here'; color: var(--text-secondary); font-size: 12px; }

.section-header { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
/* Collapsible table section (e.g. Active Senders). The <summary> is the header
   bar; a rotating ▸ acts as the collapse arrow. Closed by default (no `open`). */
.section-collapse > summary.section-header { cursor: pointer; list-style: none; }
.section-collapse > summary.section-header::-webkit-details-marker { display: none; }
.section-collapse > summary.section-header::before {
  content: '▸';
  color: var(--text-secondary);
  font-size: 15px;
  transition: transform 0.15s;
}
.section-collapse[open] > summary.section-header::before { transform: rotate(90deg); }
/* Section-level SQL expander: indent it so its (smaller) disclosure marker sits
   inset from the larger section collapse arrow rather than lining up and clashing.
   The separator line goes UNDER it (border-bottom) so it divides this section from
   the next, instead of a border-top that would wall the SQL off from its own chart.
   padding-left (not margin-left) keeps the box full width so the line spans across. */
.section-collapse > .card-query-details {
  padding-left: 22px;
  border-top: none;
  padding-top: 0;
  border-bottom: 1px solid var(--border);
  padding-bottom: 8px;
}
/* Collapsed-section preview: a one-line list of the tiles hidden inside the
   section. Only shown when the section is collapsed (hidden while open). */
.section-collapsed-preview {
  font-size: 12px;
  font-weight: 400;
  color: var(--text-secondary);
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1;
}
.section-collapse[open] > summary.section-header > .section-collapsed-preview { display: none; }
.section-drag-handle {
  cursor: grab;
  color: var(--border);
  font-size: 16px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 4px;
  user-select: none;
}
.section-drag-handle:hover { color: var(--text-secondary); background: var(--bg-card); }
.dashboard-section.dragging { opacity: 0.3; }
.card-placeholder { min-height: 80px; border: 2px dashed var(--accent); border-radius: 8px; background: rgba(25,173,121,0.05); pointer-events: none; }
.section-placeholder { min-height: 40px; border: 2px dashed var(--accent); border-radius: 8px; background: rgba(25,173,121,0.05); margin-bottom: 4px; }

.card-timing {
  position: absolute;
  bottom: 6px;
  right: 8px;
  font-size: 9px;
  color: var(--text-secondary);
  opacity: 0.4;
  font-weight: 400;
}
.timings-summary { font-size: 12px; color: var(--text-secondary); margin-bottom: 12px; padding: 4px 0; }

.card-delete {
  position: absolute;
  top: 6px;
  right: 6px;
  background: none;
  border: none;
  color: var(--border);
  font-size: 14px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s;
}
.metric-card:hover .card-delete { opacity: 1; }
.card-delete:hover { color: var(--red); }

.label.editing {
  outline: 1px solid var(--accent);
  border-radius: 3px;
  padding: 1px 4px;
  cursor: text;
  user-select: text;
}

.section-delete {
  background: none;
  border: none;
  color: var(--border);
  font-size: 16px;
  cursor: pointer;
  padding: 0 4px;
  line-height: 1;
  opacity: 0;
  transition: opacity 0.15s;
  margin-left: auto;
}
.section-header:hover .section-delete { opacity: 1; }
.section-delete:hover { color: var(--red); }
.purge-btn {
  background: none;
  border: none;
  color: var(--border);
  font-size: 14px;
  cursor: pointer;
  padding: 0 4px;
  opacity: 0;
  transition: opacity 0.15s;
}
.section-header:hover .purge-btn { opacity: 1; }
.purge-btn:hover { color: var(--yellow); }

.card-header {
  display: flex;
  align-items: center;
  gap: 4px;
}

.unused-section { opacity: 0.6; border-top: 1px dashed var(--border); padding-top: 16px; margin-top: 16px; }
.unused-card { border-style: dashed; }

.import-layout-label {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-primary);
  font-size: 13px;
  cursor: pointer;
}
.import-layout-label:hover { border-color: var(--accent); }
#export-layout-btn { background: var(--bg-card); color: var(--text-primary); border-color: var(--border); }
#export-layout-btn:hover { border-color: var(--accent); }

.card-query-details {
  margin-top: 8px;
  border-top: 1px solid var(--border);
  padding-top: 6px;
}
.card-query-details summary {
  font-size: 10px;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
  list-style: none;
}
/* Replace the browser's native (chunky, fixed-size) disclosure triangle with a
   small custom marker so the SQL expander icon stays clearly smaller than the
   section collapse arrow. */
.card-query-details summary::-webkit-details-marker { display: none; }
.card-query-details summary::before {
  content: '▸';
  display: inline-block;
  font-size: 9px;
  margin-right: 4px;
  color: var(--text-secondary);
  transition: transform 0.15s;
}
.card-query-details[open] > summary::before { transform: rotate(90deg); }
.card-query-details pre {
  font-size: 10px;
  font-family: 'Consolas', 'Monaco', monospace;
  color: var(--text-secondary);
  white-space: pre-wrap;
  word-break: break-all;
  margin: 4px 0 0;
  padding: 0;
  background: none;
}
#expand-all-btn, #collapse-all-btn {
  background: transparent;
  color: #929aac;
  border-color: rgba(146,154,172,0.3);
  font-size: 11px;
  padding: 4px 8px;
}
#expand-all-btn:hover, #collapse-all-btn:hover { border-color: #929aac; color: #fff; }

.header-tenant-info {
  font-size: 15px;
  color: #fff;
  white-space: nowrap;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.header-tenant-info strong {
  font-size: 17px;
  font-weight: 700;
}
.header-cache {
  color: #929aac;
  font-size: 11px;
  margin-left: 8px;
}

/* Header data-freshness indicator ("Last Refresh" / "Last Full History Load").
   Right-justified as the last header child: .header-center is absolutely
   positioned at left:50%, so anything in the normal flow that grows toward the
   middle overlaps the client-name title. Pinned to the right edge and stacked on
   two lines to keep the block narrow, the gap to the centre stays clear. */
.header-freshness {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  text-align: right;
  gap: 10px;
  margin-left: auto;
  font-size: 11px;
  line-height: 1.4;
  color: #929aac;
  white-space: nowrap;
  flex-shrink: 0;
  cursor: default;
}
.header-freshness:empty { display: none; }
.header-freshness .hf-dates {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}
.header-freshness .hf-env {
  font-weight: 700;
  letter-spacing: 0.4px;
  text-transform: uppercase;
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 3px;
  border: 1px solid rgba(146,154,172,0.35);
  color: #b8c0d0;
}
.header-freshness .hf-env-live { border-color: rgba(80,200,140,0.5); color: #7fd6a8; }
.header-freshness .hf-env-local { border-color: rgba(245,166,35,0.5); color: #f0b661; }
.header-freshness .hf-label { color: #6f7889; }
.header-freshness .hf-date { color: #e7ebf2; font-weight: 600; }
.header-freshness .hf-stale .hf-date { color: #f5a623; }
.header-freshness .hf-stale .hf-date::after { content: ' ⚠'; font-weight: 400; }

#export-all-btn { background: transparent; color: #929aac; border-color: rgba(146,154,172,0.3); font-size: 11px; padding: 4px 8px; }
#export-all-btn:hover { border-color: #929aac; color: #fff; }

.tenant-list-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 4px;
  flex-wrap: wrap;
}
.select-all-label {
  font-size: 11px;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 4px;
  cursor: pointer;
  flex: 1;
}
.tenant-list-controls .refresh-btn {
  font-size: 10px;
  padding: 3px 6px;
}
.tenant-checkbox {
  flex-shrink: 0;
  cursor: pointer;
  accent-color: var(--accent);
}
.tenant-item:focus {
  outline: 1px solid var(--accent);
  outline-offset: -1px;
}

.not-cached {
  font-size: 11px;
  color: var(--text-secondary);
  font-style: italic;
  font-weight: 400;
}

.heatmap-toggle {
  position: absolute;
  top: 6px;
  right: 22px;
  background: none;
  border: none;
  font-size: 12px;
  cursor: pointer;
  padding: 0 3px;
  line-height: 1;
  color: var(--border);
  opacity: 0.6;
}
.metric-card:hover .heatmap-toggle { opacity: 1; }
.heatmap-toggle.hm-up { color: var(--green); opacity: 1; }
.heatmap-toggle.hm-down { color: var(--red); opacity: 1; }

/* Tabs */
.main-area { display: flex; flex: 1; overflow: hidden; }
.vertical-tabs {
  display: flex;
  flex-direction: column;
  background: #2b303b;
  width: 70px;
  flex-shrink: 0;
  z-index: 20;
  padding: 0;
}
.vtab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  width: 70px;
  height: 60px;
  font-size: 10px;
  font-family: inherit;
  font-weight: 600;
  background: transparent;
  border: none;
  border-left: 3px solid transparent;
  border-radius: 0;
  color: #929aac;
  cursor: pointer;
  transition: color 0.15s;
  padding: 0;
}
.vtab .vtab-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  font-size: 18px;
  border-radius: 6px;
  pointer-events: none;
  color: #fff;
  background: transparent;
  transition: color 0.15s, background 0.15s;
}
.vtab span { pointer-events: none; letter-spacing: 0.02em; color: #929aac; transition: color 0.15s; }
.vtab:hover:not(.active) { color: #fff; background: transparent; border-color: transparent; }
.vtab:hover:not(:disabled) { background: transparent; }
.vtab:hover .vtab-icon { color: var(--red, #e74c3c); background: #fff; }
.vtab:hover span { color: #fff; }
.vtab.active .vtab-icon { color: var(--red, #e74c3c); background: #fff; }
.vtab.active span { color: #fff; }
.vtab.active { color: #fff; }
.tab-content { display: flex; flex-direction: column; flex: 1; overflow: hidden; }

/* Heatmap */
:root {
  --hm-uncached: #e8e8e8;
  --hm-zero: #f0f0f0;
  --hm-mid: rgba(150,150,150,0.2);
}

#comparison-panel { flex: 1; overflow: hidden; padding: 12px; background: var(--bg-primary); display: flex; flex-direction: column; }

.heatmap-container { overflow: auto; flex: 1; min-height: 0; }
/* `.heatmap-container` only scrolls while it is a FLEX CHILD of the panel: its
   `flex: 1` + `min-height: 0` is what bounds its height so `overflow: auto` has
   something to clip. `composeHeatmapBody` wraps the table in `.fallback-365d` for
   skipAllTime sections under All Time (Delivery Vectors — Sends / Response Rates,
   Normalised Touchpoints), and that plain block wrapper severed the chain: the
   container fell back to content height, so it produced no scrollbar at all, the
   rows past the fold were clipped by the panel's `overflow: hidden`, the
   horizontal scrollbar sat off-screen below the fold, and the sticky header/Client
   column lost their scrollport. Re-declare the wrapper as a flex pass-through.
   Scoped to the panel so the Client tab's `.fallback-365d` trend-table greying,
   which wraps no scrollport, is untouched. Any future wrapper added between the
   panel and the container must do the same. */
#comparison-panel > .fallback-365d {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

.heatmap-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  white-space: nowrap;
}
.heatmap-table th {
  padding: 6px 10px;
  background: #fff;
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-weight: 700;
  position: sticky;
  top: 0;
  z-index: 2;
  cursor: pointer;
  user-select: none;
  white-space: normal;
  min-width: 80px;
  max-width: 120px;
  box-shadow: 0 1px 0 var(--border);
  transition: background 0.15s;
}
.heatmap-table th:hover { background: #f4f4f4; color: var(--text-primary); }
.hm-tenant-col {
  position: sticky;
  left: 0;
  z-index: 3;
  background: #fff;
  min-width: 180px;
}
/* `.heatmap-table th` (0,1,1) out-specifies `.hm-tenant-col` (0,1,0), so without
   this the pinned Client header inherits the generic th `z-index: 2` / width caps.
   At equal z-index the later metric headers win on DOM order and paint OVER the
   pinned corner, so horizontally scrolling a wide heatmap (Countries) appeared to
   scroll the header past a frozen body column. Re-assert both here. */
.heatmap-table th.hm-tenant-col {
  z-index: 4;
  min-width: 180px;
  max-width: none;
}
.hm-dir { font-size: 10px; opacity: 0.6; }
.hm-col-desc {
  display: block;
  margin-top: 3px;
  font-weight: 400;
  font-size: 10px;
  line-height: 1.25;
  color: var(--text-secondary);
  white-space: normal;
}
.hm-compare-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 12px;
  color: var(--text-secondary);
  opacity: 0.35;
  cursor: pointer;
  border-radius: 3px;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
  margin-left: 4px;
  vertical-align: middle;
}
.hm-compare-icon:hover { opacity: 1; color: var(--accent); background: rgba(25,173,121,0.12); }
.hm-compare-icon svg { display: block; }

.heatmap-table td {
  padding: 4px 10px;
  border: 1px solid rgba(30,48,80,0.4);
  text-align: right;
  /* Fixed at "two lines tall" always, rather than autofitting per row. Only the
     tenant-name and ARR-band cells ever grow a second line — `.sf-contract`
     (contract range) and `.as-hours` (quarterly AS hours), both `display: block`,
     appear only for tenants with that Salesforce data. Left to autofit, rows with
     SF data were taller than rows without it, which read as an uneven, jittery
     table when scrolling past a mix of both. Every row now reserves that height
     unconditionally; single-line cells (the metric values) centre inside it via
     `vertical-align: middle` instead of hugging the top of extra empty space. */
  height: 44px;
  vertical-align: middle;
}
.hm-tenant-cell {
  text-align: left;
  font-weight: 500;
  position: sticky;
  left: 0;
  background: #f4f4f4;
  z-index: 1;
  min-width: 180px;
}
.hm-row { cursor: pointer; }
.hm-row:hover td { filter: brightness(1.3); }
.hm-cell { transition: background 0.15s; }
.hm-uncached { color: var(--text-secondary); font-style: italic; }
.hm-zero { color: var(--text-secondary); opacity: 0.5; }
.hm-total-row td { background: #f4f6f8; font-weight: 600; border-top: 2px solid var(--border); position: sticky; bottom: 0; z-index: 1; }
.hm-total-row .hm-tenant-cell { position: sticky; left: 0; bottom: 0; z-index: 2; background: #f4f6f8; }
/* Right-hand roll-up (Total) column for purely-table-row heatmap sections */
.hm-agg-col { border-left: 2px solid var(--border); font-weight: 600; }
/* Fixed "ARR Bin" column to the left of the metric columns (not sticky — it
   sits just right of the sticky Tenant column). */
.hm-arr-col { min-width: 150px; max-width: 170px; }
.hm-arr-cell {
  font-weight: 500;
  color: var(--text-secondary);
  border-right: 2px solid var(--border);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* One non-wrapping layout row: range pinned right, aligning with `.arr-plain`.
   The band's leading index is deliberately not rendered (it remains the column's
   sort key), so there is no left-hand element to space against. */
.hm-arr-cell .arr-bin {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  width: 100%;
}
/* Fixed range columns keep the lower and upper € symbols vertically aligned. */
.hm-arr-cell .arr-range {
  display: grid;
  grid-template-columns: 0.65em 3.2em 0.8em 3.2em 0.35em;
  align-items: center;
  text-align: left;
}
.hm-arr-cell .arr-pre { text-align: right; }
.hm-arr-cell .arr-sep { text-align: center; }
.hm-arr-cell .arr-plain {
  display: block;
  color: var(--text-tertiary, var(--text-secondary));
  text-align: right;
}

.heatmap-controls {
  margin-bottom: 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}
#heatmap-section-select {
  padding: 6px 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-card);
  color: var(--text-primary);
  font-size: 13px;
}

/* Admin mode */
.admin-only { display: none !important; }
body.admin-mode .admin-only { display: revert !important; }

.admin-toggle {
  background: transparent;
  border: 1px solid rgba(146,154,172,0.3);
  color: #929aac;
  font-size: 16px;
  padding: 2px 8px;
  border-radius: 6px;
  cursor: pointer;
  line-height: 1;
}
.admin-toggle:hover { border-color: #929aac; color: #fff; }
.admin-toggle.active { background: var(--accent); color: #fff; border-color: var(--accent); }

/* Disable drag in non-admin mode */
.metric-card[draggable="true"] { cursor: default; }
body.admin-mode .metric-card[draggable="true"] { cursor: grab; }

/* Sidebar controls */
.sidebar-controls {
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  border-bottom: 1px solid var(--border);
}
.sidebar-controls select, .sidebar-controls input:not([type="checkbox"]) {
  width: 100%;
  padding: 5px 8px;
  font-size: 12px;
}
.sidebar-help {
  font-size: 10px;
  color: #929aac;
  text-align: center;
  padding: 2px 0 0;
}

/* Edit toggle */
.edit-toggle {
  margin-left: auto;
  background: transparent;
  border: 1px solid rgba(146,154,172,0.3);
  color: #929aac;
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 6px;
  cursor: pointer;
}
.edit-toggle:hover { border-color: #929aac; color: #fff; }
.edit-toggle.active { background: var(--accent); color: #fff; border-color: var(--accent); }

/* Modal */
.modal-overlay {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.6);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
}
.modal-content {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  width: 600px;
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  box-shadow: rgba(15, 15, 15, 0.08) 0px 4px 12px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
}
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.modal-header h2 { font-size: 16px; font-weight: 600; }
.modal-close {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 20px;
  cursor: pointer;
  padding: 0 4px;
}
.modal-close:hover { color: var(--text-primary); }
.modal-body { padding: 16px 20px; overflow-y: auto; }
/* The Cache & Deploy popup needs more room than the login/newpass modals that share
   .modal-content: an indented action row is a 150px button plus its ? plus a
   timestamp. It no longer needs the 760px the side-by-side help text used — that
   prose moved into the ? tooltip, which is positioned outside the modal entirely. */
#admin-modal .modal-content { width: 600px; }
.modal-select-bar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--text-secondary);
}
.modal-select-bar label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
.modal-select-bar input { accent-color: var(--accent); }
.modal-status { margin-left: auto; color: var(--text-secondary); font-size: 12px; display: block; margin: 0 0 8px; }
.modal-status:empty { display: none; }
/* The Cache & Deploy status line is the live narration of a run that takes tens of
   minutes, so it stays pinned while the operator scrolls the action list. .modal-body
   is the scroll container, so `top: 0` sticks it to the padding edge; the negative
   margins let its background cover the body's own padding, otherwise rows would
   scroll visibly through the gutters beside it. */
#admin-modal .modal-status {
  position: sticky;
  top: 0;
  z-index: 3;
  background: #fff;
  margin: -16px -20px 8px;
  padding: 12px 20px 8px;
  border-bottom: 1px solid var(--border);
}
.startup-status { background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px; padding: 8px 12px; margin-bottom: 10px; font-size: 12px; }
.startup-header { font-weight: 600; margin-bottom: 4px; }
.startup-step { color: var(--text-secondary); padding: 1px 0; }
.startup-step-time { color: var(--text-secondary); opacity: 0.6; margin-right: 6px; font-variant-numeric: tabular-nums; }
/* Cache & Deploy action tree — one row per action: button, a ? carrying the help
   text as a tooltip, then that action's last run. Children are indented under the
   parent that runs them. The long prose used to sit beside every button in the
   flow, which made the popup several screens tall; it now hangs off the ?. */
.admin-ops-heading {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 18px 0 6px;
}
.admin-ops-heading:first-of-type { margin-top: 2px; }
.admin-ops {
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
/* One action. A node holds its own row and, when it is a parent, the rows of the
   children it runs. */
.admin-node-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
}
/* A top-level action gets the separator, so the tree reads as three groups rather
   than fourteen equally weighted rows. */
.admin-tree > .admin-node { border-top: 1px solid var(--border); }
.admin-tree > .admin-node:first-child { border-top: none; }
.admin-tree > .admin-node > .admin-node-row { padding-top: 10px; }
.admin-tree > .admin-node:last-child > .admin-node-children { padding-bottom: 6px; }
/* The indent is the whole hierarchy cue, and the guide line is what keeps a
   third-level row attached to its parent rather than reading as a sibling of the
   level above it. */
.admin-node-children {
  margin-left: 20px;
  border-left: 1px solid var(--border);
}
/* Geometry only — the tier colour comes from .refresh-light / .refresh-heavy /
   .publish-btn, which are defined earlier and would otherwise be overridden. */
.admin-op-btn {
  flex: 0 0 150px;
  width: 150px;
  padding: 7px 10px;
  font-size: 12px;
  border-radius: 6px;
  cursor: pointer;
  /* Must wrap. The button is a fixed 150px, so `nowrap` would make any label wider
     than that overflow its own button. Balanced wrapping keeps a long label inside
     the button without widening it for every other row. */
  white-space: normal;
  text-wrap: balance;
}
.admin-op-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Help tooltip. `position: fixed` so it escapes the scrolling .modal-body, and
   positioned by JS on hover/focus — see positionAdminTip() in src/admin-modal.ts.
   The tip is a DESCENDANT of its trigger on purpose: moving the pointer into the
   tip keeps the trigger hovered, which is what lets a long one be scrolled. */
.admin-help {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 16px;
  width: 16px;
  height: 16px;
  border: 1px solid var(--border);
  border-radius: 50%;
  font-size: 10px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: help;
  user-select: none;
}
.admin-help:hover, .admin-help:focus {
  background: var(--bg-card);
  color: var(--text-primary);
  border-color: var(--text-secondary);
  outline: none;
}
.admin-tip {
  display: none;
  position: fixed;
  left: 0;
  top: 0;
  width: 420px;
  max-height: 68vh;
  overflow-y: auto;
  z-index: 30;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px 12px;
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary);
  text-align: left;
  white-space: normal;
  cursor: auto;
  box-shadow: rgba(15, 15, 15, 0.08) 0px 4px 12px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
}
.admin-help:hover .admin-tip, .admin-help:focus .admin-tip { display: block; }
.admin-tip .tip-p { display: block; }
.admin-tip .tip-p + .tip-p { margin-top: 6px; }
.admin-tip code {
  font-size: 11px;
  background: var(--bg-card);
  padding: 1px 4px;
  border-radius: 3px;
}
/* Click acknowledgement. Several actions take a while before their status line
   changes, and a couple do not disable their button at all, so a press needs to be
   visible on its own. A neutral ring reads on both the outlined refresh tiers and
   the solid blue publish buttons. */
#admin-modal button:active:not(:disabled) { transform: translateY(1px); }
#admin-modal button.admin-btn-pressed {
  animation: admin-btn-pressed 0.45s ease-out;
}
@keyframes admin-btn-pressed {
  from { box-shadow: 0 0 0 0 rgba(33, 33, 33, 0.35); }
  to { box-shadow: 0 0 0 8px rgba(33, 33, 33, 0); }
}
@media (prefers-reduced-motion: reduce) {
  #admin-modal button.admin-btn-pressed { animation: none; }
  #admin-modal button:active:not(:disabled) { transform: none; }
}
/* Sits inline after the ?, on the only buttons that carry one: the leaves. */
.admin-op-lastrun {
  font-size: 11px;
  color: var(--text-secondary);
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
@media (max-width: 820px) {
  #admin-modal .modal-content { width: auto; max-width: 94vw; }
  .admin-tip { width: auto; max-width: 88vw; }
}
/* Section sidebar */
#section-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
}
.section-list-inner { padding: 8px; overflow-y: auto; flex: 1; }
.sidebar-heading {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.compare-show-grey-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 4px;
  font-size: 10px;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-secondary);
  cursor: pointer;
  white-space: nowrap;
}
.compare-show-grey-toggle input { cursor: pointer; margin: 0; }
.section-list-item {
  padding: 8px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  font-weight: 500;
}
.section-list-item:hover { background: #f4f4f4; }
.section-list-item.active { background: rgba(25,173,121,0.08); border: 1px solid var(--accent); }

.section-list-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.section-tile-count {
  font-size: 10px;
  color: var(--text-secondary);
  background: var(--bg-primary);
  padding: 1px 6px;
  border-radius: 8px;
}

/* Login */
.login-input {
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 14px;
  background: var(--bg-primary);
  color: var(--text-primary);
  font-family: inherit;
}
.login-input:focus { outline: none; border-color: var(--accent); }
.login-submit {
  width: 100%;
  padding: 10px;
  background: var(--accent);
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
}
.login-submit:hover { background: var(--accent-hover); }
.login-submit:disabled { opacity: 0.5; }
.login-error { color: var(--red); font-size: 12px; margin-top: 8px; min-height: 16px; }
.login-msg { font-size: 13px; color: var(--text-secondary); margin-bottom: 12px; }

.publish-btn { background: var(--blue) !important; color: #fff !important; border-color: var(--blue) !important; }
.publish-btn:hover { opacity: 0.9; }
.staged-btn { background: #e67e22 !important; color: #fff !important; border-color: #e67e22 !important; }
.staged-btn:hover { opacity: 0.9; }
.staged-btn[disabled] { opacity: 0.5; cursor: not-allowed; }
.restore-btn { background: #95a5a6 !important; color: #fff !important; border-color: #95a5a6 !important; }
.restore-btn:hover { opacity: 0.9; }

/* ─── Insights Tab ─── */
.insights-summary {
  padding: 4px 12px 8px;
  font-size: 12px;
  color: var(--text-secondary);
  background: #fff;
  display: flex;
  align-items: center;
  gap: 12px;
}

.insights-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  table-layout: fixed;
}

.insights-table th {
  padding: 6px 10px;
  background: #fff;
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-weight: 700;
  position: sticky;
  top: 0;
  z-index: 2;
  white-space: normal;
  word-wrap: break-word;
  line-height: 1.3;
  height: 40px;
  vertical-align: bottom;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  box-shadow: 0 1px 0 var(--border);
  transition: background 0.15s;
}

.insights-table th:last-child { width: auto; }

.insights-row {
  cursor: pointer;
  transition: background 0.15s;
  /* Sticky column headers are 40px tall; keep the selected row clear of them
     when scrollIntoView({block:'start'}) aligns it to the scroll-area top. */
  scroll-margin-top: 44px;
}

.insights-row:hover td { filter: brightness(0.97); }
.insights-row.expanded { background: rgba(25,173,121,0.04); }

.insights-row td {
  padding: 4px 10px;
  border: 1px solid rgba(30,48,80,0.12);
  vertical-align: middle;
}

.insights-row td.num {
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  max-width: 92px;
}

.insights-tenant {
  display: flex;
  align-items: center;
  gap: 2px;
}

.insights-company {
  font-weight: 500;
  font-size: 12px;
}

.insights-db {
  font-size: 10px;
  color: var(--text-secondary);
  margin-left: 4px;
}

.archetype-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

.archetype-badge-lg {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 16px;
  font-size: 14px;
  font-weight: 500;
}

.insights-detail-row td {
  padding: 0 !important;
  border-bottom: 2px solid var(--border) !important;
  border-left: none !important;
  border-right: none !important;
  width: 100% !important;
  max-width: none !important;
  min-width: 0 !important;
}

.insights-detail {
  padding: 12px 16px;
  background: #fafafa;
  width: 100%;
  box-sizing: border-box;
}

.insights-detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

.insights-reason {
  font-size: 12px;
  color: var(--text-secondary);
  flex: 1;
}

.view-client-link {
  font-size: 12px;
  color: var(--accent);
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
}

.view-client-link:hover { text-decoration: underline; }

.insights-features {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}

.feature-card {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px 10px;
  min-width: 80px;
  text-align: center;
}

.feature-value {
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.feature-label {
  font-size: 10px;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.3px;
  margin-top: 2px;
}

.insights-calendar svg.mini-cal {
  display: block;
}

.insights-calendar-large {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
  overflow-x: auto;
}

.insights-spark-large {
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
}

.insights-sparklines-stack {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.insights-sparklines-stack .insights-spark-large {
  border-radius: 6px 6px 0 0;
  border-bottom: none;
}

.insights-sparklines-stack .insights-spark-large.insights-spark-logins {
  border-radius: 0;
  border-top: 1px dashed var(--border);
  border-bottom: none;
}

.insights-sparklines-stack .insights-spark-logins .sparkline {
  --spark-stroke: #f59e0b;
  --spark-fill: rgba(245,158,11,0.12);
}

.insights-sparklines-stack .insights-spark-logins .sparkline polyline {
  stroke: #f59e0b;
}

.insights-sparklines-stack .insights-spark-logins .sparkline polygon {
  fill: rgba(245,158,11,0.12);
}

.insights-sparklines-stack .insights-spark-logins .sparkline circle {
  stroke: #f59e0b;
}

.insights-spark-dates {
  display: flex;
  justify-content: space-between;
  padding: 2px 12px 4px;
  font-size: 9px;
  color: #94a3b8;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 6px 6px;
}

.insights-spark-label {
  font-size: 11px;
  color: #64748b;
  margin-bottom: 4px;
}

.insights-spark-svg {
  height: 36px;
  display: flex;
  align-items: center;
}

.insights-spark-svg .sparkline {
  width: 100%;
  height: 36px;
}

.insights-calendar-large svg.cal-strip {
  display: block;
  height: 28px;
}

.cal-month-labels {
  position: relative;
  height: 14px;
  font-size: 10px;
  color: #94a3b8;
  margin-bottom: 2px;
}

.cal-month-label {
  position: absolute;
  white-space: nowrap;
}

.cal-tooltip {
  display: none;
  position: absolute;
  background: #1e293b;
  color: #f1f5f9;
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 4px;
  pointer-events: none;
  white-space: nowrap;
  z-index: 1000;
  transform: translateX(-50%);
}

.spark-tooltip {
  display: none;
  position: fixed;
  background: #1e293b;
  color: #f1f5f9;
  font-size: 11px;
  line-height: 1.3;
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: none;
  white-space: nowrap;
  z-index: 1000;
  transform: translate(-50%, -100%);
}

.no-data {
  color: var(--text-secondary);
  font-size: 12px;
}

/* ─── Usage Health tab ─── */

#usage-health-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  background: #fff;
  overflow: hidden;
}

#usage-health-panel {
  flex: 1;
  overflow: auto;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
}

.uh-header-area {
  background: #fff;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.uh-title {
  padding: 12px 12px 4px;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

.uh-help-note {
  padding: 0 12px 8px;
  font-size: 11px;
  color: var(--text-secondary, #64748b);
  line-height: 1.4;
  max-width: 900px;
}

/* Cadence Drops header explainer: a default-closed, non-technical account of every
   check and its standing. Mirrors .uh-attention-evidence-details in the
   drilldown so the two collapsibles read as the same control. */
.uh-attention-explainer {
  margin: 0 12px 10px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 8px;
  background: var(--bg-secondary, #f8fafc);
  max-width: 900px;
}
.uh-attention-explainer > summary {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 700;
  color: var(--text-primary, #0f172a);
}
.uh-attention-explainer > summary span {
  margin-left: 5px;
  color: var(--text-secondary, #64748b);
  font-size: 10px;
  font-weight: 400;
}
.uh-attention-explainer-body {
  padding: 2px 14px 12px;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text-primary, #0f172a);
}
.uh-attention-explainer-body p { margin: 0 0 9px; }
.uh-attention-explainer-body h4 {
  margin: 14px 0 5px;
  font-size: 12px;
  font-weight: 700;
}
.uh-attention-explainer-body ol,
.uh-attention-explainer-body ul { margin: 0 0 9px; padding-left: 20px; }
.uh-attention-explainer-body li { margin: 0 0 4px; }
.uh-attention-explainer-body .uh-explainer-checks > li { margin: 0 0 8px; }
.uh-attention-explainer-body em { color: var(--text-secondary, #64748b); font-style: italic; }
.uh-explainer-table { width: 100%; border-collapse: collapse; margin: 0 0 9px; }
.uh-explainer-table th,
.uh-explainer-table td {
  padding: 5px 8px;
  border-top: 1px solid var(--border, #e2e8f0);
  text-align: left;
  vertical-align: top;
  font-weight: 400;
}
.uh-explainer-table tr:first-child th,
.uh-explainer-table tr:first-child td { border-top: 0; }
.uh-explainer-table th { width: 128px; font-weight: 700; white-space: nowrap; }
.uh-explainer-footnote {
  margin: 12px 0 0;
  padding-top: 9px;
  border-top: 1px solid var(--border, #e2e8f0);
  color: var(--text-secondary, #64748b);
}
@media (max-width: 640px) {
  .uh-attention-explainer > summary span { display: block; margin: 3px 0 0; }
  .uh-explainer-table th { width: auto; white-space: normal; }
}

.uh-body {
  flex: 1;
  /* Alerts columns must respond to this scrollport's usable width, not the
     browser viewport: the Usage Health navigation and sidebar reduce it. */
  container-type: inline-size;
  /* No top padding: the sticky table header pins to the top of this scroll
     container, so any top padding becomes a gap between the page header and the
     table header that rows bleed through on scroll. Keep it flush. */
  padding: 0 12px 12px;
  overflow: auto;
}

.uh-placeholder {
  padding: 32px 12px;
  text-align: center;
  font-size: 13px;
  color: var(--text-secondary, #64748b);
  line-height: 1.6;
}

.uh-placeholder-sub {
  font-size: 11px;
  color: var(--text-secondary, #94a3b8);
}

/* Column legend — collapsible definitions above the score table. */
.uh-legend {
  margin: 0 12px 8px;
  font-size: 11px;
  color: var(--text-secondary, #64748b);
}

.uh-legend > summary {
  cursor: pointer;
  user-select: none;
  font-weight: 600;
  color: var(--text-primary);
  padding: 2px 0;
}

.uh-legend > summary:hover { color: var(--accent, #1e3050); }

.uh-legend-table {
  border-collapse: collapse;
  margin: 6px 0 4px;
  max-width: 1100px;
}

.uh-legend-table th,
.uh-legend-table td {
  border: 1px solid rgba(30, 48, 80, 0.12);
  padding: 3px 6px;
  text-align: left;
  vertical-align: top;
  line-height: 1.45;
}

.uh-legend-table th {
  background: #f8fafc;
  color: var(--text-primary);
  font-weight: 600;
  white-space: nowrap;
}

.uh-lg-col { font-weight: 600; color: var(--text-primary); }
.uh-lg-note { font-weight: 400; color: var(--text-secondary, #64748b); }
.uh-lg-cat,
.uh-lg-w { white-space: nowrap; text-align: center; }

.uh-lg-group td {
  background: rgba(30, 48, 80, 0.06);
  font-weight: 600;
  color: var(--text-primary);
}

.uh-legend-foot {
  max-width: 1100px;
  padding-top: 2px;
  line-height: 1.5;
}

.uh-caption {
  font-size: 11px;
  font-weight: 400;
  color: var(--text-secondary, #64748b);
  margin-left: 8px;
}

/* Health Data raw ↔ 0–10 web-mapping toggle — right-aligned checkbox bar
   sitting directly above the table header. */
.uh-table-toolbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 16px;
  margin-bottom: 6px;
}

/* Health Data scrolls a wide table beneath this toolbar. Pin the toolbar row to
   the scrollport's visible left edge; its existing end alignment keeps the
   controls fixed against the visible right edge while columns move below it. */
.uh-health-table-toolbar {
  position: sticky;
  left: 0;
  z-index: 7;
  background: var(--bg-primary, #fff);
}

/* Fixed-score distribution follows Health Data Summary with the same period columns.
   It is a cohort diagnostic, so it is deliberately not row-clickable or tinted. */
.uh-health-distribution {
  margin-top: 18px;
  padding-top: 12px;
  border-top: 1px solid var(--border, #e2e8f0);
}

.uh-distribution-heading {
  position: sticky;
  left: 0;
  z-index: 7;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 7px;
  color: var(--text-secondary, #64748b);
  background: var(--bg-primary, #fff);
  font-size: 11px;
  line-height: 1.4;
}

.uh-distribution-heading strong { color: var(--text-primary, #0f172a); }

/* Score band is a distinct, three-row-spanning table axis. Keeping the header
   and row labels separate prevents Feedback's group/metric headings shifting
   two columns left of their data cells. */
.uh-health-distribution-table .uh-distribution-score-band-header {
  width: 104px;
  min-width: 104px;
  max-width: 104px;
  text-align: left;
  vertical-align: middle;
  white-space: nowrap;
}
.uh-health-distribution-table .uh-distribution-score-band-cell {
  width: 104px;
  min-width: 104px;
  background: #f8fafc;
  color: #334155;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
}
.uh-health-distribution-table .uh-distribution-cell { text-align: right; font-variant-numeric: tabular-nums; }
.uh-health-distribution-table .uh-distribution-na { color: var(--text-secondary, #64748b); text-align: center; }

@media (max-width: 700px) {
  .uh-distribution-heading { align-items: flex-start; flex-direction: column; gap: 6px; }
}

.uh-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-secondary, #64748b);
  cursor: pointer;
  user-select: none;
}

.uh-toggle + .uh-toggle {
  padding-left: 16px;
  border-left: 1px solid var(--border, #e2e8f0);
}

.uh-toggle input,
.uh-toggle select {
  cursor: pointer;
}

.uh-toggle input {
  margin: 0;
}

.uh-toggle select {
  min-height: 28px;
  padding: 3px 8px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 6px;
  background: var(--bg-primary, #fff);
  color: var(--text-primary, #0f172a);
  font: inherit;
  font-weight: 600;
}

.uh-toggle:hover {
  color: var(--text-primary);
}

.uh-toggle select:hover,
.uh-toggle select:focus {
  border-color: var(--accent, #2563eb);
}

.uh-programme-window-evidence {
  margin: 0 0 16px;
  padding: 11px 12px;
  border: 1px solid #f1be72;
  border-radius: 8px;
  background: rgba(245, 164, 61, .08);
  font-size: 12px;
  line-height: 1.45;
}
.uh-programme-window-evidence p { margin: 5px 0; }
.uh-programme-window-evidence ul { margin: 4px 0 0; padding-left: 18px; }


/* Debug score table (Phase 2) — plain, dense, sortable. */
.uh-table {
  /* Header row heights — SINGLE SOURCE OF TRUTH for the three-row sticky header.
     The sub-header row's sticky `top` is derived from these with calc(), so
     changing a row's height here keeps all three rows aligned automatically.
     Do not hard-code pixel `top` offsets on the header rows again. */
  --uh-h-group: 22px;   /* group band row (.uh-group-th) */
  --uh-h-metric: 48px;  /* metric-label row (.uh-metric-th) — grows if the label gains lines */
  /* SEPARATE, not collapse. With `border-collapse: collapse` the grid lines
     belong to the table, not the cells, so the seam between a sticky header row
     and the scrolling body (and between the stacked sticky rows) scrolls away and
     lets a 1px sliver of body content bleed through the header. Separate borders
     stay anchored to each cell. Every grid line below is drawn as an `inset
     box-shadow`: it paints with the cell (so it travels with a sticky cell, no
     bleed) and takes no layout space (so the derived --uh-h-* sticky offsets stay
     exact). Each cell draws only its LEFT + BOTTOM line so every internal seam is
     drawn exactly once (no doubled 2px lines); the top + right perimeter is drawn
     by the table's own border below. */
  border-collapse: separate;
  border-spacing: 0;
  border-top: 1px solid rgba(30, 48, 80, 0.12);
  border-right: 1px solid rgba(30, 48, 80, 0.12);
  font-size: 11px;
  width: 100%;
}

/* :where() keeps this base grid at low specificity so the per-cell accent rules
   below (group divider, header-row bottoms) win by source order without needing
   !important or heavier selectors. */
.uh-table :where(th, td) {
  box-shadow: inset 1px 0 0 0 rgba(30, 48, 80, 0.12), inset 0 -1px 0 0 rgba(30, 48, 80, 0.12);
  padding: 3px 6px;
}

.uh-table td { white-space: nowrap; }

/* Headers are descriptive phrases, so they wrap into a narrow stack instead of
   forcing the table wide. Data cells stay on one line. */
.uh-th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: #f8fafc;
  font-weight: 600;
  text-align: center;
  cursor: pointer;
  user-select: none;
  white-space: normal;
  width: 78px;
  min-width: 62px;
  max-width: 92px;
  vertical-align: bottom;
  line-height: 1.25;
  font-size: 10px;
}

.uh-table th:first-child {
  width: auto;
  max-width: none;
  text-align: left;
}

.uh-th:hover { background: #eef2f7; }
.uh-th.uh-sorted { background: #e2e8f0; }
.uh-th.uh-sorted.asc::after { content: ' ▲'; font-size: 8px; }
.uh-th.uh-sorted.desc::after { content: ' ▼'; font-size: 8px; }

/* Group header row — spans its columns above the sortable column headers.
   Sticky above the column-header row, which is offset down by this row's height. */
.uh-group-th {
  position: sticky;
  top: 0;
  z-index: 3;
  height: var(--uh-h-group);
  background: #eef2f7;
  font-weight: 700;
  font-size: 10px;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #334155;
  text-align: center;
  white-space: nowrap;
  /* left 1px grid + 2px dark bottom divider, both inset (travel with the sticky
     cell so no bleed on scroll). */
  box-shadow: inset 1px 0 0 0 rgba(30, 48, 80, 0.12), inset 0 -2px 0 0 rgba(30, 48, 80, 0.25);
}
.uh-group-th.uh-group-blank {
  background: #f8fafc;
  box-shadow: inset 1px 0 0 0 rgba(30, 48, 80, 0.12), inset 0 -2px 0 0 rgba(30, 48, 80, 0.12);
}
/* Metric-label row: spans its three window sub-columns, sits below the group row. */
.uh-metric-th {
  position: sticky;
  top: var(--uh-h-group);
  z-index: 3;
  height: var(--uh-h-metric);
  background: #f8fafc;
  font-weight: 600;
  font-size: 10px;
  line-height: 1.2;
  text-align: center;
  vertical-align: bottom;
  white-space: normal;
  padding: 3px 6px;
  box-shadow: inset 1px 0 0 0 rgba(30, 48, 80, 0.12), inset 0 -1px 0 0 rgba(30, 48, 80, 0.18);
}
/* Second line under each metric label: what the three window figures represent. */
.uh-metric-sub {
  display: block;
  font-weight: 400;
  font-size: 8.5px;
  line-height: 1.1;
  color: #6b7280;
  margin-top: 2px;
}
/* M / Q / Y sub-columns: sortable, narrow, sit below the metric-label row.
   Offset is derived — group height + metric height — so it tracks the vars above. */
.uh-sub-row .uh-th { top: calc(var(--uh-h-group) + var(--uh-h-metric)); }
.uh-th.uh-subcol {
  width: 46px;
  min-width: 34px;
  max-width: 60px;
  font-size: 10px;
}
/* Client corner cell spans all three header rows. */
.uh-th.uh-corner { top: 0; z-index: 4; vertical-align: bottom; }
/* Vertical divider between groups — on all three header rows and the data cells.
   The group-start cell's LEFT line is thickened to 2px (replacing its 1px base
   left), composed with the cell's own bottom line. Because each cell only draws
   its left line, this 2px sits as a single clean divider at the seam. */
.uh-group-th + .uh-group-th {
  box-shadow: inset 2px 0 0 0 rgba(30, 48, 80, 0.25), inset 0 -2px 0 0 rgba(30, 48, 80, 0.25);
}
.uh-metric-th.uh-group-start {
  box-shadow: inset 2px 0 0 0 rgba(30, 48, 80, 0.25), inset 0 -1px 0 0 rgba(30, 48, 80, 0.18);
}
.uh-th.uh-group-start,
.uh-metric.uh-group-start {
  box-shadow: inset 2px 0 0 0 rgba(30, 48, 80, 0.25), inset 0 -1px 0 0 rgba(30, 48, 80, 0.12);
}

.uh-row:hover {
  outline: 2px solid #2563eb;
  outline-offset: -2px;
}

.uh-row:hover td { background: var(--uh-tint, #dbeafe); cursor: pointer; }

.uh-name {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Freeze the two client-identifying columns within Health Data's shared
   horizontal scrollport. The explicit widths make ARR's offset deterministic. */
.uh-table {
  --uh-sticky-client-width: 212px;
  --uh-sticky-arr-width: 120px;
}

.uh-table th.uh-sticky-client,
.uh-table td.uh-sticky-client {
  position: sticky;
  left: 0;
  z-index: 1;
  box-sizing: border-box;
  width: var(--uh-sticky-client-width);
  min-width: var(--uh-sticky-client-width);
  max-width: var(--uh-sticky-client-width);
}

.uh-table th.uh-sticky-arr,
.uh-table td.uh-sticky-arr {
  position: sticky;
  left: var(--uh-sticky-client-width);
  z-index: 1;
  box-sizing: border-box;
  width: var(--uh-sticky-arr-width);
  min-width: var(--uh-sticky-arr-width);
  max-width: var(--uh-sticky-arr-width);
}

/* Prevent horizontally-scrolled cells showing through the frozen body pair.
   The custom property preserves the normal per-row hover tint. */
.uh-table tbody .uh-sticky-client,
.uh-table tbody .uh-sticky-arr {
  background: var(--uh-tint, var(--bg-primary, #fff));
}

/* Keep the frozen corners above the scrolling header bands. */
.uh-table thead .uh-sticky-client { z-index: 6; }
.uh-table thead .uh-sticky-arr { z-index: 5; }

.uh-dau {
  text-align: right;
  font-variant-numeric: tabular-nums;
  background: rgba(30, 48, 80, 0.03);
}

.uh-pair {
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.uh-pair.uh-down { background: rgba(239, 68, 68, 0.10); }
.uh-pair.uh-up { background: rgba(34, 197, 94, 0.10); }

/* Natural-unit cell: one window's average per day (month, quarter or year) —
   each in its own column under the spanning metric label. */
.uh-metric {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  width: 46px;
  min-width: 34px;
  /* Heatmap tint set inline as --uh-tint (M = green magnitude within column,
     Q/Y = red/green by month-vs-window delta). Driven through a custom property
     so the .uh-row:hover rule below still wins and gives row feedback. */
  background: var(--uh-tint, transparent);
}
.uh-cat { font-weight: 600; background: rgba(30, 48, 80, 0.04); }
.uh-insufficient { color: var(--text-secondary, #94a3b8); font-style: italic; }

.uh-sep { color: #cbd5e1; margin: 0 3px; }
.uh-null { color: #cbd5e1; }
.uh-shared { color: #64748b; margin-left: 2px; }
/* Single-layer spoke: one number + ◦ instead of a duplicated n/n pair. */
.uh-pair.uh-single { color: #475569; }
.uh-override { color: #b45309; }

.uh-total {
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.uh-combined { background: rgba(30, 48, 80, 0.06); }

.uh-band { text-align: center; font-weight: 600; }
.uh-band.band-critical { background: rgba(239, 68, 68, 0.18); color: #991b1b; }
.uh-band.band-at-risk { background: rgba(245, 158, 11, 0.18); color: #92400e; }
.uh-band.band-stable { background: rgba(59, 130, 246, 0.14); color: #1e40af; }
.uh-band.band-healthy { background: rgba(34, 197, 94, 0.16); color: #166534; }
.uh-band.band-insufficient-data { color: var(--text-secondary, #94a3b8); font-style: italic; }

.uh-footnote {
  padding: 8px 2px;
  font-size: 11px;
  color: var(--text-secondary, #64748b);
}

/* ── Spider Webs view (usage-health tab): small-multiple radar per client ── */

/* Frozen tile-area header: the snapshot and sort controls are pinned to the top
   of the scrolling .uh-body so the tile grid scrolls beneath them. The spoke-key
   strip lives in the page header (.uh-header-area) alongside the help note.
   Opaque with a z-index ABOVE the position:relative cards so scrolled tiles
   never bleed through, and flush at top:0 (the .uh-body has no top padding) so
   there is no gap to the page header above. */
.sw-frozen-head {
  position: sticky;
  top: 0;
  z-index: 20;
  background: #fff;
  border-bottom: 1px solid var(--border, #e2e8f0);
}

/* Compare + sort controls, pinned to the far right of the frozen head. */
.sw-panel-bar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 6px 2px 4px;
}

.sw-panel-bar { gap: 14px; }

.sw-ctrl {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.sw-ctrl label {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-primary, #334155);
}

.sw-ctrl-sort,
.sw-ctrl-sort-dir,
.sw-ctrl-mode,
.sw-ctrl-compare {
  min-width: 0;
}

/* Inside the panel bar the label + select sit on one line, not stacked. */
.sw-panel-bar .sw-ctrl-sort,
.sw-panel-bar .sw-ctrl-sort-dir,
.sw-panel-bar .sw-ctrl-mode,
.sw-panel-bar .sw-ctrl-compare {
  flex-direction: row;
  align-items: center;
  gap: 6px;
}

.sw-ctrl-sort select,
.sw-ctrl-sort-dir select,
.sw-ctrl-mode select,
.sw-ctrl-compare select {
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 4px;
  background: #fff;
  color: var(--text-primary, #334155);
  cursor: pointer;
}

.sw-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
  padding: 8px 2px 12px;
}
.sw-card {
  position: relative;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 6px;
  padding: 6px 6px 8px;
  background: #fff;
  cursor: pointer;
  transition: box-shadow .12s, border-color .12s;
}
.sw-unavailable {
  min-height: 178px;
  display: grid;
  place-items: center;
  padding: 12px;
  text-align: center;
  font-size: 11px;
  color: var(--text-secondary);
}
/* Per-tile "?" — hover shows a rich, sectioned card of every spoke's real
   m/q/y values (custom .sw-tip, JS-positioned in usage-health.ts). */
.sw-help {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 15px;
  height: 15px;
  line-height: 14px;
  text-align: center;
  font-size: 10px;
  font-weight: 700;
  color: #64748b;
  background: #f1f5f9;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 50%;
  cursor: help;
  /* NO z-index here on purpose. The "?" is position:absolute, so it already
     paints above the static card SVG. A z-index would make .sw-help a stacking
     context, which would TRAP its child .sw-tip (z-index:60) inside that context
     and let the sticky .sw-frozen-head (z-index:20) cover the tooltip. Keeping
     .sw-help context-free lets the fixed .sw-tip float to the root at z-index:60. */
}
.sw-help:hover { background: #e2e8f0; color: #1e293b; }

/* Rich per-tile tooltip. position:fixed + JS-set top/left (see the mouseover
   handler) so it never gets clipped by the scrolling web grid. Hidden until the
   "?" (its parent) is hovered; parked off-screen so the first paint before JS
   positions it isn't visible. */
.sw-tip {
  position: fixed;
  left: 0;
  top: -9999px;
  display: none;
  z-index: 60;
  box-sizing: border-box;
  /* Sized to hold the full metric breakdown without scrolling: wider so the
     intro and metric labels wrap less, and allowed to use the whole viewport
     height (the JS positioner clamps to the same 8px margin). The overflow
     values stay as a last-resort guard on very short viewports. */
  width: min(560px, calc(100vw - 16px));
  max-height: calc(100vh - 16px);
  overflow-x: hidden;
  overflow-y: auto;
  padding: 10px 11px 11px;
  background: #fff;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  box-shadow: rgba(15, 23, 42, 0.12) 0 6px 20px, rgba(15, 23, 42, 0.08) 0 2px 6px;
  text-align: left;
  font-weight: 400;
  color: var(--text-primary, #1e293b);
  cursor: default;
}
.sw-help:hover .sw-tip { display: block; }

.sw-tip-intro {
  margin: 0 0 7px;
  padding: 0 0 7px;
  border-bottom: 1px solid #e2e8f0;
  font-size: 10px;
  line-height: 1.4;
  color: #475569;
}

.sw-tip-head {
  font-size: 12px;
  font-weight: 700;
  color: #0f172a;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.sw-tip-db {
  display: block;
  font-size: 10px;
  font-weight: 400;
  color: #94a3b8;
  margin-top: 1px;
}
.sw-tip-sub {
  font-size: 10px;
  color: #64748b;
  margin: 4px 0 2px;
}
.sw-tip-sub b { color: #475569; font-weight: 700; }

.sw-tip-band {
  margin: 9px 0 2px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #2563eb;
  border-bottom: 1px solid #e2e8f0;
  padding-bottom: 2px;
}
.sw-tip-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11px;
}
/* Fixed layout pins the 31d/92d/365d columns to one width in every band table
   so their headers and values line up vertically down the whole tooltip. The
   score breakdown table has different columns and keeps auto sizing. */
.sw-tip-table:not(.sw-score-table) { table-layout: fixed; }
.sw-tip-table thead th {
  font-size: 9px;
  font-weight: 700;
  color: #94a3b8;
  text-align: right;
  padding: 2px 0 1px 6px;
}
/* One standard width for every period column; wide enough for a raw
   completed/sent fraction on the sw-tip-frac row. */
.sw-tip-table:not(.sw-score-table) thead th { width: 54px; }
.sw-tip-table thead th:first-child { text-align: left; width: auto; }
.sw-tip-table td {
  text-align: right;
  padding: 2px 0 2px 6px;
  font-variant-numeric: tabular-nums;
  color: #1e293b;
  white-space: nowrap;
}
.sw-tip-table th[scope="row"] {
  text-align: left;
  font-weight: 500;
  color: #334155;
  padding: 2px 0 2px 0;
}
.sw-tip-unit {
  display: block;
  font-size: 9px;
  font-weight: 400;
  color: #94a3b8;
}
/* Raw ratio operands sit on their own row rather than inside the value cell,
   which keeps the value columns at the standard width. */
.sw-tip-frac th[scope="row"],
.sw-tip-frac td {
  font-size: 8.5px;
  color: #94a3b8;
  padding-top: 0;
}
.sw-tip-frac th[scope="row"] { font-weight: 400; padding-left: 10px; }
.sw-tip-frac td { overflow: hidden; text-overflow: ellipsis; }
.sw-tip-spoke th {
  text-align: left;
  font-size: 10.5px;
  font-weight: 700;
  color: #475569;
  padding: 5px 0 1px;
}
.sw-tip-part th[scope="row"] { padding-left: 10px; font-weight: 400; color: #64748b; }
.sw-tip-na { color: #cbd5e1; }
.sw-card:hover { border-color: #94a3b8; box-shadow: 0 1px 6px rgba(30, 48, 80, .12); }
.sw-name {
  font-size: 11px;
  font-weight: 600;
  color: var(--text-primary, #1e293b);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 2px;
}
/* Headline SW score at the top of each tile — a weighted mean of the seven
   spokes' 0–10 month values. The inline "?" (its own tooltip) sits beside it,
   separate from the top-right tile "?". */
.sw-score {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.1;
  color: #0f172a;
  font-variant-numeric: tabular-nums;
  margin-bottom: 3px;
}
/* The score's own "?" overrides the absolute top-right positioning of the tile
   "?" so it flows inline next to the number; it keeps the .sw-help circle look,
   hover and .sw-tip child behaviour. NO z-index (same stacking-trap reason as
   .sw-help — see the .sw-help note above). */
.sw-score-help {
  position: static;
  width: 13px;
  height: 13px;
  line-height: 12px;
  font-size: 9px;
}
/* Lifecycle dates are card metadata, not Spider dimensions: they stay beneath
   every web without changing its score, geometry, or comparison treatment. */
.sw-lifecycle {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 2px 6px;
  margin: 3px 2px 0;
  padding-top: 5px;
  border-top: 1px solid #edf1f5;
  font-size: 10px;
  line-height: 1.25;
  color: var(--text-secondary, #64748b);
}
.sw-lifecycle-label { font-weight: 600; }
.sw-lifecycle-value { font-variant-numeric: tabular-nums; }
.sw-score-table .sw-score-op { color: #94a3b8; padding: 2px 2px; width: auto; text-align: center; }
.sw-score-table tfoot .sw-score-total th,
.sw-score-table tfoot .sw-score-total td {
  border-top: 1px solid #cbd5e1;
  padding-top: 4px;
  font-weight: 700;
  color: #0f172a;
}
.sw-score-table tfoot .sw-score-total td[colspan] { text-align: right; color: #64748b; font-weight: 500; }

.sw-svg { display: block; width: 100%; height: auto; overflow: visible; }
.sw-ring { fill: none; stroke: rgba(30, 48, 80, .10); stroke-width: 1; }
.sw-axis { stroke: rgba(30, 48, 80, .10); stroke-width: 1; }
.sw-axis-dotted,
.sw-axis-dashed {
  stroke: rgba(71, 85, 105, .72);
  stroke-width: 1.4;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}
/* No value exists for this spoke in the displayed snapshot, or in either side
   of a comparison. */
.sw-axis-dotted { stroke-dasharray: 1 3; }
/* Exactly one side of a comparison has data; numeric zero remains a solid spoke. */
.sw-axis-dashed { stroke-dasharray: 5 3; }
/* Month polygon — outline only, NO fill. The blue shade was dropped so the
   red/green crossing quads underneath read clearly (small month-vs-baseline
   deltas were being masked by the tint). */
.sw-poly {
  fill: none;
  stroke: #2563eb;
  stroke-width: 1.6;
  stroke-linejoin: round;
}

/* Crossing render (the kept "D" treatment): a faint comparison baseline ring,
   the bold month outline, and per-edge quads shaded green (month above the
   baseline) / red (below). Month is outline-only — never filled. */
.sw-poly-year {
  fill: rgba(100, 116, 139, .10);
  stroke: rgba(100, 116, 139, .55);
  stroke-width: 1;
  stroke-linejoin: round;
}
.sw-poly-month {
  fill: none;
  stroke: #2563eb;
  stroke-width: 1.6;
  stroke-linejoin: round;
}
.sw-cross-up { fill: rgba(34, 197, 94, .28); stroke: none; }
.sw-cross-down { fill: rgba(239, 68, 68, .26); stroke: none; }
/* Per-web spoke keys — small, muted, drawn just past the outer ring. */
.sw-spoke-label {
  font-size: 7px;
  font-weight: 600;
  fill: #64748b;
  pointer-events: none;
}

/* Spider Webs header: title first, then a compact details row with the full
   eight-spoke key. RR scoring details now live beside their Key entries. */
.sw-header { padding-bottom: 8px; }
.sw-header .uh-title { padding-bottom: 6px; }
.sw-header-details { padding: 0 12px; }
.sw-legend {
  min-width: 620px;
  margin: 0;
  padding: 4px 10px 7px;
  border: 1px solid var(--border, #e2e8f0);
  border-radius: 6px;
}
.sw-legend-title {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #64748b;
  padding: 0 4px;
}
.sw-legend-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1px;
  margin: 0;
  padding: 0 0 0 16px;
  list-style: disc;
  font-size: 11px;
  line-height: 1.35;
  color: var(--text-primary, #334155);
}
.sw-legend-list li {
  margin: 0;
  white-space: nowrap;
}
.sw-legend-key {
  font-weight: 700;
  color: #475569;
  margin-right: 2px;
}
.sw-legend-equals { color: #94a3b8; }
.sw-legend-parts { color: var(--text-secondary, #94a3b8); }
.sw-legend-help {
  position: relative;
  top: auto;
  right: auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  margin: 0 3px 0 1px;
  padding: 0;
  font: inherit;
  line-height: 1;
  vertical-align: text-bottom;
  appearance: none;
}
.sw-legend-help:focus-visible {
  outline: 2px solid #2563eb;
  outline-offset: 1px;
}
.sw-help:focus .sw-tip,
.sw-help:focus-within .sw-tip { display: block; }
.sw-legend-tip { width: min(300px, calc(100vw - 16px)); }
/* The fixed Responses policy compares six ARR rows side-by-side. Keep its table
   readable on desktop and horizontally contained rather than widening the viewport. */
.sw-response-band-tip { width: min(760px, calc(100vw - 16px)); overflow-x: auto; }
.sw-response-band-table {
  width: 100%;
  min-width: 680px;
  border-collapse: collapse;
  font-size: 9px;
  line-height: 1.25;
  font-variant-numeric: tabular-nums;
}
.sw-response-band-table th,
.sw-response-band-table td { padding: 3px 4px; border: 1px solid #e2e8f0; white-space: nowrap; }
.sw-response-band-table thead th { background: #f8fafc; color: #475569; font-weight: 700; text-align: center; }
.sw-response-band-table tbody th { background: #f8fafc; color: #475569; text-align: center; }
.sw-response-band-table td { text-align: right; }
.sw-legend-tip-title {
  display: block;
  margin-bottom: 4px;
  font-size: 12px;
  font-weight: 700;
  color: #0f172a;
}
.sw-legend-tip-copy {
  display: block;
  margin-bottom: 8px;
  font-size: 11px;
  line-height: 1.4;
  color: #475569;
}
.sw-rr-bands-list {
  display: grid;
  width: fit-content;
  border: 1px solid #e2e8f0;
  font-size: 10px;
  line-height: 1.25;
}
.sw-rr-band {
  display: grid;
  grid-template-columns: 36px minmax(68px, auto);
}
.sw-rr-band + .sw-rr-band { border-top: 1px solid #e2e8f0; }
.sw-rr-band-score,
.sw-rr-band-range {
  padding: 2px 5px;
  white-space: nowrap;
}
.sw-rr-band-score {
  text-align: center;
  background: #f8fafc;
  color: #475569;
  font-weight: 700;
  border-right: 1px solid #e2e8f0;
}
.sw-rr-band-range {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.sw-spoke-style {
  margin-left: 12px;
  font-size: 11px;
  font-weight: 400;
  line-height: 1.45;
  color: var(--text-secondary, #64748b);
}
.sw-spoke-style b { color: var(--text-primary, #334155); }
@media (max-width: 720px) {
  .sw-legend { min-width: 0; }
  .sw-legend-list li { white-space: normal; }
  .sw-spoke-style { display: block; margin: 4px 0 0; }
}

#insights-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  background: #fff;
  overflow: hidden;
}

#insights-panel {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
}

.insights-header-area {
  background: #fff;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
  position: relative;
  z-index: 4; /* above the sticky table headers (z-index:2) */
}

.insights-title {
  padding: 12px 12px 4px;
  font-size: 16px;
  font-weight: 600;
  color: var(--text-primary);
}

.insights-help-note {
  padding: 0 12px 8px;
  font-size: 11px;
  color: var(--text-secondary, #64748b);
  line-height: 1.4;
}

.insights-totals-row td {
  position: sticky;
  bottom: 0;
  background: #f8fafc;
  border: 1px solid rgba(30,48,80,0.12);
  border-top: 2px solid var(--border, #e2e8f0);
  padding: 4px 10px;
  font-weight: 700;
  vertical-align: middle;
  z-index: 2;
}

/* Match the data cells' number styling so columns line up exactly. */
.insights-totals-row td.num {
  text-align: center;
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  max-width: 92px;
}

.insights-totals-label {
  text-transform: uppercase;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-secondary, #64748b);
}

.fixed-metric-star {
  color: #d97706;
  font-weight: 700;
  margin-left: 1px;
  cursor: help;
}

.insights-table-wrap {
  flex: 1;
  overflow: auto;
  /* Tuck up under the opaque header block (z-index:4) so its bottom edge
     covers the 1–2px seam where scrolled rows would otherwise bleed through
     above the sticky column headers. */
  margin-top: -2px;
  position: relative;
  z-index: 1;
}

.insights-summary {
  display: flex;
  align-items: center;
  gap: 12px;
}

.insights-summary .cache-date {
  margin-left: auto;
}

.insights-refresh-btn {
  margin-left: auto;
  padding: 6px 12px;
  font-size: 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-card);
  color: var(--text-primary);
  cursor: pointer;
  transition: background 0.15s;
}

.insights-refresh-btn:hover:not(:disabled) {
  background: var(--bg-primary);
  border-color: var(--accent);
  color: var(--accent);
}

.insights-refresh-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.insights-table th.num {
  text-align: center;
  max-width: 92px;
  width: 92px;
  white-space: normal;
  word-wrap: break-word;
  overflow-wrap: break-word;
  overflow: visible;
}

.insights-table th.sortable-th {
  cursor: pointer;
  user-select: none;
}

.insights-table th.sortable-th:hover {
  background: #f4f4f4;
  color: var(--text-primary);
}

.expand-arrow {
  font-size: 11px;
  color: var(--text-secondary);
  margin-right: 4px;
  flex-shrink: 0;
}

.insights-row.expanded .expand-arrow {
  color: var(--accent);
}

.insights-table th:first-child,
.insights-table td:first-child {
  width: 180px;
  min-width: 180px;
}

.insights-table th:nth-child(2),
.insights-table td:nth-child(2) {
  width: 145px;
}

.insights-table td.insights-calendar {
  overflow: hidden;
}

.vtab .insights-icon {
  color: #fff;
  background: #333;
}

.vtab:hover .insights-icon,
.vtab.active .insights-icon {
  color: var(--red, #e74c3c);
  background: #fff;
}

/* ─── Cache Status tab (internal id: debug) ─── */
/* Mappings: authoritative relationship decisions with local/API editing and S3 read-only projection. */
#mappings-layout { flex-direction: column; }
#mappings-header {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  padding: 12px 20px; border-bottom: 1px solid var(--border); background: var(--bg-secondary);
}
#mappings-header .sidebar-heading { text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
#mappings-header .sidebar-note { max-width: 760px; padding: 0; }
.mappings-header-text { min-width: 0; }
.mappings-header-side { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; flex: none; }
.mappings-filters { display: flex; align-items: center; gap: 8px; flex: none; }
.mappings-filters input { width: 250px; }
.mappings-filters select { width: auto; min-width: 128px; }
/* Salesforce export upload: local app only, so it never renders in S3 mode. */
.mappings-actions { display: flex; align-items: center; justify-content: flex-end; gap: 10px; }
.mappings-actions .publish-btn { padding: 6px 12px; white-space: nowrap; cursor: pointer; }
.mappings-actions .publish-btn:disabled { opacity: 0.6; cursor: default; }
.mappings-upload-status { max-width: 420px; color: var(--text-secondary); font-size: 11px; line-height: 1.35; text-align: right; }
.mappings-upload-status:empty { display: none; }
.mappings-upload-status.busy { color: #1d4ed8; }
.mappings-upload-status.ok { color: #15803d; }
/* A refused upload and a half-finished import read very differently, so the
   status line carries the distinction in colour as well as in words. */
.mappings-upload-status.warn { color: #b45309; }
.mappings-upload-status.error { color: #b91c1c; }
#mappings-panel { flex: 1; min-height: 0; padding: 16px 20px; overflow: auto; }
.mp-workspace { display: grid; grid-template-columns: minmax(176px, 208px) minmax(0, 1fr); gap: 16px; align-items: start; }
.mp-mode-panel { position: sticky; top: 0; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.mp-mode-kicker { display: block; margin: 0 4px 8px; color: var(--text-secondary); font-size: 10px; font-weight: 700; letter-spacing: 0.45px; text-transform: uppercase; }
.mp-mode-list { display: flex; flex-direction: column; gap: 4px; }
.mp-mode-btn { width: 100%; padding: 9px 10px; border: 1px solid transparent; border-radius: 6px; background: transparent; color: var(--text-secondary); text-align: left; cursor: pointer; }
.mp-mode-btn:hover { background: rgba(37,99,235,0.06); color: var(--text-primary); }
.mp-mode-btn.active { border-color: rgba(37,99,235,0.35); background: rgba(37,99,235,0.09); color: #1d4ed8; }
.mp-mode-btn strong, .mp-mode-btn small { display: block; }
.mp-mode-btn strong { font-size: 12px; }
.mp-mode-btn small { margin-top: 2px; color: var(--text-secondary); font-size: 10px; font-weight: 400; line-height: 1.35; }
.mp-view-content { min-width: 0; }

/* Create panel: bulk-link imported Salesforce Accounts, Client Platforms and CG Internal Accounts. */
.mp-create {
  margin-bottom: 16px; border: 1px solid rgba(37,99,235,0.30); border-radius: 8px;
  background: var(--bg-card); box-shadow: 0 1px 3px rgba(0,0,0,0.06); overflow: hidden;
}
.mp-create-head {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--border); background: rgba(37,99,235,0.05);
}
.mp-create-intro { display: flex; flex-direction: column; gap: 2px; min-width: 240px; flex: 1 1 320px; }
.mp-create-intro strong { font-size: 13px; }
.mp-create-intro small { color: var(--text-secondary); font-size: 11px; line-height: 1.4; }
.mp-create-flows { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
.mp-create-flow {
  display: flex; flex-direction: column; gap: 2px; min-width: 168px; max-width: 240px; padding: 7px 10px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--bg-card);
  color: var(--text-secondary); text-align: left; cursor: pointer;
}
.mp-create-flow:hover { border-color: rgba(37,99,235,0.35); background: rgba(37,99,235,0.06); }
.mp-create-flow.active { border-color: rgba(37,99,235,0.45); background: rgba(37,99,235,0.10); color: #1d4ed8; }
.mp-create-flow strong { font-size: 11px; }
.mp-create-flow small { font-size: 10px; font-weight: 400; line-height: 1.3; color: var(--text-secondary); }
.mp-create-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1px; background: var(--border); }
.mp-create-col { display: flex; flex-direction: column; min-width: 0; background: var(--bg-card); }
.mp-create-col-head {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 14px;
  border-bottom: 1px solid var(--border); background: var(--bg-secondary);
  color: var(--text-secondary); font-size: 10px; font-weight: 700; letter-spacing: 0.35px; text-transform: uppercase;
}
.mp-create-col-head > span { flex: 1 1 auto; min-width: 0; }
.mp-create-col-head input { flex: 0 1 150px; min-width: 96px; font-size: 11px; font-weight: 400; letter-spacing: 0; text-transform: none; }
.mp-create-kinds { display: flex; gap: 4px; flex: 1 1 100%; }
.mp-create-kind {
  flex: 1 1 0; padding: 4px 8px; border: 1px solid var(--border); border-radius: 5px;
  background: var(--bg-card); color: var(--text-secondary); font: inherit; font-size: 10px;
  text-align: left; cursor: pointer;
}
.mp-create-kind.active { border-color: rgba(37,99,235,0.45); background: rgba(37,99,235,0.10); color: #1d4ed8; }
.mp-create-list { display: flex; flex-direction: column; gap: 3px; max-height: 264px; padding: 7px; overflow: auto; }
/* The global `button` rule paints text #fff for its accent background; every
   transparent .mp-* button must therefore restate its own colour or its text
   renders white on white (the option name did, until 2026-09-22). */
.mp-create-option {
  display: flex; flex-direction: column; gap: 3px; width: 100%; padding: 6px 9px;
  border: 1px solid transparent; border-radius: 6px; background: transparent;
  color: var(--text-primary); text-align: left; cursor: pointer;
}
.mp-create-option:hover:not(:disabled) { border-color: var(--border); background: rgba(120,120,120,0.05); }
.mp-create-option.selected { border-color: rgba(37,99,235,0.45); background: rgba(37,99,235,0.09); }
.mp-create-option:disabled { opacity: 0.5; cursor: default; }
.mp-create-option:focus-visible { outline: 2px solid #2563eb; outline-offset: 1px; }
/* Names are flush left in every column: a button centres its text by default. */
.mp-create-option-main { display: flex; justify-content: flex-start; align-items: baseline; gap: 7px; flex-wrap: wrap; min-width: 0; text-align: left; }
.mp-create-option-main strong { font-size: 12px; text-align: left; overflow-wrap: anywhere; }
.mp-create-option-main code { color: var(--text-secondary); font-size: 10px; overflow-wrap: anywhere; }
.mp-create-option-chips { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; }
.mp-create-option-chips .mp-meta { font-size: 10px; }
.mp-create-option > small { color: var(--text-secondary); font-size: 10px; line-height: 1.35; overflow-wrap: anywhere; }
.mp-create-empty { padding: 16px 10px; color: var(--text-secondary); font-size: 11px; line-height: 1.45; text-align: center; }
.mp-create-note { padding: 12px 14px; color: var(--text-secondary); font-size: 11px; line-height: 1.5; }
.mp-create-note p { margin: 0 0 8px; }
.mp-create-note p:last-child { margin-bottom: 0; }
.mp-create-note strong { color: var(--text-primary); font-size: 12px; overflow-wrap: anywhere; }
.mp-create-footer {
  display: grid; grid-template-columns: minmax(220px, 1fr) minmax(280px, 1.2fr); gap: 12px 16px;
  align-items: start; padding: 10px 14px; border-top: 1px solid var(--border); background: var(--bg-secondary);
}
.mp-create-reason { display: flex; flex-direction: column; gap: 4px; color: var(--text-secondary); font-size: 11px; font-weight: 700; }
.mp-create-reason textarea { width: 100%; min-height: 46px; padding: 7px; font-weight: 400; resize: vertical; }
.mp-create-actions { display: flex; justify-content: flex-end; align-items: center; gap: 12px; flex-wrap: wrap; }
.mp-create-summary { flex: 1 1 160px; color: var(--text-secondary); font-size: 11px; line-height: 1.4; }
.mp-create-buttons { display: flex; align-items: center; gap: 8px; }
.mp-create-buttons button { padding: 6px 10px; cursor: pointer; }
.mp-create-buttons .publish-btn { min-width: 116px; }
.mp-create-footer .error-msg { grid-column: 1 / -1; }

.mp-summary {
  display: flex; justify-content: space-between; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 12px 16px; margin-bottom: 14px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--bg-card); box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.mp-summary-intro { display: flex; flex-direction: column; gap: 2px; font-size: 12px; color: var(--text-secondary); }
.mp-summary-intro strong { color: var(--text-primary); font-size: 14px; }
.mp-summary-intro small { font-size: 11px; }
.mp-summary-stats { display: flex; align-items: stretch; gap: 6px; flex-wrap: wrap; }
/* Summary tiles are the tab's filter bar, so they are <button>s — hence the font/text
   resets. Active and hover states match .mp-status below, which is the same control at
   row level. A zero-count tile is disabled: its filter can only produce the empty state. */
.mp-stat {
  display: inline-flex; flex-direction: column; gap: 1px; min-width: 72px; padding: 5px 8px;
  border: 1px solid var(--border); border-radius: 6px; font: inherit; font-size: 10px;
  text-align: left; color: var(--text-secondary); background: transparent; cursor: pointer;
}
.mp-stat strong { color: var(--text-primary); font-size: 14px; font-variant-numeric: tabular-nums; }
.mp-stat.ok { border-color: rgba(25,173,121,0.32); background: rgba(25,173,121,0.08); }
.mp-stat.warn { border-color: rgba(245,166,35,0.42); background: rgba(245,166,35,0.10); }
.mp-stat.review { border-color: rgba(139,92,246,0.34); background: rgba(139,92,246,0.08); }
.mp-stat.error { border-color: rgba(239,68,68,0.36); background: rgba(239,68,68,0.08); }
.mp-stat:hover:not(:disabled) { filter: brightness(0.97); }
.mp-stat:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
.mp-stat.active { box-shadow: inset 0 0 0 1px currentColor, 0 0 0 2px rgba(37,99,235,0.16); }
.mp-stat:disabled { opacity: 0.55; cursor: default; }

.mp-groups { display: flex; flex-direction: column; gap: 12px; }
.mp-group { min-width: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); }
.mp-unmapped-group { border-color: rgba(245,166,35,0.48); }
.mp-account-head {
  display: grid; grid-template-columns: minmax(220px, 1.4fr) minmax(150px, 1fr) auto; gap: 12px;
  align-items: center; padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--bg-secondary);
}
.mp-account-title { display: flex; align-items: center; gap: 7px; min-width: 0; }
.mp-account-title strong { overflow-wrap: anywhere; }
.mp-account-id, .mp-source { color: var(--text-secondary); font-size: 11px; }
.mp-account-id { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.mp-account-meta, .mp-account-count { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 12px; }
.mp-account-count { justify-content: flex-end; color: var(--text-secondary); white-space: nowrap; }
.mp-meta { display: inline-block; padding: 2px 7px; border-radius: 10px; border: 1px solid var(--border); background: var(--bg-card); color: var(--text-secondary); font-size: 11px; }
.mp-meta.icp { border-color: rgba(37,99,235,0.32); background: rgba(37,99,235,0.08); color: #2563eb; font-weight: 700; }
/* "No longer exported" — the Salesforce Account has left the export and its values
   are a retained snapshot. Amber, matching .mp-missing: a fact about the source
   record needing attention, not an error and not a filterable mapping status. */
.mp-retired-account { display: inline-block; padding: 2px 7px; border-radius: 10px; border: 1px solid rgba(180,83,9,0.32); background: rgba(217,119,6,0.09); color: #b45309; font-size: 11px; font-weight: 600; cursor: help; white-space: nowrap; }
/* The cell is a flex column, so the chip stretches full width without this. */
.mp-salesforce-name .mp-retired-account { align-self: flex-start; margin-top: 1px; font-size: 10px; }
.mp-source { cursor: help; }
.mp-account-note { grid-column: 1 / -1; margin-top: 6px; color: var(--text-secondary); font-size: 12px; line-height: 1.4; }

.mp-primary-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-secondary); font-size: 12px; }
.mp-primary-head > div { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mp-primary-head strong { color: var(--text-primary); font-size: 13px; overflow-wrap: anywhere; }
.mp-primary-head > span { flex: none; white-space: nowrap; }
.mp-platform-head, .mp-platform-row {
  display: grid; grid-template-columns: minmax(220px, 1fr) 70px minmax(300px, 2fr) minmax(150px, auto);
  gap: 12px; align-items: center;
}
.mp-platform-primary-head, .mp-platform-primary-row {
  display: grid; grid-template-columns: minmax(180px, 1fr) minmax(180px, 1fr) 55px minmax(220px, 1.3fr) minmax(150px, auto);
  gap: 12px; align-items: center;
}
.mp-platform-head, .mp-platform-primary-head { padding: 7px 14px; border-bottom: 1px solid var(--border); color: var(--text-secondary); font-size: 10px; font-weight: 700; letter-spacing: 0.35px; text-transform: uppercase; }
.mp-platform-row, .mp-platform-primary-row { min-width: 0; padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 12px; }
.mp-platform-row:last-child, .mp-platform-primary-row:last-child { border-bottom: 0; }
.mp-platform-row:hover, .mp-platform-primary-row:hover { background: rgba(120,120,120,0.04); }
.mp-platform-name, .mp-salesforce-name { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.mp-platform-name strong, .mp-salesforce-name strong { overflow-wrap: anywhere; }
.mp-platform-name code, .mp-salesforce-name code { color: var(--text-secondary); font-size: 11px; overflow-wrap: anywhere; }
.mp-region { display: inline-block; min-width: 25px; font-weight: 700; color: var(--text-secondary); }

.mp-internal-list { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; min-width: 0; }
.mp-internal { display: inline-flex; align-items: baseline; gap: 5px; max-width: 100%; padding: 3px 7px; border: 1px solid var(--border); border-radius: 5px; font-size: 11px; cursor: help; overflow-wrap: anywhere; }
.mp-internal.high { border-color: rgba(25,173,121,0.42); background: rgba(25,173,121,0.08); }
.mp-internal.medium { border-color: rgba(245,166,35,0.48); background: rgba(245,166,35,0.10); }
.mp-internal.low { border-color: rgba(148,163,184,0.48); background: rgba(148,163,184,0.10); }
.mp-internal small { color: var(--text-secondary); font-size: 9px; white-space: nowrap; }

.mp-status-list { display: flex; justify-content: flex-end; gap: 4px; flex-wrap: wrap; }
.mp-status { display: inline-block; padding: 3px 8px; border: 0; border-radius: 10px; font: inherit; font-size: 10px; font-weight: 700; line-height: 1.2; white-space: nowrap; cursor: pointer; }
.mp-status:hover { filter: brightness(0.96); }
.mp-status.active { box-shadow: inset 0 0 0 1px currentColor, 0 0 0 2px rgba(37,99,235,0.16); }
.mp-status:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
.mp-status.complete { color: var(--accent); background: rgba(25,173,121,0.12); }
.mp-status.warn { color: #b45309; background: rgba(245,166,35,0.16); }
.mp-status.review { color: #6d28d9; background: rgba(139,92,246,0.13); }
.mp-status.error { color: #dc2626; background: rgba(239,68,68,0.12); }
.mp-missing { color: #b45309; font-size: 11px; font-style: italic; }
.mp-no-platform { padding: 14px; color: var(--text-secondary); font-size: 12px; }
.mp-no-platform .mp-account-note { margin-top: 8px; }
.mp-orphans { margin-bottom: 12px; padding: 10px 14px; border: 1px solid rgba(239,68,68,0.34); border-radius: 8px; background: rgba(239,68,68,0.06); color: var(--text-secondary); font-size: 12px; line-height: 1.55; }
.mp-orphans strong, .mp-orphans span { display: block; }
.mp-orphans strong { color: #dc2626; }
.mp-orphans span { margin-bottom: 4px; }
.mp-orphans code { color: var(--text-primary); font-size: 11px; }
.mp-empty { min-height: 180px; }
.mp-edit-mode { margin-top: 3px; color: var(--text-secondary); font-size: 11px; }
.mp-edit-mode.editable { color: var(--accent); font-weight: 700; }
.mp-notice { margin-top: 3px; color: #2563eb; font-size: 11px; font-weight: 600; }
.mp-edit-btn {
  padding: 3px 9px; border: 1px solid rgba(37,99,235,0.35); border-radius: 5px;
  background: rgba(37,99,235,0.08); color: #2563eb; font-size: 10px; font-weight: 700; cursor: pointer;
}
.mp-edit-btn:hover { background: rgba(37,99,235,0.15); }
.mp-editor-modal { width: min(920px, calc(100vw - 32px)); max-height: min(760px, calc(100vh - 32px)); }
.mp-editor-modal .modal-header > div { min-width: 0; }
.mp-editor-modal .modal-header h2 { margin-bottom: 2px; }
.mp-editor-modal .modal-header small { color: var(--text-secondary); overflow-wrap: anywhere; }
.mp-editor-body { overflow: auto; }
.mp-editor-label { display: flex; flex-direction: column; gap: 5px; margin-bottom: 16px; color: var(--text-secondary); font-size: 12px; font-weight: 700; }
.mp-editor-label select, .mp-editor-label textarea { width: 100%; }
.mp-editor-label textarea { min-height: 72px; padding: 8px; resize: vertical; }
.mp-editor-section-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin: 4px 0 8px; }
.mp-editor-section-head > div { display: flex; flex-direction: column; gap: 2px; }
.mp-editor-section-head small { color: var(--text-secondary); font-size: 11px; font-weight: 400; }
.mp-editor-section-head button, .mp-editor-actions button, .mp-editor-remove { padding: 6px 10px; cursor: pointer; }
#mp-editor-internals { display: flex; flex-direction: column; gap: 7px; margin-bottom: 16px; }
.mp-editor-internal { display: grid; grid-template-columns: minmax(180px, 1.1fr) 115px minmax(180px, 1fr) auto; gap: 7px; }
.mp-editor-internal input, .mp-editor-internal select { width: 100%; min-width: 0; }
.mp-editor-remove { color: #dc2626; }
.mp-editor-empty { padding: 14px; border: 1px dashed var(--border); border-radius: 6px; color: var(--text-secondary); font-size: 12px; }
.mp-editor-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }
.mp-editor-actions .publish-btn { min-width: 110px; }

@media (max-width: 1050px) {
  #mappings-header { flex-direction: column; }
  .mappings-filters { width: 100%; flex-wrap: wrap; }
  .mappings-filters input { flex: 1 1 240px; }
  .mp-account-head { grid-template-columns: minmax(220px, 1fr) auto; }
  .mp-account-meta { grid-column: 1 / -1; }
  .mp-platform-head, .mp-platform-row { grid-template-columns: minmax(180px, 1fr) 55px minmax(220px, 1.4fr) minmax(130px, auto); gap: 9px; }
  .mp-platform-primary-head, .mp-platform-primary-row { grid-template-columns: minmax(160px, 1fr) minmax(150px, 1fr) 45px minmax(180px, 1.2fr) minmax(120px, auto); gap: 9px; }
}
@media (max-width: 850px) {
  .mp-workspace { grid-template-columns: 1fr; }
  .mp-mode-panel { position: static; }
  .mp-mode-list { flex-direction: row; }
  .mp-mode-btn { flex: 1 1 0; }
  .mp-create-body { grid-template-columns: 1fr; }
  .mp-create-footer { grid-template-columns: 1fr; }
  .mp-create-actions { justify-content: space-between; }
}
@media (max-width: 700px) {
  #mappings-panel, #mappings-header { padding-left: 12px; padding-right: 12px; }
  .mappings-filters > * { flex: 1 1 100%; }
  .mappings-filters select { min-width: 0; }
  .mp-mode-list { flex-direction: column; }
  .mp-create-flows { width: 100%; }
  .mp-create-flow { flex: 1 1 100%; max-width: none; }
  .mp-create-col-head input { flex: 1 1 100%; }
  .mp-summary-stats { width: 100%; }
  .mp-stat { flex: 1 1 105px; }
  .mp-account-head { display: flex; align-items: flex-start; flex-direction: column; gap: 7px; }
  .mp-account-count { justify-content: flex-start; white-space: normal; }
  .mp-platform-head, .mp-platform-primary-head { display: none; }
  .mp-platform-row, .mp-platform-primary-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px 12px; }
  .mp-platform-row > div:nth-child(3), .mp-platform-primary-row > div:nth-child(4) { grid-column: 1 / -1; }
  .mp-platform-primary-row > div:nth-child(2), .mp-platform-primary-row > div:nth-child(3) { grid-column: 1 / -1; }
  .mp-status-list { justify-content: flex-start; }
  .mp-editor-internal { grid-template-columns: 1fr; }
}

/* Single column: heading/search header on top, region blocks below (no sidebar). */
#debug-layout { flex-direction: column; }
#debug-header {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  padding: 12px 20px; border-bottom: 1px solid var(--border); background: var(--bg-secondary);
}
#debug-header .sidebar-heading { text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
#debug-header .sidebar-note { max-width: 760px; padding: 0; }
#debug-header #debug-search-input { width: 220px; flex: none; }
#debug-panel { flex: 1; min-height: 0; padding: 16px 20px; overflow: auto; }
.muted { color: #94a3b8; }
.small { font-size: 11px; }
.sidebar-note .muted { color: #94a3b8; }

/* Estate-wide summary bar */
.cs-summary {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  padding: 12px 16px; margin-bottom: 14px; flex-wrap: wrap;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.cs-summary-main { font-size: 14px; }
.cs-scope { font-weight: 700; }
.cs-dims { color: var(--text-secondary); margin-left: 4px; }
.cs-dims strong { color: var(--text-primary); }
.cs-ico { font-weight: 700; margin-right: 4px; }
.cs-ico.ok { color: var(--accent); }
.cs-ico.warn { color: #d97706; }
.cs-summary-flags { display: flex; gap: 6px; flex-wrap: wrap; }
.cs-flag { display: inline-block; padding: 2px 9px; border-radius: 10px; font-size: 12px; font-weight: 600; }
.cs-flag.ok { background: rgba(25,173,121,0.12); color: var(--accent); }
.cs-flag.warn, .cs-flag.miss { background: rgba(245,166,35,0.16); color: #b45309; }
.cs-flag.stale, .cs-flag.err { background: rgba(239,68,68,0.12); color: #dc2626; }

/* Disclosure arrow for the Cache Status <details> cards. Their <summary> is
   display:flex, which suppresses the native marker, so a rotating ▸ is drawn in
   its place — matching .section-collapse / .country-variants elsewhere. */
.cs-timing > summary,
.cs-mapping-card > summary { list-style: none; }
.cs-timing > summary::-webkit-details-marker,
.cs-mapping-card > summary::-webkit-details-marker { display: none; }
.cs-timing > summary::before,
.cs-mapping-card > summary::before {
  content: '▸';
  flex: none;
  display: inline-block;
  font-size: 10px;
  line-height: 1;
  color: var(--text-secondary);
  transition: transform 0.15s;
}
.cs-timing[open] > summary::before,
.cs-mapping-card[open] > summary::before { transform: rotate(90deg); }

/* Refresh timing log */
.cs-timing { border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); margin-bottom: 14px; overflow: hidden; }
.cs-timing > summary { display: flex; align-items: baseline; gap: 10px; padding: 9px 14px; cursor: pointer; font-size: 13px; font-weight: 700; }
.cs-timing > summary:hover { background: rgba(120,120,120,0.05); }
.cs-timing-body { border-top: 1px solid var(--border); padding: 4px 14px 10px; }
.cs-tjob { padding: 9px 0; border-bottom: 1px solid var(--border); }
.cs-tjob:last-child { border-bottom: 0; }
.cs-tjob-head { display: flex; align-items: center; gap: 9px; flex-wrap: wrap; font-size: 13px; }
.cs-ttier { padding: 2px 8px; border-radius: 10px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; background: rgba(59,130,246,0.12); color: #2563eb; }
.cs-ttier.heavy, .cs-ttier.full { background: rgba(147,51,234,0.12); color: #7c3aed; }
.cs-twhen { font-weight: 600; }
.cs-tdur { font-variant-numeric: tabular-nums; font-weight: 700; }
.cs-trun { margin: 7px 0 0 14px; padding-left: 10px; border-left: 2px solid var(--border); }
.cs-trun-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 12px; }
.cs-trun-region { min-width: 26px; font-weight: 700; }
.cs-trun-dur { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.cs-tbar { display: flex; height: 8px; margin: 5px 0 4px; border-radius: 4px; overflow: hidden; background: var(--bg-primary); }
.cs-tseg { height: 100%; }
.cs-tlegs { display: flex; gap: 12px; flex-wrap: wrap; font-size: 11px; color: var(--text-secondary); }
.cs-tleg { display: inline-flex; align-items: center; gap: 5px; }
.cs-tswatch { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }
/* One tint per refresh PHASE LABEL (see PHASE_TINT_BY_LABEL in src/debug.ts) —
   never per position, so a phase keeps the same colour in every region and tier. */
.cs-tph0 { background: #3b82f6; }   /* CG Internal NPS (both tier labels) */
.cs-tph1 { background: #64748b; }   /* tenant list */
.cs-tph2 { background: #0ea5e9; }   /* login insights */
.cs-tph3 { background: #8b5cf6; }   /* history backfill */
.cs-tph4 { background: #f5a623; }   /* all-time + derive */
.cs-tph5 { background: #19ad79; }   /* derive windows */
.cs-tph6 { background: #db2777; }   /* rebuild bundles */
.cs-tslow { margin-top: 4px; font-size: 11px; color: var(--text-secondary); }
.cs-tnote { padding: 8px 0 2px; }

/* Reference-data mapping audit */
.cs-mapping-audit { margin-bottom: 14px; }
.cs-mapping-title { display: flex; align-items: baseline; gap: 8px; margin: 0 2px 7px; }
.cs-mapping-grid { display: grid; grid-template-columns: repeat(3, minmax(260px, 1fr)); gap: 10px; }
.cs-mapping-card { min-width: 0; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); overflow: hidden; }
/* The ::before disclosure arrow is the first flex child, so the count is pinned
   right with margin-left:auto rather than by justify-content: space-between —
   otherwise the title would float to the middle of the header. */
.cs-mapping-card > summary { display: flex; align-items: center; gap: 8px; padding: 9px 12px; cursor: pointer; font-size: 13px; font-weight: 700; }
.cs-mapping-card > summary:hover { background: rgba(120,120,120,0.05); }
.cs-mapping-card > summary > .cs-mapping-count { margin-left: auto; }
.cs-mapping-count { min-width: 24px; padding: 2px 7px; border-radius: 10px; text-align: center; font-size: 11px; }
.cs-mapping-count.ok { color: var(--accent); background: rgba(25,173,121,0.12); }
.cs-mapping-count.miss { color: #b45309; background: rgba(245,166,35,0.16); }
.cs-mapping-desc { min-height: 44px; padding: 0 12px 8px; color: var(--text-secondary); font-size: 11px; line-height: 1.35; }
.cs-mapping-list { max-height: 260px; overflow: auto; border-top: 1px solid var(--border); }
.cs-mapping-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 7px 12px; border-bottom: 1px solid var(--border); font-size: 12px; }
.cs-mapping-row:last-child { border-bottom: 0; }
.cs-mapping-extra { max-width: 48%; text-align: right; color: var(--text-secondary); }
.cs-mapping-empty { padding: 16px 12px; border-top: 1px solid var(--border); font-size: 12px; }
.cs-mapping-empty.ok { color: var(--accent); }
@media (max-width: 1180px) { .cs-mapping-grid { grid-template-columns: 1fr; } .cs-mapping-desc { min-height: 0; } }

/* Status legend */
.cs-legend { display: flex; gap: 16px; flex-wrap: wrap; font-size: 11px; color: var(--text-secondary); margin: 2px 0 10px; }
.cs-legend > span { display: inline-flex; align-items: center; gap: 5px; }

/* Region bundle card */
.cs-bundles { background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px; padding: 10px 14px; margin: 12px 0 6px; }
.cs-bundles-label { font-size: 12px; font-weight: 600; margin-bottom: 7px; }
.cs-bundles-pills { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.cs-bpill { font-size: 12px; padding: 3px 9px; border-radius: 6px; border: 1px solid var(--border); background: #fff; white-space: nowrap; font-weight: 500; }
.cs-bpill.ok { color: var(--accent); border-color: rgba(25,173,121,0.35); }
.cs-bpill.warn { color: #b45309; border-color: rgba(245,166,35,0.4); }
.cs-bpill.stale { color: #dc2626; border-color: rgba(239,68,68,0.35); }
.cs-bpill.miss { color: #94a3b8; border-style: dashed; }
.cs-bnote { font-size: 11px; color: var(--text-secondary); margin-left: 6px; }
.cs-bnote.warn { color: #dc2626; font-weight: 600; }

/* Collapsible region block */
.cs-region-block { border: 1px solid var(--border); border-radius: 8px; margin: 10px 0; overflow: hidden; background: var(--bg-card); }
.cs-region-head { display: flex; align-items: center; gap: 8px; padding: 10px 14px; cursor: pointer; font-size: 14px; }
.cs-region-head:hover { background: rgba(120,120,120,0.05); }
.cs-region-head.expanded { border-bottom: 1px solid var(--border); }
.cs-region-head .expand-arrow { color: #94a3b8; width: 12px; }
.cs-region-name { font-weight: 700; }
.cs-region-flags { display: flex; gap: 6px; }
.cs-region-meta { margin-left: auto; font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
.cs-region-block .cs-bundles { margin: 10px 14px; background: var(--bg-primary); border-color: transparent; }
.cs-table { width: 100%; }
.cs-table th.cs-rail, .cs-table td.cs-rail { width: 30px; text-align: center; padding-left: 4px; padding-right: 4px; }
.cs-table th.cs-col, .cs-table td.cs-col { width: 46px; text-align: center; }
.cs-table th.cs-col.opt { color: #aab2be; font-weight: 500; }
.cs-name { min-width: 180px; }
.cs-table td.num, .cs-table th.num { text-align: right; font-variant-numeric: tabular-nums; }
.cs-row { cursor: pointer; }
.cs-row:hover { background: rgba(120,120,120,0.06); }
.cs-row.expanded { background: rgba(120,120,140,0.10); }
.cs-row .expand-arrow { display: inline-block; width: 12px; color: #94a3b8; }

/* Status pills (matrix cells, rail, legend, summary reuse) */
.cs-pill { display: inline-block; font-size: 13px; line-height: 1; }
.cs-row .cs-pill[data-art] { cursor: pointer; }
.cs-row .cs-pill[data-art]:hover { transform: scale(1.35); }
.cs-pill.ok { color: var(--accent); }
.cs-pill.warn { color: #f59e0b; }
.cs-pill.stale { color: #ef4444; }
.cs-pill.miss { color: #94a3b8; }
.cs-pill.optmiss { color: #cbd5e1; }
.cs-pill.err { color: #ef4444; font-weight: 700; }

/* Query-id chips in the artifact summary (non-history deep inspector) */
.cs-qids { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 6px; }
.cs-qid { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--text-secondary); background: var(--bg-primary); border: 1px solid var(--border); border-radius: 4px; padding: 1px 6px; }

/* Kept: deep-inspector styles (shared with the expand row) */
.debug-row { cursor: pointer; }
.debug-row.expanded { background: rgba(120,120,140,0.12); }
.debug-row .expand-arrow { display: inline-block; width: 12px; color: #94a3b8; }
.bad { color: #ef4444; font-weight: 600; }
.warn { color: #f59e0b; font-weight: 600; }
.sidebar-note { font-size: 11px; color: #94a3b8; padding: 4px 0 8px; line-height: 1.4; }
.debug-detail { padding: 10px 14px; background: rgba(0,0,0,0.02); }
.debug-artifact-tabs { display: flex; gap: 6px; margin-bottom: 10px; }
.debug-art-btn { padding: 3px 12px; border: 1px solid #cbd5e1; background: #fff; color: var(--text-primary); cursor: pointer; font-size: 12px; font-weight: 500; }
.debug-art-btn:hover:not(:disabled) { background: #f4f4f4; border-color: var(--accent); color: var(--text-primary); }
.debug-art-btn.active { background: #3b82f6; color: #fff; border-color: #3b82f6; }
.debug-art-btn.active:hover:not(:disabled) { background: #3b82f6; color: #fff; }
.debug-art-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.debug-summary-head { display: flex; gap: 12px; align-items: baseline; margin-bottom: 8px; flex-wrap: wrap; }
.debug-metric-table { width: 100%; font-size: 12px; margin-bottom: 10px; }
.debug-metric-table td, .debug-metric-table th { padding: 3px 8px; }
.debug-raw-toggle { padding: 3px 12px; border: 1px solid #cbd5e1; background: #fff; color: var(--text-primary); border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: 500; }
.debug-raw-toggle:hover { background: #f4f4f4; border-color: var(--accent); color: var(--text-primary); }
.debug-json { max-height: 420px; overflow: auto; background: #0f172a; color: #e2e8f0; padding: 12px; border-radius: 6px; font-size: 11px; line-height: 1.45; margin-top: 8px; white-space: pre; }
.debug-spark-cell { width: 140px; }
.debug-spark { display: block; }
.debug-spark-cell .muted { font-size: 11px; }

/* ─── Compare Tab ─── */
#compare-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
}
/* No bottom padding: it would sit below the sticky "All Clients" footer and
   scrolling rows would bleed through that gap. Bottom breathing room instead
   comes from a margin on the table (scrolls with content, below the footer). */
#compare-panel { flex: 1; overflow-y: auto; padding: 0 20px; background: var(--bg-primary); }
.compare-table { margin-bottom: 16px; }

.compare-section-group { margin-bottom: 4px; }
.compare-section-title {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-secondary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  padding: 6px 12px 2px;
  opacity: 0.7;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
/* Disclosure arrow for the collapsible compare sidebar sections. */
.compare-section-title::-webkit-details-marker { display: none; }
.compare-section-title::before {
  content: '\25B8'; /* ▸ */
  display: inline-block;
  margin-right: 5px;
  font-size: 9px;
  transition: transform 0.12s ease;
}
details[open] > .compare-section-title::before { transform: rotate(90deg); }
.compare-section-title:hover { opacity: 1; }
.compare-metric-item {
  padding: 6px 12px !important;
  font-size: 12px !important;
}
.compare-badge {
  font-size: 9px;
  margin-left: 4px;
  opacity: 0.6;
}
.compare-badge.additive { color: var(--green); }
.compare-metric-grey { opacity: 0.5; }
.compare-metric-grey span { color: var(--text-secondary); }

.compare-metric-title { font-size: 16px; font-weight: 600; }
.compare-metric-section { font-size: 12px; color: var(--text-secondary); }

.compare-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
}
.compare-table th {
  text-align: left;
  padding: 8px 12px;
  border-bottom: none;
  color: var(--text-secondary);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}
.compare-table td {
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
}
.compare-tenant-col { width: 180px; min-width: 180px; }
.compare-value-col { width: 90px; min-width: 90px; text-align: right; }
.compare-spark-col { width: auto; }
.compare-table th.compare-value-col { text-align: right; }
.compare-table td.compare-value-cell { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; width: 90px; }
.compare-table td.compare-spark-cell { padding: 4px 12px; line-height: 0; width: auto; }
.compare-table td.compare-spark-cell .sparkline { width: 100%; height: 24px; }
.compare-row { cursor: pointer; transition: background 0.1s; }
.compare-row:hover { background: rgba(25,173,121,0.06); }
/* "All Clients" roll-up row — pinned to the bottom of the scrolling table */
.compare-total-row td { position: sticky; bottom: 0; z-index: 2; background: var(--bg-primary); border-top: 2px solid var(--border); font-weight: 700; }
.compare-total-row td.compare-value-cell { font-weight: 700; }
.compare-table th.compare-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.compare-table th.compare-sortable:hover { color: var(--accent); }

/* Additive metric under All Time: no all-time daily series, so fall back to the
   365d view greyed out with an explanatory note. */
.compare-fallback-msg {
  font-size: 12px;
  color: var(--text-secondary);
  font-style: italic;
  padding: 6px 0 10px;
}
.compare-table.compare-greyed { opacity: 0.5; }

/* Sticky header for compare table */
.compare-sticky-title {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--bg-primary);
  padding: 16px 12px 6px;
  display: flex;
  align-items: baseline;
  gap: 12px;
}
.compare-table thead th {
  background: var(--bg-primary);
}
.compare-table thead tr.compare-row-cols th {
  position: sticky;
  top: 42px;
  z-index: 3;
  background: var(--bg-primary);
  vertical-align: bottom;
  border-bottom: none;
}
/* When markers row is absent, cols row is the last header row — show border */
.compare-table thead tr.compare-row-cols:last-child th {
  border-bottom: 1px solid var(--border);
}
.compare-table thead tr.compare-row-markers th {
  position: sticky;
  top: 66px;
  z-index: 3;
  background: var(--bg-primary);
  padding: 0 12px 6px;
  border-bottom: 1px solid var(--border);
}
.compare-markers-cell {
  padding-top: 0 !important;
  padding-bottom: 6px !important;
}

/* Trend column header with time markers */
.compare-time-markers {
  position: relative;
  height: 14px;
  width: 100%;
  min-width: 120px;
}
.compare-time-marker {
  position: absolute;
  transform: translateX(-50%);
  font-size: 9px;
  font-weight: 400;
  color: var(--text-secondary);
  opacity: 0.7;
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
  border-left: 1px solid var(--border);
  padding-left: 2px;
  line-height: 1;
}

/* ── Recent-window client filter (Compare tab) ──
   A sticky bar under the metric title that keeps only clients whose total over
   the last N days meets an operator/threshold rule. Fixed height so the sticky
   column-header offsets below it stay deterministic. */
.compare-filter-bar {
  position: sticky;
  top: 42px;                 /* directly under .compare-sticky-title (top:0, ~42px tall) */
  z-index: 4;
  background: var(--bg-primary);
  box-sizing: border-box;
  height: 52px;
  overflow: hidden;
  padding: 4px 12px 6px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 3px;
}
.compare-filter-controls {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  white-space: nowrap;
}
.compare-filter-label { font-size: 12px; color: var(--text-secondary); }
.compare-filter-days,
.compare-filter-threshold {
  width: 70px;
  padding: 3px 6px;
  font-size: 12px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
}
.compare-filter-days { width: 56px; }
.compare-filter-op {
  padding: 3px 6px;
  font-size: 12px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
}
.compare-filter-clear {
  padding: 3px 8px;
  font-size: 11px;
  font-weight: 600;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
  border-radius: 4px;
  cursor: pointer;
}
.compare-filter-clear:hover { color: var(--accent); border-color: var(--accent); background: transparent; }
.compare-filter-days:disabled,
.compare-filter-threshold:disabled,
.compare-filter-op:disabled { opacity: 0.45; cursor: not-allowed; }
.compare-filter-status {
  font-size: 11px;
  color: var(--text-secondary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.compare-filter-status.on { color: var(--text-primary); }
.compare-filter-status.on strong { color: var(--accent); }
.compare-filter-status.disabled { font-style: italic; opacity: 0.85; }
/* The trailing-window total shown under Total when the filter is active. */
.compare-winval {
  font-size: 10px;
  font-weight: 700;
  color: var(--accent);
  opacity: 0.9;
  margin-top: 2px;
  font-variant-numeric: tabular-nums;
}
/* When the filter bar is present, push the sticky column/marker header rows down
   below it (title 42 + filter bar 52 = 94; markers a further 24px). */
.compare-has-filter .compare-table thead tr.compare-row-cols th { top: 94px; }
.compare-has-filter .compare-table thead tr.compare-row-markers th { top: 118px; }

/* Compare icon on additive tiles */
.compare-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 14px;
  color: var(--text-secondary);
  opacity: 0.45;
  cursor: pointer;
  border-radius: 3px;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
  margin-left: auto;
}
.compare-icon:hover { opacity: 1 !important; color: var(--accent); background: rgba(25,173,121,0.1); }
.compare-icon svg { display: block; }
/* Row-level compare icon inside table cells */
.compare-icon-row {
  margin-left: 6px;
  opacity: 0.3;
  vertical-align: middle;
}
.compare-icon-row:hover { opacity: 1 !important; }

/* Section heatmap shortcut icon (Client view) — jumps to the Comparison heatmap
   pre-filtered to this section. Sits just after the section name in the header. */
.section-heatmap-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: var(--text-secondary);
  opacity: 0.5;
  cursor: pointer;
  border-radius: 3px;
  transition: opacity 0.15s, color 0.15s, background 0.15s;
}
.section-heatmap-link:hover { opacity: 1; color: var(--accent); background: rgba(25,173,121,0.1); }
.section-heatmap-link:focus-visible { outline: 1px solid var(--accent); outline-offset: 1px; opacity: 1; }
.section-heatmap-link svg { display: block; }

/* ─── Revenue by Financial Year bar chart ─── */
.revenue-bar-chart { width: 100%; max-width: 760px; margin-top: 4px; }
.revenue-bar-chart .rbc-svg { width: 100%; height: auto; display: block; }
.rbc-grid { stroke: var(--border); stroke-width: 1; }
.rbc-axis { stroke: var(--text-secondary); stroke-width: 1; opacity: 0.5; }
.rbc-ylabel { fill: var(--text-secondary); font-size: 10px; }
.rbc-xlabel { fill: var(--text-secondary); font-size: 11px; }
.rbc-bar { fill: var(--accent); transition: fill 0.12s; }
.rbc-bar-g:hover .rbc-bar { fill: var(--accent-hover); }
.chart-empty { color: var(--text-secondary); font-size: 13px; padding: 20px 4px; }

/* ─── Categorical horizontal bar chart (Repeat Responders q57, Flight Paths q58) ─── */
.cat-bar-header { font-size: 12px; font-weight: 600; color: var(--text-secondary); padding: 4px 4px 0; }
.cat-bar-chart { width: 100%; max-width: 760px; margin-top: 4px; }
.cat-bar-chart .cbc-svg { width: 100%; height: auto; display: block; }
.cbc-cat { fill: var(--text-secondary); font-size: 11px; }
.cbc-bar { fill: var(--accent); transition: fill 0.12s; }
.cbc-bar-g:hover .cbc-bar { fill: var(--accent-hover); }
.cbc-vallabel { fill: var(--text-primary); font-size: 11px; font-weight: 600; }
.cbc-vallabel-in { fill: #fff; }

/* ─── Reports tab ─── */
#reports-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
}
.report-section-group { margin-bottom: 2px; }
.report-section-group > summary { list-style: none; }
.report-section-group > summary::-webkit-details-marker { display: none; }
.report-section-title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--text-secondary);
  padding: 8px 12px 4px;
  cursor: pointer;
  user-select: none;
}
.report-section-title::before {
  content: '▸';
  display: inline-block;
  margin-right: 4px;
  transition: transform 0.15s;
}
.report-section-group[open] > .report-section-title::before {
  transform: rotate(90deg);
}
.report-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.report-item {
  padding: 6px 12px 6px 20px;
  font-size: 13px;
  cursor: pointer;
  border-left: 3px solid transparent;
  transition: background 0.1s, border-color 0.1s;
}
.report-item:hover { background: var(--hover-bg, rgba(255,255,255,0.05)); }
.report-item.active {
  background: var(--active-bg, rgba(59,130,246,0.12));
  border-left-color: var(--accent, #3b82f6);
  font-weight: 600;
}

#reports-panel {
  flex: 1;
  overflow: hidden;
}

/* Report panel */
.report-container { padding: 24px; height: 100%; display: flex; flex-direction: column; }
.report-header { margin-bottom: 20px; flex-shrink: 0; }
.report-title { font-size: 20px; font-weight: 700; margin: 0 0 6px; }
.report-description { font-size: 13px; color: var(--text-secondary); margin: 0; }
.report-exclusion-note { font-size: 12px; color: var(--text-secondary); margin: 4px 0 0; opacity: 0.8; }
.report-exclusion-note code { background: rgba(255,255,255,0.06); padding: 1px 4px; border-radius: 3px; font-size: 11px; }

/* Scrollable table container — header (and everything above) stays frozen,
   only the row body scrolls. Takes the remaining vertical space in the panel. */
.report-table-container.mau-by-client-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
}
.mau-by-client-scroll .mau-by-client-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg-primary);
}

/* MAU chart */
.report-chart-container { margin-bottom: 24px; }
.mau-chart { width: 100%; height: auto; max-height: 320px; }
.mau-grid-line { stroke: var(--border, rgba(255,255,255,0.08)); stroke-width: 0.5; }
.mau-axis-label { fill: var(--text-secondary); font-size: 11px; font-family: inherit; }
.mau-area { fill: var(--accent, #3b82f6); opacity: 0.12; }
.mau-line { fill: none; stroke: var(--accent, #3b82f6); stroke-width: 2; }
.mau-line-extrapolated { stroke-dasharray: 6 4; }
.mau-dot { fill: var(--accent, #3b82f6); }
.mau-dot:hover { r: 5; fill: var(--accent-hover, #2563eb); }
.mau-dot-partial { fill: var(--text-secondary, #94a3b8); stroke: var(--accent, #3b82f6); stroke-width: 1.5; }
/* Stacked MAU chart */
.mau-stacked-area { opacity: 1; }
.mau-stacked-line { opacity: 1; }
.mau-stacked-dot { cursor: crosshair; }
.mau-stacked-dot:hover { r: 6; fill: var(--text-secondary); stroke: var(--text-secondary); stroke-width: 1; }

/* MAU table */
.mau-table { width: 100%; max-width: 700px; }
.mau-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; }
.change-up { color: #22c55e; font-weight: 500; }
.change-down { color: #ef4444; font-weight: 500; }
.change-flat { color: var(--text-secondary); }
.mau-extrapolated { color: var(--text-secondary); font-size: 12px; }
.mau-partial-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.3px;
  color: var(--text-secondary);
  background: var(--hover-bg, rgba(255,255,255,0.08));
  border-radius: 3px;
  padding: 1px 5px;
  margin-left: 4px;
  vertical-align: middle;
}

/* MAU by-client table */
.mau-by-client-table { width: 100%; }
.mau-by-client-table th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.3px; }
.mau-by-client-table th.sortable { cursor: pointer; user-select: none; position: relative; padding-right: 14px; }
.mau-by-client-table th.sortable::after { content: '⇅'; position: absolute; right: 2px; opacity: 0.3; font-size: 10px; }
.mau-by-client-table th.sortable.sort-asc::after { content: '↑'; opacity: 0.8; }
.mau-by-client-table th.sortable.sort-desc::after { content: '↓'; opacity: 0.8; }
/* Client column: shrink-to-fit the longest client name (no wider).
   Uses the table id to out-specificity the generic .trend-table
   th:nth-child(N) pinned-width rules above (this table also carries the
   .trend-table class for its base look, but needs its own column sizing). */
#mau-by-client-tbl th.col-client,
#mau-by-client-tbl td.client-name-cell { width: 1%; white-space: nowrap; }
/* Latest MAU / MoM Change: shrink-to-fit their header label only. */
#mau-by-client-tbl th.col-mau,
#mau-by-client-tbl td.mau-value-cell { width: 1%; white-space: nowrap; text-align: right; }
#mau-by-client-tbl th.col-change,
#mau-by-client-tbl td.mau-change-cell { width: 1%; white-space: nowrap; }
/* Per-column heatmap for the delta columns: background carries the signal (green
   for increases, red for falls), so text is a fixed readable dark colour rather
   than the green/red used elsewhere. */
.mau-by-client-table td.mau-change-heat { text-align: right; font-variant-numeric: tabular-nums; }
.mau-by-client-table td.mau-change-heat span { color: #212121; font-weight: 600; }
.mau-by-client-table td.mau-change-heat .muted { color: var(--text-secondary); font-weight: 400; }
/* Sparkline column absorbs all remaining width so the table fills the panel. */
#mau-by-client-tbl th.col-spark,
#mau-by-client-tbl td.mau-spark-cell { width: auto; }
.mau-by-client-table .client-name-cell { font-weight: 500; white-space: nowrap; }
.mau-by-client-table .mau-value-cell { font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap; }
.mau-by-client-table .mau-spark-cell { padding: 3px 0; }

/* Total row — pinned to the bottom of the scroll container so the portfolio
   total for the Latest MAU column stays visible while the body scrolls. */
.mau-by-client-scroll .mau-by-client-table tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--bg-secondary, #f5f5f5);
  border-top: 2px solid var(--border-color, #ddd);
  font-weight: 700;
  z-index: 1;
}
.mau-by-client-table tfoot .client-name-cell,
.mau-by-client-table tfoot .mau-value-cell { font-weight: 700; }
.mau-mini-spark { display: block; width: 100%; height: 30px; }
/* Y-axis scale labels live in a flex gutter to the RIGHT of the chart (upper bound
   on top, lower bound on the bottom) so neither value overlaps the sparkline. */
.mau-spark-wrap { display: flex; align-items: stretch; gap: 5px; }
.mau-spark-wrap .mau-mini-spark { flex: 1 1 auto; width: auto; min-width: 0; }
.mau-spark-scale {
  flex: 0 0 28px;
  width: 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
  text-align: center;
  font-size: 8px;
  line-height: 1;
  color: #94a3b8;
  font-family: system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
}
.mau-mini-spark { overflow: visible; }
.mau-spark-dot { cursor: pointer; }
.mau-spark-dot-vis { opacity: 0; transition: opacity 0.15s; pointer-events: none; }
.mau-spark-dot:hover .mau-spark-dot-vis { opacity: 1; }
/* Force the invisible hit rings to capture hover even though they're
   transparent/unfilled — the default visiblePainted rule would ignore them. */
.mau-spark-dot-hit { cursor: pointer; pointer-events: all; }
.spark-date-markers { position: relative; width: 100%; height: 14px; font-size: 10px; color: var(--text-secondary); }
.spark-date-marker { position: absolute; left: 0; transform: translateX(-50%); white-space: nowrap; }
/* First/last labels sit flush with the sparkline edges instead of being
   centred on a point, so they never overhang past the chart bounds. */
.spark-date-marker-first { left: 0; transform: none; }
.spark-date-marker-last { left: auto; right: 0; transform: none; }

/* ── Risk Quadrant view (Usage Health tab) ──
   A 2×2 scatter: x = health change (score points, 0 = unchanged), y = standalone
   current health. Controls reuse Spider Webs' fixed header and compact control styling.
   Aspect-preserved SVG (not stretched) so the text stays crisp. */
/* Chart fills close to the full canvas width (was capped at 900px + centred). */
.rq-chart {
  padding: 6px 8px 4px;
  margin: 0;
}
.rq-svg { display: block; width: 100%; height: 100%; overflow: visible; }
/* RQ page header: the bold title sits on its own row with the comparison
   controls pinned right at the same level, and the help note wraps full-width
   underneath both (flowing under the filter). */
.rq-header { display: flex; flex-direction: column; }
.rq-header-top {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.rq-header-top .uh-title {
  flex: 0 1 auto;
  min-width: 0;
  padding: 10px 12px 4px;
}
.rq-help-inline {
  padding: 0 12px 8px;
  margin: 0;
  white-space: normal;
  max-width: none;
}

/* RQ body fills the remaining tab height so the chart + list use all the
   vertical space; the SVG (preserveAspectRatio meet) scales to fit. */
.rq-uh-body { display: flex; flex-direction: column; overflow: hidden; padding-top: 0; }
.rq-uh-body .rq-layout { flex: 1 1 auto; min-height: 0; }
.rq-uh-body .rq-chart { display: flex; min-height: 0; }
.rq-uh-body .rq-chart .rq-svg { flex: 1 1 auto; min-height: 0; }
.rq-header-ctrl {
  flex-shrink: 0;
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 4px 0;
}
/* RQ trend-comparison-period select (RQ-local; both windows precomputed →
   instant switch, no re-score of other views). */
.rq-ctrl-trend { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
.rq-ctrl-trend label { font-size: 12px; font-weight: 600; color: #475569; }
.rq-ctrl-trend select {
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--border, rgba(30, 48, 80, .2));
  border-radius: 6px;
  background: #fff;
  color: #1e293b;
}
.rq-ctrl-cyclic {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  font-weight: 600;
  color: #475569;
  white-space: nowrap;
  cursor: pointer;
}
.rq-ctrl-cyclic input { margin: 0; accent-color: #2563eb; }
.rq-plot { fill: #fbfcfe; stroke: rgba(30, 48, 80, .18); stroke-width: 1; }
.rq-grid { stroke: rgba(30, 48, 80, .07); stroke-width: 1; }
.rq-band { stroke: rgba(30, 48, 80, .16); stroke-width: 1; stroke-dasharray: 4 4; }
.rq-split { stroke: rgba(30, 48, 80, .45); stroke-width: 1.4; }
.rq-tick { font-size: 10px; fill: #94a3b8; }
.rq-axis-title { font-size: 11px; font-weight: 600; fill: #64748b; }
.rq-quad {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .03em;
  text-transform: uppercase;
  opacity: .5;
}
.rq-quad.q-tr { fill: #16a34a; }
.rq-quad.q-tl { fill: #d97706; }
.rq-quad.q-br { fill: #2563eb; }
.rq-quad.q-bl { fill: #dc2626; }
/* A single selected client can expose up to four canonical comparison positions.
   The neutral dashed connector distinguishes comparison positions from a dated
   time-series trajectory; fixed-size markers do not duplicate ARR bubble size. */
.rq-client-trail { isolation: isolate; }
.rq-trail-line {
  fill: none;
  stroke: #334155;
  stroke-width: 1.5;
  stroke-dasharray: 5 4;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .75;
  pointer-events: none;
}
.rq-trail-stem {
  stroke: #64748b;
  stroke-width: 1;
  stroke-dasharray: 2 2;
  pointer-events: none;
}
.rq-trail-point { cursor: pointer; }
.rq-trail-dot {
  stroke: #fff;
  stroke-width: 1.5;
  fill-opacity: .96;
}
.rq-trail-point:hover .rq-trail-dot,
.rq-trail-point:focus .rq-trail-dot { stroke: #0f172a; stroke-width: 2.25; }
.rq-trail-dot.q-tr { fill: #22c55e; }
.rq-trail-dot.q-tl { fill: #f59e0b; }
.rq-trail-dot.q-br { fill: #3b82f6; }
.rq-trail-dot.q-bl { fill: #ef4444; }
.rq-trail-label {
  font-size: 7px;
  font-weight: 700;
  fill: #334155;
  paint-order: stroke;
  stroke: #fff;
  stroke-width: 2.5px;
  stroke-linejoin: round;
  pointer-events: none;
  dominant-baseline: middle;
}
.rq-trail-point-current .rq-trail-dot { stroke: #0f172a; stroke-width: 2; }
.rq-trail-point-offscale .rq-trail-dot { stroke-dasharray: 3 2; }
.rq-trail-point-out-of-cycle .rq-trail-dot { fill: #94a3b8; stroke: #64748b; }
.rq-trail-point-out-of-cycle .rq-trail-label { fill: #64748b; }
.rq-trail-point.ex-client { opacity: .6; }
.rq-trail-point.ex-client .rq-trail-label { font-style: italic; }
.rq-dot {
  stroke: #fff;
  stroke-width: 1;
  cursor: pointer;
  fill-opacity: .82;
  transition: r .1s ease;
}
.rq-dot:hover { fill-opacity: 1; stroke: #1e293b; stroke-width: 1.5; }
.rq-dot.q-tr { fill: #22c55e; }
.rq-dot.q-tl { fill: #f59e0b; }
.rq-dot.q-br { fill: #3b82f6; }
.rq-dot.q-bl { fill: #ef4444; }
/* Unknown ARR: a hollow, dotted-perimeter ring (sized at the €10k–€25k band) so
   it reads as "no known size" rather than a real sized bubble. */
.rq-dot-unknown {
  fill: transparent;
  fill-opacity: 0;
  stroke: currentColor;
  stroke-width: 1.3;
  stroke-dasharray: 2.5 2;
}
.rq-dot.q-tr.rq-dot-unknown { color: #22c55e; }
.rq-dot.q-tl.rq-dot-unknown { color: #f59e0b; }
.rq-dot.q-br.rq-dot-unknown { color: #3b82f6; }
.rq-dot.q-bl.rq-dot-unknown { color: #ef4444; }
.rq-dot-unknown:hover { fill-opacity: 0; }
/* An explicitly included cyclic programme is grey only when its source-backed
   calendar as-of falls outside its established programme window. */
.rq-pt-out-of-cycle .rq-dot {
  fill: #94a3b8;
  stroke: #64748b;
  fill-opacity: .76;
}
.rq-pt-out-of-cycle .rq-dot-unknown { color: #64748b; fill: transparent; }
.rq-pt-out-of-cycle:hover .rq-dot { fill-opacity: 1; stroke: #334155; }
.rq-pt-out-of-cycle .rq-dot-label { fill: #64748b; }
.rq-pt-out-of-cycle:hover .rq-dot-label { fill: #334155; }

/* The health-change axis is calibrated to the estate's core spread, so a few
   extreme movers are clamped to the plot edge. The dashed ring says "this x
   position is the axis limit, not this client's real change" — the exact value
   stays in the tooltip. */
.rq-pt-offscale .rq-dot { stroke-width: 2; stroke-dasharray: 3 2; }
.rq-pt { cursor: pointer; }
.rq-dot-label {
  font-size: 7px;
  fill: #475569;
  pointer-events: none;
  dominant-baseline: middle;
}
.rq-pt:hover .rq-dot-label { fill: #0f172a; font-weight: 600; }
/* Count badge shown inside a dot when several clients overlap on one pixel.
   The tooltip lists them all; this just signals the cluster. */
.rq-dot-count {
  font-size: 7px;
  font-weight: 700;
  fill: #fff;
  pointer-events: none;
  dominant-baseline: central;
}


/* Per-quadrant fullscreen / shrink-back icons. A transparent hit rect makes the
   whole corner area clickable; the corner-bracket glyph darkens on hover. */
.rq-fs { cursor: pointer; }
.rq-fs-hit { fill: #fff; fill-opacity: 0; stroke: none; }
.rq-fs-glyph {
  fill: none;
  stroke: #94a3b8;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  pointer-events: none;
}
.rq-fs:hover .rq-fs-hit { fill-opacity: .9; stroke: rgba(30, 48, 80, .18); }
.rq-fs:hover .rq-fs-glyph { stroke: #0f172a; }

/* Chart + alphabetical tenant list laid out side by side. The chart flexes to
   fill; the list is a fixed-width scrollable column on the right. */
.rq-layout { display: flex; align-items: stretch; gap: 12px; }
.rq-layout .rq-chart { flex: 1 1 auto; min-width: 0; }
.rq-list {
  flex: 0 0 200px;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border, rgba(30, 48, 80, .18));
  border-radius: 8px;
  background: #fff;
  overflow: hidden;
  /* stretch to match the chart's rendered height (align-items:stretch on
     .rq-layout); min-height:0 lets the inner list scroll instead of growing. */
  min-height: 0;
}
.rq-arr-filter {
  padding: 7px 10px;
  border-bottom: 1px solid rgba(30, 48, 80, .12);
  background: #f8fafc;
  flex-shrink: 0;
}
.rq-arr-filter-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: 11px;
  font-weight: 600;
  color: #475569;
}
.rq-arr-options {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: 6px;
}
.rq-arr-option {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  min-width: 0;
  max-width: 100%;
  font-size: 11px;
  color: #334155;
  cursor: pointer;
}
.rq-arr-option input { margin: 0; accent-color: #2563eb; }
.rq-arr-option span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rq-list-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 10px;
  border-bottom: 1px solid rgba(30, 48, 80, .12);
  background: #f8fafc;
  flex-shrink: 0;
}
.rq-list-count { font-size: 11px; font-weight: 600; color: #475569; }
.rq-list-clear,
.rq-arr-clear {
  font-size: 11px;
  padding: 2px 8px;
  border: 1px solid var(--border, rgba(30, 48, 80, .2));
  border-radius: 6px;
  background: #fff;
  color: #1e293b;
  cursor: pointer;
}
.rq-list-clear:hover:not(:disabled),
.rq-arr-clear:hover:not(:disabled) { background: #eef2f7; }
.rq-list-clear:disabled,
.rq-arr-clear:disabled { opacity: .4; cursor: default; }
.rq-list-items {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow-y: auto;
  flex: 1 1 auto;
}
.rq-list-item {
  border-bottom: 1px solid rgba(30, 48, 80, .05);
  overflow: hidden;
}
.rq-list-button {
  display: block;
  width: 100%;
  padding: 4px 10px;
  border: 0;
  background: transparent;
  color: #334155;
  font: inherit;
  font-size: 12px;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rq-list-button:focus-visible { outline: 2px solid #2563eb; outline-offset: -2px; }
.rq-list-item:hover { background: #f1f5f9; }
.rq-list-item-selected {
  background: #e0edff;
}
.rq-list-item-selected .rq-list-button {
  color: #0f172a;
  font-weight: 600;
}
.rq-list-item-selected:hover { background: #d3e4ff; }

/* Selection cross-highlight on the scatter: fade the unselected dots right down,
   emphasise the selected ones (darker stroke, full opacity, bold label). */
.rq-pt-faded { opacity: .1; }
/* Selected dots keep their ARR-band radius; emphasis is stroke + opacity only
   (forcing r here would flatten the bubble sizing the selection sits on top of). */
.rq-pt-selected .rq-dot { fill-opacity: 1; stroke: #0f172a; stroke-width: 2; }
.rq-pt-selected .rq-dot.rq-dot-unknown { fill-opacity: 0; stroke: #0f172a; }
.rq-pt-selected .rq-dot-label { fill: #0f172a; font-weight: 700; }

/* Floating chooser popup shown when a merged (overlapping) dot with a count
   badge is clicked — lists the stacked clients so one can be picked to drill in. */
.rq-chooser {
  position: fixed;
  z-index: 210;
  min-width: 180px;
  max-width: 260px;
  max-height: 60vh;
  overflow-y: auto;
  background: #fff;
  border: 1px solid var(--border, rgba(30, 48, 80, .2));
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(15, 23, 42, .18);
  padding: 4px;
}
.rq-chooser-head {
  font-size: 11px;
  font-weight: 600;
  color: #64748b;
  padding: 4px 8px 6px;
  border-bottom: 1px solid rgba(30, 48, 80, .1);
  margin-bottom: 2px;
}
.rq-chooser-item {
  display: block;
  width: 100%;
  text-align: left;
  font-size: 12px;
  color: #1e293b;
  padding: 6px 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rq-chooser-item:hover { background: #eef2f7; }

/* ── Usage Health tenant detail modal (Spider Webs tile) ────────────────────
   Technical pop-up: all three comparison webs above the folded per-period
   metric table. Opened from a Spider Webs tile; closed by ×, backdrop, or Escape. */
.uh-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .6);
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.uh-modal {
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  width: min(1320px, 97vw);
  max-height: 96vh;
  display: flex;
  flex-direction: column;
  box-shadow: rgba(15, 15, 15, .12) 0 6px 18px, rgba(15, 15, 15, .24) 0 12px 36px;
}
.uh-modal-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}
.uh-modal-title { flex: 1 1 auto; min-width: 0; }
.uh-modal-primary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 10px;
  min-width: 0;
}
.uh-modal-spoke-style {
  flex: 0 1 430px;
  font-size: 10px;
  font-weight: 400;
  line-height: 1.35;
  color: var(--text-secondary);
}
.uh-modal-name {
  min-width: 0;
  overflow: hidden;
  font-size: 15px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.uh-modal-identity {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 1px 6px;
  margin-top: 3px;
  font-size: 10px;
  color: var(--text-secondary);
}
.uh-modal-identity-label { font-weight: 600; }
.uh-modal-identity-value { overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.uh-modal-open {
  margin-left: 0;
  padding: 5px 12px;
  font-size: 12px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: #fff;
  color: var(--text-primary);
  cursor: pointer;
  white-space: nowrap;
}
.uh-modal-open:hover { border-color: var(--accent); }
.uh-modal-close {
  background: none;
  border: none;
  color: var(--text-secondary);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  padding: 0 4px;
}
.uh-modal-close:hover { color: var(--text-primary); }
/* Programme-cycle evidence shared by the technical modal and Alerts/Risk drilldown. */
.uh-programme-cycle {
  margin: 0 0 10px;
  padding: 7px 11px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: #f8fafc;
  color: var(--text-secondary);
  font-size: 11px;
  line-height: 1.35;
}
.uh-programme-cycle-head {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-bottom: 3px;
}
.uh-programme-cycle-head strong { color: var(--text-primary); font-size: 12px; }
.uh-programme-cycle-source {
  padding: 1px 6px;
  border-radius: 999px;
  background: #e7edf5;
  color: var(--text-primary);
  font-size: 10px;
  font-weight: 600;
}
.uh-programme-cycle-source.is-override { background: #fff1c7; color: #7a5200; }
.uh-programme-cycle-facts { display: flex; flex-wrap: wrap; gap: 2px 14px; }
.uh-programme-cycle-facts span { white-space: nowrap; }
/* Separate the survey group from the login group now that the block is tighter. */
.uh-programme-cycle-facts + .uh-programme-cycle-head { margin-top: 5px; }
.uh-programme-cycle-explanation { margin: 5px 0 0; padding-left: 17px; }
.uh-programme-cycle-explanation li + li { margin-top: 2px; }
.uh-programme-cycle-correction { display: block; margin-top: 4px; font-size: 10px; }

/* Three comparison webs form a single row above the technical detail table. */
.uh-modal-body {
  padding: 12px 16px;
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.uh-modal-main { min-width: 0; }
.uh-modal-webs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin: 0 0 16px;
}
.uh-modal-web { display: flex; flex-direction: column; align-items: center; min-width: 0; }
.uh-modal-web-cap {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-size: 11px;
  color: var(--text-secondary);
  margin-bottom: 2px;
  text-align: center;
}
.uh-modal-web-score {
  color: var(--text-primary);
  font-size: 24px;
  font-weight: 700;
  line-height: 1.05;
  white-space: nowrap;
}
.uh-modal-web .sw-svg { width: 100%; max-width: 300px; height: auto; }
.uh-modal-web-unavailable {
  width: 100%;
  min-height: 150px;
  display: grid;
  place-items: center;
  text-align: center;
  font-size: 11px;
  color: var(--text-secondary);
  border: 1px dashed var(--border);
  border-radius: 6px;
}
@media (max-width: 850px) {
  .uh-modal-webs { grid-template-columns: 1fr; }
  .uh-modal-web .sw-svg { max-width: 260px; }
}

/* Alerts and Risk bubbles open a deliberately plain-language signal summary. */
.uh-sentiment-overlay {
  position: fixed;
  inset: 0;
  z-index: 205;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 10px;
  background: rgba(0, 0, 0, .6);
}
/* Wide and near-full-height: the drilldown's blocks are all horizontal runs
   (cadence facts, legend keys, topic rows), so extra width converts directly
   into fewer wrapped lines and less scrolling. <!-- 2026-09-18 --> */
.uh-sentiment-popup {
  width: min(1400px, 98vw);
  max-height: 97vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: rgba(15, 15, 15, .24) 0 12px 36px;
}
.uh-sentiment-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 9px 16px;
  border-bottom: 1px solid var(--border);
}
.uh-sentiment-title { font-size: 16px; font-weight: 700; color: var(--text-primary); }
.uh-sentiment-subtitle { margin-top: 2px; font-size: 12px; color: var(--text-secondary); }
.uh-sentiment-close {
  border: 0;
  background: none;
  color: var(--text-secondary);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.uh-sentiment-close:hover { color: var(--text-primary); }
.uh-sentiment-body { min-height: 0; overflow-y: auto; padding: 10px 16px 12px; }
/* The per-comparison Positive signals / Needs attention panels were removed on
   2026-09-18 (the trend chart above them already showed the same movements), so
   .uh-sentiment-comparison*, .uh-sentiment-period and .uh-modal-summary* went
   with them. */
.uh-sentiment-section { margin-top: 10px; }
.uh-sentiment-section-title {
  margin-bottom: 6px;
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.uh-sentiment-section-title span {
  margin-left: 5px;
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}
.uh-sentiment-topics { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
/* Sentiment counts and Opportunities share one row: the pill list is short enough
   to sit inside the topic panels' height instead of adding its own. <!-- 2026-09-18 --> */
.uh-sentiment-lower { display: flex; align-items: flex-start; gap: 12px; }
.uh-sentiment-lower > .uh-sentiment-section { flex: 1 1 auto; min-width: 0; }
/* Opportunities carries .uh-sentiment-section too, so this must stay after the
   rule above to win the cascade on equal specificity. */
.uh-sentiment-lower > .uh-modal-opportunities { flex: 0 0 clamp(170px, 17%, 250px); }
.uh-modal-opportunities {
  padding: 8px 11px;
  border: 1px solid rgba(201, 117, 21, .32);
  border-radius: 8px;
  background: rgba(245, 164, 61, .15);
}
.uh-modal-opportunities .uh-sentiment-section-title { margin-bottom: 5px; color: #9a5a10; }
.uh-modal-opportunity-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.uh-modal-opportunity-list li {
  padding: 3px 7px;
  border: 1px solid rgba(181, 104, 19, .26);
  border-radius: 999px;
  background: rgba(255, 255, 255, .55);
  color: #6e4310;
  font-size: 12px;
  font-weight: 600;
}
@media (max-width: 900px) {
  .uh-sentiment-lower { display: block; }
}
@media (max-width: 650px) {
  .uh-sentiment-overlay { padding: 8px; }
  .uh-sentiment-topics { grid-template-columns: 1fr; }
  .uh-sentiment-section-title span { display: block; margin: 2px 0 0; }
}

.uh-modal-table-wrap { overflow-x: auto; }
.uh-modal-table { border-collapse: collapse; table-layout: fixed; width: auto; font-size: 10.5px; }
/* Fixed column widths so the shared Period + metric columns align between the
   raw and score tables; the score table is wider only by its extra col. */
.uh-modal-col-period { width: 60px; }
.uh-modal-col-metric { width: 74px; }
.uh-modal-col-score { width: 62px; }
.uh-modal-table th,
.uh-modal-table td {
  border: 1px solid var(--border);
  padding: 3px 4px;
  text-align: center;
  white-space: nowrap;
}
.uh-modal-table th.uh-modal-grp { background: var(--bg-card); font-weight: 600; white-space: normal; }
.uh-modal-table th.uh-modal-mth {
  font-weight: 500;
  color: var(--text-secondary);
  width: 74px;
  white-space: normal;
  overflow-wrap: break-word;
  vertical-align: bottom;
  line-height: 1.2;
}
.uh-modal-mth-unit {
  display: block;
  margin-top: 2px;
  font-size: 9px;
  font-weight: 400;
  line-height: 1.1;
  color: var(--text-secondary);
}
.uh-modal-table th.uh-modal-scorehead { white-space: normal; }
.uh-modal-corner { background: var(--bg-card); }
.uh-modal-rowh {
  text-align: left;
  font-weight: 600;
  background: var(--bg-card);
  position: sticky;
  left: 0;
}
.uh-modal-rowsub {
  display: block;
  font-weight: 400;
  font-size: 10px;
  color: var(--text-secondary);
}
.uh-modal-cell {
  background: var(--uh-tint, transparent);
  font-variant-numeric: tabular-nums;
}
.uh-modal-delta { display: block; font-size: 9px; color: var(--text-secondary); }
.uh-modal-topic-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(3ch, max-content) minmax(6ch, max-content);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}
/* The topic list is the one unbounded block in the drilldown — a tenant's own
   taxonomy sets the row count — so the panel is capped and the rows scroll
   inside it. That keeps the popup a fixed height instead of letting a long
   taxonomy push the whole dialog into a scrollbar. The panel's third grid row is
   already minmax(0, 1fr), so it absorbs the cap. <!-- 2026-09-18 --> */
.uh-modal-topic-panel { max-height: min(300px, 32vh); }
.uh-modal-topic-rows {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-content: start;
  min-height: 0;
  overflow-y: auto;
}
.uh-modal-topic-panel h4 {
  grid-column: 1 / -1;
  margin: 0;
  padding: 5px 9px;
  font-size: 11px;
  letter-spacing: .03em;
}
.uh-modal-topic-positive { border-color: rgba(34, 160, 90, .30); }
.uh-modal-topic-positive h4 { background: rgba(34, 160, 90, .07); color: #1f8a4c; }
.uh-modal-topic-negative { border-color: rgba(210, 55, 55, .28); }
.uh-modal-topic-negative h4 { background: rgba(210, 55, 55, .06); color: #c23a3a; }
.uh-modal-topic-head,
.uh-modal-topic-row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  column-gap: 8px;
  align-items: baseline;
  padding: 3px 9px;
}
.uh-modal-topic-head {
  border-bottom: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: 10px;
  font-weight: 600;
}
.uh-modal-topic-count { text-align: right; }
.uh-modal-topic-row + .uh-modal-topic-row { border-top: 1px solid rgba(0, 0, 0, .06); }
.uh-modal-topic-name { min-width: 0; overflow-wrap: anywhere; font-size: 11px; }
.uh-modal-topic-count {
  color: var(--text-secondary);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.uh-modal-topic-count.uh-modal-topic-current--good { color: #1f8a4c; }
.uh-modal-topic-count.uh-modal-topic-current--bad { color: #c23a3a; }
.uh-modal-topic-total {
  border-top: 1px solid var(--border);
  font-weight: 700;
}
.uh-modal-topic-empty {
  grid-column: 1 / -1;
  margin: 8px 9px;
  color: var(--text-secondary);
  font-size: 12px;
  font-style: italic;
}
.uh-modal-tables {
  margin-top: 10px;
  border-top: 1px solid var(--border);
  padding-top: 6px;
}
.uh-modal-tables-toggle {
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-secondary);
  user-select: none;
  list-style: revert;
  padding: 2px 0;
}
.uh-modal-tables-toggle:hover { color: var(--text-primary); }
.uh-modal-tables-hint {
  font-weight: 400;
  font-size: 11px;
  color: var(--text-secondary);
}
.uh-modal-table-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 0 5px;
}
.uh-modal-table-label {
  font-size: 12px;
  font-weight: 600;
}
.uh-modal-mode-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
}
.uh-modal-mode-btn {
  border: none;
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font-size: 11px;
  padding: 3px 10px;
  cursor: pointer;
  line-height: 1.4;
}
.uh-modal-mode-btn + .uh-modal-mode-btn { border-left: 1px solid var(--border); }
.uh-modal-mode-btn:hover { background: var(--bg-primary); color: var(--text-primary); }
.uh-modal-mode-btn.active { background: var(--accent); color: #fff; }
.uh-modal-scorehead {
  background: var(--bg-card);
  font-weight: 600;
  border-left: 2px solid var(--border);
}
.uh-modal-scorecell {
  border-left: 2px solid var(--border);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ─── Alerts/Risk drilldown metric trend chart (uh-mtc) ───
   Replaces the folded metric table in the Alerts/Risk drilldown popup only; the
   Spider Web tenant modal keeps .uh-modal-table. One line per 0–10 metric across
   the four periods, with a show/hide key and a hover tooltip carrying the raw
   values behind each point. Each series group and legend key sets
   --uh-mtc-colour, so one rule set covers every line. */
.uh-mtc { margin-top: 10px; }
.uh-mtc-toggle {
  cursor: pointer;
  color: var(--text-primary);
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .03em;
  user-select: none;
  list-style: revert;
  padding: 0;
}
.uh-mtc-hint {
  margin-left: 6px;
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
}
.uh-mtc-body { margin-top: 6px; }
.uh-mtc-empty { margin: 0; color: var(--text-secondary); font-size: 12.5px; font-style: italic; }

.uh-mtc-legend-bar {
  display: flex;
  align-items: flex-start;
  max-width: 1266px;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}
.uh-mtc-legend { display: flex; flex-wrap: wrap; gap: 4px 6px; }
.uh-mtc-key {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px 2px 5px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: #fff;
  color: var(--text-primary);
  font-size: 11px;
  line-height: 1.5;
  cursor: pointer;
}
.uh-mtc-key-swatch {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--uh-mtc-colour, #64748b);
}
.uh-mtc-key:hover { border-color: var(--uh-mtc-colour, var(--border)); }
.uh-mtc-key.is-active {
  border-color: var(--uh-mtc-colour, var(--border));
  box-shadow: inset 0 0 0 1px var(--uh-mtc-colour, transparent);
}
/* Hidden line: the key stays legible but visibly switched off. */
.uh-mtc-key.is-off { background: var(--bg-secondary); color: var(--text-secondary); }
.uh-mtc-key.is-off .uh-mtc-key-swatch { background: transparent; box-shadow: inset 0 0 0 1.5px var(--uh-mtc-colour, #94a3b8); }
.uh-mtc-key.is-empty { cursor: not-allowed; opacity: .45; }
.uh-mtc-legend-actions { display: flex; flex: 0 0 auto; gap: 4px; }
.uh-mtc-all {
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font-size: 11px;
  padding: 2px 9px;
  line-height: 1.5;
  cursor: pointer;
}
.uh-mtc-all:hover { background: var(--bg-primary); color: var(--text-primary); }

/* The SVG keeps its viewBox aspect, so an unbounded width is an unbounded
   height. Capping the box near the 1240-unit viewBox width holds the rendered
   chart at roughly its design height instead of letting a wide popup stretch it
   vertically. <!-- 2026-09-18 --> */
.uh-mtc-chart {
  max-width: 1266px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: #fff;
  padding: 4px 6px 0;
}
.uh-mtc-svg { display: block; width: 100%; height: auto; overflow: visible; }
.uh-mtc-plot { fill: var(--bg-primary, #f8fafc); stroke: none; }
.uh-mtc-grid { stroke: rgba(30, 48, 80, .10); stroke-width: 1; }
.uh-mtc-slot { stroke: rgba(30, 48, 80, .08); stroke-width: 1; stroke-dasharray: 3 3; }
.uh-mtc-split { stroke: rgba(30, 48, 80, .26); stroke-width: 1; stroke-dasharray: 5 4; }
/* The viewBox now renders near 1:1 rather than being scaled up ~1.24x, so these
   sizes were raised to keep the same on-screen legibility. <!-- 2026-09-18 --> */
.uh-mtc-tick { font-size: 11px; fill: var(--text-secondary, #64748b); }
.uh-mtc-slot-label { font-size: 13px; font-weight: 600; fill: var(--text-primary, #1e293b); }
.uh-mtc-slot-sub { font-size: 10.5px; fill: var(--text-secondary, #64748b); }
.uh-mtc-axis-title { font-size: 10.5px; fill: var(--text-secondary, #64748b); }

.uh-mtc-series.is-hidden { display: none; }
.uh-mtc-line {
  fill: none;
  stroke: var(--uh-mtc-colour, #64748b);
  /* Narrow, metric-specific dash patterns let coincident paths all show through. */
  stroke-width: 1.9;
  stroke-dasharray: var(--uh-mtc-dash, none);
  stroke-linejoin: round;
  stroke-linecap: round;
  pointer-events: none;
}
.uh-mtc-dot { fill: var(--uh-mtc-colour, #64748b); stroke: #fff; stroke-width: 1.2; pointer-events: none; }
/* Abbreviation beside each line's newest point. The white paint-order halo keeps
   it legible where it crosses a grid line or another series. */
.uh-mtc-end-label {
  font-size: 10.5px;
  font-weight: 600;
  fill: var(--uh-mtc-colour, #64748b);
  paint-order: stroke;
  stroke: #fff;
  stroke-width: 2.6;
  stroke-linejoin: round;
  pointer-events: none;
}
.uh-mtc-series.is-active .uh-mtc-end-label { font-size: 12.5px; }
/* Invisible, generously sized hover targets: a wide stroke over the line and a
   larger circle over each marker, so a thin 2px line is still easy to hit. */
.uh-mtc-hit { fill: none; stroke: transparent; stroke-width: 16; pointer-events: stroke; }
.uh-mtc-dot-hit { fill: transparent; pointer-events: all; }
/* Escape the clutter: while one line is hovered the rest fade right back. */
.uh-mtc-chart.is-focused .uh-mtc-series { opacity: .13; }
.uh-mtc-chart.is-focused .uh-mtc-series.is-active { opacity: 1; }
.uh-mtc-series.is-active .uh-mtc-line { stroke-width: 3.9; }
.uh-mtc-series.is-active .uh-mtc-dot { r: 5.4; }

/* Floating raw-value tooltip. position:fixed + JS-set top/left, appended to the
   popup overlay (a sibling of the overflow:hidden popup) so it is never clipped
   and dies with the overlay. Above the overlay's z-index:205. */
.uh-mtc-tip {
  position: fixed;
  left: 0;
  top: -9999px;
  z-index: 210;
  box-sizing: border-box;
  width: max-content;
  max-width: min(360px, calc(100vw - 16px));
  padding: 9px 10px 10px;
  background: #fff;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  box-shadow: rgba(15, 23, 42, .14) 0 6px 20px, rgba(15, 23, 42, .08) 0 2px 6px;
  color: var(--text-primary, #1e293b);
  pointer-events: none;
}
.uh-mtc-tip[hidden] { display: none; }
.uh-mtc-tip-head {
  display: flex;
  align-items: flex-start;
  gap: 6px;
  margin-bottom: 7px;
  padding-bottom: 6px;
  border-bottom: 1px solid #e2e8f0;
}
.uh-mtc-tip-swatch { width: 10px; height: 10px; margin-top: 3px; flex: 0 0 auto; border-radius: 50%; }
.uh-mtc-tip-name { font-size: 12px; font-weight: 700; line-height: 1.3; }
.uh-mtc-tip-name span {
  display: block;
  color: var(--text-secondary);
  font-size: 10px;
  font-weight: 400;
}
.uh-mtc-tip-table { border-collapse: collapse; width: 100%; font-size: 11px; }
.uh-mtc-tip-table th,
.uh-mtc-tip-table td { padding: 3px 5px; text-align: right; vertical-align: top; }
.uh-mtc-tip-table thead th {
  border-bottom: 1px solid #e2e8f0;
  color: var(--text-secondary);
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
}
.uh-mtc-tip-table thead th:first-child,
.uh-mtc-tip-table tbody th { text-align: left; }
.uh-mtc-tip-table tbody th { font-weight: 600; white-space: nowrap; }
.uh-mtc-tip-table tbody th span {
  display: block;
  color: var(--text-secondary);
  font-size: 9.5px;
  font-weight: 400;
}
.uh-mtc-tip-score { font-weight: 700; font-variant-numeric: tabular-nums; }
.uh-mtc-tip-raw { font-variant-numeric: tabular-nums; white-space: nowrap; }
.uh-mtc-tip-raw span { display: block; color: var(--text-secondary); font-size: 9.5px; }
/* The period whose marker is under the cursor. */
.uh-mtc-tip-table tbody tr.is-hovered { background: rgba(37, 99, 235, .09); }
.uh-mtc-tip-note,
.uh-mtc-tip-desc {
  margin: 6px 0 0;
  color: var(--text-secondary);
  font-size: 10px;
  line-height: 1.4;
}
.uh-mtc-tip-desc { padding-top: 5px; border-top: 1px solid #e2e8f0; }

@media (max-width: 650px) {
  .uh-mtc-legend-bar { flex-direction: column; }
}

/* ─── MAU report Rolling-30d / Calendar-month toggle ─── */
.mau-mode-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  margin-top: 8px;
}
.mau-mode-btn {
  border: none;
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font-size: 12px;
  padding: 4px 12px;
  cursor: pointer;
  line-height: 1.4;
}
.mau-mode-btn + .mau-mode-btn { border-left: 1px solid var(--border); }
.mau-mode-btn:hover { background: var(--bg-primary); color: var(--text-primary); }
.mau-mode-btn.active { background: var(--accent); color: #fff; }

/* ─── "Show SF" mode ──────────────────────────────────────────────────────────
   The toggle prefixes every client name with its Salesforce account name
   ("Account / client"), which roughly doubles the label length. `app.ts` puts
   `sf-names` on <body> while it's on, so the name columns get more room ONLY in
   that mode — the default layout is untouched.
   The toggle itself reuses .fav-mode-toggle for layout; .sf-mode-toggle just
   drops the star's leading gap. */
.sf-mode-toggle { gap: 4px; }

body.sf-names .hm-tenant-cell { min-width: 320px; }
body.sf-names .compare-tenant-cell { min-width: 300px; }
body.sf-names .insights-tenant { min-width: 300px; }
/* Match the first column's cell width to the SF-prefixed label so it doesn't
   overflow. Room comes from demoting two heatmap columns to the expand section. */
body.sf-names .insights-table th:first-child,
body.sf-names .insights-table td:first-child { width: 300px; min-width: 300px; }
body.sf-names .uh-table { --uh-sticky-client-width: 392px; }
/* Risk Quadrant's side list and the Spider Webs tile captions: give the list
   more width, and let a tile name wrap onto a second line rather than clip. */
body.sf-names .rq-list { flex: 0 0 300px; }
body.sf-names .sw-name { white-space: normal; overflow-wrap: anywhere; }

/* Active contract window (Salesforce `Active Contract Start/End Date`), shown
   beside a client name in every NAME LIST while Show SF is on — emitted by
   `contractRangeHtml()` in sf-accounts.ts, which returns '' when the toggle is
   off, so this only ever appears in SF mode.
   `display: block` deliberately: the range sits on its own line UNDER the name
   rather than competing with it for the column's width, so the existing
   `body.sf-names` min-widths above stay sufficient and no cell has to grow
   sideways. Rows get marginally taller in SF mode; that is the whole cost. */
.sf-contract {
  display: block;
  font-size: 10px;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  opacity: 0.85;
  white-space: nowrap;
  font-weight: 400;
}
/* The labelled, tinted variant and its `.sf-contract-label` / `.sf-contract-window` /
   `.sf-contract-end` rules were removed on 2026-10-01 with `contractRangeDetailHtml`.
   Its one caller, the Recommended Actions account cell, now has a Contract column
   tinted from the row's own renewal band — see `.uh-ra-contract-*`. The plain chip
   above is unaffected and is still what every name list appends. */

/* Salesforce Industry (`industryHtml()` in sf-accounts.ts) — same rule as
   `.sf-contract` above: it rides the Show-SF toggle (empty string when off) and
   sits on its own line under the name for the same reason, rather than widening
   the cell. */
.sf-industry {
  display: block;
  font-size: 10px;
  color: var(--text-secondary);
  opacity: 0.85;
  white-space: nowrap;
  font-weight: 400;
}

/* Quarterly AS hours (`asHoursHtml()` in sf-accounts.ts), rendered directly beneath
   the ARR band at every site that shows the band. It rides the BAND, not the Show-SF
   toggle, so unlike `.sf-contract` above this can appear with SF names off.
   `display: block` for the same reason as the contract chip: it takes a line of its
   own rather than widening a column. Emitted only when the account buys or uses
   hours, so most rows carry nothing and no table grows for the estate default. */
.as-hours {
  display: block;
  font-size: 10px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  color: var(--text-secondary);
  white-space: nowrap;
}
/* In the tenant header the badge row is a flex line, so the chip sits beside the
   ARR badge instead of dropping under it — there is no column to protect there. */
.tenant-title-row .as-hours { display: inline-flex; align-items: center; font-size: 11px; }

/* AI Cost report — client x use_case pivot */
.ai-cost-table { width: 100%; }
.ai-cost-table th.ai-cost-value,
.ai-cost-table td.ai-cost-value {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.ai-cost-table tfoot td { font-weight: 700; }

/* Each cell is an equation read top-to-bottom: the interactions × avg-cents working
   above, the dollar total below. The working is deliberately quiet — the total is the
   figure you scan down a column, the working is what you check when one looks wrong. */
.ai-cost-table td.ai-cost-value .ai-cost-eq,
.ai-cost-table td.ai-cost-value .ai-cost-amount { display: block; line-height: 1.25; }
.ai-cost-table td.ai-cost-value .ai-cost-eq {
  font-size: 10px;
  color: var(--text-secondary);
}
.ai-cost-table td.ai-cost-value .ai-cost-eq-none { font-style: italic; }
/* Zero is a real observation, but a grid of $0.00 buries the signal — mute it. */
.ai-cost-table td.ai-cost-zero { color: var(--text-secondary); }
/* Margins: the row-total column and the share column read as summaries, not data. */
.ai-cost-pivot th.ai-cost-margin,
.ai-cost-pivot td.ai-cost-margin {
  border-left: 2px solid var(--border);
  font-weight: 600;
}
.ai-cost-pivot th.ai-cost-share,
.ai-cost-pivot td.ai-cost-share { color: var(--text-secondary); }
/* Column sizing: every measure column shrinks to fit its figures and the client
   name column absorbs the slack, so ~10 columns stay readable. Beats the generic
   .trend-table nth-child pins via the table id. */
#ai-cost-tbl th.ai-cost-value,
#ai-cost-tbl td.ai-cost-value { width: 1%; }
#ai-cost-tbl th:first-child,
#ai-cost-tbl td.client-name-cell { width: auto; white-space: nowrap; }
/* Dimension banner above the column headers. Its height is FIXED because the
   second header row sticks at that offset (see the sticky rule below); change
   one and you must change the other. */
.ai-cost-pivot .ai-cost-dim-row th {
  height: 22px;
  padding: 2px 8px 0;
  border-bottom: none;
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
}
.ai-cost-pivot .ai-cost-dim-measure { border-bottom: 2px solid var(--accent); }
/* Two sticky header rows: the shared rule pins every th at top:0, which would
   stack them. Offset the label row by (just under) the banner height so they
   overlap by a pixel rather than leaving a gap for body rows to show through. */
.mau-by-client-scroll .ai-cost-pivot thead tr:not(.ai-cost-dim-row) th { top: 20px; }

/* ProgramAI interaction-cost OKR */
.okr-cost-summary {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}
.okr-cost-stat {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-card);
}
.okr-cost-stat span {
  color: var(--text-secondary);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .3px;
  text-transform: uppercase;
}
.okr-cost-stat strong {
  overflow: hidden;
  font-size: 22px;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.okr-cost-chart {
  flex: 0 1 320px;
  min-height: 220px;
  margin-bottom: 18px;
}
.okr-cost-chart .mau-chart { display: block; }
.okr-cost-table { width: 100%; min-width: 760px; }
.okr-cost-table th.okr-number,
.okr-cost-table td.okr-number {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.okr-cost-table th:first-child,
.okr-cost-table td:first-child { white-space: nowrap; }
@media (max-width: 800px) {
  .okr-cost-summary { grid-template-columns: 1fr; }
  .okr-cost-stat { padding: 10px 12px; }
  .okr-cost-stat strong { font-size: 18px; }
}



/* Usage Health modal lifecycle metadata. */
.uh-modal-lifecycle {
  display: flex;
  flex: 0 0 auto;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin: 0 2px 0 auto;
  color: var(--text-secondary);
  font-size: 10px;
  text-align: right;
  white-space: nowrap;
}
.uh-modal-lifecycle-label { font-weight: 600; }
.uh-modal-lifecycle-value { font-variant-numeric: tabular-nums; }


/* ARR-cohort summary — natural-unit aggregates without the Raw Health Data heatmap. */
.uh-summary-table {
  --uh-summary-arr-width: 180px;
}

.uh-summary-table .uh-summary-arr {
  position: sticky;
  left: 0;
  z-index: 1;
  box-sizing: border-box;
  width: var(--uh-summary-arr-width);
  min-width: var(--uh-summary-arr-width);
  max-width: var(--uh-summary-arr-width);
  background: var(--bg-primary, #fff);
  font-weight: 600;
  text-align: left;
  white-space: nowrap;
}

.uh-summary-table thead .uh-summary-arr {
  top: 0;
  z-index: 6;
  background: #f8fafc;
  vertical-align: bottom;
}

.uh-summary-sub {
  position: sticky;
  top: calc(var(--uh-h-group) + var(--uh-h-metric));
  z-index: 2;
  width: 58px;
  min-width: 48px;
  max-width: 70px;
  background: #f8fafc;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  vertical-align: bottom;
  white-space: normal;
}

.uh-summary-stat {
  width: 58px;
  min-width: 48px;
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.uh-summary-sub.uh-group-start,
.uh-summary-stat.uh-group-start {
  box-shadow: inset 2px 0 0 0 rgba(30, 48, 80, 0.25), inset 0 -1px 0 0 rgba(30, 48, 80, 0.12);
}

.uh-summary-table .uh-row:hover td { background: #dbeafe; }

/* Cadence Drops: persisted raw-evidence queue. The uh-client-attention-* class
   names are the retained older feature name; see the terminology note in
   .kiro/steering/usage-health-tab.md. */
.uh-client-attention-summary {
  display: grid;
  grid-template-columns: repeat(5, minmax(90px, 1fr)) minmax(190px, 1.7fr);
  gap: 8px;
  margin-bottom: 10px;
}
.uh-attention-count,
.uh-attention-asof {
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--border-color, #e2e8f0);
  border-radius: 8px;
  background: var(--bg-primary, #fff);
}
.uh-attention-count span,
.uh-attention-asof span,
.uh-attention-asof small {
  display: block;
  color: var(--text-secondary, #64748b);
  font-size: 10px;
}
.uh-attention-count strong,
.uh-attention-asof strong { display: block; margin-top: 2px; font-size: 19px; }
.uh-attention-asof strong { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.uh-attention-asof small { margin-top: 3px; }
.uh-attention-act-now { border-color: #f3a4a0; background: rgba(239, 68, 68, .08); }
.uh-attention-review { border-color: #f1be72; background: rgba(245, 164, 61, .08); }
.uh-attention-monitor { border-color: #9fc5ee; background: rgba(37, 99, 235, .06); }
.uh-attention-data-check { border-color: #cbd5e1; background: rgba(100, 116, 139, .06); }
.uh-attention-none { border-color: #a7d7b5; background: rgba(34, 197, 94, .06); }
.uh-client-attention-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: center;
  margin: 0 0 10px;
  color: var(--text-secondary, #64748b);
  font-size: 11px;
}
.uh-client-attention-filters label { display: inline-flex; align-items: center; gap: 5px; }
.uh-client-attention-filters select {
  min-height: 28px;
  padding: 3px 7px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 6px;
  background: var(--bg-primary, #fff);
  color: var(--text-primary, #0f172a);
  font: inherit;
}
.uh-client-attention-banners { display: grid; gap: 7px; margin: 0 0 10px; }
.uh-client-attention-banner {
  padding: 9px 11px;
  border: 1px solid #9fc5ee;
  border-radius: 8px;
  background: rgba(37, 99, 235, .06);
  color: #1e4c7a;
  font-size: 12px;
  line-height: 1.35;
}
.uh-client-attention-state {
  margin: 0 0 12px;
  padding: 13px;
  border: 1px solid var(--border-color, #e2e8f0);
  border-radius: 8px;
  background: var(--bg-secondary, #f8fafc);
  color: var(--text-secondary, #64748b);
  font-size: 12px;
}
.uh-client-attention-state.stale { border-color: #f1be72; color: #8a4b08; background: rgba(245, 164, 61, .08); }
.uh-client-attention-state.error { border-color: #f3a4a0; color: #9f2520; background: rgba(239, 68, 68, .08); }
.uh-client-attention-top-scroll,
.uh-client-attention-table-wrap {
  --uh-client-attention-table-min-width: 1660px;
  max-width: 100%;
  scrollbar-gutter: stable;
}
.uh-client-attention-top-scroll {
  position: sticky;
  top: 0;
  z-index: 3;
  height: 20px;
  overflow-x: auto;
  overflow-y: hidden;
  margin: 0 0 6px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 5px;
  background: var(--bg-secondary, #f8fafc);
}
.uh-client-attention-top-scroll:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
.uh-client-attention-scroll-spacer,
.uh-client-attention-table { width: 100%; min-width: var(--uh-client-attention-table-min-width); }
.uh-client-attention-table-wrap {
  overflow-x: auto;
  margin-bottom: 14px;
}
.uh-client-attention-table { table-layout: fixed; }
.uh-client-attention-table th,
.uh-client-attention-table td {
  padding: 10px 8px;
  text-align: left;
  vertical-align: top;
  font-size: 11px;
  line-height: 1.45;
}
.uh-client-attention-table td {
  white-space: normal;
  overflow-wrap: anywhere;
}
.uh-client-attention-table td.uh-name {
  overflow: visible;
  text-overflow: clip;
}
.uh-attention-region,
.uh-attention-commercial,
.uh-attention-strength {
  display: block;
  margin-top: 3px;
  color: var(--text-secondary, #64748b);
  font-size: 9px;
  font-style: normal;
  font-weight: 700;
  letter-spacing: .04em;
}
.uh-attention-commercial {
  font-weight: 500;
  letter-spacing: normal;
  line-height: 1.35;
}
.uh-attention-strength { font-size: 10px; }
.uh-client-attention-table th {
  color: var(--text-secondary, #64748b);
  font-size: 10px;
  text-align: center;
  white-space: normal;
  overflow-wrap: normal;
  word-break: normal;
}
.uh-attention-threshold-row th {
  height: 118px;
  padding: 6px 2px;
  vertical-align: bottom;
  background: color-mix(in srgb, var(--bg-secondary, #f8fafc) 82%, #dbeafe);
}
.uh-attention-threshold-intro,
.uh-attention-threshold-note { font-size: 9px !important; line-height: 1.35; }
.uh-attention-threshold-intro button {
  margin-top: 4px;
  padding: 2px 5px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 4px;
  background: var(--bg-primary, #fff);
  color: inherit;
  font: inherit;
  cursor: pointer;
}
.uh-attention-threshold-intro button:disabled { cursor: default; opacity: .55; }
.uh-attention-threshold-control {
  display: inline-flex;
  width: 49%;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  color: var(--text-secondary, #64748b);
  font-size: 8px;
  font-weight: 700;
  line-height: 1;
}
.uh-attention-threshold-control:only-child { width: 100%; }
.uh-attention-threshold-slider {
  box-sizing: border-box;
  width: 16px;
  height: 70px;
  margin: 0;
  accent-color: #2563eb;
  cursor: ns-resize;
  direction: rtl;
  writing-mode: vertical-lr;
}
.uh-attention-threshold-control output {
  min-width: 22px;
  color: var(--text-primary, #0f172a);
  font-size: 8px;
  font-variant-numeric: tabular-nums;
}
.uh-attention-threshold-summary {
  margin: 9px 0;
  padding: 8px 10px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  background: rgba(148, 163, 184, .07);
  color: var(--text-secondary, #64748b);
  font-size: 11px;
  line-height: 1.4;
}
.uh-attention-threshold-summary.active {
  border-color: #7cb3ec;
  background: rgba(37, 99, 235, .07);
  color: #1e4c7a;
}
.uh-attention-col-client { width: 14%; }
.uh-attention-col-priority { width: 8%; }
.uh-attention-col-alarm { width: 3.5%; }
.uh-attention-col-rationale { width: 29%; }
.uh-attention-col-action { width: 17.5%; }
.uh-attention-priority-cell { white-space: nowrap; }
.uh-attention-alarm-cell { padding: 10px 2px !important; text-align: center !important; vertical-align: middle !important; }
.uh-attention-alarm {
  display: inline-block;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  color: transparent;
  vertical-align: middle;
  box-shadow: inset 0 0 0 1px rgba(15, 23, 42, .18), 0 1px 2px rgba(15, 23, 42, .15);
}
.uh-attention-alarm-red { background: #dc2626; }
.uh-attention-alarm-green { background: #22c55e; }
.uh-attention-alarm-grey { background: #94a3b8; }
.uh-attention-rationale { margin: 0; padding-left: 17px; }
.uh-attention-rationale li + li { margin-top: 5px; }
.uh-attention-no-alarm { color: var(--text-secondary, #64748b); }
.uh-client-attention-row { cursor: pointer; }
.uh-client-attention-row:focus { outline: 2px solid #2563eb; outline-offset: -2px; }
.uh-attention-priority { display: inline-block; padding: 2px 6px; border-radius: 999px; font-size: 10px; font-weight: 700; white-space: nowrap; }
.uh-attention-priority-act-now { color: #9f2520; background: rgba(239, 68, 68, .14); }
.uh-attention-priority-review { color: #8a4b08; background: rgba(245, 164, 61, .16); }
.uh-attention-priority-monitor { color: #1e4c7a; background: rgba(37, 99, 235, .12); }
.uh-attention-priority-data-check { color: #475569; background: rgba(100, 116, 139, .12); }
.uh-attention-priority-dormant { color: #6b21a8; background: rgba(168, 85, 247, .12); }
.uh-attention-priority-none { color: #166534; background: rgba(34, 197, 94, .12); }
@container (max-width: 850px) {
  .uh-client-attention-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .uh-attention-asof { grid-column: span 2; }
}

/* Recommended Actions: one stack-ranked queue read from the persisted artifact.
   Deliberately plain — urgency, account, paragraph, graph plan, freshness — so
   the row never exposes weights, scores, source labels, or packet identity. The
   row itself opens the detail overlay; there is no See-detail column. */
.uh-ra-summary {
  display: grid;
  grid-template-columns: repeat(5, minmax(90px, 1fr)) minmax(190px, 1.7fr);
  gap: 8px;
  margin-bottom: 10px;
}
.uh-ra-count,
.uh-ra-asof {
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--border-color, #e2e8f0);
  border-radius: 8px;
  background: var(--bg-primary, #fff);
}
.uh-ra-count span,
.uh-ra-asof span,
.uh-ra-asof small {
  display: block;
  color: var(--text-secondary, #64748b);
  font-size: 10px;
}
.uh-ra-count strong,
.uh-ra-asof strong { display: block; margin-top: 2px; font-size: 19px; }
.uh-ra-asof strong { overflow: hidden; font-size: 12px; text-overflow: ellipsis; white-space: nowrap; }
.uh-ra-asof small { margin-top: 3px; }
.uh-ra-act-now { border-color: #f3a4a0; background: rgba(239, 68, 68, .08); }
.uh-ra-review { border-color: #f1be72; background: rgba(245, 164, 61, .08); }
.uh-ra-monitor { border-color: #9fc5ee; background: rgba(37, 99, 235, .06); }
.uh-ra-data-check { border-color: #cbd5e1; background: rgba(100, 116, 139, .06); }
.uh-ra-none { border-color: #a7d7b5; background: rgba(34, 197, 94, .06); }
/* Each count tile is a <button> that filters the table to its urgency, so it needs
   the button resets a div did not: `font: inherit` (a button does not inherit the
   page font) and `text-align: left`.

   `display: grid` + `align-content: start` is the load-bearing one. A button
   vertically centres its own content, and these tiles are stretched to the taller
   `.uh-ra-asof` tile's height — so without it the labels and numbers would drift
   down off the top edge they currently sit on. Making the button its own grid
   container removes that centring outright rather than fighting it.

   The active ring is neutral slate and deliberately NOT from the urgency palette:
   the tile already carries its own urgency tint, and a coloured ring would read as
   a second status rather than as "this one is selected". Colour is never the only
   cue — the tile also carries `aria-pressed`. */
.uh-ra-count {
  display: grid;
  align-content: start;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
/* Black label and count, overriding the secondary grey the shared tile rule sets on
   the label. These five tiles sit on their own urgency tint, so the grey that reads
   as a quiet caption on the white `.uh-ra-asof` tile loses contrast here. The
   `.uh-ra-asof` tile keeps the grey — it is a caption, not a number. */
.uh-ra-count,
.uh-ra-count span { color: #000; }
.uh-ra-count:hover { border-color: #94a3b8; }
.uh-ra-count:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 1px; }
.uh-ra-count.is-active { box-shadow: inset 0 0 0 2px #475569; }
.uh-ra-count.is-active strong { font-weight: 800; }
.uh-ra-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 14px;
  align-items: center;
  margin: 0 0 10px;
  color: var(--text-secondary, #64748b);
  font-size: 11px;
}
.uh-ra-controls label { display: inline-flex; align-items: center; gap: 5px; }
/* Expand / Collapse all, pushed to the trailing edge: they act on the table rather than
   filtering it, so they read as a pair of actions beside the two filters and not as a third
   filter. Same treatment as the dashboard's own Expand All / Collapse All. */
.uh-ra-fold-all { display: inline-flex; gap: 5px; margin-left: auto; }
.uh-ra-fold-all button {
  min-height: 28px; padding: 3px 9px;
  border: 1px solid var(--border, #cbd5e1); border-radius: 6px;
  background: var(--bg-primary, #fff); color: var(--text-primary, #0f172a);
  font: inherit; font-size: 11px; cursor: pointer;
}
.uh-ra-fold-all button:hover { background: var(--bg-secondary, #f1f5f9); }
.uh-ra-fold-all button:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 1px; }
.uh-ra-controls select {
  min-height: 28px;
  padding: 3px 7px;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 6px;
  background: var(--bg-primary, #fff);
  color: var(--text-primary, #0f172a);
  font: inherit;
}
.uh-ra-state {
  margin: 0 0 12px;
  padding: 13px;
  border: 1px solid var(--border-color, #e2e8f0);
  border-radius: 8px;
  background: var(--bg-primary, #fff);
  color: var(--text-secondary, #64748b);
  line-height: 1.45;
  font-size: 12px;
}
.uh-ra-state.stale { border-color: #f1be72; color: #8a4b08; background: rgba(245, 164, 61, .08); }
.uh-ra-state code { padding: 1px 4px; border-radius: 4px; background: rgba(100, 116, 139, .12); font-size: 11px; }
/* The summary counts and the controls, frozen at the top of the .uh-body
   scrollport with the table header pinned directly beneath them.

   Bleed-through is the whole difficulty here, so three things are deliberate:
   - `padding-bottom` (not 0) blocks the last child's bottom margin from collapsing
     out of this box. A collapsed margin would leave a transparent strip below the
     sticky block that scrolling rows show through.
   - the background is opaque, and the z-index beats the sticky `thead`, so the one
     pixel the header tucks underneath is covered rather than blended.
   - no negative side margins: .uh-body already has 12px side padding and every
     child sits inside its content box, so nothing can appear in the gutters —
     whereas pulling this block out to the padding edge would make it wider than the
     scrollport and create a horizontal scrollbar of its own.
   The block's height is measured in `pinFrozenHeader()` and published as
   --uh-ra-head-top on .uh-ra-table-wrap; it is not derivable in CSS because the
   summary grid and the controls both rewrap with the panel width. */
.uh-ra-frozen {
  position: sticky;
  top: 0;
  z-index: 9;
  padding-bottom: 4px;
  background: var(--bg-primary, #fff);
}
.uh-ra-table-wrap { margin-bottom: 14px; }
/* Client first: it is what a reader scans down. Wide enough for the name, region, and
   ARR band stacked. Trimmed from 204px on 2026-10-01 when the labelled contract chip
   left this cell for its own column — the chip was the widest thing stacked here, and
   the 16px went to Analysis along with the rest of the new column's cost. */
.uh-ra-col-account { width: 188px; }
.uh-ra-col-urgency { width: 92px; }
/* Concern sits beside Priority: two pills, two axes, read together. It takes back the
   width the removed `Evidence as of` column briefly gave to Analysis. `No concern` is
   the longest label, so it is a shade narrower than the Priority column's `No action
   needed`. */
.uh-ra-col-concern { width: 86px; }
/* Contract sits after the two pills: the decision, then the two things it is made of.
   Sized for `30/11/26` above `ended 120 days ago`, the longest distance phrase, on two
   lines. `Not recorded` fits on one. */
.uh-ra-col-contract { width: 96px; }
/* Wider than a badge needs, because a changed row also lists what moved underneath
   it. The Analysis column absorbs the difference via `table-layout: fixed`. */
.uh-ra-col-change { width: 148px; }
/* `.uh-ra-col-asof` (100px) was removed with the per-row Evidence as of column on
   2026-09-29. Its width went to Analysis, and the Concern column above took it back. */
/* This table's Why-flagged cell holds a paragraph, so it must wrap rather than
   inherit the dense score-table `white-space: nowrap` — that made the row as wide
   as the sentence and put a horizontal scrollbar on the whole .uh-body panel.
   `table-layout: fixed` then holds the fixed columns and lets Why take the rest,
   so every pixel trimmed from a fixed column above widens Analysis. */
.uh-ra-table { table-layout: fixed; }
/* One size for the whole table. The analysis used to render a step smaller than
   the cells around it, which read as a different typeface for the main text of the
   row; the row's own prose should look like the row. */
.uh-ra-table { font-size: 12px; }
.uh-ra-table td { vertical-align: top; white-space: normal; }
/* Frozen column header. `.uh-table` already sets `border-collapse: separate`, so
   the grid lines below travel with the cell instead of scrolling away and letting a
   sliver of a row through the seam. */
.uh-ra-table thead th {
  position: sticky;
  top: var(--uh-ra-head-top, 0px);
  z-index: 4;
  background: #f8fafc;
  box-shadow: inset 1px 0 0 0 rgba(30, 48, 80, .12), inset 0 -2px 0 0 rgba(30, 48, 80, .25);
  text-align: left;
  vertical-align: bottom;
  white-space: normal;
  font-weight: 600;
  font-size: 11px;
}
.uh-ra-table thead th.uh-ra-sort { cursor: pointer; user-select: none; }
.uh-ra-table thead th.uh-ra-sort:hover { background: #eef2f7; }
.uh-ra-table thead th.uh-ra-sorted { background: #e2e8f0; }
.uh-ra-table thead th.uh-ra-sorted.asc::after { content: ' ▲'; font-size: 8px; }
.uh-ra-table thead th.uh-ra-sorted.desc::after { content: ' ▼'; font-size: 8px; }
/* The account cell stacks name, region, ARR band, and contract, so it must grow
   downwards rather than clip like the dense Health Data name column it shares a
   class with. */
.uh-ra-table .uh-name { max-width: none; overflow: visible; overflow-wrap: anywhere; }
.uh-ra-arr {
  display: block;
  margin-top: 2px;
  color: var(--text-secondary, #64748b);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}
/* Contract column. The date leads and the distance is the supporting line, because the
   date is what a reader looks up and the distance is why it matters. Tinted by the
   renewal BAND, so the colour follows the same 120/270 boundaries the Priority pill
   beside it was computed from — never a cutoff of its own. */
.uh-ra-contract, .uh-ra-contract-absent { display: block; }
.uh-ra-contract-date { display: block; font-variant-numeric: tabular-nums; }
.uh-ra-contract-distance {
  display: block;
  margin-top: 1px;
  color: var(--text-secondary, #64748b);
  font-size: 10px;
}
.uh-ra-contract-overdue .uh-ra-contract-date,
.uh-ra-contract-due .uh-ra-contract-date { color: #b91c1c; font-weight: 700; }
.uh-ra-contract-mid .uh-ra-contract-date { color: #b45309; font-weight: 700; }
/* Stated, never a dash: a missing contract end took the `unknown` matrix column, and a
   blank cell would read as a distant renewal. */
.uh-ra-contract-absent { color: var(--text-secondary, #64748b); font-style: italic; font-size: 11px; }
.uh-ra-why-absent { color: var(--text-secondary, #64748b); font-style: italic; }
/* The fixed policy's own reading, rendered through the SAME field-based renderer as the
   model's — since artifact v9 both are `{ sections: [{ heading, lead, points, quotes,
   detail }] }`, so there is one visual language for "the analysis" rather than a headed
   document in one state and a `white-space: pre-line` bullet string in the other. */
.uh-ra-why-deterministic .uh-ra-field-points { margin: 0; }

/* ── Field-based analysis and Summary. Artifact v9. ──
   Every class below renders a NAMED FIELD rather than a pattern found in a string, which
   is the point of the schema change: the renderer no longer infers layout from `## ` or
   `•` or a quote mark it had to match as `&quot;`. */

/* The Summary's one-sentence judgement. It is the first thing a reader reads and often
   the only thing, so it is the one line allowed to be heavier than the body. */
.uh-ra-field-headline {
  margin: 0 0 6px; font-size: 15px; font-weight: 700; line-height: 1.4;
  max-width: 70ch; color: var(--text-primary, #0f172a);
}
/* No browser marker: the `::before` bullet is ours, so a point's text never has to carry
   one and a model that emitted one anyway cannot double it up. */
.uh-ra-field-points { margin: 0 0 6px; padding: 0; list-style: none; max-width: 76ch; }
.uh-ra-field-points:last-child { margin-bottom: 0; }
.uh-ra-field-points li { position: relative; padding-left: 14px; margin: 0 0 4px; line-height: 1.45; }
.uh-ra-field-points li:last-child { margin-bottom: 0; }
.uh-ra-field-points li::before { content: '•'; position: absolute; left: 0; color: var(--text-secondary, #64748b); }

/* The quote stack. ⚠️ A background TINT, never a `border-left`, for the same reason
   `.uh-ra-prose-quote` uses one: an inline border draws only on the first line fragment,
   which showed one stray vertical bar and then ran on. These are block-level so a border
   would work here — but keeping both quote treatments on one mechanism is what stops the
   next edit reintroducing the inline version. */
.uh-ra-field-quotes { margin: 0 0 8px; display: grid; gap: 6px; }
.uh-ra-field-quotes:last-child { margin-bottom: 0; }
.uh-ra-field-quote {
  position: relative; margin: 0; padding: 6px 8px 6px 10px;
  background: rgba(37, 99, 235, .08); border-radius: 4px;
  box-decoration-break: clone; -webkit-box-decoration-break: clone;
  font-style: italic; line-height: 1.45; max-width: 74ch;
}
/* The number tying a Summary quote to its entry in the under-fold provenance list. */
.uh-ra-field-quote-n {
  display: inline-block; min-width: 14px; margin-right: 4px;
  font-style: normal; font-weight: 700; font-size: 10px;
  color: var(--text-secondary, #64748b); vertical-align: super;
}
/* Inline attribution, analysis-side only. The Summary defers this under the fold. */
.uh-ra-field-quote-src {
  display: block; margin-top: 2px; font-style: normal; font-size: 11px;
  color: var(--text-secondary, #64748b);
}
/* ⚠️ The STATED-ABSENCE variant, and it must not read as a gap or a fault: 33 of the 81
   model-backed EU records have no quotable comment at all, so this is the ordinary case.
   Muted and untinted, so it is visibly a fact about the account rather than an empty box. */
.uh-ra-field-quote-absent {
  margin: 0 0 6px; color: var(--text-secondary, #64748b); font-style: italic; font-size: 11px;
}
/* `detail`, behind a disclosure triangle. Nullable per section, so this often renders
   nothing at all — which is why it carries its own margins rather than relying on a
   sibling. */
.uh-ra-field-detail { margin: 0 0 6px; max-width: 76ch; }
.uh-ra-field-detail > summary {
  cursor: pointer; font-size: 11px; color: var(--accent-primary, #2563eb);
}
.uh-ra-field-detail > p { margin: 4px 0 0; line-height: 1.5; }
/* Where each Summary quote came from, under the fold, numbered against the blocks above
   it. Four inline attribution lines doubled the Summary's height while adding nothing a
   scanning reader uses; a reader who opened the fold is reading closely. */
.uh-ra-field-srcs {
  margin: 0 0 8px; padding-left: 18px; font-size: 11px;
  color: var(--text-secondary, #64748b); line-height: 1.4;
}
/* `structuredProseHtml` block markup — shared by the row's folded Analysis cell and
   the overlay's "What the fixed policy decided" panel, so one set of rules covers
   both the model's headed document and the fixed policy's bullet list. */
.uh-ra-prose-heading { margin: 10px 0 4px; font-size: 12px; font-weight: 700; color: var(--text-primary, #0f172a); }
.uh-ra-prose-heading:first-child { margin-top: 0; }
/* `line-height` and a bounded measure are the only things CSS can do for a long
   paragraph. The Analysis column is wide, and a ~1,000-character rationale set as one
   unbounded line runs well past the ~75-character measure the eye tracks comfortably —
   which is a large part of why it reads as a wall. `max-width` in `ch` caps the line
   without fixing a pixel width, so it still reflows with the column. */
.uh-ra-prose-p { margin: 0 0 6px; max-width: 78ch; line-height: 1.5; }
.uh-ra-prose-p:last-child { margin-bottom: 0; }
/* A real list rather than a flat paragraph of `•` lines: each bullet becomes its own
   block so a reader can scan it rather than parse run-on sentences separated by a
   character. No browser bullet marker of its own — the model/policy text already
   supplied one before this ran, and a second marker would double it up. */
.uh-ra-prose-list { margin: 0 0 6px; padding: 0; list-style: none; }
.uh-ra-prose-list:last-child { margin-bottom: 0; }
.uh-ra-prose-list li { position: relative; padding-left: 14px; margin: 0 0 4px; }
.uh-ra-prose-list li:last-child { margin-bottom: 0; }
.uh-ra-prose-list li::before { content: '•'; position: absolute; left: 0; color: var(--text-secondary, #64748b); }
/* A client's own words, inline in the analysis prose. Quote marks pattern-matched out
   of existing text (see `highlightQuotes` in formatting.ts) — no new field, no prompt
   change.
   ⚠️ A tint, NOT a left border. An inline box draws `border-left` only at the start of
   its FIRST line fragment, so a quote that wrapped showed a single stray vertical bar
   and then ran on unbounded — the defect this replaced. A background tint repeats on
   every fragment, and `box-decoration-break: clone` gives each wrapped line its own
   rounded ends instead of one box sliced open. */
.uh-ra-prose-quote {
  font-style: italic;
  background: rgba(37, 99, 235, .08);
  border-radius: 3px;
  padding: 0 3px;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}
/* `<q>` adds its own quote marks, and `highlightQuotes` deliberately keeps the literal
   marks from the source text inside the wrap — they are what close the quotation. Left
   on, every quote would print doubled marks (`""like this""`). */
.uh-ra-prose-quote::before, .uh-ra-prose-quote::after { content: none; }
/* The reviewer's verdict, above its analysis. It is the reason this row sits where
   it does, so it leads the cell and the analysis below it is de-emphasised. */
.uh-ra-review-verdict { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 4px; }
.uh-ra-review-badge { display: inline-block; padding: 2px 6px; border-radius: 999px; font-size: 10px; font-weight: 700; white-space: nowrap; }
.uh-ra-review-agree { color: #475569; background: rgba(100, 116, 139, .12); }
.uh-ra-review-understated { color: #9f2520; background: rgba(239, 68, 68, .14); }
.uh-ra-review-overstated { color: #1e4c7a; background: rgba(37, 99, 235, .12); }
/* "fixed policy said X" is the displaced cross-check, not this row's state — the
   Priority column is the decision. Kept quieter than the urgency pill for that
   reason. */
.uh-ra-review-proposed { font-size: 11px; font-weight: 600; color: var(--text-secondary, #64748b); }
.uh-ra-review-confidence { font-size: 10px; color: var(--text-secondary, #64748b); }
/* The rationale is the cell's summary: the one unheaded block in a cell whose
   analysis sections are all headed by the prompt, so it gets a label of its own
   and reads two points above them (14 against the table's 12). It is why the row
   sits where it does; the sections below are the supporting detail. The label
   matches its own body size rather than the table's, the same way
   `.uh-ra-prose-heading` matches the analysis body — move the two together. */
.uh-ra-summary-heading { margin: 0 0 2px; font-size: 14px; font-weight: 700; color: var(--text-primary, #0f172a); }
.uh-ra-review-rationale { margin: 0 0 6px; font-size: 14px; line-height: 1.45; }
/* Onboarding caveat for an account whose first survey response is under three
   months old, above the Summary. A bordered note rather than a badge or a tint:
   it reframes the whole cell, so it has to read as an aside the reader takes in
   before the judgement, not as another status on the row. Deliberately amber and
   deliberately NOT from the urgency palette — this does not change the priority,
   and a note wearing an urgency colour would imply it had. */
.uh-ra-onboarding-note {
  margin: 0 0 6px; padding: 5px 8px; font-size: 12px; line-height: 1.4;
  color: #7c5410; background: rgba(245, 158, 11, .1);
  border-left: 3px solid rgba(245, 158, 11, .55); border-radius: 3px;
}
/* The row is the detail trigger (there is no See-detail column). */
.uh-ra-row { cursor: pointer; }
.uh-ra-row:hover { background: rgba(37, 99, 235, .06); }
.uh-ra-row:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: -2px; }
/* Since-last-queue cell. Styled deliberately quieter than the urgency pill beside
   it: the row's decision is the urgency, and this only qualifies it. The badge
   colours are directional (escalated warm, eased cool) and must not reuse the
   urgency palette, or a "Escalated" badge would read as an urgency of its own. */
.uh-ra-change-cell { line-height: 1.5; }
.uh-ra-change-badge {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 999px;
  font-size: 10px;
  font-weight: 700;
  white-space: nowrap;
}
.uh-ra-change-new { color: #5b3593; background: rgba(139, 92, 246, .14); }
/* Renamed from -escalated/-eased on 2026-09-29 with the labels they carry
   ("Increased"/"Decreased"); the slug and the visible word must not drift apart.
   There is deliberately no -verdict badge any more: the reviewer's verdict is not
   shown outside the overlay's Technical detail fold. */
.uh-ra-change-increased { color: #9f2520; background: rgba(239, 68, 68, .12); }
.uh-ra-change-decreased { color: #166534; background: rgba(34, 197, 94, .12); }
.uh-ra-change-moved { color: #475569; background: rgba(100, 116, 139, .12); }
.uh-ra-change-detail { display: block; color: var(--text-secondary, #64748b); font-size: 10px; }
/* What moved underneath a changed row. Indented and rule-marked so the triggers
   read as evidence for the badge above them rather than as more badges. */
.uh-ra-change-trigger {
  display: block;
  margin-top: 3px;
  padding-left: 6px;
  border-left: 2px solid var(--border-color, #e2e8f0);
  color: var(--text-primary, #0f172a);
  font-size: 10px;
  line-height: 1.35;
}
.uh-ra-change-quiet { color: var(--text-secondary, #64748b); font-size: 11px; }
.uh-ra-urgency { display: inline-block; padding: 2px 6px; border-radius: 999px; font-size: 10px; font-weight: 700; white-space: nowrap; }
.uh-ra-urgency-act-now { color: #9f2520; background: rgba(239, 68, 68, .14); }
.uh-ra-urgency-review { color: #8a4b08; background: rgba(245, 164, 61, .16); }
.uh-ra-urgency-monitor { color: #1e4c7a; background: rgba(37, 99, 235, .12); }
.uh-ra-urgency-data-check { color: #475569; background: rgba(100, 116, 139, .12); }
.uh-ra-urgency-none { color: #166534; background: rgba(34, 197, 94, .12); }
/* Concern pills. Deliberately OUTLINED where the urgency pills are filled: the two sit
   side by side on every row and a reader must be able to tell at a glance which axis
   they are reading, which a second set of filled pills in the same palette would not
   allow. Hue tracks severity so the pair still reads as one story left to right. */
.uh-ra-concern {
  display: inline-block; padding: 1px 6px; border-radius: 999px;
  font-size: 10px; font-weight: 700; white-space: nowrap;
  background: transparent; border: 1px solid currentColor;
}
.uh-ra-concern-severe { color: #9f2520; }
.uh-ra-concern-elevated { color: #8a4b08; }
.uh-ra-concern-watch { color: #1e4c7a; }
/* Violet, and outside the severity ramp on purpose: `dormant` is not a severity tier.
   It says the account never had a real survey programme, which is an onboarding problem
   and a different conversation from "the signals are weak". */
.uh-ra-concern-dormant { color: #6b46c1; }
.uh-ra-concern-unreadable { color: #475569; }
.uh-ra-concern-none { color: #166534; }
.uh-ra-account {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent, #2563eb);
  font: inherit;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.uh-ra-account:hover { text-decoration: underline; }
.uh-ra-region { display: block; color: var(--text-secondary, #64748b); font-size: 10px; }
/* Inherits the table's size on purpose: the analysis is the row's main text, so it
   should look like the row. It is the summary above it that now carries the step in
   size — deliberately, as the lead — rather than the analysis being set below the
   cells around it, which is what read as a second typeface. */
.uh-ra-why { margin: 0; line-height: 1.45; font-size: inherit; }
/* The model analysis is a headed document as of the v6 prompt, so it renders as
   blocks rather than one escaped string. `pre-line` is deliberately NOT used here:
   the structure is real markup. The heading is distinguished by weight alone, at
   the body's own size, so the section breaks are visible without the cell turning
   into two different fonts. */
.uh-ra-prose > :first-child { margin-top: 0; }
.uh-ra-prose > :last-child { margin-bottom: 0; }
.uh-ra-prose-heading { margin: 9px 0 2px; font-size: inherit; font-weight: 700; color: var(--text-primary, #0f172a); }
.uh-ra-prose-p { margin: 0 0 5px; }
.uh-ra-graph-plan { display: block; margin-top: 4px; color: var(--text-secondary, #64748b); line-height: 1.35; font-size: 10px; }

/* Recommended Actions detail: a focused, persisted graph plan rather than a broad health drilldown. */
/* ⚠️ The `.uh-ra-detail-*` OVERLAY is gone as of 2026-09-28 — its own dialog, head,
   actions, body, urgency pill, as-of line and hand-rolled activity bars were all removed
   when the second overlay became a fold inside the first. What survives here is the part
   the fold and the first overlay's open body still render: the graph cards, the reviewer
   verdict panel, the comment bodies, the fixed-policy panel, and the technical disclosure.
   The prefix is kept rather than renamed because these selectors are shared by two hosts
   and a rename would be churn for no reader. */
.uh-ra-detail-graphs { display: grid; gap: 12px; }
.uh-ra-detail-graph { padding: 13px; border: 1px solid var(--border, #cbd5e1); border-radius: 8px; background: var(--bg-secondary, #f8fafc); }
.uh-ra-detail-graph h4 { margin: 0 0 4px; font-size: 13px; }
.uh-ra-detail-metric { margin: 0 0 10px; color: var(--text-secondary, #64748b); font-size: 11px; line-height: 1.4; }
.uh-ra-detail-periods { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 9px; }
.uh-ra-detail-period { padding: 9px; border: 1px solid var(--border, #cbd5e1); border-radius: 6px; background: var(--bg-primary, #fff); }
.uh-ra-detail-period.unavailable { opacity: .72; }
.uh-ra-detail-period h5 { margin: 0 0 4px; font-size: 11px; }
.uh-ra-detail-period strong { display: block; font-size: 18px; }
.uh-ra-detail-period small, .uh-ra-detail-period p, .uh-ra-detail-scale { margin: 4px 0 0; color: var(--text-secondary, #64748b); font-size: 10px; line-height: 1.35; }
.uh-ra-detail-graph-unavailable { border-color: #f1be72; background: rgba(245, 164, 61, .08); color: #8a4b08; }
/* The reviewer's verdict. Since 2026-09-28 it renders in the FIRST overlay, beneath the
   trend chart and above the Feedback panel — it is the judgement that set this row's
   priority, not provenance about how the decision was recorded, which is why it never
   belonged behind a technical disclosure. Selectors are deliberately unscoped so the one
   set of rules serves wherever it is rendered. The left border colour carries the
   verdict, matching the row badges. */
.uh-ra-detail-review { margin: 10px 0 14px; padding: 8px 10px; border-left: 3px solid #94a3b8; border-radius: 0 6px 6px 0; background: rgba(148, 163, 184, .08); }
.uh-ra-detail-review-understated { border-left-color: #ef4444; background: rgba(239, 68, 68, .07); }
.uh-ra-detail-review-overstated { border-left-color: #2563eb; background: rgba(37, 99, 235, .06); }
.uh-ra-detail-review h4 { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; margin: 0 0 5px; font-size: 12px; }
.uh-ra-detail-review-confidence { font-weight: 400; font-size: 10px; color: var(--text-secondary, #64748b); }
.uh-ra-detail-review p { margin: 4px 0 0; font-size: 11px; line-height: 1.45; }
.uh-ra-detail-review-overlooked { color: var(--text-secondary, #64748b); font-size: 10px; }
/* CG-internal feedback comment bodies. The list wrapper and the `<li>` treatment were
   removed on 2026-09-28 when the comments moved to the first overlay's Feedback panel,
   which renders each one as a `<details class="uh-ra-feedback-item">`; the per-comment
   body rules below are shared by both and stay. */
.uh-ra-detail-comment-meta { margin: 0 0 4px; font-size: 10px; font-weight: 600; color: var(--text-secondary, #64748b); }
.uh-ra-detail-comment-meta em { font-weight: 400; font-style: italic; }
/* Verbatim text: preserve the author's own wording and let it wrap naturally. */
.uh-ra-detail-comment blockquote,
.uh-ra-feedback-item blockquote { margin: 0; font-size: 11px; line-height: 1.5; overflow-wrap: break-word; }
.uh-ra-detail-comment-truncated { font-size: 9px; color: var(--text-secondary, #64748b); }
/* Additional question answers, inside the comment they belong to. A definition list
   because that is what they are: the question asked and the answer given. The answer
   text is the same size as the comment quote above it — on a call-transcript response
   it is the stronger evidence of the two, so it must not be styled as a footnote. */
.uh-ra-detail-comment-answers { margin: 6px 0 0; padding: 6px 0 0; border-top: 1px dashed rgba(148, 163, 184, .45); }
.uh-ra-detail-comment-answers dt { margin: 5px 0 1px; font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: var(--text-secondary, #64748b); }
.uh-ra-detail-comment-answers dt:first-child { margin-top: 0; }
.uh-ra-detail-comment-answers dd { margin: 0; font-size: 11px; line-height: 1.5; overflow-wrap: break-word; }
/* Answers were never captured for this record, which is NOT the same as the response
   having answered nothing. Amber rather than the muted grey of `-topics`/`-ref`: it is
   a gap in what we hold, not a quieter detail about the comment. */
.uh-ra-detail-comment-answers-absent {
  margin: 6px 0 0;
  padding: 5px 7px;
  border-left: 2px solid #f1be72;
  background: rgba(245, 164, 61, .08);
  color: #8a4b08;
  font-size: 9px;
  line-height: 1.45;
}

.uh-ra-detail-comment-topics,
.uh-ra-detail-comment-ref { margin: 4px 0 0; font-size: 9px; color: var(--text-secondary, #64748b); }
/* The fixed policy's own reading, in the open body. It took over from the queue
   table's Deterministic column, so it has to be readable as evidence rather than as
   a footnote — but it stays visually quieter than the reviewer's panel above it,
   because it is the cross-check and not the live decision. */
.uh-ra-detail-deterministic-panel { margin-top: 12px; padding: 9px 11px; border: 1px solid var(--border, #e2e8f0); border-radius: 8px; background: rgba(148, 163, 184, .07); }
.uh-ra-detail-deterministic-panel h4 { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 4px; font-size: 12px; }
.uh-ra-detail-deterministic-urgency { padding: 2px 7px; border-radius: 999px; background: rgba(100, 116, 139, .14); color: #475569; font-size: 10px; font-weight: 700; }
.uh-ra-detail-deterministic-note { margin: 0 0 6px; font-size: 10px; color: var(--text-secondary, #64748b); }
/* One block per bullet, so the list reads as a list. */
.uh-ra-detail-deterministic-panel .uh-ra-detail-deterministic { margin: 3px 0 0; font-size: 11px; line-height: 1.45; }
.uh-ra-detail-technical { margin-top: 14px; color: var(--text-secondary, #64748b); font-size: 10px; }
.uh-ra-detail-technical summary { cursor: pointer; font-weight: 600; }
.uh-ra-detail-technical p { margin: 5px 0 0; line-height: 1.4; }
@container (max-width: 850px) {
  .uh-ra-summary { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .uh-ra-asof { grid-column: span 2; }
}
@media (max-width: 640px) {
  .uh-ra-detail-periods { grid-template-columns: 1fr; }
}

/* Recommended Actions: the ONE overlay a row opens. Line chart, saved evidence cards,
   feedback, and a collapsed technical fold.

   ⚠️ It no longer fits 1366x768 without a scrollbar, and `overflow: auto` is now the
   expected reading mode rather than a safety valve <!-- 2026-09-28 -->. That is the
   accepted cost of folding the second overlay in: a reader who had to close one dialog
   to open another could never see the evidence and the reasoning together. Growth is
   bounded rather than open-ended — the feedback list scrolls inside itself and the
   technical fold is collapsed by default.

   The width still matters and is still interdependent: 1180px leaves the .uh-mtc SVG
   (a 1240x300 viewBox at width:100%) rendering near 275px. Widening the popup makes the
   line chart TALLER, not wider, because the viewBox aspect is fixed. <!-- 2026-09-23 --> */
.uh-ra-charts-overlay { position: fixed; inset: 0; z-index: 210; display: flex; align-items: center; justify-content: center; padding: 16px; background: rgba(0, 0, 0, .6); }
.uh-ra-charts-popup {
  width: min(1180px, 97vw);
  max-height: 96vh;
  overflow: auto;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 12px;
  background: var(--bg-primary, #fff);
  color: var(--text-primary, #0f172a);
  box-shadow: 0 20px 60px rgba(15, 23, 42, .3);
}
.uh-ra-charts-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; padding: 10px 16px; border-bottom: 1px solid var(--border, #cbd5e1); }
.uh-ra-charts-head h2 { margin: 0; font-size: 15px; }
.uh-ra-charts-identity { min-width: 0; }
.uh-ra-charts-client { display: flex; align-items: center; gap: 7px; margin: 2px 0 0; font-size: 12px; font-weight: 600; }
.uh-ra-charts-region, .uh-ra-charts-arr { border: 1px solid var(--border, #cbd5e1); border-radius: 999px; padding: 0 7px; color: var(--text-secondary, #64748b); font-size: 10px; font-weight: 600; }
.uh-ra-charts-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 3px; margin-left: auto; }
.uh-ra-charts-meta small { color: var(--text-secondary, #64748b); font-size: 10px; }
/* Reuses the queue's .uh-ra-urgency-* palette so the pill reads as the same fact. */
.uh-ra-charts-urgency { border-radius: 999px; padding: 1px 9px; font-size: 11px; font-weight: 700; }
.uh-ra-charts-actions { display: flex; align-items: center; gap: 7px; }
.uh-ra-charts-actions button { border: 1px solid var(--border, #cbd5e1); border-radius: 7px; background: var(--bg-secondary, #f1f5f9); color: var(--text-primary, #0f172a); cursor: pointer; font-size: 11px; padding: 4px 10px; }
.uh-ra-charts-actions button:hover { background: var(--bg-primary, #fff); }
.uh-ra-charts-close { font-size: 15px !important; line-height: 1; padding: 3px 9px !important; }
.uh-ra-charts-body { display: grid; gap: 8px; padding: 10px 16px 14px; }
.uh-ra-charts-body .uh-mtc { margin: 0; }
.uh-ra-charts-body .uh-mtc-toggle { font-size: 12px; }
/* Compact the legend here. With four series dropped it is ~8 keys, and the legend is
   the only part of the line chart whose height is not fixed by the viewBox — a third
   wrapped row is what would push this popup into a scrollbar. */
.uh-ra-charts-body .uh-mtc-body { margin-top: 4px; }
.uh-ra-charts-body .uh-mtc-legend-bar { margin-bottom: 4px; }
.uh-ra-charts-body .uh-mtc-legend { gap: 3px 5px; }
.uh-ra-charts-body .uh-mtc-key { font-size: 10px; padding: 1px 7px 1px 4px; gap: 4px; }
.uh-ra-charts-body .uh-mtc-key-swatch { width: 8px; height: 8px; }
.uh-ra-charts-body .uh-mtc-all { font-size: 10px; padding: 1px 8px; }
.uh-ra-charts-unavailable { margin: 0; color: var(--text-secondary, #64748b); font-size: 11px; }
/* The saved supporting evidence, moved into this overlay's open body on 2026-09-28 when
   the second overlay was folded in. It is evidence a reader weighs, so it is open; the
   reasoning about how the decision was reached is the collapsed fold below. */
.uh-ra-charts-evidence { margin: 2px 0 0; }
.uh-ra-charts-evidence > h4 { margin: 0 0 4px; font-size: 12px; }
/* Two cards abreast where there is room. The graph plan is 1–4 references, so a single
   column wasted most of a 1180px dialog. */
.uh-ra-charts-evidence .uh-ra-detail-graphs { grid-template-columns: repeat(auto-fit, minmax(330px, 1fr)); }
/* The row already draws this account's 24-month charts, so the card is a pointer rather
   than a second copy of them. Quieter than an unavailable card: nothing is missing. */
.uh-ra-detail-graph-pointer { border-style: dashed; }
/* How the decision was reached — collapsed, because a reader acting on the row has the
   priority and the summary already, and this overlay's height budget is finite. */
.uh-ra-charts-technical { margin: 4px 0 0; border-top: 1px solid var(--border, #e2e8f0); padding-top: 7px; }
.uh-ra-charts-technical > summary {
  cursor: pointer; width: fit-content; padding: 1px 4px; border-radius: 4px;
  font-size: 11px; font-weight: 600; color: var(--text-secondary, #64748b);
  list-style-position: inside;
}
.uh-ra-charts-technical > summary:hover { color: var(--text-primary, #0f172a); background: var(--bg-secondary, #f1f5f9); }
.uh-ra-charts-technical > summary:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 1px; }
/* The verdict panel's own top margin is written for an open body, so it is trimmed here
   where the summary above it already provides the separation. */
.uh-ra-charts-technical-body > .uh-ra-detail-review:first-child { margin-top: 6px; }
@media (max-width: 900px) {
  .uh-ra-charts-head { flex-wrap: wrap; }
  .uh-ra-charts-evidence .uh-ra-detail-graphs { grid-template-columns: 1fr; }
}

/* Recommended Actions: the row fold.
   <!-- 2026-09-28 -->
   The CONTROL is in the Account cell and the CONTENT is in the Analysis cell, four
   columns away — which is why this is a button driving `hidden` rather than a
   `<details>`: no element may span two `<td>`s, so a disclosure cannot wrap content in
   another cell. The button carries aria-expanded/aria-controls instead. */
/* The arrow sits left of the name and the rest of the cell stacks beside it. A flex row
   INSIDE the td rather than `display: flex` on the td itself, which would take the cell out
   of table layout and break vertical-align and border-collapse. */
.uh-ra-account-row { display: flex; align-items: flex-start; gap: 3px; }
.uh-ra-account-detail { min-width: 0; }
/* Arrow-only, and large: the labelled pill this replaced competed with the account name for
   the eye in a 204px column. No border or fill — a disclosure arrow beside a name is
   understood without being dressed as a button, and the row is already a click target. */
.uh-ra-row-toggle {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; margin: -1px 0 0 -3px; padding: 0;
  border: 0; border-radius: 5px; background: none;
  color: var(--text-secondary, #64748b); cursor: pointer;
}
.uh-ra-row-toggle:hover { color: var(--text-primary, #0f172a); background: var(--bg-secondary, #f1f5f9); }
.uh-ra-row-toggle:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 1px; }
/* A CSS triangle rather than a character: a glyph's size and baseline vary by font, and
   this has to line up with the name beside it at a fixed size. It rotates on state because
   the button is the only thing that knows whether the row is open. */
.uh-ra-row-toggle-caret {
  width: 0; height: 0; border-left: 7px solid currentColor;
  border-top: 5.5px solid transparent; border-bottom: 5.5px solid transparent;
  transition: transform .12s ease-out;
}
.uh-ra-row-toggle[aria-expanded="true"] .uh-ra-row-toggle-caret { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
  .uh-ra-row-toggle-caret { transition: none; }
}
/* The arrow's former caption, repurposed. The row opens the overlay on click and on
   Enter/Space, which is the least discoverable thing in this table — nothing about a row
   says it is clickable, and the arrow now explains only itself. Quiet enough to repeat on
   every row without becoming noise. */
.uh-ra-row-hint { display: block; margin-top: 3px; color: var(--text-secondary, #94a3b8); font-size: 9px; font-style: italic; }
.uh-ra-row:hover .uh-ra-row-hint { color: var(--text-secondary, #64748b); }
/* The CG Internal platform deep link, at the foot of the Account cell. `display: block`
   so it sits under the chips above rather than competing for the 188px column width —
   the same reasoning as `.sf-contract`. */
.uh-ra-cvm-link {
  display: block;
  margin-top: 4px;
  color: var(--accent, #2563eb);
  font-size: 10px;
  text-decoration: none;
}
.uh-ra-cvm-link:hover, .uh-ra-cvm-link:focus-visible { text-decoration: underline; }
/* Stated rather than left blank: a client with no CG Internal Account is usually a
   mapping still owed, which is actionable. Quiet and italic because it is an absence,
   not a status of its own — and deliberately not amber, which in this table already
   means the onboarding caveat. */
.uh-ra-cvm-absent {
  display: block;
  margin-top: 4px;
  color: var(--text-secondary, #94a3b8);
  font-size: 9px;
  font-style: italic;
  line-height: 1.35;
}
/* Everything in the Analysis cell below the fold: the charts and the analysis document.
   Only the reviewer's summary sits above it, so a collapsed queue is scannable. The rule
   above it separates the summary from the detail it introduces. */
.uh-ra-analysis-more { margin-top: 7px; padding-top: 7px; border-top: 1px dashed rgba(148, 163, 184, .5); }
.uh-ra-analysis-more[hidden] { display: none; }
/* The mount is a SIBLING of the fold since 2026-09-30, not a child of it — the charts are
   always on screen and only the prose folds. `:not(:empty)` because the mount is filled
   when its row scrolls into view, so an unbuilt one must take no vertical space at all or
   every collapsed row would carry a phantom gap. */
.uh-ra-row-charts-mount:not(:empty) { margin-top: 8px; }
/* Side by side where the column is wide enough, stacked where it is not. The two
   sections must opt out of the Cadence popup's grid-column: 1 / -1, which is written
   for that popup's single-column frame. */
.uh-ra-row-bars { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; }
.uh-ra-row-bars .uh-cadence-survey-chart, .uh-ra-row-bars .uh-cadence-login-chart { grid-column: auto; min-width: 0; }
.uh-ra-row-bars h5 { margin: 0 0 2px; font-size: 11px; }
.uh-ra-row-bars > section > p { margin: 0 0 4px; font-size: 10px; }
/* ⚠️ The scale column's height and the SVG's height are ONE UNIT — the scale is a
   flex column with space-between, so overriding one alone puts the max label out of
   line with the top of the plot. Move both or neither. */
.uh-ra-row-bars .uh-cadence-chart-scale { height: 72px; font-size: 8px; }
.uh-ra-row-bars .uh-cadence-survey-chart svg, .uh-ra-row-bars .uh-cadence-login-chart svg { height: 72px; }
.uh-ra-row-charts-unavailable { margin: 0; color: var(--text-secondary, #64748b); font-size: 11px; }

/* Recommended Actions overlay 1: the feedback panel beside the trend chart.
   Each comment is a collapsed disclosure — a Signal transcript runs to a 2,000-char
   quote plus up to 24 answers and a record can retain eight of them, so collapsed
   headers are what keep this overlay readable at 1366x768. */
.uh-ra-feedback { margin: 2px 0 0; }
.uh-ra-feedback > h4 { margin: 0 0 3px; font-size: 12px; display: flex; align-items: center; gap: 6px; }
.uh-ra-feedback-count {
  font-size: 9px; font-weight: 600; padding: 0 5px; border-radius: 8px;
  background: var(--bg-secondary, #f1f5f9); color: var(--text-secondary, #64748b);
}
.uh-ra-feedback-note { margin: 0 0 6px; font-size: 10px; color: var(--text-secondary, #64748b); }
.uh-ra-feedback-note em { font-style: italic; }
/* ⚠️ The one unbounded block in this overlay, so it scrolls inside itself rather than
   growing the dialog — same containment as `.uh-modal-topic-rows` in the Risk
   drilldown. Without it, opening three transcripts puts an outer scrollbar on a popup
   that is deliberately sized not to have one. */
.uh-ra-feedback-list {
  display: flex; flex-direction: column; gap: 5px;
  max-height: 260px; overflow-y: auto; padding-right: 2px;
}
.uh-ra-feedback-item {
  padding: 5px 8px; border-left: 3px solid #cbd5e1; border-radius: 0 6px 6px 0;
  background: rgba(148, 163, 184, .07);
}
/* Promoter / detractor shading, from the comment's own NPS band. Passive and unscored
   keep the neutral slate so the two ends stay the only things that read as a signal. */
.uh-ra-feedback-detractor { border-left-color: #ef4444; background: rgba(239, 68, 68, .06); }
.uh-ra-feedback-promoter { border-left-color: #16a34a; background: rgba(22, 163, 74, .06); }
.uh-ra-feedback-item > summary {
  cursor: pointer; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 7px;
  font-size: 10px; color: var(--text-secondary, #64748b);
}
.uh-ra-feedback-item > summary:focus-visible { outline: 2px solid var(--accent, #2563eb); outline-offset: 2px; }
.uh-ra-feedback-item[open] > summary { margin-bottom: 5px; }
.uh-ra-feedback-when { font-weight: 600; color: var(--text-primary, #0f172a); }
.uh-ra-feedback-band { font-weight: 600; }
.uh-ra-feedback-detractor .uh-ra-feedback-band { color: #b91c1c; }
.uh-ra-feedback-promoter .uh-ra-feedback-band { color: #15803d; }
.uh-ra-feedback-provenance { font-style: italic; }
.uh-ra-feedback-cited {
  font-size: 9px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  padding: 0 5px; border-radius: 8px; color: #1d4ed8; background: rgba(37, 99, 235, .12);
}

/* Cadence Drops popup: deterministic survey/login evidence, distinct from the
   Risk, sentiment, and Spider drilldowns. */
.uh-client-attention-overlay {
  position: fixed;
  inset: 0;
  z-index: 210;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
  background: rgba(0, 0, 0, .6);
}
.uh-client-attention-popup {
  width: min(1120px, 97vw);
  max-height: 96vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--border, #cbd5e1);
  border-radius: 12px;
  background: var(--bg-primary, #fff);
  box-shadow: rgba(15, 15, 15, .24) 0 12px 36px;
  color: var(--text-primary, #0f172a);
}
.uh-client-attention-popup-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border, #cbd5e1);
}
.uh-client-attention-popup-identity { min-width: 0; }
.uh-client-attention-popup-head h2 { margin: 0; font-size: 17px; }
.uh-client-attention-client { display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; margin: 3px 0 0; color: var(--text-primary, #0f172a); font-size: 12px; font-weight: 700; overflow-wrap: anywhere; }
.uh-client-attention-client-region { flex: 0 0 auto; color: var(--text-secondary, #64748b); font-size: 11px; font-weight: 400; }
.uh-client-attention-cadence-badge { display: inline-flex; flex: 0 0 auto; align-items: center; padding: 2px 6px; border: 1px solid color-mix(in srgb, #2563eb 45%, var(--border, #cbd5e1)); border-radius: 999px; background: color-mix(in srgb, #dbeafe 60%, var(--bg-primary, #fff)); color: #1d4ed8; font-size: 10px; font-weight: 700; line-height: 1.2; white-space: nowrap; }
.uh-client-attention-rhythm { display: flex; flex-wrap: wrap; gap: 2px 8px; margin: 3px 0 0; color: var(--text-secondary, #64748b); font-size: 11px; line-height: 1.35; }
.uh-client-attention-rhythm > span + span::before { content: '· '; }
.uh-client-attention-glance-charts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; width: 100%; margin-top: 7px; }
.uh-client-attention-glance-charts .uh-cadence-survey-chart, .uh-client-attention-glance-charts .uh-cadence-login-chart { min-width: 0; padding: 8px 10px; border: 1px solid var(--border, #e2e8f0); border-radius: 7px; background: var(--bg-primary, #fff); }
.uh-client-attention-glance-charts .uh-cadence-survey-chart > h5, .uh-client-attention-glance-charts .uh-cadence-login-chart > h5 { margin: 0 0 4px; font-size: 11px; }
.uh-client-attention-glance-charts .uh-cadence-survey-chart > p, .uh-client-attention-glance-charts .uh-cadence-login-chart > p { font-size: 10px; line-height: 1.4; }
.uh-client-attention-glance-charts .uh-cadence-chart-scale, .uh-client-attention-glance-charts .uh-cadence-survey-chart svg, .uh-client-attention-glance-charts .uh-cadence-login-chart svg { height: 68px; }
.uh-client-attention-glance-charts .uh-cadence-survey-chart-note, .uh-client-attention-glance-charts .uh-cadence-login-chart-note { margin: 4px 0 0; }
.uh-client-attention-popup-actions { display: flex; flex: 0 0 auto; align-items: center; gap: 8px; }
.uh-client-attention-open {
  padding: 6px 11px;
  border: 1px solid #2563eb;
  border-radius: 6px;
  background: #2563eb;
  color: #fff;
  font: inherit;
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
}
.uh-client-attention-open:hover { background: #1d4ed8; }
.uh-client-attention-open:focus-visible,
.uh-client-attention-close:focus-visible,
.uh-attention-evidence-details > summary:focus-visible { outline: 3px solid #2563eb; outline-offset: 2px; }
.uh-client-attention-close {
  border: 0;
  background: none;
  color: var(--text-secondary, #64748b);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.uh-client-attention-close:hover { color: var(--text-primary, #0f172a); }
.uh-client-attention-popup-body { min-height: 0; overflow-y: auto; padding: 11px 14px 12px; user-select: text; }
.uh-client-attention-section-frame { display: grid; gap: 8px; margin-bottom: 9px; }
.uh-client-attention-section { padding: 8px 10px; border: 1px solid var(--border, #e2e8f0); border-radius: 8px; background: var(--bg-secondary, #f8fafc); }
.uh-client-attention-section h3 { margin: 0; font-size: 13px; }
.uh-client-attention-glance { display: grid; gap: 6px; margin-top: 6px; padding: 8px 10px; border: 1px solid var(--border, #cbd5e1); border-left: 4px solid #dc2626; border-radius: 7px; background: color-mix(in srgb, var(--bg-primary, #fff) 86%, #fef2f2); }
.uh-client-attention-glance--no-attention { border-left-color: #16a34a; background: color-mix(in srgb, var(--bg-primary, #fff) 86%, #f0fdf4); }
.uh-client-attention-glance--data-check { border-left-color: #64748b; background: color-mix(in srgb, var(--bg-primary, #fff) 86%, #f1f5f9); }
.uh-client-attention-glance-summary { margin: 0; font-size: 12px; line-height: 1.45; }
.uh-client-attention-glance-meta { margin: 0; color: var(--text-secondary, #64748b); font-size: 10px; line-height: 1.3; }
.uh-cadence-source-cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 6px; }
.uh-cadence-activity-card { display: grid; min-width: 0; gap: 7px; margin: 0; padding: 8px 10px; border: 1px solid var(--border, #cbd5e1); border-radius: 7px; background: var(--bg-primary, #fff); }
.uh-cadence-activity-card > h4 { margin: 0; font-size: 12px; }
.uh-cadence-activity-card > p { margin: -4px 0 0; color: var(--text-secondary, #64748b); font-size: 11px; line-height: 1.4; }
.uh-cadence-activity-story { display: grid; grid-template-columns: minmax(0, 1fr); gap: 7px; }
.uh-cadence-activity-story section { padding: 7px 9px; border: 1px solid var(--border, #e2e8f0); border-radius: 7px; background: var(--bg-secondary, #f8fafc); }
.uh-cadence-activity-story h5 { margin: 0 0 4px; font-size: 11px; }
.uh-cadence-activity-story p { margin: 0; font-size: 11px; line-height: 1.45; }
.uh-cadence-activity-story small { display: block; margin-top: 4px; color: var(--text-secondary, #64748b); font-size: 10px; line-height: 1.4; }
.uh-cadence-activity-comparisons { grid-column: 1 / -1; }
.uh-cadence-activity-comparison-list { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.uh-cadence-activity-comparison { display: grid; justify-items: center; gap: 3px; min-width: 0; padding: 7px 6px; border: 1px solid var(--border, #e2e8f0); border-radius: 7px; background: var(--bg-primary, #fff); text-align: center; }
.uh-cadence-activity-comparison-heading { font-size: 11px; line-height: 1.25; }
.uh-cadence-activity-comparison-change { font-size: 15px; font-weight: 800; line-height: 1.2; white-space: nowrap; }
.uh-cadence-activity-comparison-change--up { color: #16a34a; }
.uh-cadence-activity-comparison-change--down { color: #dc2626; }
.uh-cadence-activity-comparison-change--neutral,
.uh-cadence-activity-comparison-change--unavailable { color: var(--text-secondary, #64748b); }
.uh-cadence-activity-comparison-average-label { color: var(--text-secondary, #64748b); font-size: 9px; line-height: 1.25; }
.uh-cadence-activity-comparison-average-values { font-size: 11px; font-weight: 700; line-height: 1.25; }
.uh-cadence-activity-comparison-average-values--unavailable { color: var(--text-secondary, #64748b); font-weight: 400; }
@media (max-width: 900px) {
  .uh-cadence-source-cards { grid-template-columns: 1fr; }
  .uh-cadence-activity-comparison-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.uh-cadence-survey-chart, .uh-cadence-login-chart { grid-column: 1 / -1; }
.uh-cadence-survey-chart > p, .uh-cadence-login-chart > p { margin: 0 0 5px; }
.uh-cadence-chart-frame { display: grid; grid-template-columns: 32px minmax(0, 1fr); gap: 5px; }
.uh-cadence-chart-scale { display: flex; flex-direction: column; justify-content: space-between; height: 92px; color: var(--text-secondary, #64748b); font-size: 9px; line-height: 1; text-align: right; }
.uh-cadence-chart-plot { min-width: 0; }
.uh-cadence-survey-chart svg, .uh-cadence-login-chart svg { display: block; width: 100%; height: 92px; overflow: visible; }
.uh-cadence-survey-chart-baseline, .uh-cadence-login-chart-baseline { stroke: var(--border, #cbd5e1); stroke-width: 1; }
.uh-cadence-survey-chart-bar { fill: #2563eb; }
.uh-cadence-login-chart-bar { fill: #0f766e; }
/* The month in progress: dimmed with a dashed outline so it never reads as a settled
   month. Rect-scoped so the zero line keeps its own dotted stroke and only dims, and
   placed before --expected so an amber expected-window bar keeps its amber outline. */
.uh-cadence-survey-chart-bar--partial, .uh-cadence-login-chart-bar--partial { opacity: .62; }
rect.uh-cadence-survey-chart-bar--partial { stroke: #1d4ed8; stroke-dasharray: 1.5 1; stroke-width: 1; }
rect.uh-cadence-login-chart-bar--partial { stroke: #0f766e; stroke-dasharray: 1.5 1; stroke-width: 1; }
.uh-cadence-survey-chart-bar--expected, .uh-cadence-login-chart-bar--expected { fill: #d97706; stroke: #92400e; stroke-width: 1; }
/* The chart SVG is stretched non-uniformly (preserveAspectRatio="none"), so a scaled stroke
   renders as uneven, smeared dashes on the narrow in-progress bar. Keep strokes a constant
   pixel width, and let an amber in-progress bar keep its amber outline: the rect-scoped
   partial rule above out-ranks --expected and was painting a blue dashed edge on amber. */
rect.uh-cadence-survey-chart-bar--partial, rect.uh-cadence-login-chart-bar--partial { vector-effect: non-scaling-stroke; stroke-dasharray: 3 2; }
rect.uh-cadence-survey-chart-bar--partial.uh-cadence-survey-chart-bar--expected, rect.uh-cadence-login-chart-bar--partial.uh-cadence-login-chart-bar--expected { stroke: #92400e; }
/* A thin dotted line just above the baseline is observed zero; small solid bars are low, nonzero activity. */
.uh-cadence-survey-chart-bar--zero, .uh-cadence-login-chart-bar--zero { fill: none; stroke: #64748b; stroke-dasharray: .6 1.4; stroke-linecap: round; stroke-width: 1; }
.uh-cadence-survey-chart-bar--zero.uh-cadence-survey-chart-bar--expected, .uh-cadence-login-chart-bar--zero.uh-cadence-login-chart-bar--expected { stroke: #92400e; }
/* Full-height outlined slots are before the available client-start proxy, not missing source coverage. */
.uh-cadence-survey-chart-bar--pre-client, .uh-cadence-login-chart-bar--pre-client { fill: none; stroke: #94a3b8; stroke-dasharray: 1 2; stroke-width: 1; opacity: .7; }
.uh-cadence-survey-chart-bar--unavailable, .uh-cadence-login-chart-bar--unavailable { fill: #cbd5e1; stroke: #64748b; stroke-dasharray: 2 1; stroke-width: 1; opacity: .75; }
.uh-cadence-survey-chart-bar, .uh-cadence-login-chart-bar { cursor: crosshair; }
.uh-cadence-chart-bar--active { stroke: #0f172a; stroke-width: 2; }
.uh-cadence-chart-tooltip { position: fixed; z-index: 211; max-width: min(280px, calc(100vw - 24px)); padding: 6px 8px; border-radius: 5px; background: #0f172a; color: #fff; font-size: 11px; line-height: 1.35; pointer-events: none; transform: translateY(-100%); }
.uh-cadence-survey-chart-labels, .uh-cadence-login-chart-labels { display: flex; justify-content: space-between; gap: 4px; color: var(--text-secondary, #64748b); font-size: 9px; }
.uh-cadence-survey-chart-note, .uh-cadence-login-chart-note { color: var(--text-secondary, #64748b); font-size: 10px !important; }
.uh-attention-evidence-summary,
.uh-attention-evidence-chart-intro { margin: 9px 0 0; font-size: 12px; line-height: 1.5; }
.uh-attention-evidence-summary-list { display: grid; gap: 5px; margin: 8px 0 0; padding-left: 18px; font-size: 11px; line-height: 1.45; }
.uh-attention-technical-section h4 { margin: 0 0 7px; font-size: 13px; }
.uh-attention-assessment-copy,
.uh-attention-rationale,
.uh-attention-empty { margin: 0; font-size: 12px; line-height: 1.5; }
.uh-attention-empty { color: var(--text-secondary, #64748b); font-style: italic; }
.uh-attention-findings,
.uh-attention-actions { display: grid; gap: 7px; margin: 0; padding-left: 20px; }
.uh-attention-finding,
.uh-attention-actions li { display: grid; gap: 2px; font-size: 12px; line-height: 1.4; }
.uh-attention-finding small { color: var(--text-secondary, #64748b); font-size: 10px; }
.uh-attention-actions li::marker { color: #2563eb; font-weight: 700; }
.uh-attention-actions strong { color: var(--text-secondary, #64748b); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 10px; }
.uh-attention-facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0; }
.uh-attention-facts > div { padding: 8px 10px; border: 1px solid var(--border, #e2e8f0); border-radius: 7px; background: var(--bg-secondary, #f8fafc); }
.uh-attention-facts dt { color: var(--text-secondary, #64748b); font-size: 10px; }
.uh-attention-facts dd { margin: 3px 0 0; font-size: 11px; line-height: 1.35; }
.uh-attention-cadence-status { margin-bottom: 9px; }
.uh-attention-cyclic-details { margin: 9px 0; padding: 10px; border: 1px solid var(--border, #cbd5e1); border-radius: 8px; background: color-mix(in srgb, var(--bg-secondary, #f8fafc) 84%, #dbeafe); }
.uh-attention-cyclic-details h5 { margin: 0 0 8px; color: var(--text-primary, #0f172a); font-size: 11px; font-weight: 700; }
.uh-attention-cyclic-details .uh-attention-empty { font-style: normal; }
.uh-attention-evidence-details { margin-top: 12px; }
.uh-attention-evidence-details > summary { cursor: pointer; font-size: 12px; font-weight: 700; }
.uh-attention-evidence-details > summary span { margin-left: 5px; color: var(--text-secondary, #64748b); font-size: 10px; font-weight: 400; }
.uh-attention-evidence-body { padding: 0; }
.uh-attention-evidence-body .uh-attention-facts { display: block; margin: 8px 0 0; }
.uh-attention-evidence-body .uh-attention-facts > div { padding: 0; border: 0; border-radius: 0; background: transparent; }
.uh-attention-evidence-body .uh-attention-facts > div + div { margin-top: 4px; }
.uh-attention-evidence-body .uh-attention-facts dt,
.uh-attention-evidence-body .uh-attention-facts dd { display: inline; margin: 0; font-size: 11px; line-height: 1.45; }
.uh-attention-evidence-body .uh-attention-facts dt { color: inherit; font-weight: 700; }
.uh-attention-evidence-body .uh-attention-facts dt::after { content: ': '; }
.uh-attention-evidence-body .uh-attention-cyclic-details { padding: 0; border: 0; border-radius: 0; background: transparent; }
.uh-attention-technical-section { margin: 12px 0 0; padding-top: 12px; border-top: 1px solid var(--border, #e2e8f0); }
.uh-attention-technical-section p { margin: 0; font-size: 11px; line-height: 1.45; }
.uh-attention-technical-list { margin: 0; padding-left: 18px; font-size: 11px; line-height: 1.45; overflow-wrap: anywhere; }
.uh-attention-technical-list ul { margin: 3px 0; padding-left: 18px; }
@media (max-width: 640px) {
  .uh-client-attention-overlay { align-items: stretch; padding: 8px; }
  .uh-client-attention-popup { width: 100%; max-height: none; }
  .uh-client-attention-popup-head { flex-wrap: wrap; gap: 10px; padding: 12px; }
  .uh-client-attention-popup-identity { flex: 1 1 180px; }
  .uh-client-attention-popup-actions { margin-left: auto; }
  .uh-client-attention-popup-body { padding: 12px; }
  .uh-client-attention-glance-charts,
  .uh-attention-facts,
  .uh-client-attention-glance-facts,
  .uh-cadence-activity-story,
  .uh-cadence-activity-comparison-list { grid-template-columns: 1fr; }
  .uh-attention-evidence-details > summary span { display: block; margin: 3px 0 0; }
}

/* ─── Benchmarks tab ───
   Industry (rows) × calendar year (columns) for one selected metric. Shares the
   heatmap's structural vocabulary (fixed-width sidebar, one scrollport, sticky
   first column and header) and its `--hm-*` empty-cell tokens, but has its own
   `bm-` classes because the cell semantics differ: a cell here is an aggregate
   over several clients, not one client's value. */

#benchmark-sidebar {
  width: 280px;
  min-width: 280px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
}
/* Sections group the catalogue; their metrics are listed underneath rather than
   behind a click, so the whole benchmarkable set is visible at once. */
.bm-section { margin-bottom: 10px; }
.bm-section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 4px 6px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-secondary);
}
.bm-section-count {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-secondary);
  background: var(--bg-primary);
  padding: 1px 6px;
  border-radius: 8px;
  letter-spacing: 0;
}
.bm-metric-list { display: flex; flex-direction: column; gap: 1px; }
.bm-metric-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 500;
  border: 1px solid transparent;
}
.bm-metric-item:hover { background: #f4f4f4; }
.bm-metric-item.active { background: rgba(25,173,121,0.08); border-color: var(--accent); }
.bm-metric-label { line-height: 1.3; }
.bm-metric-dir { font-size: 10px; opacity: 0.55; flex: none; }

#benchmarks-panel {
  flex: 1;
  overflow: hidden;
  padding: 12px;
  background: var(--bg-primary);
  display: flex;
  flex-direction: column;
}
.bm-header { flex: none; margin-bottom: 8px; }
.bm-title {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: 16px;
  font-weight: 700;
  color: var(--text-primary);
}
.bm-dir { font-size: 11px; font-weight: 500; color: var(--text-secondary); }
.bm-desc {
  margin-top: 3px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text-secondary);
  max-width: 105ch;
}
.bm-toolbar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
/* Left-hand control group. `.bm-toolbar` is `space-between`, so grouping keeps the
   scope note pinned right however many controls sit beside the agg switch. */
.bm-controls { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.bm-agg { display: flex; align-items: center; gap: 8px; }
.bm-agg-label { font-size: 11px; font-weight: 600; color: var(--text-secondary); }
/* Year-axis direction. A checkbox rather than another segmented switch: it is one
   binary reading preference, not a choice between framings like the agg modes. */
.bm-year-order {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  user-select: none;
}
.bm-year-order input { margin: 0; cursor: pointer; }
.bm-agg-switch {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: #fff;
}
.bm-agg-btn {
  border: none;
  background: #fff;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.bm-agg-btn + .bm-agg-btn { border-left: 1px solid var(--border); }
.bm-agg-btn:hover { background: #f4f4f4; }
.bm-agg-btn.active { background: var(--accent); color: #fff; }
.bm-scope { font-size: 11px; color: var(--text-secondary); text-align: right; }

.bm-container { overflow: auto; flex: 1; min-height: 0; }
.bm-table {
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
  white-space: nowrap;
  margin-bottom: 4px;
}
.bm-table th {
  padding: 6px 10px;
  background: #fff;
  border: 1px solid var(--border);
  color: var(--text-primary);
  font-weight: 700;
  position: sticky;
  top: 0;
  z-index: 2;
  cursor: pointer;
  user-select: none;
  min-width: 74px;
  box-shadow: 0 1px 0 var(--border);
  transition: background 0.15s;
}
.bm-table th:hover { background: #f4f4f4; }
/* Same specificity problem the heatmap's pinned Client header has: the generic
   `.bm-table th` rule out-specifies a bare class, so the corner cell has to
   re-assert its z-index or the year headers paint over it while scrolling. */
.bm-table th.bm-industry-col {
  position: sticky;
  left: 0;
  z-index: 4;
  text-align: left;
  min-width: 210px;
}
.bm-table th.bm-n-col { min-width: 62px; }
.bm-year-col { font-variant-numeric: tabular-nums; }
/* The in-progress calendar year. A rate over a part-year is still comparable,
   which is why the column is shown at all — the marker says the volume behind it
   is not yet a full year. */
.bm-partial { background: #fffdf5; }
.bm-partial-mark {
  display: block;
  margin-top: 2px;
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.2px;
  color: #a07800;
  text-transform: uppercase;
}
.bm-allyears-col { border-left: 2px solid var(--border); min-width: 84px; }

.bm-table td {
  padding: 4px 10px;
  border: 1px solid rgba(30,48,80,0.4);
  text-align: right;
  height: 30px;
  vertical-align: middle;
  font-variant-numeric: tabular-nums;
}
.bm-industry-cell {
  text-align: left;
  font-weight: 500;
  position: sticky;
  left: 0;
  background: #f4f4f4;
  z-index: 1;
  min-width: 210px;
  white-space: normal;
}
.bm-n-cell { color: var(--text-secondary); font-weight: 500; }
/* `--bm-tint` is the 40%-alpha ramp colour set per cell by `cellHtml`. It is a
   custom property rather than an inline `background` so the pinned estate row can
   layer the same tint over an opaque base — see `.bm-estate-row` below. */
.bm-cell { background: var(--bm-tint, transparent); transition: background 0.15s; }
.bm-row:hover td { filter: brightness(1.06); }

/* Industry fold. The whole row is the click target (a 15-column row with one
   clickable glyph is a poor target for a frequent action), so the caret is a
   button purely for keyboard and assistive-tech access and inherits the row's
   own pointer. */
.bm-industry-row { cursor: pointer; }
/* Caret and name stay INLINE. `display: flex` on a `<td>` drops it out of
   `table-cell` and breaks both the column sizing and the sticky first column, and
   `.bm-industry-cell` is shared with the client and estate rows, so it would have
   broken those too. */
.bm-fold {
  border: none;
  background: none;
  padding: 0;
  margin-right: 4px;
  width: 12px;
  font-size: 10px;
  line-height: 1;
  color: var(--text-secondary);
  cursor: pointer;
}
.bm-industry-row.bm-open .bm-fold { color: var(--accent); }
.bm-industry-row.bm-open .bm-industry-name { font-weight: 600; }
.bm-industry-name { line-height: 1.3; }

/* Client child rows. Indented and de-emphasised so the industry aggregate stays
   the primary read, with a left rule tying the group together. */
.bm-client-row td { height: 26px; font-size: 12px; }
.bm-client-cell {
  padding-left: 30px;
  font-weight: 400;
  color: var(--text-secondary);
  box-shadow: inset 3px 0 0 var(--accent);
}
.bm-client-row:hover td { filter: brightness(1.1); }
.bm-empty { color: var(--text-secondary); opacity: 0.45; }
/* Thin cells stay readable but are marked, because a "benchmark" computed from
   one or two clients is that client, not a peer group. */
.bm-low-n { font-style: italic; opacity: 0.8; }
.bm-cell-n {
  margin-left: 5px;
  font-size: 9px;
  font-style: normal;
  opacity: 0.7;
  vertical-align: 1px;
}
.bm-agg-cell { font-weight: 600; }
/* Clients with no Salesforce industry. Kept visible as a coverage row so silence
   about them is not mistaken for there being none, and styled apart so it cannot
   be read as an industry to compare against. */
.bm-row-unmapped { opacity: 0.62; font-style: italic; }
.bm-row-unmapped .bm-industry-cell { border-top: 2px solid var(--border); }
/* Pinned to the bottom of the scrollport, so every cell in it needs an opaque
   backdrop or the body rows scroll through — including the otherwise-unpainted
   Clients cell. */
.bm-estate-row td {
  font-weight: 600;
  border-top: 2px solid var(--border);
  position: sticky;
  bottom: 0;
  z-index: 1;
  background: #f4f6f8;
}
/* Two layers — tint over base — not a flat override: the estate row is read
   against the same ramp as the body, so it has to composite to the same colour a
   body cell does. The base is therefore `--bg-primary`, which is what the body
   cells' alpha actually sits on (the panel background). */
.bm-estate-row td.bm-cell {
  background-color: var(--bg-primary);
  background-image: linear-gradient(var(--bm-tint, transparent), var(--bm-tint, transparent));
}
.bm-estate-row .bm-industry-cell { z-index: 2; background: #f4f6f8; }

/* Rows basis (By Vertical / By Group). */
.bm-basis { display: flex; align-items: center; gap: 6px; }
.bm-basis select { width: auto; font-size: 11.5px; padding: 3px 6px; }

/* Sub-group rows sit one level in, so the parent aggregate stays the primary read. */
.bm-subgroup-row .bm-industry-cell { padding-left: 24px; box-shadow: inset 3px 0 0 #9fb3c8; }
.bm-subgroup-row td { font-size: 12.5px; }
.bm-client-nested .bm-client-cell { padding-left: 48px; }

/* Totals: volume, not a rate, so never tinted — muted so the benchmark row above
   stays the thing being compared. */
.bm-totals-row td { height: 22px; font-size: 10.5px; color: var(--text-secondary); background: #fafbfc; }
.bm-totals-row .bm-industry-cell { padding-left: 30px; font-weight: 400; font-style: italic; background: #fafbfc; }
.bm-sub-totals .bm-industry-cell { padding-left: 54px; }
.bm-total-cell { white-space: nowrap; }
.bm-totals-row:hover td { filter: none; }

/* A platform that also sits in other groups — the double-counting cue. */
.bm-overlap {
  margin-left: 6px; padding: 0 4px; border-radius: 6px;
  font-size: 9.5px; font-style: normal; color: #92400e; background: #fef3c7;
}

/* ─── Groupings tab: local-only Platform Group editor ─── */
#groupings-layout { flex-direction: column; }
#groupings-header {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  padding: 12px 20px; border-bottom: 1px solid var(--border); background: var(--bg-secondary);
}
#groupings-header .sidebar-heading { text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 3px; }
#groupings-header .sidebar-note { max-width: 820px; padding: 0; }
#groupings-panel { flex: 1; min-height: 0; padding: 16px 20px; overflow: auto; }
.gp-workspace { display: grid; grid-template-columns: minmax(220px, 280px) minmax(0, 1fr); gap: 16px; align-items: start; }
.gp-card { padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--bg-card); box-shadow: 0 1px 3px rgba(0,0,0,0.06); }
.gp-list { position: sticky; top: 0; }
.gp-list-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; }
.gp-list-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-secondary); }
.gp-group-item {
  display: flex; justify-content: space-between; gap: 8px; padding: 5px 8px; border-radius: 4px;
  font-size: 12.5px; cursor: pointer; border: 1px solid transparent;
}
.gp-group-item:hover { background: #f4f4f4; }
.gp-group-item.active { background: rgba(25,173,121,0.08); border-color: var(--accent); }
.gp-group-item.gp-sub { padding-left: 22px; }
.gp-group-count { color: var(--text-secondary); font-size: 11px; flex: none; }
.gp-empty { font-size: 12px; color: var(--text-secondary); padding: 6px 2px; }
/* The global `button` rule paints white text on an accent background, so every
   light .gp-* button restates its text colour, and its hover is written with
   :not(:disabled) to out-rank the global hover — otherwise the label is white on
   white until hovered. */
.gp-btn { padding: 5px 10px; font-size: 12px; border: 1px solid var(--border); border-radius: 4px; background: #fff; color: var(--text-primary); cursor: pointer; }
.gp-btn:hover:not(:disabled) { background: #f4f4f4; }
.gp-btn:disabled { opacity: 0.55; cursor: default; }
.gp-btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.gp-btn-primary:hover:not(:disabled) { background: var(--accent-hover); }
.gp-btn-danger { color: #b91c1c; border-color: #fca5a5; }
.gp-form { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 8px 12px; align-items: center; margin-bottom: 12px; }
.gp-form label { font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.gp-form input, .gp-form select { width: 100%; max-width: 420px; }
.gp-hint { font-size: 11px; color: var(--text-secondary); grid-column: 2; margin-top: -4px; }
.gp-columns { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 16px; }
.gp-col-title { font-size: 12px; font-weight: 600; margin-bottom: 6px; display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.gp-picker-search { width: 100%; margin-bottom: 6px; }
.gp-rows { max-height: 52vh; overflow: auto; border: 1px solid var(--border); border-radius: 4px; }
.gp-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; padding: 4px 8px; font-size: 12px; border-bottom: 1px solid #f0f0f0; }
.gp-row:last-child { border-bottom: none; }
.gp-row-name { min-width: 0; }
.gp-row-db { color: var(--text-secondary); font-size: 10.5px; }
.gp-row-note { color: #92400e; font-size: 10.5px; }
.gp-row button { flex: none; padding: 1px 8px; font-size: 11px; border: 1px solid var(--border); border-radius: 4px; background: #fff; color: var(--text-primary); cursor: pointer; }
.gp-row button:hover:not(:disabled) { background: #f4f4f4; }
.gp-actions { display: flex; gap: 8px; align-items: center; margin-top: 12px; }
.gp-status { font-size: 11.5px; color: var(--text-secondary); }
.gp-status.ok { color: #15803d; }
.gp-status.error { color: #b91c1c; }
.gp-caution { margin: 0 0 12px; padding: 8px 10px; font-size: 11.5px; line-height: 1.4; border-radius: 6px; background: #fffbeb; border: 1px solid #fde68a; color: #78350f; }
