
/* ── Admin view ────────────────────────────────────────────────────────── */
.adm-view {
  max-width: 1160px;
  width: 100%;
  min-width: 0;
  margin: 0 auto;
  padding: var(--s5) 20px 72px;
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  box-sizing: border-box;
}

/* ── Page header ────────────────────────────────────────────────────────── */
.adm-page-header { border-bottom: 1px solid var(--border-subtle); padding-bottom: 18px; }
.adm-heading-sub { color: var(--text-muted); font-size: 13px; margin: 0; }

/* ── Stats strip ────────────────────────────────────────────────────────── */
.adm-stats {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
  gap: var(--s3);
}
.adm-stats .adm-stat-gone .stat-value { color: var(--warn); }
/* Nested Ops/Storage tiles are narrower than the top strip. A 28px mono
   value such as "$0.0940" was wider than its tile. */
.adm-sub-body .adm-stats { grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
.adm-sub-body .stat-value { font-size: 22px; max-width: 100%; }

/* ── Sections container ─────────────────────────────────────────────────── */
.adm-sections { display: flex; flex-direction: column; gap: 10px; min-width: 0; }

/* Accordion, link rows and the ← Admin header live in styles/section.css,
   hashed into the shell by scripts/build.mjs (ensure: section). Phone padding
   overrides for .adm-section-summary / .adm-section-body stay in the media
   query below so they win over that sheet (this <style> is appended later). */

/* ── Key-value grid ─────────────────────────────────────────────────────── */
.adm-kv-grid { display: flex; flex-direction: column; gap: 0; margin-bottom: 14px; }
.adm-kv-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: 7px 0; border-bottom: 1px solid var(--border-subtle); font-size: 13px;
}
.adm-kv-row:last-child { border-bottom: none; }
.adm-kv-key { color: var(--text-muted); font-family: var(--font-mono); font-size: 12px; min-width: 220px; flex-shrink: 0; }
.adm-kv-val { color: var(--text-1); font-size: 13px; }
/* A long unbroken value (Platform: the settings JSON, ~600px on one line) was
   clipped by .adm-section's overflow:hidden. min-width:0 lets the flex item
   shrink below its content; overflow-wrap:anywhere breaks it at any character
   (and counts that in min-content, so the row can actually narrow). Not
   pointer-gated: it clipped at every width. */
.adm-kv-val { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }

/* ── Inline form (below list) ───────────────────────────────────────────── */
/* .adm-inline-form (stacked column form) retired — every admin create/add
   form now uses the single-row .adm-inline-row idiom (item 16). */

/* ── Action row ─────────────────────────────────────────────────────────── */
.adm-action-row { display: flex; flex-wrap: wrap; gap: var(--s2); margin-top: 14px; }
/* Filter / search bar under a section header. The section body padding is the
   gap under the divider; this margin is the gap before the table. */
.adm-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s4); }
.adm-toolbar-filters, .adm-toolbar-side { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.adm-bulk:empty { display: none; margin: 0; }
.adm-count-pills { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.adm-add-user { display: flex; flex-direction: column; gap: var(--s3); }
.adm-add-user-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, max-content));
  gap: var(--s3) var(--s4);
  align-items: end;
  justify-content: start;
}
.adm-add-user-footer { display: flex; flex-wrap: wrap; justify-content: flex-end; align-items: center; gap: var(--s3); }
.adm-event-pop { margin: 0; padding-left: 1.1em; }
@media (max-width: 720px) {
  .adm-add-user-grid { grid-template-columns: 1fr; }
}

/* ── Form fields ────────────────────────────────────────────────────────── */
.adm-field { display: flex; flex-direction: column; gap: 5px; max-width: 460px; align-items: flex-start; }
/* In modals/popovers fields should fill the dialog, not keep the panel cap. */
.modal-body .adm-field, .cov-popover .adm-field { max-width: none; }
.adm-label { font-size: 12px; font-weight: 600; color: var(--text-2); letter-spacing: .2px; }
/* .adm-input / .adm-select appearance and width: styles/components.css */

