/* governetics panel — Phase 6 full UI mock implementation.
 *
 * Hand-crafted; not Tailwind/Bootstrap. Phase 3 baseline preserved (badge
 * `.b-<value>` classes + form layout) for backward-compat with existing
 * templates; Phase 6 layer extends with semantic classes (severity-*-*) +
 * layout primitives mirroring the design mock
 * (docs/sessions/design/260504-02-inventory-dashboard-mock/inventory-mock.html).
 *
 * CSS enum→class normalization (Phase 6 side-task #3):
 *   `.severity-impact-{minor,major,critical}`
 *   `.severity-criticality-{low,medium,high,critical}`
 *   `.severity-lifecycle-{new,bootstrapped,fleet-ready,failed,retired}`
 *   `.severity-rollout-{rolling-normally,rollout-stuck,config-drift,
 *      apply-failed,apply-stale,awaiting-deploy,n-a}`
 *   `.severity-redundancy-{ok,spof,n-a}`
 *   `.severity-freshness-{fresh,stale,lost}`
 *   `.badge.b-ignored`  (D-004 ignored axis — muted orange-grey)
 */

:root {
  --bg: #f7f8fa;
  --surface: #ffffff;
  --surface-2: #f1f3f6;
  --surface-3: #e8eaee;
  --border: #e3e6eb;
  --border-strong: #c8cdd5;
  --text: #1d2330;
  --text-2: #5b6473;
  --text-3: #8b94a3;
  --accent: #2f5dff;
  --accent-bg: #e8efff;
  --danger: #b91c1c;
  --danger-bg: #fee2e2;
  --success: #15803d;
  --success-bg: #dcfce7;

  --c-healthy: #15803d;        --c-healthy-bg: #dcfce7;
  --c-degraded: #b45309;       --c-degraded-bg: #fef3c7;
  --c-offline: #b91c1c;        --c-offline-bg: #fee2e2;
  --c-unknown: #475569;        --c-unknown-bg: #e2e8f0;

  --c-crit: #991b1b;           --c-crit-bg: #fee2e2;
  --c-high: #c2410c;           --c-high-bg: #ffedd5;
  --c-med: #1e40af;            --c-med-bg: #dbeafe;
  --c-low: #475569;            --c-low-bg: #e2e8f0;

  --c-spof: #b91c1c;           --c-spof-bg: #fee2e2;
  --c-ok: #15803d;             --c-ok-bg: #dcfce7;

  --c-stuck: #b91c1c;          --c-stuck-bg: #fee2e2;
  --c-drift: #b45309;          --c-drift-bg: #fef3c7;
  --c-rolling: #1e40af;        --c-rolling-bg: #dbeafe;

  --c-fresh: #15803d;
  --c-stale: #b45309;
  --c-lost: #b91c1c;

  /* Muted "operator decided this, it is not a fault" pairs. Deliberately
   * desaturated: an ignored or retired node must not read as an alarm next
   * to the loud `--c-offline` / `--c-crit` reds in the same row.
   *   ignored — warm orange-grey (amber pulled towards grey);
   *   retired — grey-red (a red that has lost most of its saturation).
   * Both keep >=4.5:1 text-on-bg contrast (badge text is 11.5px/600 =
   * "normal text" for WCAG purposes). */
  --c-ignored: #6f5e49;        --c-ignored-bg: #efeae2;
  --c-retired: #745757;        --c-retired-bg: #eee6e6;

  --shadow-sm: 0 1px 2px rgba(15,23,42,0.04);
  --shadow-md: 0 6px 18px rgba(15,23,42,0.10);
  --shadow-lg: 0 24px 60px rgba(15,23,42,0.22);

  /* B-039 closure 2026-05-10 — alias tokens used by Phase 6.5 auth pages
   * + the former _auto_promote_toggle.html (retired in PROJ-UX W4-UI2;
   * login/setup/change_password) which referenced
   * undefined CSS-vars previously. Aliased к existing Block G.1 design palette. */
  --bg-2: var(--surface-2);
  --text-1: var(--text);
  --severity-criticality-low: var(--c-low);
  --severity-criticality-medium: var(--c-med);
  --severity-criticality-high: var(--c-high);
  --severity-criticality-critical: var(--c-crit);
  --ok: var(--success);
  --err: var(--danger);
}

/* B-031 closure 2026-05-10 — auth pages card-shell wrapper.
 * Wraps login/setup/change_password page content для visual grouping
 * (Designer Block B finding: «form floats в пустоте без panel»).
 * Mobile (<768px) auto-stretches viewport-width minus margin. */
.auth-card {
  max-width: 480px;
  margin: 48px auto;
  padding: 32px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}
