/* Admin panel (ML-26) - separate small stylesheet since this is its own
   growing area (Release tests today; Usage, Accounts later), not part of
   the practice-tracker SPA's layout. Reuses style.css's design tokens
   (colors, spacing, radius, dark mode) rather than redefining them. */

body.admin-body { display: block; background: var(--bg-color); }

.admin-logged-out { max-width: var(--app-max-width); margin: var(--space-10) auto; text-align: center; padding: 0 var(--space-5); }

.admin-shell { display: flex; min-height: 100vh; }

/* ML-277: the menu stays where it is while the page beside it scrolls; if it is taller than the window it scrolls by itself */
.admin-sidebar { width: 220px; flex-shrink: 0; background: var(--container-bg); border-right: 1px solid var(--input-border); padding: var(--space-5) 0; box-sizing: border-box; position: sticky; top: 0; align-self: flex-start; height: 100vh; overflow-y: auto; }
.admin-sidebar-title { font-weight: var(--font-weight-bold); font-size: var(--font-lg); padding: 0 var(--space-5) var(--space-5) var(--space-5); color: var(--text-color); }
.admin-nav-item { display: block; width: 100%; box-sizing: border-box; text-align: left; background: none; border: none; border-left: 3px solid transparent; padding: var(--space-3) var(--space-5); font-size: var(--font-base); font-weight: var(--font-weight-semibold); font-family: var(--font-sans); color: var(--text-color); cursor: pointer; }
.admin-nav-item:disabled { color: var(--label-color); cursor: default; }
.admin-nav-item.active { background: var(--secondary-color); border-left-color: var(--primary-action); }
/* ML-110: the sidebar's own <a> (not <button>) needs its default link colour/underline reset to
   match the plain nav buttons above/below it, plus a separator so it doesn't read as just another
   section tab. */
.admin-back-link { text-decoration: none; color: var(--label-color); border-bottom: 1px solid var(--input-border); margin-bottom: var(--space-2); padding-bottom: var(--space-4); }
.admin-back-link:hover { color: var(--text-color); }

/* ML-443: the menu in groups. A heading (a button) opens and closes its group; a shut group's heading carries
   the count of what is waiting inside. On a wide screen the double arrow folds the whole menu down to a
   strip, so a wide table gets the window - a phone has the ☰ toggle instead. */
.admin-sidebar-head { display: flex; align-items: flex-start; justify-content: space-between; }
.admin-nav-fold { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: var(--touch-target); height: var(--touch-target); margin: calc(-1 * var(--space-3)) var(--space-2) 0 0; background: none; border: none; border-radius: var(--radius-sm); color: var(--label-color); cursor: pointer; }
.admin-nav-fold:hover { color: var(--text-color); }
.admin-nav-group { border-top: 1px solid var(--input-border); }
.admin-nav-group:first-of-type { border-top: none; }
.admin-nav-group-head { display: flex; align-items: center; gap: var(--space-2); width: 100%; min-height: var(--touch-target); box-sizing: border-box; padding: var(--space-2) var(--space-4) var(--space-2) var(--space-5); background: none; border: none; font-family: var(--font-sans); font-size: var(--font-sm); font-weight: var(--font-weight-bold); color: var(--label-color); text-align: left; cursor: pointer; }
.admin-nav-group-head:hover { color: var(--text-color); }
.admin-nav-group-name { flex: 1; min-width: 0; }
.admin-nav-group-items { padding-bottom: var(--space-2); }
@media (min-width: 701px) {
  .admin-shell.is-nav-folded .admin-sidebar { width: auto; padding: var(--space-2) var(--space-1); }
  .admin-shell.is-nav-folded .admin-sidebar-title, .admin-shell.is-nav-folded .admin-nav-items { display: none; }
  .admin-shell.is-nav-folded .admin-nav-fold { margin: 0; }
}

.admin-content { flex: 1; min-width: 0; padding: var(--space-6) var(--space-7); box-sizing: border-box; max-width: 900px; overflow-wrap: break-word; } /* min-width: 0 lets wide tables scroll inside .admin-stat-table-wrap instead of widening the page (ML-204) */
.admin-content h1 { margin-top: 0; color: var(--text-color); }
.admin-intro { color: var(--label-color); font-size: var(--font-sm); margin: calc(-1 * var(--space-2)) 0 var(--space-3); }
.admin-intro code { background: var(--input-bg); padding: var(--space-0-5) var(--space-1); border-radius: var(--radius-xs); }

.admin-link { display: inline-block; color: var(--primary-action-strong); font-weight: var(--font-weight-bold); font-size: var(--font-base); text-decoration: none; margin-bottom: var(--space-5); }
.admin-link:hover { text-decoration: underline; }

.admin-summary-grid { grid-template-columns: repeat(4, 1fr); margin-bottom: var(--space-7); }

.admin-add-btn { max-width: 220px; margin-bottom: var(--space-5); }

/* ML-109: the Metadata lists section's own inner tab row (Durations/Time signatures/Note values/
   Playback speeds) - a horizontal counterpart to .admin-nav-item's vertical sidebar tabs, since these
   four live inside one section rather than as separate top-level sidebar entries. */
.admin-subtabs { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-bottom: var(--space-5); border-bottom: 1px solid var(--input-border); }
.admin-subtab-item { background: none; border: none; border-bottom: 3px solid transparent; padding: var(--space-3) var(--space-4); margin-bottom: -1px; /* token-audit-ignore: overlaps the row border so the active underline sits on it */ font-size: var(--font-base); font-weight: var(--font-weight-semibold); font-family: var(--font-sans); color: var(--label-color); cursor: pointer; }
.admin-subtab-item.active { color: var(--text-color); border-bottom-color: var(--primary-action); }