/* ── Platform-settings modal (metadata-driven editor) ───────────────────── */
.adm-plat-form { display: flex; flex-direction: column; gap: var(--s4); }
.adm-plat-field { display: flex; flex-direction: column; gap: var(--s1); }
.adm-plat-frow { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.adm-plat-hint { font-size: 11px; line-height: 1.5; color: var(--text-muted); max-width: 52ch; }

/* ── Invitations: send-result line ──────────────────────────────────────── */
/* Collapses while empty so the blank line never reserves space below the
   "+ Send invite" button (root cause of the oversized section bottom gap). */
.adm-invite-result { font-size: 12px; color: var(--text-muted); margin-top: 6px; min-height: 16px; }
.adm-invite-result:empty { display: none; }

/* ── Single-row inline forms (org-create idiom — orgs, categories, invites;
      item 16). "Label: [control]" pairs on one flex row; each pair
      is the wrap unit on narrow viewports, so nothing overflows sideways.
      Add-user uses .adm-add-user (labels above the inputs). ── */
.adm-org-create-row, .adm-inline-row { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.adm-org-create-row { margin-top: 14px; }
.adm-inline-pair { display: inline-flex; align-items: center; gap: 6px; }
/* Field(s) + button on one row (idle / auto-stop / max-length): every control
   in a row shares ONE height (the .btn's 33px), whichever of the input
   variants (.adm-input / --sm) or select sits beside the button. Shared by all
   inline field+button rows so a new one needs no per-button sizing. */
.adm-field-row { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: flex-end; }
.adm-field-row, .adm-inline-row, .adm-org-create-row { --adm-ctl-h: 33px; }
.adm-field-row .adm-input, .adm-field-row .adm-select, .adm-field-row .btn,
.adm-inline-row .adm-input, .adm-inline-row .adm-select, .adm-inline-row .btn,
.adm-org-create-row .adm-input, .adm-org-create-row .adm-select, .adm-org-create-row .btn {
  height: var(--adm-ctl-h); min-height: var(--adm-ctl-h); box-sizing: border-box;
}

/* ── Checkbox row ───────────────────────────────────────────────────────── */
.adm-checkbox-row {
  display: flex; align-items: center; gap: var(--s2);
  font-size: 13px; color: var(--text-1); cursor: pointer; user-select: none;
}
.adm-checkbox-row input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); cursor: pointer; }

/* ── Modal footer ───────────────────────────────────────────────────────── */
.adm-modal-footer { display: flex; justify-content: flex-end; gap: var(--s2); }

/* ── Category grid ──────────────────────────────────────────────────────── */
.adm-cat-grid { display: flex; flex-direction: column; gap: 0; margin-bottom: var(--s1); max-width: 760px; }
.adm-cat-row {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0; border-bottom: 1px solid var(--border-subtle); font-size: 13px;
}
.adm-cat-row:last-child { border-bottom: none; }
.adm-cat-swatch { width: 14px; height: 14px; border-radius: 3px; flex-shrink: 0; border: 1px solid rgba(255,255,255,.1); }
.adm-cat-label { color: var(--text-1); font-weight: 600; min-width: 100px; }
.adm-cat-color { color: var(--text-muted); font-size: 12px; }
.adm-cat-bw { color: var(--text-muted); font-size: 12px; min-width: 70px; }

/* ── Toggle row ─────────────────────────────────────────────────────────── */
.adm-toggle-row { display: flex; align-items: center; gap: 14px; padding: var(--s3) 0; font-size: 13px; }
.adm-toggle {
  position: relative; width: 40px; height: 22px;
  background: none; border: none; padding: 0; cursor: pointer; flex-shrink: 0;
}
.adm-toggle:focus-visible .adm-toggle-track {
  box-shadow: 0 0 0 2px var(--bg-card), 0 0 0 4px var(--accent);
}
.adm-toggle-track {
  display: block; width: 100%; height: 100%; border-radius: 99px;
  transition: background 200ms ease; position: relative;
}
.adm-toggle--safe .adm-toggle-track { background: var(--ok-dim); border: 1px solid var(--ok); }
.adm-toggle--live .adm-toggle-track { background: var(--danger-dim); border: 1px solid var(--danger); }
.adm-toggle-thumb {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; border-radius: 50%;
  transition: left 200ms ease, background 200ms ease;
}
.adm-toggle--safe .adm-toggle-thumb { left: 3px; background: var(--ok); }
.adm-toggle--live .adm-toggle-thumb { left: calc(100% - 17px); background: var(--danger); }
.adm-toggle-label { font-size: 12px; font-weight: 500; font-family: var(--font-mono); letter-spacing: .3px; transition: color 200ms ease; }

/* ── Ops / DB maintenance ───────────────────────────────────────────────── */
.adm-divider { height: 1px; background: var(--border-subtle); margin: var(--s4) 0; }
/* uPlot legend under the Ops chart. The CDN default (light-theme table,
   centered, dark text) sat on a mismatched grey strip against the panel —
   restyle to the panel background with normal label styling. Series marker
   colors stay inline from uPlot. */
