
/* ── 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; }
  .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; }
