/* page-vms.css — extracted from style.css 2026-05-27 (UX-6 cut 3).
 *
 * /system/vms styles — the tree + tabs primary shell (XCP-ng-Center
 * inspired), Backups summary cards, VM action menu, inline tag editor,
 * action progress modal, tree search input, dashboard cards (XOA-v6
 * style default landing), view toggle, and split-panel filterable
 * list. All `.vms-*` selectors plus a couple `.tag-*` for the inline
 * editor and `.vac-*` for the action confirmation modal.
 *
 * Largest single page block in the codebase — was the audit's worst
 * cognitive-load offender on style.css. Originally style.css commits
 * 2.4 through 2.11.
 *
 * Loaded AFTER style.css + components.css via base.html.
 */

/* ─── /system/vms — tree + tabs (XCP-ng-Center inspired) ─────────────── */
.vms-shell {
  display: grid;
  /* Tree pane width is overridden inline by system_vms.js when the user
     drags the resize handle. Default 280px is the comfortable starting
     width; min/max enforced in JS. */
  grid-template-columns: var(--vms-tree-width, 280px) 1fr;
  gap: 18px;
  align-items: start;
  margin-top: 8px;
}

.vms-tree {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 12px;
  /* Internal scrolling so the tree doesn't push the right pane down on
     long fleets. We previously had position:sticky here which created
     dead space above the pane in some grid contexts even at scroll=0. */
  max-height: calc(100vh - var(--hdr-h) - 60px);
  overflow-y: auto;
  overflow-x: hidden;
  box-shadow: var(--shadow-sm);
  font-size: 14px;
  line-height: 1.55;
  /* relative for the absolute-positioned resize handle */
  position: relative;
}
/* Vertical drag-handle on the right edge of the tree pane. Click + drag
   to widen / narrow. Width is clamped to 220–600px and persisted to
   localStorage so the user's preferred width sticks. The handle sits
   INSIDE the right edge (not bleeding past) so overflow-x:hidden on the
   tree doesn't clip it. */
.vms-tree-resize-handle {
  position: absolute;
  top: 0;
  right: 0;
  width: 5px;
  height: 100%;
  cursor: col-resize;
  background: transparent;
  z-index: 5;
  transition: background 0.12s;
}
.vms-tree-resize-handle::before {
  /* Subtle visible affordance — a thin vertical line on hover */
  content: "";
  position: absolute;
  top: 14px;
  bottom: 14px;
  right: 1px;
  width: 2px;
  background: var(--border);
  border-radius: 1px;
  opacity: 0;
  transition: opacity 0.12s;
}
.vms-tree-resize-handle:hover::before,
.vms-tree-resize-handle.resizing::before { opacity: 1; }
.vms-tree-resize-handle:hover,
.vms-tree-resize-handle.resizing {
  background: var(--brand-soft);
}
.vms-tree-pool { margin-bottom: 18px; }
.vms-tree-pool-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  font-size: 15px;
  line-height: 1.45;
  color: var(--text);
  cursor: pointer;
  border-radius: 5px;
}
.vms-tree-pool-head:hover { background: var(--bg-soft); }

/* Hosts and SR sub-branches indented from the pool with a vertical rule
   so the parent → child relationship is visually obvious. */
.vms-tree-host,
.vms-tree-srs {
  margin-left: 14px;
  padding-left: 16px;
  border-left: 1px solid var(--border-soft);
  position: relative;
}
.vms-tree-host-head,
.vms-tree-srs-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 10px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text-2);
  cursor: pointer;
  border-radius: 5px;
}
.vms-tree-host-head:hover,
.vms-tree-srs-head:hover { background: var(--bg-soft); color: var(--text); }

/* Host name as a real link inside the summary — clicking it navigates to
   the host detail page; clicking the chevron or empty space toggles the
   children. The host-link click handler in system_vms.js stops propagation
   so we don't toggle mid-navigation. */
.vms-tree-host-link {
  color: inherit;
  text-decoration: none;
  font-weight: 500;
  cursor: pointer;
}
.vms-tree-host-link:hover { color: var(--brand-deep); text-decoration: underline; }
/* Active host (selected via ?host=<uuid>) gets the same chip treatment as
   selected VMs/SRs in the tree. */