.admin-feature { border: 1px solid var(--input-border); border-radius: var(--radius-md); margin-bottom: var(--space-5); overflow: hidden; }
.admin-feature[data-feedback-row] { cursor: pointer; } /* a Feedback card opens its review pop-up */
/* ML-294: Warm-ups - the list and the tap-to-build editor (see specs/components/admin-shell.md). */
.admin-warmup-kind { margin: var(--space-5) 0 var(--space-2) 0; font-size: var(--font-md); }
.admin-warmup-row-preview svg { display: block; width: 100%; max-width: 480px; height: auto; margin-top: var(--space-2); }
.admin-warmup-off { opacity: var(--opacity-muted); }
.modal-content.admin-modal-wide { max-width: 720px; }
.admin-warmup-fields { display: grid; grid-template-columns: 2fr 1.4fr 1fr 1fr; gap: var(--space-3); }
.admin-warmup-preview-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); margin-top: var(--space-3); }
.admin-warmup-preview-head .radio-group { margin: 0; width: 240px; flex-shrink: 0; }
.admin-warmup-preview { background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-2); min-height: calc(var(--touch-target) * 2); margin-top: var(--space-2); }
.admin-warmup-preview svg { display: block; width: 100%; height: auto; }
.admin-warmup-preview .warmup-note { cursor: pointer; }
.admin-warmup-preview .is-selected { fill: var(--primary-action-strong); }
.admin-warmup-status { font-size: var(--font-sm); color: var(--label-color); min-height: 1.4em; margin: var(--space-2) 0; }
.admin-warmup-status.has-errors { color: var(--danger-text); }
.admin-warmup-inline { margin-top: var(--space-2); }
.admin-warmup-tools { display: flex; flex-wrap: wrap; gap: var(--space-2); }
.admin-warmup-tools .btn-edit, .admin-warmup-tools .btn-delete { width: auto; min-width: var(--touch-target); }
@media (max-width: 700px) { .admin-warmup-fields { grid-template-columns: 1fr 1fr; } }
/* flex-wrap (plus the text side's own min-width:0 below) lets a wide sibling - the level <select>,
   or actions - drop to its own line under the text on a narrow viewport instead of overlapping it:
   the admin sidebar (.admin-sidebar, 220px fixed) leaves very little width for content on a phone-
   width screen, and a plain no-wrap flex row has nowhere else to put a sibling that doesn't fit. */
.admin-feature-header { background: var(--input-bg); padding: var(--space-4); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: var(--space-3); }
.admin-feature-header-text { flex: 1 1 calc(var(--touch-target) * 5); min-width: 0; } /* ML-390: a basis, so on a phone the buttons wrap under the text instead of squeezing it to one letter wide */
.admin-feature-header h2 { margin: 0 0 var(--space-1) 0; font-size: var(--font-md); color: var(--text-color); }
.admin-feature-header p { margin: 0; color: var(--label-color); font-size: var(--font-sm); }
/* Bare <a> tags (band website links) otherwise fall back to the browser's default link blue/purple,
   which is very low-contrast against a dark background - every other in-app link already sets an
   explicit colour (e.g. .admin-test-case-meta a below), this one just hadn't yet. */
.admin-feature-header p a { color: var(--info-text); }
.admin-feature-actions { display: flex; gap: var(--space-2); flex-shrink: 0; }
.admin-feature-actions .btn-icon-edit,
.admin-feature-actions .btn-icon-delete { width: 30px; height: 30px; }
.admin-feature-actions .material-symbols-outlined { font-size: var(--icon-sm); }

.admin-level-select { flex-shrink: 0; max-width: 100%; box-sizing: border-box; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); border: 1px solid var(--control-border); background: var(--input-bg); color: var(--text-color); font-size: var(--font-sm); }

.admin-test-case { padding: var(--space-4); border-top: 1px solid var(--input-border); }
.admin-test-case-head { display: flex; justify-content: space-between; align-items: center; cursor: pointer; gap: var(--space-3); }
.admin-test-case-title { font-weight: var(--font-weight-semibold); color: var(--text-color); }
.admin-test-case-meta { font-size: var(--font-sm); color: var(--label-color); margin-top: var(--space-0-5); }
.admin-test-case-meta a { color: var(--info-text); }

.admin-badge { display: inline-block; padding: var(--space-0-5) var(--space-3); border-radius: var(--radius-pill); font-size: var(--font-xs); font-weight: var(--font-weight-bold); text-transform: uppercase; white-space: nowrap; }
.admin-badge.pass { background: var(--success-color); color: var(--text-on-accent); }
.admin-badge.fail { background: var(--danger-color); color: var(--text-on-accent); }
.admin-badge.skipped { background: var(--nav-action); color: var(--nav-action-text); }
.admin-badge.never { background: var(--input-border); color: var(--label-color); }

.admin-run-history { margin-top: var(--space-3); display: none; }
.admin-run-history.show { display: block; }
.admin-run-row { display: flex; gap: var(--space-3); padding: var(--space-2) 0; border-top: 1px solid var(--input-border); font-size: var(--font-sm); align-items: flex-start; }
.admin-run-row:first-child { border-top: none; }
.admin-run-when { color: var(--label-color); white-space: nowrap; width: 150px; flex-shrink: 0; }
.admin-run-detail { flex: 1; min-width: 0; }
.admin-run-duration { color: var(--label-color); font-size: var(--font-xs); margin-left: var(--space-2); }
.admin-run-error { color: var(--danger-text); margin: var(--space-1) 0 0 0; font-family: var(--font-mono); font-size: var(--font-xs); white-space: pre-wrap; word-break: break-word; }
.admin-run-notes { margin: var(--space-1) 0 0 0; font-size: var(--font-xs); color: var(--text-color); }