.adm-ops-chart .u-legend {
  background: transparent; text-align: left; margin-top: var(--s1);
  font-family: var(--font-ui); font-size: 11px; color: var(--text-2);
}
.adm-ops-chart .u-legend th { color: var(--text-2); font-weight: 500; background: transparent; }
.adm-ops-chart .u-legend td { background: transparent; }
.adm-ops-chart .u-legend .u-value { color: var(--text-1); font-family: var(--font-mono); }
.adm-ops-title {
  font-size: 12px; font-weight: 600; color: var(--text-2);
  letter-spacing: .8px; text-transform: uppercase; margin-bottom: var(--s3);
}
.adm-ops-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px; }
/* ── DO Status — shared-grid-tracks table (item 20) ─────────────────────── */
/* Header and data cells share ONE grid template, so labels always align with
   their columns; explicit gaps keep Subs / Last-frame from visually merging. */
.adm-do-grid {
  display: grid;
  grid-template-columns: 14px minmax(9rem, max-content) minmax(0, 1fr) 4rem 9rem minmax(6rem, max-content);
  gap: var(--s1) 14px; align-items: center;
  font-size: 12px; min-width: 560px;
}
.adm-do-grid .adm-do-head {
  font-family: var(--font-mono); font-size: 10px; font-weight: 600;
  letter-spacing: .07em; text-transform: uppercase; color: var(--text-muted);
  padding-bottom: var(--s1); border-bottom: 1px solid var(--border);
}
.adm-do-right { text-align: right; }
.adm-do-num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── Feature flags — columnar list (item 18) ────────────────────────────── */
/* One row per flag: NAME + description left in a shared text column, the
   segmented audience control right-aligned. Replaces per-flag cards whose
   centered/wrapping content made every line start at a different x. */