@media (max-width: 768px) {
  .auth-card {
    max-width: calc(100vw - 24px);
    margin: 16px auto;
    padding: 20px;
  }
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  font: 13px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
        Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
button { cursor: pointer; }

/* --- Header / nav --- */
header.topbar {
  display: flex; align-items: center; gap: 16px;
  padding: 10px 20px; background: var(--surface);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 60;
}
header.topbar .brand { font-weight: 700; font-size: 15px; letter-spacing: 0.3px; }
header.topbar .brand .dot { color: var(--accent); }
header.topbar nav { display: flex; gap: 14px; }
header.topbar nav a { color: var(--text-2); }
header.topbar nav a.active { color: var(--text); font-weight: 600; }
header.topbar .spacer { flex: 1; }
header.topbar .actor {
  font-size: 11px; color: var(--text-3);
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 3px 9px; border-radius: 12px;
}

main { padding: 18px 20px 40px; }
h1 { font-size: 20px; font-weight: 700; margin: 0 0 16px; }
h2 { font-size: 14px; font-weight: 600; margin: 18px 0 8px; color: var(--text-2); }

/* --- Page header (with title + actions) --- */
.page-header {
  display: flex; align-items: center; gap: 16px; margin-bottom: 16px;
  flex-wrap: wrap;
}
.page-header .page-title { font-size: 20px; font-weight: 700; margin: 0; }
.page-header .page-sub { color: var(--text-3); font-size: 12px; }
.page-header .spacer { flex: 1; }

/* 260511-03 C3 — group page-header CTAs into a single wrapping flex cluster
 * so the three Inventory action buttons (Управление образами / + Добавить
 * ноду / Add existing observer) stay together on desktop AND collapse to a
 * column-stretch stack on mobile (<768px) instead of fragmenting across
 * the four-element header into 3-4 rows. */
.page-actions-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
@media (max-width: 768px) {
  .page-actions-cluster {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .page-actions-cluster .btn,
  .page-actions-cluster a.btn {
    width: 100%;
    text-align: center;
  }
}

/* --- Scope-switcher (namespace selector + actor display) --- */
.scope-switcher {
  display: flex; align-items: center; gap: 8px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px 10px;
}
.scope-switcher label {
  color: var(--text-3); font-size: 11px;
  text-transform: uppercase; letter-spacing: 0.5px;
}
.scope-switcher select {
  background: transparent; border: none; padding: 4px 4px;
  font-weight: 600; outline: none; color: var(--text);
  font-size: 12.5px;
}
.scope-switcher .ns-pill {
  background: var(--surface); border: 1px solid var(--border);
  padding: 3px 9px; border-radius: 12px; font-size: 12px; color: var(--text);
}

/* --- Summary strip (top metric tiles) --- */
.summary-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 16px;
}
/* Caption spans the whole grid row (260802): the strip aggregates the
   working cohort only, so it MUST NOT read as a header for the list below
   it. `1 / -1` keeps the tile grid untouched at every breakpoint. */
.summary-caption {
  grid-column: 1 / -1;
  font-size: 11.5px; line-height: 1.45; color: var(--text-3);
  margin-bottom: -2px;
}
.summary-tile {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px 16px; box-shadow: var(--shadow-sm);
  text-align: left; width: 100%;
}
.summary-tile .tile-title {
  text-transform: uppercase; letter-spacing: 0.6px; font-size: 10.5px;
  color: var(--text-3); font-weight: 600; margin-bottom: 8px;
}
.summary-tile .tile-big {
  font-size: 26px; font-weight: 700; line-height: 1; margin-bottom: 8px;
  display: flex; align-items: baseline; gap: 8px;
}
.summary-tile .tile-big .unit {
  font-size: 13px; color: var(--text-3); font-weight: 500;
}
.summary-tile .tile-breakdown {
  display: flex; flex-wrap: wrap; gap: 6px;
}
.mini-stat {
  font-size: 11.5px; padding: 2px 8px; border-radius: 8px;
  background: var(--surface-2); color: var(--text-2);
  border: 1px solid var(--border);
}
.mini-stat strong { color: var(--text); font-weight: 600; }
/* D-028 E.7.4 + B-186 — «Панель: предупреждения» under the strip (the
   panel's own warnings, read by the browser; hidden for non-superadmins). */
.summary-panel-warnings { margin: -4px 0 16px; }
.summary-panel-warnings[hidden] { display: none; }
.summary-panel-warnings .panel-warnings {
  margin: 0; padding-left: 18px; font-size: 12px; line-height: 1.5;
  color: var(--text-2);
}
.mini-stat.is-warn { background: var(--c-degraded-bg); color: var(--c-degraded); border-color: var(--c-degraded-bg); }
.mini-stat.is-bad  { background: var(--c-offline-bg);  color: var(--c-offline);  border-color: var(--c-offline-bg);  }
.mini-stat.is-good { background: var(--c-healthy-bg);  color: var(--c-healthy);  border-color: var(--c-healthy-bg);  }

/* --- Retired tab toggle --- */
.retired-tab {
  display: flex; gap: 4px; border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.retired-tab .tab {
  background: transparent; border: none; padding: 10px 14px;
  color: var(--text-2); font-weight: 500;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  text-decoration: none;
}
.retired-tab .tab.is-active {
  color: var(--text); border-bottom-color: var(--accent);
}
.retired-tab .tab .tab-count {
  background: var(--surface-2); padding: 1px 7px; border-radius: 10px;
  font-size: 11px; margin-left: 4px; color: var(--text-2);
}

/* --- Filter bar + popovers (Alpine x-data driven) --- */
.filter-bar {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 12px; box-shadow: var(--shadow-sm);
  position: relative;
}
.filter-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.filter-popover-button {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 8px; padding: 6px 10px;
  color: var(--text-2); font-size: 12px;
  display: inline-flex; align-items: center; gap: 6px;
  position: relative;
}
.filter-popover-button:hover {
  border-color: var(--border-strong); color: var(--text);
}
.filter-popover-button.is-active {
  background: var(--accent-bg); border-color: var(--accent); color: var(--accent);
}
.filter-popover-button .count {
  background: rgba(47,93,255,0.18); border-radius: 10px;
  padding: 0 6px; font-size: 11px; font-weight: 600; color: var(--accent);
}
.filter-popover-button .caret { color: var(--text-3); }

.filter-popover {
  position: absolute; top: calc(100% + 4px); left: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-md); padding: 6px; min-width: 220px; z-index: 30;
}
.filter-popover .pop-title {
  font-size: 10.5px; color: var(--text-3); padding: 6px 10px 4px;
  text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600;
}
.filter-popover label.opt-row {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 10px; border-radius: 6px; cursor: pointer;
  font-size: 12.5px;
}
.filter-popover label.opt-row:hover { background: var(--surface-2); }
.filter-popover .pop-foot {
  border-top: 1px solid var(--border); margin-top: 4px;
  padding: 6px 6px 2px; display: flex; justify-content: space-between;
}
.filter-popover .pop-foot button {
  background: transparent; border: none; color: var(--accent); font-size: 11.5px;
  padding: 4px 6px;
}
.filter-popover .pop-foot button:hover { text-decoration: underline; }

.active-chips {
  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; min-height: 0;
}
.active-chips:empty { display: none; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--accent-bg); color: var(--accent);
  padding: 3px 4px 3px 10px; border-radius: 14px; font-size: 11.5px;
  border: 1px solid transparent;
}
.chip .x {
  background: rgba(47,93,255,0.18); color: var(--accent); border-radius: 50%;
  width: 16px; height: 16px; display: inline-flex; align-items: center; justify-content: center;
  border: none; padding: 0; font-size: 11px; line-height: 1;
}
.chip .x:hover { background: var(--accent); color: #fff; }

/* Legacy filter form (Phase 3 baseline; kept for compatibility) */
form.filters {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px 14px; margin-bottom: 12px;
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
}
form.filters label {
  font-size: 11.5px; color: var(--text-3);
  display: inline-flex; align-items: center; gap: 6px;
}
form.filters select, form.filters input[type=text] {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 6px; padding: 5px 8px; font-size: 12px; color: var(--text);
  outline: none;
}
form.filters select:focus, form.filters input:focus { border-color: var(--accent); }
form.filters .spacer { flex: 1; }

/* --- Buttons --- */
.btn {
  border: 1px solid var(--border); background: var(--surface);
  padding: 6px 12px; border-radius: 8px; color: var(--text);
  font-size: 12px; font-weight: 500; cursor: pointer;
  text-decoration: none; display: inline-flex; align-items: center; gap: 6px;
}
.btn:hover { background: var(--surface-2); text-decoration: none; }
.btn.btn-primary { background: var(--accent); color: #fff; border-color: var(--accent); }
.btn.btn-primary:hover { filter: brightness(1.05); background: var(--accent); }
.btn.btn-ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn.btn-ghost:hover { background: var(--surface-2); }
.btn.btn-danger { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-bg); }
.btn.btn-danger:hover { background: #fcd1d1; }
.btn.disabled {
  background: var(--surface-2); color: var(--text-3); border-color: var(--border);
  cursor: not-allowed; filter: none;
}
.btn .lock {
  margin-left: 6px; font-size: 10px; color: var(--text-3); background: var(--surface);
  padding: 0 5px; border-radius: 4px; border: 1px solid var(--border);
}
.btn.btn-primary:not(.disabled) .lock {
  background: rgba(255,255,255,0.18); color: rgba(255,255,255,0.85); border-color: transparent;
}

/* --- Bulk-action bar --- */
.bulk-action-bar {
  align-items: center; gap: 10px;
  background: var(--text); color: #fff; padding: 10px 14px;
  border-radius: 10px; margin-bottom: 10px;
  box-shadow: var(--shadow-md);
  display: flex;
}
.bulk-action-bar .count {
  font-weight: 700; padding-right: 8px;
  border-right: 1px solid rgba(255,255,255,0.2); margin-right: 4px;
}
.bulk-action-bar .bulk-btn {
  background: rgba(255,255,255,0.12); color: #fff; border: none;
  padding: 5px 12px; border-radius: 6px; font-size: 12px;
}
.bulk-action-bar .bulk-btn:hover { background: rgba(255,255,255,0.22); }
.bulk-action-bar .bulk-btn.disabled { opacity: 0.4; cursor: not-allowed; }
.bulk-action-bar .spacer { flex: 1; }
.bulk-action-bar .x-clear {
  background: transparent; color: #fff;
  border: 1px solid rgba(255,255,255,0.3); padding: 4px 10px;
  border-radius: 6px; font-size: 12px;
}

/* --- Inventory grid (table) --- */
.inventory-grid, .table-wrap {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  overflow: visible; box-shadow: var(--shadow-sm);
}
table.inv { width: 100%; border-collapse: collapse; }
table.inv th, table.inv td {
  text-align: left; padding: 10px 12px; vertical-align: middle;
  border-bottom: 1px solid var(--border); font-size: 12.5px;
}
table.inv thead th {
  background: var(--surface-2); color: var(--text-3);
  font-weight: 600; font-size: 10.5px; text-transform: uppercase;
  letter-spacing: 0.5px; white-space: nowrap;
}
table.inv tbody tr { cursor: pointer; }
table.inv tbody tr:hover { background: #fafbfd; }
table.inv tbody tr:hover .row-quick-actions { opacity: 1; }
table.inv tbody tr.is-selected { background: var(--accent-bg); }
table.inv tbody tr.is-suppressed { opacity: 0.62; }
table.inv tbody tr:last-child td { border-bottom: none; }
table.inv th.col-check, table.inv td.col-check { width: 30px; padding-right: 0; }
table.inv th.col-actions, table.inv td.col-actions { width: 110px; text-align: right; }
table.inv td.caption-cell { font-weight: 600; }
table.inv td.caption-cell a { color: var(--text); }
table.inv td.caption-cell a:hover { color: var(--accent); }
table.inv td.muted { color: var(--text-3); }
table.inv td.dim { color: var(--text-3); font-family: ui-monospace, monospace; font-size: 11.5px; }
.row-checkbox { transform: translateY(1px); cursor: pointer; }

/* Component cell — caption + meta */
.comp-cell { min-width: 220px; }
.comp-name {
  font-weight: 600; color: var(--text);
  display: flex; align-items: center; gap: 8px;
}
.comp-meta {
  font-size: 11px; color: var(--text-3); margin-top: 2px;
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
}
.comp-meta .ns { color: var(--text-2); font-weight: 500; }

/* --- Action menu (per-row) --- */
.action-menu-anchor { position: relative; display: inline-block; }
.action-menu-button {
  border: none; background: transparent; color: var(--text-3);
  width: 28px; height: 28px; border-radius: 6px;
  font-size: 18px; line-height: 1;
}
.action-menu-button:hover { background: var(--surface-2); color: var(--text); }
.action-menu {
  position: absolute; right: 4px; top: 32px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-md); padding: 6px; min-width: 240px; z-index: 30;
}
.action-menu .menu-section {
  font-size: 10.5px; color: var(--text-3); padding: 6px 10px 4px;
  text-transform: uppercase; letter-spacing: 0.5px; font-weight: 600;
}
.action-menu-item {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: transparent; border: none;
  padding: 6px 10px; border-radius: 6px;
  color: var(--text); font-size: 12.5px; text-align: left;
  text-decoration: none;
}
.action-menu-item:hover { background: var(--surface-2); text-decoration: none; }
.action-menu-item.disabled { color: var(--text-3); cursor: not-allowed; }
.action-menu-item.disabled:hover { background: transparent; }
.action-menu-item.danger { color: var(--c-offline); }
.action-menu-item.danger.disabled { color: var(--text-3); }
.action-menu-item .lock {
  margin-left: auto; font-size: 10px; color: var(--text-3);
  background: var(--surface-2); padding: 0 6px; border-radius: 4px;
}
.action-menu .divider { height: 1px; background: var(--border); margin: 4px 0; }

/* --- Side panel (htmx swap target) --- */
.side-panel-overlay {
  position: fixed; inset: 0; background: rgba(15,23,42,0.28);
  z-index: 40;
}
.side-panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: 580px; max-width: 100vw;
  background: var(--surface); box-shadow: -8px 0 32px rgba(15,23,42,0.18);
  display: flex; flex-direction: column;
  z-index: 50;
  overflow-y: auto;
}
.side-panel.is-empty { display: none; }
.side-panel .panel-head {
  padding: 14px 18px; border-bottom: 1px solid var(--border);
  display: flex; align-items: flex-start; gap: 12px;
}
.side-panel .panel-title { font-size: 16px; font-weight: 700; }
.side-panel .panel-sub { font-size: 12px; color: var(--text-3); margin-top: 3px; }
.side-panel .panel-close {
  margin-left: auto; background: transparent; border: none;
  width: 30px; height: 30px; font-size: 18px; color: var(--text-3); border-radius: 6px;
}
.side-panel .panel-close:hover { background: var(--surface-2); color: var(--text); }
.side-panel .panel-body { padding: 0; flex: 1; }
.side-panel .panel-actions {
  padding: 14px 18px; border-top: 1px solid var(--border);
  display: flex; gap: 8px; flex-wrap: wrap; background: var(--surface);
  align-items: center;
}

/* --- Section blocks (used in detail page + side panel) --- */
.section {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 16px 18px; margin-bottom: 14px;
}
.side-panel .section {
  border: none; border-radius: 0; border-bottom: 1px solid var(--border);
  margin-bottom: 0; padding: 14px 18px;
}
.section .section-title {
  font-size: 10.5px; color: var(--text-3); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.7px; margin-bottom: 12px;
  display: flex; align-items: center; gap: 8px;
}
.section .section-title .private-tag,
.private-tag {
  display: inline-block; margin-left: 4px;
  background: var(--surface-2); color: var(--text-3); border-radius: 4px;
  padding: 0 5px; font-size: 10px; font-weight: 600; letter-spacing: 0.4px;
  text-transform: uppercase;
}
.section .section-title .inline-action {
  margin-left: auto; font-size: 11px;
  border: 1px solid var(--border); background: var(--surface);
  padding: 3px 8px; border-radius: 6px; color: var(--text); font-weight: 600;
  text-transform: none; letter-spacing: 0;
}

/* --- KV grid (used in detail + side panel) --- */
.detail-grid, .kv {
  display: grid; grid-template-columns: 132px 1fr;
  gap: 4px 12px; font-size: 12.5px;
  margin-bottom: 18px;
}
.kv { margin-bottom: 0; }
.detail-grid .k, .kv .k { color: var(--text-3); padding: 3px 0; }
.detail-grid .v, .kv .v { color: var(--text); padding: 3px 0; word-break: break-word; }
.detail-grid .v.muted, .kv .v.muted { color: var(--text-3); font-style: italic; }
.detail-grid .v code, .kv .v code {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 11.5px; background: var(--surface-2);
  padding: 1px 5px; border-radius: 4px;
}
/* Ignore-reason line under the `ignored` badge in the identity grid. The
   reason is the whole point of the D-004 axis, so it renders as visible
   text on the detail card (the list view carries it in the tooltip). */
.detail-grid .ignored-reason {
  margin-top: 3px; font-size: 11.5px; line-height: 1.4;
  color: var(--c-ignored);
}
.detail-grid .ignored-reason.muted { color: var(--text-3); }
/* Dim children INSIDE the ignored cell (raw enum literal, «нет» placeholder).
   The generic `.muted` token matches `.detail-grid .v.muted` — the cell
   itself — so it is inert on a child element; these two need their own
   selector rather than a widened `.v .muted` rule (which would silently
   repaint every neighbouring cell in the identity grid). */
.detail-grid .v .ignored-dim { color: var(--text-3); }

/* --- Audit timeline (detail page) --- */
.timeline { margin: 0; padding: 0; list-style: none; font-size: 12px; }
.timeline li {
  display: flex; gap: 10px; padding: 5px 0;
  border-bottom: 1px dashed var(--border);
}
.timeline li:last-child { border-bottom: none; }
.timeline .when {
  color: var(--text-3); font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 11px; min-width: 95px;
}
.timeline .what { color: var(--text-2); }
.timeline .what code {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 11px; background: var(--surface-2);
  padding: 1px 5px; border-radius: 4px;
}

/* --- Form rows (severity PATCH; also used inside modals) --- */
form.severity-form .form-row,
.form-row {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 8px 12px;
  margin-bottom: 10px;
  align-items: center;
}
form.severity-form label,
.form-row > label {
  color: var(--text-2); font-size: 12.5px; font-weight: 500;
}
form.severity-form .opt,
.form-row > label .opt {
  color: var(--text-3); font-weight: 400; font-size: 11px;
}
form.severity-form input,
form.severity-form select,
.form-control {
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 6px; padding: 6px 10px; font-size: 12.5px;
  outline: none;
}
form.severity-form input:focus,
form.severity-form select:focus,
.form-control:focus {
  border-color: var(--accent);
}
form.severity-form .form-actions { margin-top: 12px; }

#patch-result {
  margin-top: 10px; font-size: 12px; padding: 8px 10px; border-radius: 6px;
  display: none;
}
#patch-result.ok  { display: block; background: var(--c-healthy-bg); color: var(--c-healthy); }
#patch-result.err { display: block; background: var(--c-offline-bg); color: var(--c-offline); }