.vms-tree-host-head.active {
  background: var(--brand-soft);
  color: var(--brand-deep);
}
.vms-tree-host-head.active .vms-tree-host-link { color: var(--brand-deep); }

/* SVG icons inline in the tree — pool/host/vm/sr — colored via currentColor
   so they pick up the surrounding text color. Bumped 14→17 / 13→16 per
   Matt's 2026-05-08 "I am not 10 years old" feedback on the deployed view. */
.vms-tree-svg-icon {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--text-mute);
}
.vms-tree-vm-icon { width: 16px; height: 16px; }
.vms-detail-svg-icon {
  width: 20px;
  height: 20px;
  color: var(--text-mute);
  flex-shrink: 0;
}

.vms-tree-sr-badge {
  display: inline-block;
  padding: 1px 6px;
  margin-right: 2px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.05em;
  background: #dbeafe;
  color: #1d4ed8;
  border-radius: 3px;
  flex-shrink: 0;
}
[data-theme="dark"] .vms-tree-sr-badge { background: #1e3a8a; color: #93c5fd; }
.vms-tree-icon {
  display: inline-block;
  width: 12px;
  text-align: center;
  color: var(--text-faint);
  font-size: 14px;
}
.vms-tree-tag {
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand-deep);
  background: var(--brand-soft);
  padding: 1px 5px;
  border-radius: 3px;
}
.vms-tree-vms {
  list-style: none;
  padding: 0 0 0 18px;
  margin: 6px 0;
}
.vms-tree-vms li { margin: 3px 0; }
.vms-tree-vm {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 10px;
  border-radius: 5px;
  text-decoration: none;
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vms-tree-vm:hover { background: var(--bg-soft); color: var(--text); }
.vms-tree-vm.active { background: var(--brand-soft); color: var(--brand-deep); font-weight: 600; }
.vms-tree-vm-name {
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
}

/* ─── Backups summary cards (commit 2.9) ──────────────────────────────
   Clickable card-as-anchor pattern. Hover lifts slightly + arrows
   indicate the link affordance. Used on /system/backups + drill-down
   pages so the operator clearly sees "this card opens a subpage." */
.vms-summary-card {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
  transition: box-shadow 0.15s ease, transform 0.1s ease;
  position: relative;
}
.vms-summary-card:hover {
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
  transform: translateY(-1px);
}
.vms-summary-card-arrow {
  position: absolute;
  top: 14px;
  right: 16px;
  font-size: 14px;
  color: var(--text-mute);
  opacity: 0.7;
}
.vms-summary-card:hover .vms-summary-card-arrow {
  color: var(--brand-deep);
  opacity: 1;
}

/* ─── VM action menu (commit 2.4) ───────────────────────────────────────
   The 3-dot dropdown in the VM detail header. Built on <details>/<summary>
   so it opens on click without JS. Each menu item is its own form so only
   the verb posted gets executed. */
.vms-action-menu {
  position: relative;
  display: inline-block;
}
.vms-action-menu > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
.vms-action-menu > summary::-webkit-details-marker { display: none; }
.vms-action-menu-items {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  min-width: 240px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
  padding: 4px;
  z-index: 100;
}
.vms-action-menu-items form { margin: 0; }
.vms-action-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 7px 12px;
  border: none;
  background: transparent;
  color: var(--text);
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
  border-radius: 4px;
}
.vms-action-item:hover { background: var(--bg-soft); }
.vms-action-danger { color: var(--red); }
.vms-action-danger:hover { background: var(--red-bg); }
.vms-action-sep {
  border: none;
  border-top: 1px solid var(--border-soft);
  margin: 4px 0;
}
/* Inline typed-confirm form expands inside the menu */
.vms-action-confirm[open] > summary { background: var(--bg-soft); }
.vms-action-confirm-form {
  padding: 6px 8px 8px;
  border-top: 1px solid var(--border-soft);
}
.vms-action-confirm-input {
  width: 100%;
  padding: 5px 8px;
  margin-bottom: 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 14px;
}
.vms-action-confirm-input:focus {
  /* This input gates a destructive VM action — it MUST show a clear
     focus ring. Keep the danger-red intent, but as a real ring (UX-3). */
  outline: 2px solid var(--red);
  outline-offset: 2px;
  border-color: var(--red);
}