.adm-flag-list { display: flex; flex-direction: column; }
.adm-flag-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 10px var(--s1); border-bottom: 1px solid var(--border-subtle);
}
.adm-flag-row:last-child { border-bottom: none; }
.adm-flag-row:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.adm-flag-text { flex: 1 1 auto; min-width: 0; }
.adm-flag-name {
  font-size: 12px; font-weight: 600; color: var(--text-2);
  letter-spacing: .8px; text-transform: uppercase;
}
.adm-flag-desc { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
.adm-flag-control { flex: 0 0 auto; }
@media (max-width: 560px) {
  .adm-flag-row { flex-direction: column; align-items: flex-start; gap: var(--s2); }
}

.adm-op-card {
  background: var(--bg-raised); border: 1px solid var(--border-subtle);
  border-radius: var(--r-md); padding: var(--s3) 14px;
  display: flex; flex-direction: column; gap: var(--s1);
}
.adm-op-title { font-size: 13px; font-weight: 600; color: var(--text-1); }
.adm-op-desc  { font-size: 12px; color: var(--text-muted); line-height: 1.45; }

/* ── DB maintenance rows (templates here, not inline, so the ≤760px phone
      block below can reflow them) ──────────────────────────────────────── */
.adm-maint-rule-row { grid-template-columns: 1fr 80px 120px auto; }
.adm-maint-hist-row { grid-template-columns: 140px 70px 70px auto 24px; }

/* ── Version footer ─────────────────────────────────────────────────────── */
.adm-version-footer { text-align: center; padding: var(--s4) 0 var(--s1); }
.adm-version-link { font-size: 12px; color: var(--text-muted); font-family: var(--font-mono); text-decoration: none; }
.adm-version-link:hover, .adm-version-link:focus-visible { color: var(--accent-text); text-decoration: underline; }

/* ── R5 Regulatory registry ─────────────────────────────────────────────── */
.regreg-intro { font-size: 12px; color: var(--text-muted); margin: 0 0 var(--s3); line-height: 1.5; }
.regreg-board, .regreg-driftlist { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: 14px; }
.regreg-row {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: var(--bg-raised); border: 1px solid var(--border-subtle);
  border-radius: var(--r-md); padding: 10px var(--s3);
}
.regreg-lamp { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.regreg-lamp--live  { background: var(--ok);     box-shadow: 0 0 6px var(--ok); }
.regreg-lamp--stale { background: var(--warn);   box-shadow: 0 0 6px var(--warn); }
.regreg-lamp--dead  { background: var(--danger); box-shadow: 0 0 6px var(--danger); }
.regreg-cc {
  font-size: 10px; font-weight: 700; letter-spacing: .5px; color: var(--text-2);
  border: 1px solid var(--border); border-radius: 4px; padding: 2px 6px; flex: none;
}
.regreg-main { flex: 1; min-width: 140px; }
.regreg-label { font-size: 13px; font-weight: 600; color: var(--text-1); }
.regreg-kind { font-size: 11px; color: var(--text-muted); }
.regreg-pill {
  font-size: 10px; font-weight: 600; border-radius: var(--r-pill); padding: 2px var(--s2);
  letter-spacing: .4px; text-transform: uppercase;
}
.regreg-pill--on  { color: var(--ok); border: 1px solid var(--ok); }
.regreg-pill--off { color: var(--text-muted); border: 1px solid var(--border); }
.regreg-actions { display: flex; gap: 6px; }
.regreg-drift { border: 1px solid var(--border-subtle); border-radius: var(--r-md); padding: 10px var(--s3); }
.regreg-drift-head { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.regreg-chip {
  font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  border-radius: 4px; padding: 2px 6px;
}
.regreg-chip--danger { color: var(--danger); border: 1px solid var(--danger); }
.regreg-chip--accent { color: var(--accent-text); border: 1px solid var(--accent); }
.regreg-chip--warn   { color: var(--warn);   border: 1px solid var(--warn); }
.regreg-chip--ok     { color: var(--ok);     border: 1px solid var(--ok); }
.regreg-ep { font-size: 11px; color: var(--text-2); }
.regreg-when { font-size: 11px; color: var(--text-muted); }
.regreg-ack { margin-left: auto; }
.regreg-acked { margin-left: auto; font-size: 11px; color: var(--text-muted); font-style: italic; }
.regreg-detail { font-size: 11px; color: var(--text-2); margin-top: 6px; }
.regreg-impact { font-size: 12px; color: var(--text-2); font-weight: 500; margin-top: var(--s1); }
.regreg-error { font-size: 12px; color: var(--danger); margin: 6px 0 14px; }
.regreg-empty { font-size: 12px; color: var(--text-muted); margin: 6px 0 14px; }
.regreg-skel-bar {
  height: 34px; border-radius: var(--r-md); background: var(--bg-raised);
  opacity: .5; margin-bottom: var(--s2); animation: regreg-pulse 1.2s ease-in-out infinite;
}
@keyframes regreg-pulse { 50% { opacity: .25; } }
@media (max-width: 640px) {
  .regreg-row { align-items: flex-start; }
  .regreg-actions { width: 100%; justify-content: flex-end; }
}

/* ── Events table ─────────────────────────────────────────────────────────
   Fixed columns only at ≥1200px, where .adm-view is at its 1160px cap and
   the table is ~1082px. Name takes the remainder (at least 240px) and
   ellipsizes; the title attribute keeps the full string.
   Below that, auto layout. Name stays readable and the DataTable wrapper
   scrolls. The page itself does not. ≤760px stays the card reflow. */
.adm-ev-scroll { min-width: 0; max-width: 100%; }
#adm-events { min-width: 0; max-width: 100%; }
.adm-ev-num { font-variant-numeric: tabular-nums; }
.adm-ev-name { min-width: 0; }
.adm-ev-name-input {
  display: block; width: 100%; min-width: 0; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.adm-ev-by { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.adm-ev-sched {
  display: flex; flex-wrap: wrap; align-items: center; column-gap: 0.35em;
  max-width: 100%; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; font-size: 12px; line-height: 1.35; text-align: left;
  cursor: pointer; color: inherit;
  text-decoration: underline; text-decoration-style: dotted;
}
.adm-ev-sched-when, .adm-ev-sched-time { white-space: nowrap; }
.adm-ev-sched-glyph { display: inline-flex; align-items: center; margin-right: 0.28em; }
.adm-ev-actions { display: flex; flex-wrap: nowrap; gap: var(--s1); justify-content: flex-end; }
.adm-ev-actions .btn { padding: 3px 7px; font-size: 11px; white-space: nowrap; }
@media (min-width: 761px) and (max-width: 1199px) {
  #adm-events .dt { table-layout: auto; width: max-content; min-width: 100%; }
  #adm-events .adm-ev-name { min-width: 12rem; }
  #adm-events .adm-ev-name-input {
    width: auto; min-width: 10rem; max-width: 24rem; field-sizing: content;
  }
}
@media (min-width: 1200px) {
  #adm-events .dt { table-layout: fixed; width: 100%; }
  /* Fixed columns sum to 824px, so Name keeps ~258px of the 1082px table. */
  #adm-events .adm-ev-id { width: 44px; }
  #adm-events .adm-ev-status { width: 104px; }
  #adm-events .adm-ev-sched-col { width: 164px; }
  #adm-events .adm-ev-count { width: 68px; }
  #adm-events .adm-ev-by { width: 92px; }
  #adm-events .adm-ev-test { width: 48px; }
  #adm-events .adm-ev-arch { width: 84px; }
  #adm-events .adm-ev-act { width: 152px; }
  #adm-events .adm-ev-name { overflow: hidden; }
  #adm-events .adm-ev-id,
  #adm-events .adm-ev-count,
  #adm-events .adm-ev-test,
  #adm-events .adm-ev-arch,
  #adm-events .adm-ev-act { padding-left: 6px; padding-right: 6px; }
  #adm-events .dt th { overflow: hidden; text-overflow: ellipsis; }
}

/* ── Responsive ─────────────────────────────────────────────────────────── */
/* ── D4 (UI audit N42/N44): was inline in admin.js ─────────────────────────
   Same values as the inline styles they replace. Kept above the phone and
   coarse-pointer blocks so those still win where they did before; the kit
   button paddings are at the end of the file for the same reason. */
.adm-load-error { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; color: var(--danger); font-size: 12px; }
.adm-secret { display: inline-flex; align-items: center; gap: var(--s1); min-width: 0; }
.adm-help { font-size: 11px; color: var(--text-muted); margin: var(--s1) 0 0; }
.adm-row-actions { display: flex; gap: 6px; justify-content: flex-end; }
.adm-row-actions--center { align-items: center; }
.adm-chip-row { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.adm-cell-muted { font-size: 12px; color: var(--text-muted); }
.adm-cell-sub { font-size: 11px; color: var(--text-muted); }
.adm-push-end { margin-left: auto; }
.adm-flex-fill { flex: 1; }
.adm-stack { display: flex; flex-direction: column; gap: var(--s3); }
/* Status / empty / error line inside a section. */
.adm-msg { font-size: 12px; }
.adm-msg--pad { padding: 6px; }
.adm-footnote { font-size: 11px; color: var(--text-muted); margin: 6px 0 0; }

/* Global recording / enforcement / dry-run switches. --plain: green track when
   ON, neutral when OFF (the class default is red/green). */
.adm-toggle-title { font-weight: 600; color: var(--text-2); }
.adm-toggle--plain.adm-toggle--live .adm-toggle-track { background: var(--ok-dim); }
.adm-toggle--plain.adm-toggle--safe .adm-toggle-track { background: var(--bg-raised); }
.adm-toggle-label.adm-toggle-label--on { color: var(--ok); font-weight: 700; }
.adm-toggle-label.adm-toggle-label--off { color: var(--text-muted); font-weight: 400; }
.adm-toggle-label.adm-toggle-label--safe { color: var(--ok); font-weight: 400; }
.adm-toggle-label.adm-toggle-label--danger { color: var(--danger); font-weight: 700; }

/* Invitations, orgs and their modals */
.adm-invite-note { font-size: 12px; color: var(--text-muted); margin: 0 0 var(--s2); }
.adm-invite-code { font-size: 11px; }
.adm-members-note { font-size: 13px; color: var(--text-2); margin: 0; }
.adm-kv-row.adm-kv-empty { color: var(--text-muted); font-style: italic; }
.adm-modal-form { display: flex; flex-direction: column; gap: 14px; }
.adm-modal-intro { font-size: 12px; color: var(--text-muted); margin: 0; }
/* Under the org name, not beside it (the Name column stays narrow). */
.badge.adm-org-not-member { display: table; margin-top: 3px; }

/* Event schedule popover */
.adm-sched-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: currentColor; flex-shrink: 0; vertical-align: middle;
}
.adm-sched-pop { display: flex; flex-direction: column; gap: 10px; min-width: 240px; }
.adm-sched-field { display: flex; flex-direction: column; gap: var(--s1); }
.adm-sched-dt { display: flex; gap: 6px; flex-wrap: wrap; }
.adm-sched-btns { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 2px; }
.adm-sched-msg { font-size: 11px; color: var(--danger); min-height: 14px; }

/* Categories: the swatch colour comes from the row (--adm-cat-color, set in admin.js,
   which always sets one); the fallback only paints if the property is missing. */
.adm-cat-swatch { background: var(--adm-cat-color, var(--text-muted)); }

/* Devices */
.adm-dev-name { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.adm-dev-health { display: inline-flex; align-items: center; gap: var(--s2); }
.adm-apply-err {
  display: inline-flex; align-items: center; padding: 1px 7px;
  font-size: 10px; font-weight: 600; border-radius: 9px;
  background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger);
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
}
.adm-sub-body.adm-add-device-body { display: flex; flex-direction: column; gap: 10px; padding: var(--s3) 0 var(--s1); }
.adm-inline-note {
  border-left: 3px solid var(--warn); padding: 6px 0 6px 10px;
  font-size: 12px; line-height: 1.5; color: var(--text-2);
}

/* Feature flags, traces */
.adm-flags-intro { font-size: 13px; color: var(--text-muted); margin-bottom: var(--s3); }
.adm-bulk-note { font-size: 12px; color: var(--text-2); }
.adm-trace-name { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.adm-trace-status { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; }

/* Ops dashboard */
.adm-win-label { font-size: 12px; color: var(--text-2); font-weight: 600; align-self: center; }
.adm-ops-chart { margin-top: 10px; min-height: 60px; }
.adm-ops-subhead { margin: 20px 0 6px; font-size: 12px; font-weight: 600; color: var(--text-2); }
.adm-ops-subhead--tight { margin-top: var(--s4); }
.adm-poll-note { font-size: 11px; color: var(--text-muted); margin-top: 10px; }
.adm-poll-note--tight { margin-top: var(--s2); }
.adm-priv-hint { font-size: 11px; color: var(--text-muted); align-self: center; }
.adm-ops-title.adm-ops-title--flush { margin: 0; }
.adm-ops-title.adm-ops-title--tight { margin-bottom: var(--s1); }
.adm-ops-title.adm-ops-title--mid { margin-bottom: var(--s2); }

/* DO status */
.adm-sub-intro { font-size: 12px; color: var(--text-muted); margin: 0 0 6px; }
.adm-sub-intro--loose { margin-bottom: 10px; }
.adm-do-meta { font-size: 11px; color: var(--text-muted); margin-bottom: 6px; }
.adm-do-scroll { overflow-x: auto; }
.adm-do-live { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); }
.adm-do-live--on { background: var(--live); }
.adm-do-live--err { background: var(--danger); }
.adm-do-flag-err { color: var(--danger); font-size: 11px; }
.adm-do-flag-release { color: var(--warn); font-size: 10px; }
.adm-do-flag-retain { color: var(--accent-text); font-size: 10px; }
.adm-do-ago { color: var(--text-muted); font-size: 11px; }

/* Database maintenance */
.state.adm-maint-loading { color: var(--text-muted); padding: var(--s3); font-size: 13px; }
.adm-op-card.adm-maint-storage {
  display: flex; flex-direction: row; justify-content: space-between; align-items: center;
  margin-bottom: 10px;
}
.adm-maint-stor-line { font-size: 13px; }
.adm-maint-stor-size { color: var(--text-1); font-size: 18px; font-weight: 700; font-family: var(--font-mono); }
.adm-maint-stor-rows { color: var(--text-1); font-family: var(--font-mono); }
/* Label column sized to the longest table name, count right next to it
   (item 19), capped at ~34rem. */
.adm-maint-tbl-grid {
  display: grid; grid-template-columns: max-content auto; gap: var(--s1) var(--s4);
  padding: 10px 14px; font-size: 12px; max-width: 34rem;
}
.adm-maint-ret-tag { color: var(--text-muted); font-size: 10px; }
.adm-maint-tbl-count { text-align: right; color: var(--text-2); font-variant-numeric: tabular-nums; }
.adm-maint-rules-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: var(--s2); }
.adm-maint-stale { font-size: 11px; }
.adm-maint-rule-row { display: grid; gap: 6px; align-items: center; padding: var(--s1) 6px; border-radius: var(--r-sm); }
.adm-maint-rule-row--hit { background: color-mix(in srgb, var(--warn) 8%, transparent); }
.adm-maint-ret { color: var(--text-muted); font-size: 11px; text-align: right; }
.adm-maint-matched { text-align: right; }
.adm-maint-rule-btns { display: flex; gap: 6px; margin-top: var(--s2); }
.adm-maint-hist { padding: 10px 14px; font-size: 11px; }
.adm-maint-hist-row {
  display: grid; gap: var(--s1) var(--s3); padding: 3px 0;
  border-bottom: 1px solid var(--border-subtle); color: var(--text-2);
}
.adm-maint-hist-ts { font-size: 10px; }
.adm-maint-hist-num { text-align: right; }

/* Webtool integrations */
.adm-int-intro { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-muted); margin: 0 0 10px; }
.adm-op-card.adm-int-card { display: flex; flex-direction: column; gap: var(--s2); margin-bottom: var(--s2); }
.adm-int-head { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.adm-int-key {
  color: var(--accent-text); background: var(--accent-soft);
  padding: 2px 6px; border-radius: var(--r-sm); font-size: 11px;
}
.adm-int-enabled { display: flex; align-items: center; gap: var(--s1); font-size: 11px; color: var(--text-2); }
.adm-int-enabled-cb { width: 14px; height: 14px; accent-color: var(--accent); }
.adm-int-field { display: flex; align-items: center; gap: 6px; }
.adm-int-field--wrap { flex-wrap: wrap; }
.adm-int-field-label { font-size: 11px; color: var(--text-muted); width: 90px; flex-shrink: 0; }
/* Status line of the stored secret; --fresh holds a just-generated secret. */
.adm-int-secret {
  flex: 1 1 160px; min-width: 0; padding: 5px var(--s2);
  background: var(--bg-input); border: 1px solid var(--border-subtle); border-radius: var(--r-sm);
  color: var(--text-muted); font-size: 12px; overflow-x: auto; white-space: normal;
}
.adm-int-secret.adm-int-secret--fresh { white-space: nowrap; color: var(--ok); }
.adm-int-at-rest { font-size: 11px; }
.adm-int-hook { font-size: 11px; color: var(--text-muted); }
.adm-int-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--s3); align-items: end;
}
.adm-int-label-row { display: inline-flex; align-items: center; gap: var(--s1); }
.adm-int-created {
  margin-top: 10px; padding: 10px var(--s3);
  background: var(--bg-input); border: 1px solid var(--border-subtle); border-radius: var(--r-sm);
}
.adm-int-created-secret { font-size: 12px; word-break: break-all; color: var(--ok); }

/* Storage drill-down (shown with style.display = 'block') */
.adm-drill { margin-top: 14px; display: none; }
.adm-drill-title { font-size: 12px; font-weight: 600; color: var(--text-2); margin: 0 0 var(--s2); }
.state.adm-drill-loading { color: var(--text-muted); font-size: 12px; }

/* Text tones (setTone in admin.js). Last colour rules in the sheet, so a tone
   wins over the base colour of the element it is set on. */
.adm-tone-muted { color: var(--text-muted); }
.adm-tone-ok { color: var(--ok); }
.adm-tone-warn { color: var(--warn); }
.adm-tone-danger { color: var(--danger); }
.adm-tone-accent { color: var(--accent-text); }
.adm-tone-1 { color: var(--text-1); }
.adm-tone-2 { color: var(--text-2); }

/* ── Phone pass (≤760px — the codebase layout breakpoint; iPad 761–1099 and
      desktop ≥1100 are untouched). Pattern-level reflow only. ───────────── */
@media (max-width: 760px) {
  /* DataTable card reflow (.rtable, components.css) leaves the <table> itself
     display:table, so its min-content width (≈306px from the anonymous
     row/cell boxes around the block <tr>s) beats width:100% and every card
     clips at the section edge (invitations: pills/dates/emails cut at 320).
     Block-ify the table so cards track the container; td min-width:0 +
     overflow-wrap:anywhere (already in the utility) do the rest. Scoped to
     admin — the utility's home file belongs to another pass. */
  .adm-view .rtable, .adm-view .rtable tbody { display: block; width: 100%; }
  /* Card action cells hold a whole button row in ONE non-wrapping flex div
     (orgs/events: Members/Bands/…/Delete squeezed to 1-char-per-line text).
     Let the inner row wrap and keep each button label on one line. */
  .adm-view .rtable td:not([data-label]) > div { flex-wrap: wrap; min-width: 0; }
  .adm-view .rtable td .btn { white-space: nowrap; }
  /* Long badge chips (invite org-scope "→ Org as role") are nowrap pills that
     can't shrink below their text — let them wrap inside cards. */
  .adm-view .rtable td .badge { white-space: normal; }
  /* Inline "Label: [control]" pairs: fixed-width inputs (email = 16rem) ran
     past the card edge; cap the pair to its row so the input gives way
     (its 9ch min-width floor keeps it usable). */
  .adm-inline-pair { max-width: 100%; min-width: 0; }
  /* Categories rows: fixed-min-width columns + Edit/Delete pushed actions
     off-canvas — wrap instead (actions drop to their own line). */
  .adm-cat-row { flex-wrap: wrap; }
  /* Traces segmented filter (≈334px) clipped at 320 — horizontal pan with a
     hidden scrollbar (views-monitor.css ≤760 phone tab-strip pattern). */
  /* The pan only engages once the strip is narrower than its tabs: its
     toolbar group is a flex item whose automatic min-width is the strip's
     full width, so at 375px it stayed ≈334px and was clipped by the
     section. min-width:0 on the group lets the strip shrink and pan;
     Segmented's reveal keeps the active tab in view. */
  #adm-traces .adm-toolbar-filters { min-width: 0; max-width: 100%; }
  #adm-traces .segmented {
    max-width: 100%; min-width: 0; overflow-x: auto;
    -webkit-overflow-scrolling: touch; scrollbar-width: none;
  }
  #adm-traces .segmented::-webkit-scrollbar { display: none; }
  #adm-traces .seg-btn { white-space: nowrap; flex: none; }
  /* DB maintenance: collapse the fixed-column rule/history rows so counts and
     status stop clipping mid-number; label column takes the slack. */
  .adm-maint-rule-row { grid-template-columns: minmax(0, 1fr) auto; }
  .adm-maint-hist-row { grid-template-columns: minmax(0, 1fr) auto auto; }
  .adm-maint-tbl-grid { grid-template-columns: minmax(0, 1fr) auto; }
  /* Op cards (storage line, cleanup header with its dry-run note, webhook
     cards): let flex rows wrap and long mono/code runs (webhook URLs, hashes)
     break instead of overflowing the card. */
  .adm-op-card, .adm-op-card > div { flex-wrap: wrap; }
  .adm-op-card code, .adm-op-card .mono { overflow-wrap: anywhere; }
  /* DO Status pan container (inline overflow-x:auto wrapper): iOS momentum. */
  .adm-view div:has(> .adm-do-grid) { -webkit-overflow-scrolling: touch; }
}
@media (max-width: 640px) {
  .adm-view { padding: var(--s4) var(--s3) 56px; }
  .adm-stats { grid-template-columns: repeat(3, 1fr); }
  /* Ops / Cloud-load tiles sit INSIDE a sub-section (narrower than the
     top-level strip by two card paddings): 3 columns only ~2.7-fit at 430
     (third tile clipped mid-value) — give nested grids 2 columns. The
     top-level stats strip keeps 3. */
  .adm-sub-body .adm-stats { grid-template-columns: repeat(2, 1fr); }
  .adm-kv-key { min-width: 140px; }
  .adm-section-summary { padding: var(--s3) 14px; }
  /* Phone: the action bar does not fit beside the title and its chips, so it takes its own
     row under them. The summary reserves that row (padding) and the bar sits in it (top =
     measured summary height - bar height - bottom padding); the chevron stays in the title
     row, so it can no longer be pushed past the section edge. */
  .adm-section-frame > .adm-section > .adm-section-summary { min-height: 0; padding-bottom: calc(var(--adm-actions-h, 0px) + var(--s3) + var(--s2)); }
  .adm-section-frame > .adm-section > .adm-section-summary .adm-chevron { margin-left: 0; align-self: flex-start; }
  .adm-section-actionbar {
    top: calc(var(--adm-section-bw) + var(--adm-summary-h, 0px) - var(--adm-actions-h, 0px) - var(--s3));
    left: calc(var(--adm-section-bw) + 14px); right: calc(var(--adm-section-bw) + 14px);
    flex-wrap: wrap; justify-content: flex-end;
  }
  .adm-section-body { padding: var(--s4) 14px 14px; }
  .adm-ops-grid { grid-template-columns: 1fr; }
}
@media (max-width: 420px) {
  .adm-stats { grid-template-columns: repeat(2, 1fr); }
}
/* ── Touch targets (Wave 4 round 2) ─────────────────────────────────────────
   MEASURED 2026-10-11 at 375x812, pointer:coarse: .btn / .adm-select 33px,
   .adm-input 30-36px, .adm-toggle 40x22, .seg-btn 38px. Raise to --tap-min.
   Pointer-only (fine-pointer/desktop is untouched) and scoped to .adm-view so no
   other view changes. min-height beats the 33px height pinned by the inline-row
   rules above; their shared --adm-ctl-h is raised too so every control in one
   field+button row stays the same height. */