.admin-feature-chips { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-top: var(--space-2); }
.admin-chip { background: var(--secondary-color); color: var(--text-color); border-radius: var(--radius-pill); padding: var(--space-0-5) var(--space-3); font-size: var(--font-xs); font-weight: var(--font-weight-semibold); }
.admin-chip-empty { background: var(--input-border); color: var(--label-color); font-weight: var(--font-weight-normal); }

/* ML-240: phone-width menu. The head row (title + current section + ☰ toggle) only shows as a row
   on a phone; on wider screens the toggle and current-section label are hidden and the list is the
   plain sidebar as before. */
.admin-sidebar-current { display: none; margin-left: var(--space-2); color: var(--label-color); font-weight: var(--font-weight-semibold); font-size: var(--font-base); }
.admin-nav-toggle { display: none; align-items: center; justify-content: center; flex-shrink: 0; width: var(--touch-target); height: var(--touch-target); background: none; border: none; border-radius: var(--radius-sm); color: var(--text-color); cursor: pointer; }

@media (max-width: 700px) {
  .admin-shell { flex-direction: column; }
  /* The section list used to become one long horizontal row here, which pushed the whole page to
     ~1200px wide - everything else (cards, stat tiles, pop-ups centred on the page) then sat
     partly off-screen. Now it folds away behind the ☰ toggle and opens as a vertical list. */
  .admin-sidebar { width: 100%; padding: var(--space-2) var(--space-4); border-right: none; border-bottom: 1px solid var(--input-border); position: static; align-self: auto; height: auto; overflow-y: visible; }
  .admin-sidebar-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
  .admin-sidebar-title { padding: 0; min-width: 0; overflow-wrap: anywhere; }
  .admin-sidebar-current { display: inline; }
  .admin-nav-toggle { display: flex; }
  .admin-nav-fold { display: none; }
  .admin-sidebar-head { align-items: center; }
  .admin-nav-group-head { padding: var(--space-2) var(--space-4); }
  .admin-nav-items { display: none; padding: var(--space-2) 0; }
  .admin-sidebar.expanded .admin-nav-items { display: block; }
  .admin-nav-item { min-height: var(--touch-target); padding: var(--space-3) var(--space-4); }
  .admin-content { padding: var(--space-4); }
  /* minmax(0, 1fr), not plain 1fr, so a long number or label can't stretch a column past the
     screen edge - it wraps inside its tile instead. */
  .admin-summary-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .admin-run-row { flex-direction: column; }
  .admin-run-when { width: auto; }
}

/* ML-199 - Flow authoring time. Plain tables rather than the .admin-feature card stack the rest of
   this panel uses: these are dense numeric comparisons (median/mean/min/max across several
   groupings), and the whole point is reading DOWN a column to compare one app version against
   another, which a stack of cards makes impossible. */
.admin-stat-tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--space-3); margin-bottom: var(--space-6); }
/* ML-203: number first, then its spread, then the label - same value-over-caption order as the app's
   stat cards and tiles (flex order only, so the markup still reads label-first). */
.admin-stat-tile { display: flex; flex-direction: column; border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-4); background: var(--input-bg); }
.admin-stat-tile-value { order: 1; }
.admin-stat-tile-sub { order: 2; }
.admin-stat-tile-label { order: 3; font-size: var(--font-sm); color: var(--label-color); margin-top: var(--space-1); }
.admin-stat-tile-value { font-size: var(--font-lg); font-weight: var(--font-weight-bold); color: var(--text-color); }
/* The spread (min-max) sits under every headline number deliberately - a median with no sense of
   its spread invites a conclusion the sample can't support. */
.admin-stat-tile-sub { font-size: var(--font-sm); color: var(--label-color); margin-top: var(--space-1); }

.admin-stat-section-title { font-size: var(--font-md); font-weight: var(--font-weight-bold); color: var(--text-color); margin: var(--space-6) 0 var(--space-2) 0; }
.admin-stat-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: var(--space-5); }
/* Feature access's grid (7 columns) uses the whole width beside the menu, not the usual 900px reading width;
   its intro stays at that width so the lines don't run too long. Still scrolls sideways when the window is narrower. */