/* ─── Inline tag editor (commit 2.6) ──────────────────────────────────
   Each tag chip in the VM detail header has an x-remove button (admin),
   plus a "+ Add" affordance that expands to a small form. CSP-safe via
   <details>/<summary> and standard <form> POSTs. */
.vms-tags-edit {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
}
.vms-tag-removable {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding-right: 3px;
}
.vms-tag-rm-form { display: inline; margin: 0; }
.vms-tag-rm {
  border: none;
  background: transparent;
  color: var(--text-mute);
  cursor: pointer;
  padding: 0 2px;
  font-size: 14px;
  line-height: 1;
  border-radius: 50%;
}
.vms-tag-rm:hover { background: var(--red-bg); color: var(--red); }
.vms-tag-add { display: inline-block; }
.vms-tag-add > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
  background: var(--bg-soft);
  color: var(--text-mute);
  border: 1px dashed var(--border);
}
.vms-tag-add > summary::-webkit-details-marker { display: none; }
.vms-tag-add[open] > summary { background: var(--brand-soft); color: var(--brand-deep); border-style: solid; }
.vms-tag-add-form {
  position: absolute;
  margin-top: 4px;
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 10px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.12);
  z-index: 100;
  min-width: 280px;
}
.vms-tag-add-input {
  width: 100%;
  padding: 5px 8px;
  margin-bottom: 6px;
  border: 1px solid var(--border);
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 14px;
}

/* Capacity bar — used by disks tab + SR detail to show actual-vs-allocated
   for thin-provisioned VHDs. Compact (4px) since it's a row-level indicator. */
.vms-cap-bar {
  width: 100%;
  max-width: 180px;
  height: 5px;
  background: var(--bg-soft);
  border-radius: 3px;
  margin-top: 3px;
  overflow: hidden;
}
.vms-cap-bar-fill { height: 100%; border-radius: 3px; transition: width 0.2s; }
.vms-cap-green  { background: var(--green); }
.vms-cap-yellow { background: var(--yellow); }
.vms-cap-red    { background: var(--red); }

/* Status dot — colored circle used in tree and detail header.
   XO-6-style prominence: bumped to 12px with an inner-shadow ring and a
   subtle outer halo, so green vs gray is unmistakable at the row scale.
   Per Matt's 2026-05-08 feedback that XO 6's dots are visibly louder. */
.vms-status-dot {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1.5px solid rgba(255,255,255,0.85);
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 2px transparent;
  transition: box-shadow 0.15s;
}
.vms-status-dot-lg { width: 16px; height: 16px; border-width: 2px; }
/* Strong saturated colors with a soft same-color halo so the dot reads
   as a small status pill, not a faint hint. */
.vms-status-dot-green {
  background: #22c55e;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 3px rgba(34, 197, 94, 0.22);
}
.vms-status-dot-yellow {
  background: #eab308;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 3px rgba(234, 179, 8, 0.25);
}
.vms-status-dot-red {
  background: #ef4444;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 3px rgba(239, 68, 68, 0.25);
}
.vms-status-dot-gray {
  background: #94a3b8;
  opacity: 0.7;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.12);
}

/* Paused — green dot with two dark vertical bars overlaid (the universal
   pause glyph). Matches XOA's convention. The bars are pure CSS via
   ::before/::after so we don't need a font/icon dependency. Per Matt
   2026-05-08: "when pausing a vm, it does not turn green with pause
   markers" — this is the marker. */
.vms-status-dot-paused {
  background: #22c55e;  /* same green as Running — the VM hasn't lost state */
  position: relative;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 3px rgba(34, 197, 94, 0.22);
}
.vms-status-dot-paused::before,
.vms-status-dot-paused::after {
  content: "";
  position: absolute;
  top: 22%;
  bottom: 22%;
  width: 1.5px;
  background: rgba(0, 0, 0, 0.78);
  border-radius: 0.5px;
}
.vms-status-dot-paused::before { left: 30%; }
.vms-status-dot-paused::after  { right: 30%; }
/* Larger variant — bars scale with the dot. */
.vms-status-dot-lg.vms-status-dot-paused::before,
.vms-status-dot-lg.vms-status-dot-paused::after {
  width: 2px;
  border-radius: 1px;
}