@media (pointer: coarse) {
  .adm-field-row, .adm-inline-row, .adm-org-create-row { --adm-ctl-h: var(--tap-min); }
  .adm-view .btn, .adm-view .adm-input, .adm-view .adm-select, .adm-view .seg-btn {
    min-height: var(--tap-min);
  }
  .adm-view .btn { padding-top: 0; padding-bottom: 0; align-items: center; }
  /* Switch: the 40x22 track is the visual; an invisible 44px-tall overlay (and
     2px each side for 44 wide) is the hit area, so the layout does not move. */
  .adm-toggle::before {
    content: ''; position: absolute; top: 50%; left: -2px; right: -2px;
    height: var(--tap-min); transform: translateY(-50%);
  }
}
@media (max-width: 380px) {
  /* Nested (sub-section) tiles: at 320 even two columns can't hold the wide
     mono values ("9 / 6" @28px ⇒ 118px min track) — stack them. */
  .adm-sub-body .adm-stats { grid-template-columns: 1fr; }
}
    

/* ── D4: kit-button paddings that were inline in admin.js ──────────────────
   Last in the sheet so they win over the coarse-pointer
   `.adm-view .btn { padding-top: 0 }` above, as the inline style did. Height
   stays the kit's. */
.btn.adm-btn-tight { padding: 3px var(--s2); font-size: 11px; }
.btn.adm-btn-pad { padding: var(--s1) var(--s3); font-size: 12px; }