.admin-content:has(> #feature-access-section:not(.hidden-group)) { max-width: none; }
/* ML-415 / ML-416: the Accounts and Flows tables use the window's width too */
.admin-content:has(> #accounts-section:not(.hidden-group)), .admin-content:has(> #flows-section:not(.hidden-group)) { max-width: none; }
#accounts-section .admin-intro, #flows-section .admin-intro { max-width: 900px; }
/* ML-429: so do Third parties' cost and usage tables; the reading text stays at reading width */
.admin-content:has(> #third-parties-section:not(.hidden-group)), .admin-content:has(> #costs-usage-section:not(.hidden-group)) { max-width: none; }
#third-parties-section .admin-intro, #third-parties-section .admin-feature, #third-parties-section .admin-stat-tiles, #costs-usage-section .admin-intro, #costs-usage-section .admin-feature, #costs-usage-section .admin-stat-tiles { max-width: 900px; }
/* ML-427: Usage's tables (Recent sessions has 15 columns) use the window's width as well */
.admin-content:has(> #usage-section:not(.hidden-group)) { max-width: none; }
#usage-section .admin-intro { max-width: 900px; }
#usage-section .admin-stat-table td:first-child { white-space: normal; } /* a long piece name wraps, so the other columns stay on screen */
/* ML-415: one line per account - text columns read from the left, the ⋮ sits at the right */
.admin-stat-table.admin-accounts-table th, .admin-stat-table.admin-accounts-table td { text-align: left; vertical-align: middle; }
.admin-stat-table.admin-accounts-table td:last-child, .admin-flows-table td:last-child { text-align: right; width: 1%; }
.admin-flows-table td:last-child { vertical-align: middle; }
#feature-access-section .admin-intro { max-width: 900px; }
.admin-stat-table { border-collapse: collapse; width: 100%; font-size: var(--font-sm); }
.admin-stat-table th, .admin-stat-table td { padding: var(--space-2) var(--space-3); text-align: right; border-bottom: 1px solid var(--input-border); white-space: nowrap; }
.admin-stat-table th { color: var(--label-color); font-weight: var(--font-weight-semibold); text-align: right; }
.admin-stat-table th:first-child, .admin-stat-table td:first-child { text-align: left; }
.admin-stat-table tbody tr:hover { background: var(--input-bg); }
/* An excluded run stays visible and readable, just visibly not counted - the point of excluding is
   to keep the evidence, so hiding the row would defeat it. */
.admin-stat-row-excluded td { opacity: 0.45; text-decoration: line-through; }
.admin-stat-empty { color: var(--label-color); font-size: var(--font-sm); padding: var(--space-4) 0; }
.admin-stat-pill { display: inline-block; font-size: var(--font-sm); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-md); background: var(--input-bg); border: 1px solid var(--input-border); color: var(--label-color); }
.admin-stat-exclude-btn { background: none; border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-0-5) var(--space-2); font-size: var(--font-sm); font-family: var(--font-sans); color: var(--label-color); cursor: pointer; }
.admin-stat-exclude-btn:hover { color: var(--text-color); }

/* ML-170 - Feedback triage. */
.admin-nav-count { display: inline-block; min-width: 18px; padding: 0 var(--space-1); border-radius: var(--radius-sm); background: var(--primary-action); color: var(--text-on-accent); font-size: var(--font-sm); text-align: center; }
/* white-space: pre-wrap so a submission's own line breaks survive - people write bug reports as
   short lists, and collapsing those into a paragraph makes them harder to act on. */
.admin-feedback-message { white-space: pre-wrap; background: var(--input-bg); border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-4); margin-bottom: var(--space-4); color: var(--text-color); }
.admin-feedback-snippet { color: var(--text-color); margin: var(--space-1) 0 0 0; }
.admin-feedback-badges { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-2); }
.admin-feedback-badge { font-size: var(--font-sm); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-md); border: 1px solid transparent; }
/* The colours ML-170 asks for, extended to the two statuses its own dropdown mentions but never
   gave a colour to (in progress, resolved) - see 045_feedback.sql on reconciling the three lists.
   Each pairs a tinted background with a readable foreground rather than relying on hue alone, so
   the status is still distinguishable without colour vision. */
.admin-feedback-badge.status-under_review { background: var(--status-amber-bg); color: var(--status-amber-fg); }
.admin-feedback-badge.status-planned { background: var(--status-green-bg); color: var(--status-green-fg); }
.admin-feedback-badge.status-in_progress { background: var(--status-blue-bg); color: var(--status-blue-fg); }
.admin-feedback-badge.status-not_progressing { background: var(--status-grey-bg); color: var(--status-grey-fg); }
.admin-feedback-badge.status-resolved { background: var(--status-purple-bg); color: var(--status-purple-fg); }
.admin-feedback-badge.cat { background: var(--input-bg); color: var(--label-color); border-color: var(--input-border); }
/* Dark-mode variants come from tokens.css - body.dark-mode remaps the --status-* aliases (ML-198). */

/* Must come AFTER the base rules above, not folded into the existing max-width:700px block near the
   top of this file - these have the same specificity, so whichever is declared last wins and a
   narrow-screen override placed above the base rule would simply never apply.
   Four stat tiles don't fit a phone once the fixed 220px sidebar has taken its share, and the
   tables carry more columns than that leaves room for - they scroll sideways inside their own
   wrapper (.admin-stat-table-wrap) rather than crushing every column to unreadable width. */
@media (max-width: 700px) {
  .admin-stat-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ML-201 - Notifications */
.admin-notification-body { white-space: pre-wrap; margin: var(--space-2) 0 0 !important; color: var(--text-color) !important; }
.admin-feature-actions .btn-edit, .admin-feature-actions .btn-delete { min-height: 36px; padding: var(--space-1) var(--space-3); }
.admin-feedback-badge.notification-status-live { background: var(--status-green-bg); color: var(--status-green-fg); }
.admin-feedback-badge.notification-status-scheduled { background: var(--status-blue-bg); color: var(--status-blue-fg); }
.admin-feedback-badge.notification-status-expired, .admin-feedback-badge.notification-status-withdrawn { background: var(--status-grey-bg); color: var(--status-grey-fg); }
/* ML-167: an urgent notification (pops up in the app until read) */
.admin-feedback-badge.notification-status-urgent { background: var(--status-amber-bg); color: var(--status-amber-fg); }

/* ML-204 - Flows (export/import between environments). Reuses .admin-stat-table for the list; the
   import preview is a scrolling list inside the standard modal, one card per flow in the file. */
.admin-flows-toolbar { display: flex; flex-wrap: wrap; gap: var(--space-3); align-items: center; margin-bottom: var(--space-5); }
.admin-flows-toolbar .btn-submit { width: auto; flex: 0 0 auto; padding-left: var(--space-5); padding-right: var(--space-5); }
.admin-flows-filter { flex: 1 1 240px; min-width: 0; padding: var(--space-3); border: 1px solid var(--control-border); border-radius: var(--radius-md); background: var(--input-bg); color: var(--text-color); font-family: var(--font-sans); font-size: var(--font-base); }
.admin-flows-table td { vertical-align: top; }
.admin-flows-table td:nth-child(2), .admin-flows-table th:nth-child(2), .admin-flows-table td:nth-child(3), .admin-flows-table th:nth-child(3) { text-align: left; white-space: normal; min-width: 110px; }
.admin-flows-table td:nth-child(6), .admin-flows-table td:nth-child(7) { white-space: normal; }
.admin-flows-table th, .admin-flows-table td { padding-left: var(--space-2); padding-right: var(--space-2); }
.admin-flows-import-modal { max-width: 640px; }
#flowsImportList { max-height: 50vh; overflow-y: auto; margin: var(--space-4) 0; }
.admin-flows-import-item { border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-3); margin-bottom: var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); }
.admin-flows-import-item.has-errors { border-color: var(--danger-text); }
.admin-flows-import-item p { margin: 0; font-size: var(--font-sm); }
.admin-flows-import-error { color: var(--danger-text); }
.admin-flows-import-note { color: var(--label-color); }