/* Alpine x-cloak — hide cloaked nodes until Alpine binds (avoids flash). */
[x-cloak] { display: none !important; }

/* D-023 settings form — input cluster, tri-state control */
/* PROJ-UX UI2 (D1) — the form never grows wider than its dialog. Three
   things used to push it out: a <fieldset>'s UA default
   ``min-width: min-content`` (the section takes its widest row's width),
   the row grid's ``1fr`` (= minmax(auto, 1fr): the field column never
   shrinks below its content), and a non-wrapping cluster (input + 👁 +
   «редактировать» + the editor note in one line). Fieldsets and grid
   tracks may shrink to 0, the cluster wraps, the editor note takes a line
   of its own under the field; below 560px the label sits above the field. */
.deploy-config-form fieldset { min-width: 0; }
.deploy-config-form .form-row {
  grid-template-columns: minmax(0, 160px) minmax(0, 1fr);
}
.deploy-config-form .form-row > label { min-width: 0; overflow-wrap: anywhere; }
@media (max-width: 560px) {
  .deploy-config-form .form-row { grid-template-columns: minmax(0, 1fr); }
}
.deploy-input-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: stretch;
  min-width: 0;
}
.deploy-input-cluster input {
  flex: 1 1 140px;
  min-width: 0;
}


/* --- D-023 tri-state per-field control (preserve / overwrite / clear) --- */
.tristate-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  font-size: 11px;
  margin-bottom: 8px;
}
.tristate-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
.tristate-swatch {
  width: 10px; height: 10px; border-radius: 2px; display: inline-block;
  border: 1px solid var(--border);
}
.tristate-swatch-preserve { background: var(--surface-2); }
.tristate-swatch-overwrite { background: var(--accent); border-color: var(--accent); }
.tristate-swatch-clear { background: var(--c-crit); border-color: var(--c-crit); }
/* D-023 A-3 — true-delete (4th state). Dashed red to distinguish from clear. */
.tristate-swatch-delete {
  background: repeating-linear-gradient(
    45deg, var(--c-crit), var(--c-crit) 2px, transparent 2px, transparent 4px);
  border-color: var(--c-crit);
}


/* segmented 3-button mode switch */
.tristate-control {
  display: inline-flex;
  gap: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  width: fit-content;
}
.tristate-btn {
  border: none;
  background: var(--surface);
  color: var(--text-3);
  font-size: 11px;
  font-weight: 600;
  padding: 4px 10px;
  cursor: pointer;
  border-right: 1px solid var(--border);
}
.tristate-btn:last-child { border-right: none; }
.tristate-btn:hover { background: var(--surface-2); }
.tristate-btn.is-active {
  background: var(--accent);
  color: #fff;
}
/* red warning text under а required field being cleared */
.tristate-clear-warning {
  font-size: 11px;
  font-weight: 600;
  color: var(--c-crit);
}

.tristate-delete-warning {
  font-size: 11px;
  font-weight: 600;
  color: var(--c-crit);
}

/* --- The node's settings form (contract CFG-AXES п. 9) ------------------
   Everything state-dependent is driven by data attributes the client sets
   from GET …/config (static/deploy.js): the form's ``data-cfg-state``
   (loading | ready | error | undecryptable) and each row's ``data-set``
   (the key has a stored value), ``data-hidden`` (effective visibility
   invisible), ``data-action`` (keep | value | clear | delete),
   ``data-mutability``, ``data-new`` (an operator key added in the form). */
.deploy-config-form .cfg-loading,
.deploy-config-form .cfg-read-error,
.deploy-config-form .cfg-undecryptable,
.deploy-config-form .cfg-body { display: none; }
.deploy-config-form[data-cfg-state="loading"] .cfg-loading,
.deploy-config-form[data-cfg-state="error"] .cfg-read-error,
.deploy-config-form[data-cfg-state="undecryptable"] .cfg-undecryptable,
.deploy-config-form[data-cfg-state="ready"] .cfg-body { display: block; }
.deploy-config-form .cfg-undecryptable > * { margin-top: 6px; }
.deploy-config-form .cfg-reset-name { margin-left: 6px; }

.deploy-config-form .cfg-template-drift,
.deploy-config-form .cfg-review-required,
.deploy-config-form .cfg-review-recreate,
.deploy-config-form .cfg-review-reread,
.deploy-config-form .cfg-review-errors,
.deploy-config-form .cfg-review-hints { display: none; margin-top: 8px; white-space: pre-line; }
.deploy-config-form [data-shown="1"] { display: block; }
.deploy-config-form .cfg-review-recreate {
  background: var(--c-crit-bg); border-left: 3px solid var(--c-crit);
  color: var(--c-crit); padding: 8px 10px; font-size: 12px; font-weight: 600;
  border-radius: 4px;
}

.deploy-config-form .form-row.cfg-row { display: flex; flex-direction: column; gap: 6px; padding: 6px 0; }
.cfg-key-head { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-width: 0; }
.cfg-key-name { overflow-wrap: anywhere; }
.cfg-label {
  font-size: 10.5px; font-weight: 600; padding: 1px 6px; border-radius: 10px;
  background: var(--surface-2); color: var(--text-2); white-space: nowrap;
}
.cfg-label-immutable { background: var(--c-info-bg); color: var(--c-info); }
.cfg-label-managed { background: var(--c-degraded-bg); color: var(--c-degraded); }
.cfg-row .cfg-label-hidden { display: none; }
.cfg-row[data-hidden="1"] .cfg-label-hidden { display: inline; }
.cfg-rights input { width: 5.5em; }
.cfg-rights input[readonly] { background: var(--surface-2); color: var(--text-3); }
.cfg-row .cfg-key-input { flex: 1 1 140px; min-width: 0; }

.cfg-state > span { display: none; font-size: 11px; }
.cfg-row[data-set="1"][data-hidden="1"][data-action="keep"] .cfg-state-masked { display: inline; }
.cfg-row[data-set="0"] .cfg-state-unset,
.cfg-row[data-set="0"] .cfg-state-unset-managed { display: inline; }
.cfg-row[data-set="0"] .cfg-state-unset-required {
  display: inline; color: var(--c-crit); font-weight: 600;
}
.cfg-row[data-mutability="immutable"][data-set="1"] .cfg-state-immutable-set { display: inline; }
.cfg-mask { letter-spacing: 1px; }