/* Suspended — yellow dot with two bars (state is on disk, not the same
   as Paused which is RAM-resident). Distinguishable at a glance from
   Paused because color is different but bars convey "not running." */
.vms-status-dot-suspended {
  background: #eab308;
  position: relative;
  box-shadow:
    0 0 0 1px rgba(0,0,0,0.12),
    0 0 0 3px rgba(234, 179, 8, 0.25);
}
.vms-status-dot-suspended::before,
.vms-status-dot-suspended::after {
  content: "";
  position: absolute;
  top: 22%;
  bottom: 22%;
  width: 1.5px;
  background: rgba(0, 0, 0, 0.78);
  border-radius: 0.5px;
}
.vms-status-dot-suspended::before { left: 30%; }
.vms-status-dot-suspended::after  { right: 30%; }
.vms-status-dot-lg.vms-status-dot-suspended::before,
.vms-status-dot-lg.vms-status-dot-suspended::after {
  width: 2px;
  border-radius: 1px;
}

/* Transitional / pending state — pulsing yellow with two bars. Applied
   via JS during an in-flight VM action so the operator sees "something is
   happening" in the tree while the progress modal is open. */
.vms-status-dot-transition {
  background: #eab308;
  position: relative;
  animation: vms-dot-pulse 1.1s ease-in-out infinite;
}
.vms-status-dot-transition::before,
.vms-status-dot-transition::after {
  content: "";
  position: absolute;
  top: 22%;
  bottom: 22%;
  width: 1.5px;
  background: rgba(0, 0, 0, 0.78);
  border-radius: 0.5px;
}
.vms-status-dot-transition::before { left: 30%; }
.vms-status-dot-transition::after  { right: 30%; }
@keyframes vms-dot-pulse {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(0,0,0,0.12),
      0 0 0 3px rgba(234, 179, 8, 0.25);
  }
  50% {
    box-shadow:
      0 0 0 1px rgba(0,0,0,0.12),
      0 0 0 7px rgba(234, 179, 8, 0.10);
  }
}

/* ─── Action progress modal (commit 2.11) ────────────────────────────────
   Replaces the boring confirm-popup + bare-redirect flow. When the user
   triggers a VM action (pause, suspend, reboot, force-shutdown, etc.),
   JS opens this modal, posts the action over fetch, polls the new
   /state endpoint until power_state matches expected, then closes.

   Hidden by default. JS toggles `.is-open` to display.
*/
.vmop-modal {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  z-index: 1000;
  display: none;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(2px);
}
.vmop-modal.is-open { display: flex; }

.vmop-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  width: 480px;
  max-width: calc(100vw - 32px);
  padding: 26px 28px 22px;
  box-shadow: 0 24px 64px rgba(0,0,0,0.25);
}

.vmop-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 6px;
}
.vmop-icon {
  font-size: 28px;
  line-height: 1;
}
.vmop-title {
  font-size: 18px;
  font-weight: 600;
  color: var(--text);
  letter-spacing: -0.01em;
}
.vmop-vm {
  font-family: var(--mono);
  font-size: 14px;
  color: var(--text-mute);
  margin: 2px 0 18px;
  word-break: break-all;
}