/* ML-192 - Security (review of the OMR service). Cards, tiles, run rows and badges are the shared
   admin ones; these add the two statuses a security check has that a back-test doesn't (warn, info),
   the check row's title/badge line (not clickable - unlike .admin-test-case-head), and the native
   <details> disclosure used for evidence and history (keyboard/screen-reader behaviour for free). */
.admin-badge.warn { background: var(--status-amber-bg); color: var(--status-amber-fg); }
.admin-badge.info { background: var(--status-blue-bg); color: var(--status-blue-fg); }
.admin-security-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-bottom: var(--space-5); }
.admin-security-toolbar .btn-submit { width: auto; flex: 0 0 auto; padding-left: var(--space-5); padding-right: var(--space-5); }
.admin-security-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); }
/* display: list-item (the default) keeps the disclosure triangle - display:flex would drop it. */
.admin-security-details summary { display: list-item; min-height: var(--touch-target); box-sizing: border-box; padding: var(--space-3) 0; cursor: pointer; font-size: var(--font-sm); font-weight: var(--font-weight-semibold); color: var(--info-text); }
.admin-security-evidence { margin: var(--space-1) 0 var(--space-2) 0; padding-left: var(--space-5); font-size: var(--font-xs); color: var(--text-color); word-break: break-word; }
.admin-security-evidence li { margin-bottom: var(--space-1); }

/* ML-198 - Design (read-only design-system catalogue, admin-design.js). Page chrome only - every
   example inside .admin-design-stage is rendered with the real app classes, untouched. */
.admin-design-toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-4); margin-bottom: var(--space-4); }
.admin-design-theme { margin-bottom: 0; min-width: 200px; }
.admin-design-toggle { display: flex; align-items: center; gap: var(--space-3); margin: 0; font-weight: var(--font-weight-semibold); }
.admin-design-jumps { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-bottom: var(--space-5); }
.admin-design-jump { margin-bottom: 0; }
.admin-design-group { margin: var(--space-8) 0 var(--space-3); padding-bottom: var(--space-2); border-bottom: 2px solid var(--primary-action-strong); color: var(--text-color); }
.admin-design-subhead { margin: var(--space-7) 0 var(--space-3); color: var(--text-color); }
.admin-design-minihead { margin: var(--space-5) 0 var(--space-2); color: var(--label-color); font-size: var(--font-sm); }
.admin-design-section { border: 1px solid var(--input-border); border-radius: var(--radius-md); padding: var(--space-5); margin-bottom: var(--space-5); background: var(--container-bg); }
.admin-design-section-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-2); margin-bottom: var(--space-3); }
.admin-design-section-head h3 { margin: 0; color: var(--text-color); }
.admin-design-section-head code, .admin-design-annotation code { font-family: var(--font-mono); font-size: var(--font-xs); color: var(--label-color); }
.admin-design-example { padding: var(--space-4) 0; border-top: 1px dashed var(--input-border); }
.admin-design-example:first-of-type { border-top: none; }
.admin-design-example-label { font-size: var(--font-sm); font-weight: var(--font-weight-semibold); color: var(--label-color); margin-bottom: var(--space-2); }
/* App components are built for the 500px app column - show them at that width. */
.admin-design-stage { max-width: var(--app-max-width); padding: var(--space-4); border-radius: var(--radius-sm); background: var(--bg-color); color: var(--text-color); }
.admin-design-stage-wide { max-width: none; }
.admin-design-annotations { display: flex; flex-direction: column; gap: var(--space-1); margin-top: var(--space-2); }
.admin-design-annotation { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-1); }
.admin-design-chip { font-size: var(--font-xs); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-pill); background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text-color); }
.admin-design-chip b { color: var(--label-color); font-weight: var(--font-weight-semibold); }
.admin-design-chip-warn { background: var(--danger-tint); border-color: var(--danger-text); }
/* What's new (design sign-off): public/design-new.json from npm run design-gate marks every example
   that uses a new class; "Only what's new" hides the rest, so the owner reviews pictures. */
.admin-design-new-panel { border: 2px solid var(--primary-action-strong); border-radius: var(--radius-md); padding: var(--space-5); margin-bottom: var(--space-5); background: var(--container-bg); }
.admin-design-new-title { display: flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-2); color: var(--text-color); }
.admin-design-new-badge { display: inline-block; padding: var(--space-0-5) var(--space-2); margin-right: var(--space-1); border-radius: var(--radius-pill); background: var(--primary-action); color: var(--primary-action-text); font-size: var(--font-xs); font-weight: var(--font-weight-bold); vertical-align: middle; }
.admin-design-new-classes { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-bottom: var(--space-2); }
.admin-design-new-classes code { font-family: var(--font-mono); font-size: var(--font-xs); padding: var(--space-0-5) var(--space-2); border-radius: var(--radius-pill); background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text-color); }
.admin-design-new-swatch { display: inline-block; width: var(--space-6); height: var(--space-6); border-radius: var(--radius-sm); border: 1px solid var(--input-border); background: var(--sample); }
.admin-design-example.admin-design-is-new { border-left: 3px solid var(--primary-action-strong); padding-left: var(--space-3); }
.admin-design-only-new :is(.admin-design-foundations, .admin-design-jumps, .admin-design-group-wrap:not(.admin-design-is-new), .admin-design-section:not(.admin-design-is-new), .admin-design-example:not(.admin-design-is-new)) { display: none; }
.admin-design-show-spacing .admin-design-measured { outline: 1px dashed var(--info-text); outline-offset: 0; }
.admin-design-show-spacing .admin-design-stage * { outline: 1px dotted var(--info-tint); }