.cfg-row[data-set="0"] .cfg-act-keep,
.cfg-row[data-set="0"] .cfg-act-value,
.cfg-row[data-set="0"] .cfg-act-delete,
.cfg-row[data-mutability="immutable"][data-set="1"] .cfg-controls,
.cfg-row:not([data-new="1"]) .cfg-op-remove { display: none; }
.cfg-row[data-action="clear"] .cfg-act-clear.is-active,
.cfg-row[data-action="delete"] .cfg-act-delete.is-active { background: var(--c-crit); color: #fff; }
.cfg-row[data-action="clear"],
.cfg-row[data-action="delete"] { border-left: 3px solid var(--c-crit); padding-left: 8px; }
.cfg-row[data-action="delete"] { border-left-style: dashed; }

.cfg-row[data-action="clear"] .cfg-value-wrap,
.cfg-row[data-action="delete"] .cfg-value-wrap,
.cfg-row[data-action="keep"][data-hidden="1"] .cfg-value-wrap { display: none; }
.cfg-value-wrap textarea.cfg-value { flex: 1 1 100%; min-width: 0; font-family: var(--mono, monospace); }
.cfg-value-wrap .cfg-value[readonly] { background: var(--surface-2); color: var(--text-3); }
.cfg-value-wrap textarea.cfg-value.cfg-masked { -webkit-text-security: disc; }
/* The editor note: a line of its own in the wrapping cluster. */
.cfg-editor-note { font-size: 11px; flex: 1 1 100%; min-width: 0; overflow-wrap: anywhere; }
.cfg-row .cfg-reveal,
.cfg-row .cfg-download { display: none; }
.cfg-row[data-hidden="1"][data-action="value"] .cfg-reveal,
.cfg-row[data-hidden="0"][data-set="1"] .cfg-download { display: inline-block; }
.cfg-row[data-mutability="immutable"][data-set="1"] .cfg-upload,
.cfg-row[data-action="keep"] .cfg-upload { display: none; }

.cfg-row .cfg-warn-clear,
.cfg-row .cfg-warn-delete,
.cfg-row .cfg-hint-first-write,
.cfg-row .cfg-hint-reveal { display: none; }
.cfg-row[data-visibility="visible"][data-hidden="1"][data-action="value"] .cfg-hint-reveal { display: block; font-size: 11px; }
.cfg-row[data-action="clear"] .cfg-warn-clear,
.cfg-row[data-action="delete"] .cfg-warn-delete { display: block; }
.cfg-row[data-mutability="immutable"][data-set="0"][data-action="value"] .cfg-hint-first-write { display: block; font-size: 11px; }

/* --- Badges (Phase 3 legacy `.b-<value>` aliases preserved) --- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 12px;
  background: var(--surface-2); color: var(--text-2); white-space: nowrap;
}
.badge .dot {
  width: 6px; height: 6px; border-radius: 50%; display: inline-block;
  background: currentColor;
}

/* health-shaped badge values (workload / disk / ram badges render
   ``b-{{ value }}`` and may land on these) */
.badge.b-healthy   { background: var(--c-healthy-bg);   color: var(--c-healthy); }
.badge.b-degraded  { background: var(--c-degraded-bg);  color: var(--c-degraded); }
.badge.b-offline   { background: var(--c-offline-bg);   color: var(--c-offline); }
.badge.b-unknown   { background: var(--c-unknown-bg);   color: var(--c-unknown); }

/* criticality (Phase 3 legacy) */
.badge.b-critical  { background: var(--c-crit-bg);      color: var(--c-crit); }
.badge.b-high      { background: var(--c-high-bg);      color: var(--c-high); }
.badge.b-medium    { background: var(--c-med-bg);       color: var(--c-med); }
.badge.b-low       { background: var(--c-low-bg);       color: var(--c-low); }

/* rollout_verdict (Phase 3 legacy) */
.badge.b-rolling-normally       { background: var(--c-rolling-bg);   color: var(--c-rolling); }
.badge.b-rollout-stuck          { background: var(--c-stuck-bg);     color: var(--c-stuck); }
.badge.b-config-drift           { background: var(--c-drift-bg);     color: var(--c-drift); }

/* warm-progress (D-017 A-2 — async pre-warm observability) */
.badge.b-warming { background: var(--c-rolling-bg);  color: var(--c-rolling); }
.badge.b-pending { background: var(--c-unknown-bg);  color: var(--c-unknown); }
.badge.b-failed  { background: var(--c-stuck-bg);    color: var(--c-stuck); }

/* Э3 / D-026 — control-plane alarm on an inventory row. Not part of any
   value-enum palette on purpose: it is not a value of an axis, it is a node
   saying it cannot verify the panel at all, and it must not be read as one
   more shade of «rollout». Sits next to the node NAME, so it is deliberately
   small and high-contrast rather than large: an operator scanning N rows has
   to catch it, not be blocked by it. */
.badge.b-error,
.node-control-plane-alarm {
  background: var(--c-offline-bg);
  color: var(--c-offline);
  font-weight: 600;
}

/* The fleet-level twin of the badge above. The failure is frontal — one
   panel key for the whole fleet — so the banner is what turns N identical
   row badges into one readable fault. Full-width, above the tiles, and
   rendered only when the count is non-zero. */
.summary-banner {
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 12px;
  font-size: 12.5px;
  line-height: 1.5;
  border: 1px solid var(--c-offline);
  background: var(--c-offline-bg);
  color: var(--text-1);
}
.summary-banner code { font-size: 11.5px; }

/* Operator-readable gloss printed under a machine reason code (Э3 / D-026).
   Deliberately quiet: the identifier is the value, this is what it MEANS. */
.reason-gloss {
  margin-top: 2px;
  font-size: 11.5px;
  line-height: 1.4;
}

/* redundancy (Phase 3 legacy) */
.badge.b-ok    { background: var(--c-ok-bg);    color: var(--c-ok); }
.badge.b-spof  { background: var(--c-spof-bg);  color: var(--c-spof); }

/* resource_usage (D-008 Amendment A-2 — disk_usage / ram_usage). Reuses the
   shared `.b-<value>` palette: `ok` (green) / `critical` (red) / `unknown`
   (grey) already defined above; `warning` (amber) is the only missing value,
   mapped to the degraded amber pair for visual parity with rollout drift. */
.badge.b-warning { background: var(--c-degraded-bg); color: var(--c-degraded); }

/* telemetry_freshness (Phase 3 legacy) */
.badge.b-fresh { background: var(--c-healthy-bg);  color: var(--c-healthy); }
.badge.b-stale { background: var(--c-degraded-bg); color: var(--c-degraded); }
.badge.b-lost  { background: var(--c-offline-bg);  color: var(--c-offline); }

/* `n-a` enum value renders as class `b-n-a` (Jinja drops dashes verbatim);
   we keep `b-na` for literal "na" usage and add `b-n-a` alias for enum. */
.badge.b-na, .badge.b-n-a { background: var(--surface-2);  color: var(--text-3); }

/* ignored (D-004:26-30 — operator decision axis). Muted orange-grey: the
   node is deliberately excluded from redundancy math and from the main
   inventory list, which is a decision, not an incident. `tabindex="0"` on
   the badge makes the reason tooltip keyboard-reachable. */
.badge.b-ignored { background: var(--c-ignored-bg); color: var(--c-ignored); cursor: help; }
.badge.b-ignored:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- Phase 6 semantic enum→class normalization (side-task #3) --- */

/* severity-impact-{minor,major,critical} (operator-private free-form
   text, but operators may use these informal tags). */
.severity-impact-minor    { background: var(--c-low-bg);  color: var(--c-low);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-impact-major    { background: var(--c-high-bg); color: var(--c-high); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-impact-critical { background: var(--c-crit-bg); color: var(--c-crit); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* severity-criticality-* */
.severity-criticality-low      { background: var(--c-low-bg);  color: var(--c-low);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-criticality-medium   { background: var(--c-med-bg);  color: var(--c-med);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-criticality-high     { background: var(--c-high-bg); color: var(--c-high); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-criticality-critical { background: var(--c-crit-bg); color: var(--c-crit); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* severity-lifecycle-* (D-002 enum: new, bootstrapped, fleet-ready, failed, retired) */
.severity-lifecycle-new          { background: var(--surface-2);     color: var(--text-2);    border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-lifecycle-bootstrapped { background: var(--c-rolling-bg);  color: var(--c-rolling); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-lifecycle-fleet-ready  { background: var(--c-healthy-bg);  color: var(--c-healthy); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-lifecycle-failed       { background: var(--c-offline-bg);  color: var(--c-offline); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
/* retired — muted grey-red (repainted 260802: was the flat neutral
   `--surface-3` / `--text-3` pair, which read as "no state at all"; the
   tombstone deserves a recognisable tone, but a desaturated one — a retired
   node is an operator decision, not an outage, so it must not compete with
   `--c-offline` red in the same row). */
.severity-lifecycle-retired      { background: var(--c-retired-bg);   color: var(--c-retired); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* severity-rollout-* (closed enum from compute_rollout_verdict) */
.severity-rollout-rolling-normally       { background: var(--c-rolling-bg);   color: var(--c-rolling);   border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-rollout-rollout-stuck          { background: var(--c-stuck-bg);     color: var(--c-stuck);     border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-rollout-config-drift           { background: var(--c-drift-bg);     color: var(--c-drift);     border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-rollout-awaiting-deploy        { background: var(--accent-bg);      color: var(--accent);      border: 1px dashed var(--accent); border-radius: 12px; padding: 1px 7px; font-size: 11.5px; font-weight: 600; }
.severity-rollout-n-a                    { background: var(--surface-2);      color: var(--text-3);      border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* severity-redundancy-* */
.severity-redundancy-ok   { background: var(--c-ok-bg);    color: var(--c-ok);     border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-redundancy-spof { background: var(--c-spof-bg);  color: var(--c-spof);   border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-redundancy-n-a  { background: var(--surface-2);  color: var(--text-3);   border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* severity-freshness-* (telemetry) */
.severity-freshness-fresh { background: var(--c-healthy-bg);  color: var(--c-healthy);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-freshness-stale { background: var(--c-degraded-bg); color: var(--c-degraded); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.severity-freshness-lost  { background: var(--c-offline-bg);  color: var(--c-offline);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* --- Empty state --- */
.empty {
  padding: 60px 20px; text-align: center; color: var(--text-3);
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
}

/* --- Tooltip helper (CSS-only) — used for derived-field explanations --- */
.tooltip-anchor {
  position: relative; display: inline-block; cursor: help;
  border-bottom: 1px dotted var(--text-3);
}
.tooltip-anchor .tooltip-body {
  position: absolute; left: 0; top: calc(100% + 4px);
  background: var(--text); color: #fff;
  padding: 6px 10px; border-radius: 6px; font-size: 11px;
  white-space: nowrap; z-index: 70;
  opacity: 0; pointer-events: none; transition: opacity 0.12s;
}
.tooltip-anchor:hover .tooltip-body {
  opacity: 1; pointer-events: auto;
}

/* --- Phase 6 Implementer #3 / G.1.b — Modals (native <dialog> + legacy <div>) ---
   Two coexisting shells:
     1) Legacy `.modal-overlay > .modal` (Phase 6 div-based modals — Add-node,
        set-ref, retire, bulkRefModal). Keep working until full migration.
     2) Native `dialog.modal` (G.1.b) — browser focus-trap, ESC close, top-layer.
        `.modal-overlay` rule below skips dialog (`:not(dialog)`).
*/
.modal-overlay:not(dialog) {
  position: fixed; top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex; align-items: center; justify-content: center;
  z-index: 100;
}
.modal {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 0;
  width: min(560px, 95vw); max-width: 95vw; max-height: 90vh;
  display: flex; flex-direction: column;
  box-shadow: 0 20px 50px rgba(0,0,0,0.25);
}
/* Native dialog.modal — hidden until showModal()/show(); when [open] match the
   layout of legacy <div> modals (flex column, capped width). The browser
   handles focus-trap, ESC, top-layer rendering, inert background.
   260511-03 C2 — explicit ``max-width: 95vw`` so the dialog NEVER exceeds
   viewport width on mobile (375px stress confirmed _add_existing_node_modal
   overflowed without this; UA dialog default ``max-width: -webkit-fill-
   available`` is unreliable across engines). */
dialog.modal {
  display: none;
  /* Override UA dialog defaults for consistent shell. */
  margin: auto;
  max-width: 95vw;
  box-sizing: border-box;
  border: 1px solid var(--border);
  padding: 0;
}
dialog.modal[open] {
  display: flex;
}
dialog.modal::backdrop {
  background: rgba(0, 0, 0, 0.45);
}
.modal-head {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; border-bottom: 1px solid var(--border);
}
.modal-head .panel-close {
  margin-left: auto; background: transparent; border: none;
  font-size: 22px; line-height: 1; cursor: pointer; color: var(--text-3);
}
.modal-head .panel-close:hover { color: var(--text); }
.modal-body {
  padding: 18px; overflow-y: auto;
}
.modal-result {
  margin-top: 14px; padding: 10px 12px; border-radius: 6px; font-size: 12.5px;
}
.modal-result.ok  { background: var(--c-healthy-bg); color: var(--c-healthy); }
/* The outcome the request did not fail and did not succeed at: a retention
   pass that refused fail-closed, a sweep that stopped mid-mirror, a sweep
   that finished and reclaimed nothing. Green would tell the operator to
   stop looking. */
.modal-result.warn { background: var(--c-degraded-bg); color: var(--c-degraded); }
/* Not an outcome yet — a pass still in flight. It wore the success colour
   for as long as it ran, which reads as "done" the moment it is glanced at. */
.modal-result.pending { background: var(--c-unknown-bg); color: var(--c-unknown); }
.modal-result.err { background: var(--c-offline-bg); color: var(--c-offline); }
.modal-result pre {
  background: rgba(255,255,255,0.4); border: 1px solid var(--border);
  padding: 8px; border-radius: 6px; overflow-x: auto; font-size: 11.5px;
  white-space: pre-wrap; word-break: break-all;
}
.visible-once {
  background: var(--c-stuck-bg); color: var(--c-stuck);
  border: 1px dashed var(--c-stuck);
  padding: 8px; border-radius: 6px; font-family: monospace;
  font-size: 12px; word-break: break-all; user-select: all;
}

/* --- RPC results table (207 Multi-Status display) --- */
.rpc-results {
  margin: 14px 0; padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.rpc-results-head {
  display: flex; align-items: center; gap: 12px;
  margin-bottom: 8px; font-size: 12.5px;
}
.rpc-results-summary {
  display: flex; gap: 10px; margin-bottom: 8px; font-size: 12px;
}
.rpc-results-table {
  width: 100%; border-collapse: collapse; font-size: 12px;
}
.rpc-results-table th, .rpc-results-table td {
  text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.rpc-results-table th { font-weight: 600; color: var(--text-2); }

/* --- Registry management UI (Phase 6) --- */
.registry-section { margin-bottom: 28px; }
.registry-section .section-title { font-weight: 600; margin-bottom: 8px; }
.registry-section .registry-table {
  width: 100%; border-collapse: collapse; font-size: 12.5px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 8px;
}
.registry-section .registry-table th,
.registry-section .registry-table td {
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border);
}
.registry-section .registry-table th {
  font-weight: 600; color: var(--text-2); background: var(--surface-2);
}
.promote-mode-toggle {
  display: inline-flex; gap: 0;
  border: 1px solid var(--border); border-radius: 6px; overflow: hidden;
}
.promote-mode-toggle button {
  background: var(--surface); border: none; padding: 4px 10px;
  font-size: 11.5px; cursor: pointer; color: var(--text-2);
}
.promote-mode-toggle button.is-active {
  background: var(--accent); color: #fff;
}
.promote-mode-toggle button:disabled {
  opacity: 0.5; cursor: not-allowed;
}

/* --- Bootstrap-progress badges (Phase 7 Wave 3b — D-012 Amendment A-1 (viii))
       Pragmatic mapping from lifecycle_state + role (no audit-event read)
       — see docs/architecture/decisions/D-012-installer-first-boot.md (viii).
   G.1.n — replaced hardcoded hex with CSS-vars (semantic tokens). */
.bootstrap-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 7px;
  font-size: 11px;
  font-weight: 600;
  border-radius: 10px;
  border: 1px solid transparent;
  vertical-align: middle;
}
.bootstrap-in-flight {
  background: var(--c-rolling-bg);
  color: var(--c-rolling);
  border-color: var(--c-rolling);
}
.bootstrap-succeeded {
  background: var(--c-healthy-bg);
  color: var(--c-healthy);
  border-color: var(--c-healthy);
}
.bootstrap-failed {
  background: var(--c-offline-bg);
  color: var(--c-offline);
  border-color: var(--c-offline);
}

/* --- Container categories (260510-02 Decision 3 — three-category
       distinction; PROJ-UX W4-UI1: the container name in the «▸ контейнеры»
       fold of a project row carries ``container-<category>``). Mate /
       g9s-system / project are told apart by accent colour so the operator
       sees which containers are project payload (opaque-transit) vs which
       are g9s-managed. */
.container-mate {
  border-left-color: #4a8ed8;     /* mate accent — blue */
  background: rgba(74, 142, 216, 0.06);
}
.container-g9s-system {
  border-left-color: #8a8a8a;     /* g9s-system — neutral grey */
  background: rgba(138, 138, 138, 0.04);
}
.container-project {
  border-left-color: #2b7;        /* project — accent green (matches brand) */
  background: rgba(43, 187, 119, 0.05);
}

/* --- Responsive (G.1.h-i — mobile top-nav + table overflow) --- */
@media (max-width: 768px) {
  .summary-strip { grid-template-columns: repeat(2, 1fr); }
  .side-panel { width: 100vw; }
  .filter-row { gap: 6px; }
  .scope-switcher { padding: 3px 6px; }
  .scope-switcher label { display: none; }
}

/* G.1.h — top-nav mobile collapse. Hamburger toggle on narrow viewports;
   Alpine `navOpen` state sets `.is-open` class on header.topbar. */
.nav-toggle {
  display: none;
  background: transparent; border: 1px solid var(--border);
  border-radius: 6px; padding: 4px 10px;
  font-size: 16px; line-height: 1; color: var(--text-2);
}
.nav-toggle:hover { background: var(--surface-2); color: var(--text); }
@media (max-width: 768px) {
  header.topbar { flex-wrap: wrap; }
  header.topbar nav {
    order: 99;
    display: none;
    width: 100%;
    flex-direction: column;
    gap: 6px;
    padding: 8px 0 4px;
    border-top: 1px solid var(--border);
    margin-top: 8px;
  }
  header.topbar.is-nav-open nav { display: flex; }
  header.topbar nav a { padding: 6px 4px; }
  .nav-toggle { display: inline-block; }
}

/* G.1.i — table-scroll wrapper. Inventory table can overflow on narrow
   viewports; wrap в `.table-scroll` для horizontal-scroll фолбэк.

   260512-02 rc6 — overflow-x: auto scoped к narrow viewports only.
   На desktop `overflow` остаётся `visible` so absolute-positioned
   `.action-menu` dropdown (per-row «...» button) can spill out the
   table cell vertically без clipping (CSS spec: `overflow-x: auto`
   с `overflow-y: visible` computes overflow-y к `auto`, clipping
   children — moved за пределы media query чтобы desktop rendering
   stay unaffected). */
.table-scroll {
  -webkit-overflow-scrolling: touch;
}
@media (max-width: 768px) {
  .table-scroll {
    overflow-x: auto;
  }
}

/* --- G.1.a Toast manager (centralized — replaces inline <style> blocks
       from access_keys.html / admin_users.html / namespaces.html).
       Stack vertical-bottom-right; auto-dismiss timer paused on hover.
       Q2=A hybrid: info/success auto-dismiss; error/warning/secret persist. */
.toast-stack {
  position: fixed;
  bottom: 18px;
  right: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 1000;
  max-width: calc(100vw - 36px);
}
.toast {
  background: var(--surface);
  color: var(--text);
  padding: 12px 14px;
  border-radius: 8px;
  box-shadow: var(--shadow-md);
  border-left: 4px solid var(--text-3);
  min-width: 280px;
  max-width: 480px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  animation: toast-slide-in 0.18s ease-out;
}
@keyframes toast-slide-in {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: translateX(0); }
}
.toast.toast-info     { border-left-color: var(--accent);    background: var(--surface); }
.toast.toast-success  { border-left-color: var(--c-healthy); background: var(--surface); }
.toast.toast-error    { border-left-color: var(--c-offline); background: var(--surface); }
.toast.toast-warning  { border-left-color: var(--c-degraded); background: var(--surface); }
.toast.toast-secret   { border-left-color: var(--c-stuck);   background: var(--surface); }
.toast .toast-title {
  font-weight: 600;
  font-size: 12.5px;
  color: var(--text);
}
.toast.toast-success .toast-title { color: var(--c-healthy); }
.toast.toast-error   .toast-title { color: var(--c-offline); }
.toast.toast-warning .toast-title { color: var(--c-degraded); }
.toast.toast-secret  .toast-title { color: var(--c-stuck); }
.toast .toast-body {
  font-size: 12px;
  color: var(--text-2);
  word-break: break-word;
  white-space: pre-line;  /* refusal specifics (_detailText) come one per line */
}
.toast .toast-body code {
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 11.5px; background: var(--surface-2);
  padding: 2px 6px; border-radius: 4px;
  display: inline-block;
  user-select: all;
  word-break: break-all;
}
.toast .toast-secret-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 4px;
}
.toast .toast-secret-row code {
  flex: 1; min-width: 0; padding: 6px 10px;
  background: var(--surface-2); border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 12px; user-select: all; word-break: break-all;
}
.toast .toast-actions {
  display: flex; gap: 6px; align-items: center;
  margin-top: 4px;
}
.toast .toast-close {
  margin-left: auto;
  background: transparent; border: none; cursor: pointer;
  color: var(--text-3); font-size: 16px; line-height: 1;
  padding: 0 6px; border-radius: 4px;
}
.toast .toast-close:hover { background: var(--surface-2); color: var(--text); }

/* --- G.1.c ConfirmDialog component shell. Native <dialog>; styled like
       legacy modals but compact. */
dialog.confirm-dialog {
  display: none;
  width: min(440px, 92vw);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0;
  background: var(--surface);
}
dialog.confirm-dialog[open] { display: flex; flex-direction: column; }
dialog.confirm-dialog::backdrop { background: rgba(0, 0, 0, 0.45); }
dialog.confirm-dialog .confirm-head {
  padding: 14px 18px; border-bottom: 1px solid var(--border);
  font-weight: 600; font-size: 14px; color: var(--text);
}
dialog.confirm-dialog .confirm-body {
  padding: 14px 18px; font-size: 13px; color: var(--text-2);
  white-space: pre-wrap; word-break: break-word;
}
dialog.confirm-dialog .confirm-body strong { color: var(--text); }
dialog.confirm-dialog .confirm-type-row {
  padding: 0 18px 12px; font-size: 12px; color: var(--text-2);
}
dialog.confirm-dialog .confirm-type-row input {
  display: block; margin-top: 4px; width: 100%;
  border: 1px solid var(--border); background: var(--surface);
  border-radius: 6px; padding: 6px 10px; font-size: 12.5px;
  outline: none;
}
dialog.confirm-dialog .confirm-type-row input:focus {
  border-color: var(--accent);
}
dialog.confirm-dialog .confirm-actions {
  padding: 12px 18px; border-top: 1px solid var(--border);
  display: flex; gap: 8px; justify-content: flex-end;
}

/* --- G.1.d focus-visible global a11y baseline. --- */
.btn:focus-visible,
.action-menu-item:focus-visible,
.action-menu-button:focus-visible,
.filter-popover-button:focus-visible,
.retired-tab .tab:focus-visible,
.bulk-action-bar .bulk-btn:focus-visible,
.bulk-action-bar .x-clear:focus-visible,
table.inv tbody tr:focus-visible,
.row-checkbox:focus-visible,
.nav-toggle:focus-visible,
.toast .toast-close:focus-visible,
dialog.modal:focus-visible,
dialog.confirm-dialog:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
header.topbar nav a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* --- G.1.e skip-link a11y. Visually hidden until keyboard focus reveals it. */
.skip-link {
  position: absolute;
  top: -40px;
  left: 8px;
  background: var(--accent);
  color: #fff;
  padding: 8px 14px;
  border-radius: 0 0 6px 6px;
  font-weight: 600;
  font-size: 12.5px;
  z-index: 1100;
  text-decoration: none;
  transition: top 0.15s ease-out;
}
.skip-link:focus,
.skip-link:focus-visible {
  top: 0;
  outline: 2px solid var(--text);
  outline-offset: -2px;
  text-decoration: none;
}

/* --- G.1.g htmx loading indicator (inline spinner). Visible only while
       htmx requests are in flight; hidden otherwise. */
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline-block; }
.htmx-request.htmx-indicator { display: inline-block; }
.spinner {
  width: 14px;
  height: 14px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
  display: inline-block;
  vertical-align: middle;
}
@keyframes spin {
  to { transform: rotate(360deg); }
}

/* --- G.1.j Detail page-header grouping. Title + status-cluster grid. */
.detail-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.detail-header h1 { margin: 0; }
.detail-header .detail-status-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.detail-header .detail-status-cluster .sep {
  color: var(--text-3);
  font-size: 11px;
}

/* G.1.k — destructive ghost variant (used for retire / cancel-bootstrap). */
.btn.btn-ghost-destructive {
  background: transparent;
  border-color: var(--c-offline);
  color: var(--c-offline);
}
.btn.btn-ghost-destructive:hover {
  background: var(--c-offline-bg);
}
.btn.btn-ghost-destructive.disabled {
  border-color: var(--border);
  color: var(--text-3);
  background: var(--surface-2);
}

/* ============================================================================
 * 260511-01 — Phase 7 main UI overhaul: registry restructure (3-zone) +
 *             mate-as-entity (D-015) + compose preview UX.
 * ============================================================================ */

/* --- Registry zones (Designer R1+R3) --- */
.registry-zone {
  margin: 0 0 32px;
  padding: 18px 20px 20px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-sm);
}
.registry-zone.primary-zone {
  border-color: var(--accent);
  box-shadow: var(--shadow-md);
}
.registry-zone-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin-bottom: 14px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}
.registry-zone-head .zone-title {
  font-size: 16px;
  font-weight: 700;
  margin: 0;
  color: var(--text);
  flex: 0 0 auto;
}
.registry-zone-head .zone-sub {
  color: var(--text-3);
  font-size: 12px;
  flex: 1 1 240px;
}
.registry-zone-head .btn {
  margin-left: auto;
}
.registry-zone .zone-subsection {
  margin: 0 0 16px;
}
.registry-zone .zone-subsection:last-child {
  margin-bottom: 0;
}
.registry-zone .advanced-section {
  margin-top: 14px;
  padding: 8px 10px;
  border: 1px dashed var(--border);
  border-radius: 6px;
  background: var(--surface-2);
}
.registry-zone .advanced-section > summary {
  cursor: pointer;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-2);
  list-style: revert;
}
.registry-zone .advanced-section[open] > summary {
  margin-bottom: 8px;
}

/* --- Activity log table (Zone B) — promote button dominance --- */
.registry-activity-log .activity-log-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.registry-activity-log .activity-log-table th,
.registry-activity-log .activity-log-table td {
  text-align: left;
  padding: 8px 10px;
  border-bottom: 1px solid var(--border);
}
.registry-activity-log .activity-log-table th {
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface-2);
}
.registry-activity-log .activity-log-table .col-actions {
  text-align: right;
  white-space: nowrap;
  width: 1%;
}
/* Stabilise column widths so every <tbody> aligns (single-table layout). */
.registry-activity-log .activity-log-table .registry-tag-select {
  max-width: 100%;
}
.registry-activity-log .btn-promote {
  font-size: 11.5px;
  padding: 4px 10px;
}
.registry-activity-log .btn-copy-digest {
  font-size: 13px;
  padding: 2px 8px;
  margin-left: 4px;
  color: var(--text-3);
  border-color: transparent;
}
.registry-activity-log .btn-copy-digest:hover {
  color: var(--text);
  background: var(--surface-2);
}
.registry-activity-log .digest-cell {
  color: var(--text-3);
  font-size: 11.5px;
}
.registry-activity-log .activity-row-mate {
  background: var(--accent-bg);
}
.repo-kind-badge {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  border-radius: 6px;
}
.repo-kind-badge.repo-kind-mate {
  background: var(--c-rolling-bg);
  color: var(--c-rolling);
  border: 1px solid var(--c-rolling);
}

/* --- Image-group accordion (Zone B / 260602-01 batch 3 — single table) ---
   All entries share ONE <table class="activity-log-table">; each entry is its
   own <tbody> so columns align by construction. Groups carry Alpine collapse
   state on the <tbody class="image-group">. */

/* Hide collapsed child rows before Alpine boots (x-cloak on x-show rows). */
.registry-activity-log [x-cloak] {
  display: none !important;
}

/* Group header row — subtle accent tint distinguishing it from single rows. */
.registry-activity-log .image-group-head {
  cursor: pointer;
  background: var(--accent-bg);
}
.registry-activity-log .image-group-head:hover {
  background: var(--surface-2);
}
.registry-activity-log .image-group-head:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.registry-activity-log .image-group-arrow {
  display: inline-block;
  width: 1em;
  margin-right: 4px;
  color: var(--accent);
  font-size: 10px;
  vertical-align: middle;
}
.registry-activity-log .image-group-head-key code {
  font-size: 12.5px;
  font-weight: 600;
}
.registry-activity-log .image-group-head-count {
  color: var(--accent);
  font-weight: 600;
  white-space: nowrap;
}
.registry-activity-log .image-group-head-digest {
  color: var(--text-3);
}
/* Date cell uses the SAME typography as the single-repo date (NOT muted):
   inherit the default near-black cell color + match the default cell font-size
   so grouped + single dates render identically (operator point #2). */
.registry-activity-log .image-group-head-date code {
  font-size: 12.5px;
}
/* used_by badges — always-visible sub-line spanning all columns. */
.registry-activity-log .image-group-usedby td {
  color: var(--text-3);
  font-size: 11px;
  padding: 4px 10px 6px 28px;
  background: var(--accent-bg);
}
.registry-activity-log .image-group-usedby .usedby-project {
  font-size: 10.5px;
}
/* Child repo rows — light indent under the group header. */
.registry-activity-log .image-group-child .col-repo {
  padding-left: 28px;
}
.registry-activity-log .image-group-child .col-repo code {
  color: var(--text-2);
}

/* --- Project card grid (Zone C / Designer Top-5 #1) --- */
.project-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 14px;
}
.project-card {
  padding: 14px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.project-card-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
.project-card-title {
  font-size: 14px;
  margin: 0;
  font-weight: 600;
}
.project-card-title code {
  font-size: 13px;
}
/* 260602-01 — image-group badge next to the project title (Zone C). */
.project-image-group-badge {
  margin-left: 6px;
  font-size: 10.5px;
  font-weight: 500;
  vertical-align: middle;
}
/* 260602-01 — light image-group subheading spanning the full grid row. */
.project-group-subhead {
  grid-column: 1 / -1;
  font-size: 11.5px;
  color: var(--text-2);
  padding: 4px 2px 0 2px;
  border-top: 1px solid var(--border);
}
.project-group-subhead:first-child {
  border-top: none;
}
.project-group-subhead code {
  font-size: 11.5px;
}
.project-card-meta {
  font-size: 12px;
  color: var(--text-2);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.project-card-meta .project-meta-row {
  display: flex;
  gap: 6px;
  align-items: baseline;
  flex-wrap: wrap;
}
.project-pins {
  font-size: 11.5px;
  background: var(--surface-2);
  padding: 1px 6px;
  border-radius: 3px;
  word-break: break-all;
}
.project-card-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  border-top: 1px solid var(--border);
  padding-top: 8px;
}
.template-editor-panel {
  margin-top: 8px;
  padding: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
}
@media (max-width: 768px) {
  .project-card-grid {
    grid-template-columns: 1fr;
  }
}

/* The two version pickers of «Проекты на узле» (agent / panel rows,
   PROJ-UX W4-UI1; the runtime cards they lived on are gone). */
.mate-version-select {
  min-width: min(220px, 100%);
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.mate-version-stale {
  color: var(--c-degraded);
  border-bottom: 1px dashed var(--c-degraded);
}

.panel-version-select {
  min-width: min(220px, 100%);
  padding: 4px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  font-size: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.panel-version-stale {
  color: var(--c-degraded);
  border-bottom: 1px dashed var(--c-degraded);
}

/* --- D-017 (ii) — tag_pattern_regex row. --- */
.tag-pattern-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.tag-pattern-regex {
  padding: 3px 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
}

/* Inventory list — Mate ver column. */
.mate-ver-cell code {
  font-size: 11.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* --- Compose preview modal --- */
.compose-preview-modal {
  width: min(820px, 94vw);
}
.preview-meta-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}
.preview-meta-tile {
  padding: 8px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.preview-meta-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text-3);
  margin-bottom: 4px;
}
.preview-meta-value {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.preview-svc-chip,
.preview-image-chip {
  font-size: 11.5px;
  background: var(--surface);
  padding: 1px 6px;
  border-radius: 3px;
  border: 1px solid var(--border);
}
/* M6c/Блок 2 — the delivery mode next to the ref it belongs to. Colour is
   NOT severity: `direct` is a legitimate mode, not a warning, so it reads as
   a distinct route rather than as a problem. */
.preview-image-line {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 8px 4px 0;
}
.preview-delivery-chip {
  font-size: 10.5px;
  padding: 1px 6px;
  border-radius: 10px;
  border: 1px solid var(--border);
  white-space: nowrap;
}
.preview-delivery-proxy {
  color: var(--text-2);
}
.preview-delivery-direct {
  color: var(--text-1);
  border-style: dashed;
}
.preview-blob-head {
  font-size: 12px;
  color: var(--text-2);
  margin-bottom: 6px;
}
.preview-blob {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 10px;
  font-size: 11.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  overflow: auto;
  max-height: 50vh;
  white-space: pre;
  margin: 0;
}

/* --- Mate promote modal --- */
.mate-promote-modal {
  width: min(620px, 94vw);
}
.promote-summary-row {
  display: flex;
  gap: 16px;
  margin-bottom: 12px;
  padding: 8px 10px;
  background: var(--surface-2);
  border-radius: 6px;
  font-size: 12px;
}
.promote-summary-row .muted {
  font-size: 11px;
  margin-right: 4px;
}
.promote-node-list {
  max-height: 240px;
  overflow-y: auto;
  padding: 6px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.promote-node-row {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 4px 6px;
  font-size: 12px;
  cursor: pointer;
  border-radius: 4px;
}
.promote-node-row:hover {
  background: var(--surface-2);
}
.promote-node-caption {
  flex: 1;
}
.promote-result-list {
  margin: 6px 0 0;
  padding: 0 0 0 18px;
  font-size: 11.5px;
}
.promote-result-list li {
  margin-bottom: 2px;
  display: flex;
  align-items: center;
  gap: 8px;
}

/* === D-016 Wave 3.3 — multi-project + observer mode + project-axis ===== */

/* Observer-mode badge — surfaces brownfield adoption state (mate-only,
 * no operator projects yet). Orange/warn palette mirrors
 * `.mate-version-stale` (drift hint — not critical).
 *
 * 260511-03 A1+B5 — promoted to canonical `.badge.b-observer` family
 * (parallels `.b-degraded` / `.b-stale` shape). `.observer-mode-badge`
 * legacy class kept as alias so existing markup keeps working. */
.badge.b-observer {
  background: var(--c-degraded-bg);
  color: var(--c-degraded);
  cursor: help;
}
.observer-mode-badge {
  display: inline-block;
  padding: 2px 8px;
  background: var(--c-degraded-bg);
  color: var(--c-degraded);
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  margin-left: 6px;
}
/* 260511-03 A2 — explicit focus outline для tabindex'd badge so keyboard /
 * screen-reader users can reach the tooltip surface. Global `:focus-visible`
 * baseline only covers `.btn` / interactive cells; badge needs опт-in. */
.badge.b-observer:focus-visible,
.observer-mode-badge:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* «Проекты на узле» — the node page's one project section (PROJ-UX
 * W4-UI1): one row per project (panel stack, agent, operator projects);
 * the agent's row keeps the pale-blue tint of the panel-managed axis. */
.multi-project-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  background: var(--surface);
  margin-bottom: 18px;
}
.multi-project-card .section-title {
  font-weight: 700;
  margin-bottom: 8px;
}

/* Per-project row within the multi-project card. Stacked layout (header
 * + meta line) so each project reads as an independent unit even at
 * narrow widths. */
.node-project-row {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  margin-bottom: 8px;
}
.node-project-row:last-of-type {
  margin-bottom: 0;
}
.node-project-row-head {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
/* 260511-03 B2 — long project_name (operator stress-test naming) wrapped
 * mid-word and pushed the axis-badge to a third line on mobile. Allow
 * break at ANY character inside the strong title; the flex container
 * (`.node-project-row-head`) needs `min-width: 0` chains to actually
 * collapse instead of forcing horizontal overflow. */
.node-project-row-head strong {
  overflow-wrap: anywhere;
  word-break: break-word;
  min-width: 0;
}

/* Mate-project row — panel-managed; pale-blue tint matches mate-runtime
 * card's `--c-rolling-bg` family so the panel-axis surface is visually
 * coherent across cards. */
.node-project-mate {
  background: var(--c-rolling-bg);
  border-color: var(--c-rolling);
}

/* Operator-project row — neutral surface (mirrors `.container-project`
 * default-tone palette so the operator axis reads as the «application
 * workload» surface). */
.node-project-operator {
  background: var(--surface-2);
  border-color: var(--border);
}

/* Writer-axis badge — labels each row's authority class (panel vs
 * operator). Compact uppercase pill. */
.project-axis-badge {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 10px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 700;
  vertical-align: middle;
}
.project-axis-badge.axis-panel {
  background: var(--c-rolling-bg);
  color: var(--c-rolling);
  border: 1px solid var(--c-rolling);
}
.project-axis-badge.axis-operator {
  background: var(--surface);
  color: var(--text-2);
  border: 1px solid var(--border-strong);
}

/* Destructive ghost button — used by «Удалить проект» (operator-project
 * removal). Aligned with the existing `.btn-danger` palette but with
 * ghost-style outline (matches `.btn-ghost` width / radius). */
.btn-ghost-destructive {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--danger);
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.btn-ghost-destructive:hover:not(:disabled),
.btn-ghost-destructive:focus-visible:not(:disabled) {
  background: var(--danger-bg);
}
.btn-ghost-destructive:disabled,
.btn-ghost-destructive.disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Monospace ref renderer — sha256 hashes shown в multi-project / mate
 * cards. Subdued colour because the hash itself is rarely interesting
 * standalone (operator scans for drift / version change, not exact value). */
.mono-ref {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11.5px;
  color: var(--text-2);
}

/* --- 260513-01 — paired compose+config refs одной строкой через `/`.
 * Shared shape для inventory list + the node page's project rows
 * (uniform UI per operator's spec).
 * `.ref-display` = inline cluster of `<label> declared / applied [⚠]`.
 * `.ref-display-label` = small caption «compose» / «config».
 * `.ref-sep` = visual `/` separator.
 * `.ref-null` = muted `—` placeholder for NULL refs.
 * `.ref-divergent` = highlight `applied` code когда applied ≠ declared
 *   (reuses `--c-degraded` palette analog `.mate-version-stale`).
 * `.ref-divergent-marker` = ⚠ glyph after divergent ref. */
.ref-display {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-right: 10px;
  white-space: nowrap;
  vertical-align: middle;
}
.ref-display-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-3);
  font-weight: 600;
  margin-right: 2px;
}
.ref-sep {
  color: var(--text-3);
  font-size: 11.5px;
  margin: 0 1px;
}
.ref-null {
  color: var(--text-3);
  font-size: 11.5px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.ref-divergent {
  color: var(--c-degraded);
  border-bottom: 1px dashed var(--c-degraded);
}
.ref-divergent-marker {
  color: var(--c-degraded);
  font-size: 11px;
  margin-left: 2px;
}
/* Migration 0027 (session-ADR M5d) — the semver tag of a project's
 * canonical image, rendered NEXT TO the truncated ref, never instead of
 * it. Deliberately quiet (no accent colour, no border): the tag is the
 * string an operator reads, but the ref is what the system decides on,
 * and a louder tag would invite reading it as the authority. `title`
 * carries that caveat in words. The state tints below colour it by
 * agreement (declared vs applied), still without a border or accent. */
.image-tag-chip {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-2);
  background: var(--surface-2, rgba(127, 127, 127, 0.12));
  border-radius: 8px;
  padding: 0 5px;
  margin-left: 2px;
  white-space: nowrap;
  vertical-align: middle;
}
/* PROJ-UX W3 — the chip's state (``ui._image_versions_view``): agreement is
 * a calm green, a drift (declared ≠ applied, or a service being removed)
 * amber, a declared version without the agent's echo informational blue,
 * «версия неизвестна» neutral slate. Existing tokens only. */
.image-tag-chip.image-version-ok      { color: var(--c-healthy); background: var(--c-healthy-bg); }
.image-tag-chip.image-version-drift   { color: var(--c-drift);   background: var(--c-drift-bg); }
.image-tag-chip.image-version-pending { color: var(--c-rolling); background: var(--c-rolling-bg); }
.image-tag-chip.image-version-unknown { color: var(--c-unknown); background: var(--c-unknown-bg); }

/* D-027 A-2 — the DELIVERY chip beside the version chip: how the bytes of
 * this slot reach the node, read off the declared reference. Quieter than
 * the version chip it follows (no weight, no tint by default): the version
 * is what an operator reads first, and the delivery answers a second
 * question about the same string. Only two kinds are tinted, and each
 * because it is a condition rather than a shape — a tag form means nobody
 * has pinned what the node will pull, and a variable in the image position
 * means the panel does not read the value at all. «Через зеркало» and
 * «напрямую» are both fully pinned and need no colour; «доставка
 * неизвестна» stays neutral, like the version chip's own gap. Existing
 * tokens only. */
.delivery-chip {
  font-size: 10px;
  color: var(--text-2);
  background: var(--surface-2, rgba(127, 127, 127, 0.10));
  border-radius: 8px;
  padding: 0 5px;
  margin-left: 2px;
  white-space: nowrap;
  vertical-align: middle;
}
.delivery-chip.delivery-direct-tag  { color: var(--c-drift);   background: var(--c-drift-bg); }
.delivery-chip.delivery-passthrough { color: var(--c-unknown); background: var(--c-unknown-bg); }

/* Compact refs cell в table row — keep narrow + scrollable when both
 * pairs surface; mate-project только на inventory-list (operator-projects
 * + panel-project shown в multi-project card на detail page). */
.refs-cell {
  font-size: 11px;
  white-space: nowrap;
}

/* --- Post-Bug-F follow-up (2026-05-22) — apply-state surfaces -------------
 *
 * Mate emits typed ``ApplyState`` per project per piggyback; panel
 * derives rollout_verdict extension с two new values (``apply-failed``,
 * ``apply-stale``) per :func:`panel.derived.compute_apply_state_rollout_verdict`.
 * The per-project state is the API's row verdict (``.verdict-badge``
 * below); no per-project apply-status badge (operator decision 2026-10-14).
 *
 * Palette aligned с existing severity tokens: red for hard failure
 * (apply-failed), orange-red for silent drift (apply-stale).
 */

/* Aggregate rollout_verdict badge (inventory list / detail header). */
.badge.b-apply-failed   { background: var(--c-offline-bg);  color: var(--c-offline);  }
.badge.b-apply-stale    { background: var(--c-degraded-bg); color: var(--c-degraded); }

/* severity-rollout-* extension для new closed-enum members.
 * Mirror palette of badge classes above — operator visual signal
 * consistent across inventory list table + detail page. */
.severity-rollout-apply-failed {
  background: var(--c-offline-bg);
  color: var(--c-offline);
  border-radius: 12px;
  padding: 2px 8px;
  font-size: 11.5px;
  font-weight: 600;
}
.severity-rollout-apply-stale {
  background: var(--c-degraded-bg);
  color: var(--c-degraded);
  border-radius: 12px;
  padding: 2px 8px;
  font-size: 11.5px;
  font-weight: 600;
}


/* Per-container chip — informational snapshot mate-reported via
 * ``containers_json``. Compact pill с tooltip carrying full
 * (name, state, health) tuple. */
.node-project-containers {
  margin-top: 8px;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.badge.b-container-running    { background: var(--c-healthy-bg);  color: var(--c-healthy);  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
.badge.b-container-restarting { background: var(--c-degraded-bg); color: var(--c-degraded); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
.badge.b-container-exited     { background: var(--c-offline-bg);  color: var(--c-offline);  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
.badge.b-container-created    { background: var(--surface-2);     color: var(--text-3);     font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
.badge.b-container-paused     { background: var(--surface-3);     color: var(--text-2);     font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
.badge.b-container-dead       { background: var(--c-offline-bg);  color: var(--c-offline);  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
/* B-230 — a one-shot job that finished by design (exited 0 under restart
   policy no / on-failure): neutral, never the red of a dead service. */
.badge.b-container-finished   { background: var(--surface-2);     color: var(--text-2);     font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 6px; }
/* D-030 (vi) / B-228 — the API's row verdict (verdict.health) on the node
   page's project rows and the inventory list. The UI paints the API's
   health; it folds no verdict of its own. */
.badge.verdict-badge                  { font-size: 11px; padding: 1px 6px; margin-left: 4px; }
.badge.verdict-badge.verdict-health-healthy  { background: var(--c-healthy-bg);  color: var(--c-healthy);  }
.badge.verdict-badge.verdict-health-applying { background: var(--c-rolling-bg);  color: var(--c-rolling);  }
.badge.verdict-badge.verdict-health-failed   { background: var(--c-offline-bg);  color: var(--c-offline);  }
.badge.verdict-badge.verdict-health-degraded { background: var(--c-degraded-bg); color: var(--c-degraded); }
.badge.verdict-badge.verdict-health-unknown,
.badge.verdict-badge.verdict-unread          { background: var(--surface-2);     color: var(--text-3);     }

/* Healthcheck overlay — adds suffix indicator on running containers. */
.badge.b-container-running.health-unhealthy {
  border: 1px solid var(--c-offline);
}
.badge.b-container-running.health-starting {
  border: 1px dashed var(--c-degraded);
}

/* D-008 Amendment A-1 (2026-06-04) — workload_health derived axis badge.
 * `.b-workload-<value>` family; dashes render verbatim (`b-workload-no-workloads`).
 * Reuses the severity colour tokens (worst-of aggregate over containers). */
.badge.b-workload-healthy      { background: var(--c-healthy-bg);  color: var(--c-healthy);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.badge.b-workload-unhealthy    { background: var(--c-offline-bg);  color: var(--c-offline);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.badge.b-workload-starting     { background: var(--c-degraded-bg); color: var(--c-degraded); border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.badge.b-workload-unknown      { background: var(--c-unknown-bg);  color: var(--c-unknown);  border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }
.badge.b-workload-no-workloads { background: var(--surface-2);     color: var(--text-3);     border-radius: 12px; padding: 2px 8px; font-size: 11.5px; font-weight: 600; }

/* D-024 / A-2 — workload rows (since PROJ-UX W4-UI1 the «▸ контейнеры»
 * fold of a project row, ``_node_project_row.html``). Per-service rows с
 * state/health badge + «Перезапустить сервис» button. */
.node-project-containers .workload-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  border-bottom: 1px solid var(--border);
}
.node-project-containers .workload-row:last-child { border-bottom: none; }
.node-project-containers .workload-name {
  flex: 1 1 auto;
  min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.node-project-containers .workload-badges {
  display: flex;
  gap: 4px;
  flex-shrink: 0;
}
.node-project-containers .workload-actions { flex-shrink: 0; }

/* --- PROJ-UX W4-UI1 — response warnings (``warnings[]`` of a 2xx, the
       ``installs_in_flight`` banner and its pre-click twin on the g9s-panel
       row / settings dialog). Colours — the ``.modal-result.warn`` tokens;
       here only the shape: an accent edge, room for «×», blocks spaced. */
.response-warning {
  position: relative;
  border-left: 3px solid var(--c-degraded);
  padding-right: 28px;
}
.response-warning + .response-warning { margin-top: 6px; }
.response-warning .response-warning-close {
  position: absolute;
  top: 4px;
  right: 6px;
}
.node-project-row .installs-in-flight-row-banner { margin: 6px 0; }
.promote-result-warning {
  margin-top: 4px;
  padding: 4px 8px;
  border-radius: 3px;
  background: var(--c-degraded-bg);
  color: var(--c-degraded);
  font-size: 12px;
}

/* --- PROJ-UX W4-UI2 — project page (/ui/projects/<name>) --- */
.project-page-back { margin-bottom: 6px; font-size: 12px; }
.project-page-head { flex-wrap: wrap; gap: 8px; }
.project-page-head .page-title code { font-size: 18px; }
.project-retired-banner {
  background: var(--c-retired-bg); color: var(--c-retired);
  border-left: 3px solid var(--c-retired); border-radius: 6px;
  padding: 10px 12px; margin-bottom: 14px; font-size: 12.5px;
  display: flex; flex-direction: column; gap: 8px;
}
.project-retired-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.project-section-hint { font-size: 11.5px; margin-bottom: 8px; }
.project-section-result { margin-top: 10px; white-space: pre-wrap; overflow-wrap: anywhere; }
.project-section-result[hidden] { display: none; }
.project-node-list { display: flex; flex-direction: column; gap: 6px; }
.project-node-row {
  display: flex; flex-wrap: wrap; gap: 6px 14px; align-items: center;
  padding: 6px 0; border-bottom: 1px solid var(--border); font-size: 12.5px;
}
.project-node-row:last-child { border-bottom: none; }
.project-node-name { flex: 1 1 160px; min-width: 0; overflow-wrap: anywhere; }
.project-node-state { flex: 2 1 200px; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; }
.project-node-version { flex: 0 1 auto; font-size: 11.5px; }
.project-node-actions { flex: 0 0 auto; font-size: 12px; }
.project-pins-managed-note {
  background: var(--c-low-bg); color: var(--c-low); border-radius: 6px;
  padding: 6px 10px; font-size: 11.5px; margin-bottom: 8px;
}
.project-pin-row label code { overflow-wrap: anywhere; }
.project-pin-field { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.project-pin-field input[type="text"] {
  flex: 1 1 220px; min-width: 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}
.project-pin-hint { font-size: 11px; margin-top: 2px; }
.project-template-origin { font-size: 12.5px; margin-bottom: 8px; }
.project-template-actions { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }
.project-images-form { margin-top: 12px; border-top: 1px solid var(--border); padding-top: 10px; }
.project-images-form textarea {
  width: 100%; box-sizing: border-box;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}
.project-replace-template { display: block; font-size: 12px; margin: 6px 0; }
.project-promote-mode { border: none; padding: 0; margin: 0 0 10px; font-size: 12.5px; }
.project-promote-mode label { display: block; margin: 3px 0; }
.project-auto-warning {
  background: var(--c-degraded-bg); color: var(--c-degraded);
  border-radius: 6px; padding: 6px 10px; font-size: 11.5px; margin: 6px 0;
}
.project-danger-zone { border-color: var(--danger); }
.project-danger-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin: 6px 0; font-size: 12px; }
.project-danger-blocked { font-size: 12px; color: var(--danger); margin-bottom: 6px; }
.project-reserved-note { font-size: 12px; margin: 6px 0 14px; }
.project-page .btn[disabled] { opacity: 0.5; cursor: not-allowed; }

/* Registry card summary + retired cohort (D-018 A-4 п. 1). */
.project-card-retired { opacity: 0.6; }
.project-card-retired:hover, .project-card-retired:focus-within { opacity: 0.85; }
.project-pin-chip {
  font-size: 11px; background: var(--surface-2); border-radius: 3px;
  padding: 1px 5px; overflow-wrap: anywhere;
}

/* Shared editor modal (_editor_modal.html / static/editor-modal.js). */
dialog.modal.editor-modal { width: min(920px, 95vw); }
.editor-modal-hint { font-size: 12px; margin-bottom: 8px; }
.editor-modal-toolbar { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; font-size: 12px; }
.editor-modal-toggle { display: inline-flex; gap: 4px; align-items: center; }
.editor-modal-toggle[hidden] { display: none; }
.editor-modal-filename { font-size: 11.5px; overflow-wrap: anywhere; }
.editor-modal-text {
  width: 100%; box-sizing: border-box; min-height: 260px; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.editor-modal-text.editor-modal-nowrap { white-space: pre; overflow-wrap: normal; overflow-x: auto; }
/* Secret mode: the typed text is masked until «показать ввод». */
.editor-modal-text.editor-modal-masked { -webkit-text-security: disc; }
.editor-modal-result[hidden] { display: none; }
/* A server refusal (e.g. the 422 of a YAML that does not parse) is printed
   as sent: its line breaks and the column of its «^» caret only line up
   with the line breaks kept and a monospace face. */
.editor-modal-result {
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.editor-modal-result.err {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
}

/* --- PROJ-UX W4-UI1 — «Проекты на узле» (one row per project) ---------- */
.node-project-row-title {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0;
}
.node-project-page-link { font-size: 11.5px; white-space: nowrap; }
.node-project-line {
  display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 8px;  /* «контейнеры» fits the key column (real-env W5, O2) */
  font-size: 12px; color: var(--text-2); margin: 2px 0; min-width: 0;
}
.node-project-line-k { color: var(--text-3); }
.node-project-line-v { min-width: 0; overflow-wrap: anywhere; }
.node-project-runtime-versions { margin-left: 6px; font-size: 11.5px; }
.config-axis-state { white-space: nowrap; }
.config-axis-drift { color: var(--c-degraded); }
.config-axis-in-sync { color: var(--c-healthy); }
.level-note { font-size: 11px; margin-left: 4px; }
.node-project-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 8px 0 4px;
}
.version-pick {
  display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0;
}
.version-pick select { max-width: 100%; }
.version-pick-hint { font-size: 11px; flex: 1 1 220px; min-width: 0; }
.node-project-fold { margin-top: 4px; font-size: 12px; }
.node-project-fold > summary { cursor: pointer; color: var(--text-2); font-size: 11.5px; }
.node-project-fold .detail-grid { margin: 6px 0 4px; }
.node-project-fold .workload-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 3px 0;
}
.badge.b-auto { background: var(--c-degraded-bg); color: var(--c-degraded); }
.badge.b-retired { background: var(--surface-2); color: var(--text-3); }
.node-project-dc-retired { opacity: 0.75; }
.toast-link { display: inline-block; margin-top: 6px; font-weight: 600; }

/* O-4 (browser check UI2) — the node page scrolled sideways at 375 px.
   Long tokens (ids, hashes, keys) wrap inside their cell instead of
   widening the page; the narrow grid shrinks its label column. */
.detail-grid .v, .detail-grid .v code,
.timeline .what, .timeline .what code { overflow-wrap: anywhere; }
.ref-display { max-width: 100%; }
@media (max-width: 560px) {
  .detail-grid { grid-template-columns: minmax(0, 96px) minmax(0, 1fr); }
  .ref-display { white-space: normal; flex-wrap: wrap; }
  .node-project-row-head { align-items: flex-start; }
}

/* PROJ-UX п. 34 — access-keys issue form: option groups as fieldset +
   legend (a11y), styled like a .form-row label, without the UA border. */
.ak-group {
  border: 0;
  padding: 0;
  margin: 0 0 10px;
  min-width: 0;
}
.ak-group > legend {
  color: var(--text-2); font-size: 12.5px; font-weight: 500;
  padding: 0; margin-bottom: 4px;
}
.ak-group > legend .opt {
  color: var(--text-3); font-weight: 400; font-size: 11px;
}
.ak-option { display: block; font-weight: normal; }
.ak-option-inline { display: inline-block; margin-right: 12px; }