/* Progress bar — fills 0→100% as the action completes */
.vmop-progress {
  height: 8px;
  background: var(--border-soft);
  border-radius: 4px;
  overflow: hidden;
}
.vmop-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--brand, #2563eb), #60a5fa);
  width: 0%;
  transition: width 0.25s ease;
  border-radius: 4px;
}
.vmop-modal[data-status="success"] .vmop-progress-fill {
  background: linear-gradient(90deg, var(--green, #16a34a), #4ade80);
}
.vmop-modal[data-status="error"] .vmop-progress-fill {
  background: linear-gradient(90deg, var(--red, #dc2626), #f87171);
}

.vmop-status {
  margin-top: 14px;
  font-size: 14px;
  color: var(--text-2);
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.vmop-pct {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--text);
}
.vmop-detail {
  margin-top: 14px;
  font-size: 14px;
  color: var(--text-mute);
  line-height: 1.5;
  min-height: 18px;
}

.vmop-actions {
  margin-top: 22px;
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
.vmop-btn {
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--text-2);
  padding: 7px 14px;
  border-radius: 6px;
  font-size: 14px;
  font-family: inherit;
  cursor: pointer;
}
.vmop-btn:hover {
  border-color: var(--brand);
  color: var(--brand-deep);
}
.vmop-btn-primary {
  background: var(--brand, #2563eb);
  border-color: var(--brand, #2563eb);
  color: white;
}
.vmop-btn-primary:hover {
  background: var(--brand-deep, #1d4ed8);
  color: white;
}
.vmop-btn-danger {
  background: var(--red, #dc2626);
  border-color: var(--red, #dc2626);
  color: white;
}
.vmop-btn-danger:hover {
  background: #b91c1c;
  color: white;
}
.vmop-btn[disabled] {
  opacity: 0.55;
  cursor: not-allowed;
}

/* Confirm-name input (lives inside the modal for destructive verbs) */
.vmop-confirm-block {
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px dashed var(--border-soft);
}
.vmop-confirm-label {
  font-size: 14px;
  color: var(--text-mute);
  margin-bottom: 6px;
  line-height: 1.5;
}
.vmop-confirm-label code {
  background: var(--bg-soft);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 14px;
}
.vmop-confirm-input {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-family: var(--mono);
  font-size: 14px;
  background: var(--bg);
  color: var(--text);
  box-sizing: border-box;
}
.vmop-confirm-input:focus {
  outline: 2px solid var(--brand);
  border-color: var(--brand);
}
.vmop-confirm-input.is-mismatch {
  border-color: var(--yellow, #ca8a04);
}

/* Detail pane */
.vms-detail {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 18px 22px;
  box-shadow: var(--shadow-sm);
  min-height: 320px;
}
.vms-detail-empty {
  text-align: center;
  padding: 80px 20px;
}
.vms-detail-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border-soft);
  margin-bottom: 12px;
}
.vms-detail-title {
  display: flex;
  align-items: center;
  gap: 10px;
}
.vms-detail-title h2 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}
.vms-detail-actions {
  display: flex;
  gap: 6px;
}
.vms-detail-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 22px;
  font-size: 14px;
  color: var(--text-2);
  margin-bottom: 16px;
}
.vms-detail-facts strong {
  color: var(--text-mute);
  font-weight: 600;
  margin-right: 4px;
}
.vms-tag {
  display: inline-block;
  padding: 1px 7px;
  margin-right: 4px;
  font-size: 14px;
  background: var(--bg-soft);
  color: var(--text-2);
  border-radius: 10px;
}

/* Tabs */
.vms-tabs {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 16px;
}
.vms-tab {
  padding: 7px 14px;
  font-size: 14px;
  color: var(--text-mute);
  text-decoration: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.vms-tab:hover { color: var(--text); }
.vms-tab.active {
  color: var(--brand-deep);
  border-bottom-color: var(--brand);
  font-weight: 600;
}

/* Tab content key/value table */
.vms-detail-kv {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.vms-detail-kv th {
  text-align: left;
  font-weight: 600;
  color: var(--text-mute);
  padding: 6px 16px 6px 0;
  width: 140px;
  vertical-align: top;
}
.vms-detail-kv td {
  padding: 6px 0;
  color: var(--text);
  vertical-align: top;
}
.vms-detail-kv tr + tr th, .vms-detail-kv tr + tr td {
  border-top: 1px solid var(--border-soft);
}

@media (max-width: 1100px) {
  .vms-shell { grid-template-columns: 240px 1fr; }
}
@media (max-width: 900px) {
  .vms-shell { grid-template-columns: 1fr; }
  .vms-tree, .vms-list { position: static; max-height: 300px; }
}

/* ─── /system/vms — tree search input ────────────────────────────────── */
.vms-tree-search {
  padding: 4px 4px 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border-soft);
}
.vms-tree-search input[type="search"] {
  width: 100%;
  font-size: 14px;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
}
.vms-tree-search input[type="search"]:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-soft);
}

/* Collapsible <details>/<summary> tree styling — replaces the manual ▸/▾
   icons with the browser-native triangle. The triangle is unstyled by
   default and is positioned by the user-agent inside <summary>. */
/* All collapsible <details> in the tree (pool, host, srs subtrees) get a
   consistent chevron at the start, hidden user-agent triangle, and a
   prominent hover state on the whole summary so it's unambiguous that the
   row is the toggle target. The chevron rotates 90° when open.
   Per Matt's 2026-05-08 feedback that the toggle target was inconsistent
   ("sometimes text, sometimes number"). */
details.vms-tree-pool > summary,
details.vms-tree-host > summary,
details.vms-tree-srs > summary {
  list-style: none;
  cursor: pointer;
  user-select: none;
}
details.vms-tree-pool > summary::-webkit-details-marker,
details.vms-tree-host > summary::-webkit-details-marker,
details.vms-tree-srs > summary::-webkit-details-marker { display: none; }
details.vms-tree-pool > summary::marker,
details.vms-tree-host > summary::marker,
details.vms-tree-srs > summary::marker { content: ""; }

/* Custom chevron — rotates open/closed. CSS-only, no JS. */
details.vms-tree-pool > summary::before,
details.vms-tree-host > summary::before,
details.vms-tree-srs > summary::before {
  content: "";
  display: inline-block;
  width: 0; height: 0;
  margin-right: 4px;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  border-left: 6px solid var(--text-mute);
  transition: transform 0.15s ease;
  transform-origin: 25% 50%;
  flex-shrink: 0;
}
details[open].vms-tree-pool > summary::before,
details[open].vms-tree-host > summary::before,
details[open].vms-tree-srs > summary::before {
  transform: rotate(90deg);
}

/* Whole-row hover so it's obvious the row is clickable. */
details.vms-tree-pool > summary:hover,
details.vms-tree-host > summary:hover,
details.vms-tree-srs > summary:hover {
  background: var(--bg-soft);
}

details.vms-tree-pool > summary > .vms-tree-icon,
details.vms-tree-host > summary > .vms-tree-icon {
  display: none;  /* legacy unicode markers — chevron above replaces them */
}

/* ─── /system/vms — dashboard cards (XOA-v6-style default landing) ────── */
.vms-dashboard {
  padding: 4px 0 0;
}

/* Issue cards (red badge) — surface at the top, before the status grid */
.vms-dash-card-issue {
  border-left: 4px solid var(--red);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  margin-bottom: 14px;
  box-shadow: var(--shadow-sm);
}
.vms-dash-card-head {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}
.vms-dash-card-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.vms-dash-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 7px;
  font-size: 14px;
  font-weight: 700;
  color: white;
  border-radius: 11px;
}
.vms-dash-badge-red    { background: var(--red); }
.vms-dash-badge-yellow { background: var(--yellow); color: var(--text); }
.vms-dash-issue-list {
  list-style: none;
  padding: 0;
  margin: 0;
  font-size: 14px;
}
.vms-dash-issue-list li {
  padding: 6px 0;
  border-top: 1px solid var(--border-soft);
}
.vms-dash-issue-list li:first-child { border-top: 0; }

.vms-dash-source-xo,
.vms-dash-source-noc {
  display: inline-block;
  padding: 1px 6px;
  margin-right: 6px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.04em;
  border-radius: 3px;
  text-transform: uppercase;
}
.vms-dash-source-xo  { background: #dbeafe; color: #1d4ed8; }
.vms-dash-source-noc { background: var(--brand-soft); color: var(--brand-deep); }
[data-theme="dark"] .vms-dash-source-xo { background: #1e3a8a; color: #93c5fd; }

/* Status grid — counts + breakdown lists, mimics XOA's top-row cards */
.vms-dash-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 14px;
  margin-bottom: 18px;
}
/* Explicit 2-col grid for the donutless summary cards (backup jobs +
   storage repositories) — avoids the "alone on a row" gap when they
   were mixed into the auto-fit grid above. Falls back to a single col
   on narrow viewports. */
.vms-dash-grid-2col {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
  margin-bottom: 18px;
}
@media (max-width: 720px) {
  .vms-dash-grid-2col { grid-template-columns: 1fr; }
}
.vms-dash-card {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow: var(--shadow-sm);
  display: flex;
  gap: 14px;
  align-items: flex-start;
  min-height: 96px;
}
.vms-dash-card-wide { grid-column: span 2; flex-direction: column; }

/* Cards WITHOUT a donut chart (Backup jobs, Storage repositories) need a
   vertical stack — label / value / breakdown — instead of the horizontal
   flex used when a donut is present. Detected by ":not(:has(.vms-dash-donut))"
   so we don't have to add a modifier class to every donut-less card. */
.vms-dash-card:not(:has(.vms-dash-donut)) {
  flex-direction: column;
  gap: 6px;
}
.vms-dash-card-label {
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-mute);
  font-weight: 700;
  margin-bottom: 6px;
}
.vms-dash-card-body { flex: 1; }
.vms-dash-card-value {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text);
  line-height: 1.05;
}
.vms-dash-card-breakdown {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
  font-size: 14px;
  color: var(--text-2);
}
.vms-dash-card-breakdown li {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 1px 0;
}

/* Donut chart — pure CSS conic-gradient. The chart's `style` attribute
   sets `--ring` to the gradient (e.g., var(--green) 0deg 200deg,
   var(--gray) 200deg 360deg). The center hole is a smaller absolute
   circle covering the inner area. */
.vms-dash-donut {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: conic-gradient(var(--ring, var(--gray) 0deg 360deg));
  flex-shrink: 0;
}
.vms-dash-donut::after {
  content: "";
  position: absolute;
  inset: 9px;
  border-radius: 50%;
  background: var(--bg-elev);
}
.vms-dash-donut-label {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: 600;
  z-index: 1;
}

/* Resources card uses a different layout — inline number trio */
.vms-dash-resources {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.vms-dash-resource-label {
  font-size: 14px;
  color: var(--text-mute);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.vms-dash-resource-value {
  font-size: 22px;
  font-weight: 600;
  color: var(--text);
  margin-top: 2px;
}

/* Status dots reused from tree — add a red variant for unreachable pools */
.vms-status-dot-red { background: var(--red); }

.vms-dash-footer {
  margin-top: 18px;
  font-size: 14px;
  text-align: center;
  color: var(--text-mute);
}

@media (max-width: 1100px) {
  .vms-dash-card-wide { grid-column: span 1; }
}

/* ─── /system/vms — view toggle (Tree | Split) ───────────────────────── */
.vms-view-toggle {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 6px;
  overflow: hidden;
  background: var(--bg);
  margin: 0;
}
.vms-view-toggle-btn {
  background: var(--bg-elev);
  color: var(--text-2);
  border: 0;
  padding: 6px 14px;
  font-size: 14px;
  cursor: pointer;
  border-right: 1px solid var(--border);
  font-family: inherit;
}
.vms-view-toggle-btn:last-child { border-right: 0; }
.vms-view-toggle-btn:hover { background: var(--bg-soft); color: var(--text); }
.vms-view-toggle-btn.active {
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-weight: 600;
}

/* ─── /system/vms — split-panel filterable list (alternative view) ───── */
.vms-list {
  background: var(--bg-elev);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 10px 8px;
  position: sticky;
  top: calc(var(--hdr-h) + 14px);
  max-height: calc(100vh - var(--hdr-h) - 32px);
  overflow-y: auto;
  box-shadow: var(--shadow-sm);
  font-size: 14px;
}
.vms-list-filter {
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 4px 4px;
}
.vms-list-filter-input {
  flex: 1;
  font-size: 14px;
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
  font-family: inherit;
}
.vms-list-filter-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-soft);
}
.vms-list-filter-clear {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  color: var(--text-mute);
  text-decoration: none;
  font-size: 16px;
  line-height: 1;
}
.vms-list-filter-clear:hover {
  background: var(--bg-soft);
  color: var(--red);
}
.vms-list-items {
  list-style: none;
  padding: 0;
  margin: 0;
}
.vms-list-items li { margin: 1px 0; }
.vms-list-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 5px;
  text-decoration: none;
  color: var(--text-2);
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vms-list-item:hover { background: var(--bg-soft); color: var(--text); }
.vms-list-item.active {
  background: var(--brand-soft);
  color: var(--brand-deep);
  font-weight: 600;
}
.vms-list-item-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vms-list-item-tags {
  display: inline-flex;
  gap: 3px;
  flex-shrink: 0;
}