/* ML-210 overlays: every tap target (and its invisible 44px hit area), and the keyboard focus ring. */
.admin-design-show-targets .admin-design-stage :is(button, a[href], input, select, textarea, [role="button"], [role="slider"]) { outline: 1px dashed var(--info-text); }
.admin-design-show-targets .admin-design-stage :is(button, [role="button"])::before { outline: 1px dashed var(--danger-text); }
.admin-design-show-focus .admin-design-stage :is(button, a[href], input, select, textarea, [role="button"], [role="slider"]) { box-shadow: var(--focus-ring); }

/* Overlays render in place here rather than floating over the page. */
.admin-design-static .modal { position: relative; inset: auto; display: flex; z-index: auto; padding: var(--space-6) var(--space-4); border-radius: var(--radius-sm); }
.admin-design-static .toast { position: relative; left: auto; bottom: auto; transform: none; display: inline-flex; z-index: auto; }
.admin-design-static .dropdown-menu { position: relative; top: auto; right: auto; z-index: auto; max-width: 240px; }
.admin-design-static .dropdown-menu.nav-menu { position: static; }
/* The phone-width admin head row, shown at desktop width - the same rules as the 700px media query. */
.admin-design-phone .admin-sidebar-head { display: flex; align-items: center; justify-content: space-between; }
.admin-design-phone .admin-sidebar-title { padding: 0; }
.admin-design-phone .admin-sidebar-current { display: inline; }
.admin-design-phone .admin-nav-toggle { display: flex; }
.admin-design-static .anchored-popup { position: relative; display: inline-block; z-index: auto; }
.admin-design-static .splash-screen { position: relative; inset: auto; z-index: auto; min-height: 260px; border-radius: var(--radius-sm); }
.admin-design-static .splash-login-btn { display: block; }
.admin-design-static .top-bar-sticky-group { position: relative; z-index: auto; }
.admin-design-relative { position: relative; min-height: var(--touch-target); }
.admin-design-badge-host { display: inline-block; min-height: 0; width: var(--space-6); height: var(--space-6); }
.admin-design-sidebar { max-width: 220px; background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-sm); }
.admin-design-dots .metro-tier { margin-left: var(--space-4); margin-right: var(--space-4); }
.admin-design-bars { display: flex; align-items: flex-end; gap: var(--space-2); height: 120px; }
.admin-design-bars .chart-bar { width: var(--space-7); }
.admin-design-bars .admin-design-bar-slot { height: 100%; min-width: 0; width: var(--space-7); margin: 0; cursor: default; } /* a stacked projected bar in the bar-colour row */

/* Foundations */
.admin-design-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: var(--space-3); }
.admin-design-swatch { border: 1px solid var(--input-border); border-radius: var(--radius-sm); overflow: hidden; background: var(--container-bg); }
/* Token tables: each row's token arrives as --sample (admin-design.js) and the sample class applies it. */
.admin-design-swatch-color { background: var(--sample); height: 56px; border-bottom: 1px solid var(--input-border); }
.admin-design-swatch-label { display: flex; flex-direction: column; gap: var(--space-0-5); padding: var(--space-2); font-size: var(--font-xs); color: var(--text-color); }
.admin-design-swatch-label code { font-family: var(--font-mono); font-weight: var(--font-weight-bold); }
.admin-design-swatch-label small, .admin-design-shadow small { color: var(--label-color); }
.admin-design-token-value { font-family: var(--font-mono); font-size: var(--font-xs); color: var(--label-color); }
.admin-design-table td { text-align: left; white-space: normal; vertical-align: middle; }
.admin-design-table code { font-family: var(--font-mono); }
.admin-design-sample-size { font-size: var(--sample); }
.admin-design-sample-weight { font-weight: var(--sample); }
.admin-design-sample-family { font-family: var(--sample); }
.admin-design-space-bar { width: var(--sample); display: inline-block; height: var(--space-3); background: var(--primary-action); border-radius: var(--radius-2xs); }
.admin-design-leading { line-height: var(--sample); display: inline-block; font-size: var(--font-sm); background: var(--primary-action-tint); }
.admin-design-shape { border-radius: var(--sample); display: flex; flex-direction: column; justify-content: center; gap: var(--space-1); min-height: 90px; padding: var(--space-3); background: var(--input-bg); border: 2px solid var(--primary-action-strong); font-size: var(--font-xs); }
.admin-design-shadow { box-shadow: var(--sample); display: flex; flex-direction: column; justify-content: center; gap: var(--space-1); min-height: 90px; padding: var(--space-3); background: var(--container-bg); border-radius: var(--radius-sm); font-size: var(--font-xs); }
.admin-design-motion-track { position: relative; display: inline-block; width: 160px; height: var(--space-4); border-radius: var(--radius-pill); background: var(--input-bg); border: 1px solid var(--input-border); }
.admin-design-motion-dot { transition-duration: var(--sample); position: absolute; top: 50%; left: 0; width: var(--space-3); height: var(--space-3); border-radius: var(--radius-circle); background: var(--primary-action); transform: translate(0, -50%); transition-property: left; transition-timing-function: var(--ease-standard); }
.admin-design-table tr:hover .admin-design-motion-dot, .admin-design-table tr:active .admin-design-motion-dot { left: calc(100% - var(--space-3)); }
.admin-design-probe { color: var(--probe-color); box-shadow: var(--probe-shadow); } /* hidden; resolves token values for the annotations */

/* ML-345: Admin -> Feature access - see specs/components/admin-feature-access.md. The grid (every
   account type) reuses .admin-stat-table inside .admin-stat-table-wrap (it scrolls sideways on a narrow
   screen, the feature column staying put); the one-type view is a list of switch rows. */
.admin-access-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-bottom: var(--space-4); }
.admin-access-table th, .admin-access-table td { text-align: center; vertical-align: middle; }
.admin-access-table th[scope="row"] { position: sticky; left: 0; z-index: var(--z-sticky); text-align: left; white-space: normal; min-width: 200px; background: var(--container-bg); font-weight: var(--font-weight-normal); color: var(--text-color); }
.admin-access-table th[scope="row"] small, .admin-access-row small { display: block; color: var(--label-color); font-size: var(--font-xs); }
.admin-access-group th { text-align: left; background: var(--input-bg); color: var(--label-color); font-weight: var(--font-weight-bold); }
.admin-access-live { border-right: 1px solid var(--input-border); }
.admin-access-cell { display: inline-grid; place-items: center; width: var(--touch-target); height: var(--touch-target); border-radius: var(--radius-sm); cursor: pointer; }
.admin-access-cell input { width: var(--icon-md); height: var(--icon-md); accent-color: var(--primary-action); cursor: pointer; }
.admin-access-cell, .admin-access-row { border: 2px solid transparent; }
.admin-access-cell.is-changed, .admin-access-row.is-changed { border-color: var(--primary-action); }
/* ML-383: a limit - a number per account type (Limits group). Changed = the same gold outline as a changed cell */
.admin-access-limit { width: 5.5em; min-height: var(--touch-target); box-sizing: border-box; padding: var(--space-1) var(--space-2); font: inherit; text-align: right; color: var(--text-color); background: var(--input-bg); border: 1px solid var(--control-border); border-radius: var(--radius-sm); }
.admin-access-limit.is-changed { border: 2px solid var(--primary-action); }
.admin-access-copy { display: block; margin: var(--space-1) auto 0; font-size: var(--font-xs); font-weight: var(--font-weight-normal); }
.admin-access-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-2); border-bottom: 1px solid var(--input-border); border-radius: var(--radius-sm); }
.admin-access-savebar { position: sticky; bottom: var(--space-3); z-index: var(--z-float); display: flex; align-items: center; gap: var(--space-3); margin-top: var(--space-4); padding: var(--space-3) var(--space-4); background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-md); box-shadow: var(--shadow-md); }
.admin-access-toolbar select { width: auto; max-width: 100%; margin: 0; }
/* The catalog's descriptions are long - two lines here, the whole text on hover (title) and on Features. */
.admin-access-table th[scope="row"] small, .admin-access-row small { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }

/* ML-443: Admin -> Business case (specs/components/admin-business-case.md). The page is built from the panel's
   own pieces - stat tiles, tables, the Save bar, switches, value boxes that open a pop-up. Only what is new
   to it is here. Like the other table pages it uses the window's width; its reading text keeps 900px. */
.admin-content:has(> #business-case-section:not(.hidden-group)) { max-width: none; }
#business-case-section .admin-intro, #business-case-section .admin-feature, #business-case-section .admin-stat-tiles { max-width: 900px; }
/* The plan's settings: a row of value boxes (launch, years, the dollar rate, how it is counted) */
.admin-bc-settings { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--space-3); max-width: 900px; margin-bottom: var(--space-5); }
.admin-bc-settings .metroBlk-ctrl-value-btn { width: 100%; }
/* A scenario at a glance - a button, because it opens the scenario. The one the owner is in now has a gold edge
   as well as saying so. */
.admin-bc-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--space-3); margin-bottom: var(--space-4); }
.admin-bc-card { display: flex; flex-direction: column; gap: var(--space-1); min-width: 0; min-height: var(--touch-target); padding: var(--space-4); text-align: left; font-family: var(--font-sans); color: var(--text-color); background: var(--input-bg); border: 1px solid var(--control-border); border-radius: var(--radius-md); cursor: pointer; }
.admin-bc-card.is-current { border-color: var(--primary-action-strong); }
.admin-bc-card-name { font-size: var(--font-sm); font-weight: var(--font-weight-semibold); color: var(--label-color); }
.admin-bc-card-value { font-size: var(--font-xl); font-weight: var(--font-weight-bold); font-variant-numeric: tabular-nums; }
.admin-bc-card-line { font-size: var(--font-sm); color: var(--label-color); }
/* A result that is up or down: green or red text, and always a plus or minus sign as well */
.admin-bc-good, .admin-bc-table td.admin-bc-good { color: var(--success-text); }
.admin-bc-bad, .admin-bc-table td.admin-bc-bad { color: var(--danger-text); }
/* A heading with something to its right (a scenario's name and its menu; the chart's title and its picker) */
.admin-bc-head { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; gap: var(--space-3); max-width: 900px; margin-bottom: var(--space-3); }
.admin-bc-head > div { flex: 1 1 calc(var(--touch-target) * 5); min-width: 0; }
.admin-bc-head h2 { margin: 0 0 var(--space-2) 0; font-size: var(--font-lg); color: var(--text-color); }
.admin-bc-head .admin-intro { margin: 0; }
/* The page's tables: words read from the left and wrap; a group row, a total row, and a cost that is left out */
.admin-bc-table th, .admin-bc-table td { vertical-align: middle; }
.admin-bc-table .admin-bc-text { text-align: left; white-space: normal; min-width: 180px; }
.admin-bc-table tbody th { font-weight: var(--font-weight-semibold); color: var(--text-color); }
.admin-bc-table small { display: block; max-width: 60ch; margin-top: var(--space-0-5); color: var(--label-color); font-size: var(--font-xs); font-weight: var(--font-weight-normal); }
.admin-bc-table small a { color: var(--info-text); }
.admin-bc-group th, .admin-bc-group td { text-align: left; background: var(--input-bg); color: var(--label-color); font-weight: var(--font-weight-bold); }
.admin-bc-group td { text-align: right; }
.admin-bc-total th, .admin-bc-total td { font-weight: var(--font-weight-bold); color: var(--text-color); background: var(--input-bg); }
.admin-bc-table .admin-bc-off th, .admin-bc-table .admin-bc-off td { color: var(--label-color); }
/* A row of small labelled number boxes (members by year, a price, a share) */
.admin-bc-fields { display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--space-3) var(--space-4); max-width: 900px; margin: var(--space-3) 0; }
.admin-bc-field { display: flex; flex-direction: column; gap: var(--space-1); margin: 0; font-size: var(--font-sm); font-weight: var(--font-weight-semibold); color: var(--label-color); }
.admin-bc-num { width: 7em; min-height: var(--touch-target); box-sizing: border-box; margin: 0; padding: var(--space-1) var(--space-2); font: inherit; font-weight: var(--font-weight-normal); font-variant-numeric: tabular-nums; text-align: right; color: var(--text-color); background: var(--input-bg); border: 1px solid var(--control-border); border-radius: var(--radius-sm); }
/* One kind of income: its switch, its name, what it comes to, then its figures */
.admin-bc-income { max-width: 900px; box-sizing: border-box; margin-bottom: var(--space-3); padding: var(--space-3) var(--space-4); background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-md); }
.admin-bc-income-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.admin-bc-income-head strong { flex: 1; min-width: 0; color: var(--text-color); }
.admin-bc-income-head span { font-size: var(--font-sm); color: var(--label-color); }
.admin-bc-income .admin-intro { margin: 0; }
.admin-bc-income.admin-bc-off .admin-bc-fields { opacity: var(--opacity-muted); }
/* The chart: every scenario's running total, month by month. The chosen scenario is the thick gold line; the
   others are thin grey lines numbered at the end. Its numbers are in the table under it. */
.admin-bc-chart-card { position: relative; max-width: 1100px; box-sizing: border-box; margin-bottom: var(--space-5); padding: var(--space-4); background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-md); }
.admin-bc-chart-card .admin-bc-head { max-width: none; }
.admin-bc-chart-host { position: relative; }
.admin-bc-chart { display: block; max-width: 100%; height: auto; }
.admin-bc-chart text { font-family: var(--font-sans); font-size: var(--font-xs); fill: var(--label-color); font-variant-numeric: tabular-nums; }
.admin-bc-chart .admin-bc-chart-end { fill: var(--text-color); font-weight: var(--font-weight-semibold); }
.admin-bc-chart-grid { stroke: var(--input-border); stroke-width: 1px; }
.admin-bc-chart-zero { stroke: var(--control-border); stroke-width: 1px; }
.admin-bc-chart-other { fill: none; stroke: var(--label-color); stroke-width: 1px; }
.admin-bc-chart-line { fill: none; stroke: var(--primary-action-strong); stroke-width: 3px; stroke-linejoin: round; stroke-linecap: round; }
.admin-bc-chart-dot { fill: var(--primary-action-strong); stroke: var(--container-bg); stroke-width: 2px; }
/* What the chart says at the month under the pointer; placed by --tip-x / --tip-y (set as it moves) */
.admin-bc-chart-tip { position: absolute; left: var(--tip-x); top: var(--tip-y); z-index: var(--z-raised); min-width: 170px; padding: var(--space-2) var(--space-3); pointer-events: none; font-size: var(--font-sm); color: var(--text-color); background: var(--container-bg); border: 1px solid var(--input-border); border-radius: var(--radius-sm); box-shadow: var(--shadow-md); }
.admin-bc-chart-tip-row { display: flex; justify-content: space-between; gap: var(--space-4); color: var(--label-color); }
.admin-bc-chart-tip-row strong { color: var(--text-color); font-variant-numeric: tabular-nums; }

/* ML-443: the Dashboard - the page the panel opens on. Its boxes are the stat tiles as buttons (each
   opens the page behind it), and "Needs you" is a list of rows that do the same. */
.admin-dash-tile { width: 100%; box-sizing: border-box; font-family: var(--font-sans); text-align: left; cursor: pointer; }
.admin-dash-tile:hover { border-color: var(--control-border); }
#dashboard-section .admin-stat-section-title:first-child { margin-top: var(--space-4); }
.admin-dash-need { display: flex; align-items: center; gap: var(--space-3); width: 100%; min-height: var(--touch-target); box-sizing: border-box; padding: var(--space-3) var(--space-4); background: var(--container-bg); border: none; border-bottom: 1px solid var(--input-border); font-family: var(--font-sans); font-size: var(--font-base); color: var(--text-color); text-align: left; cursor: pointer; }
.admin-dash-need:last-child { border-bottom: none; }
.admin-dash-need:hover { background: var(--input-bg); }
.admin-dash-need .admin-badge { flex-shrink: 0; }
.admin-dash-need-text { flex: 1; min-width: 0; }
