/* NSGDV Remote control-plane UI — minimal, dependency-free. */

/* Design tokens live in ONE place, shared with the browser viewer.
   Must stay the first rule in the file: @import is only legal before
   other statements. See that file for why it sits under viewer/. */
@import url("/viewer/tokens.css");

* { box-sizing: border-box; }
body {
  margin: 0;
  color: var(--text);
  font: 15px/1.5 system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  /* Subtle lift at the top of the page. Kept very low-alpha: on the warm
     neutral ground a stronger accent wash reads as a cold haze rather
     than a highlight (it was tuned for the old blue-tinted ground). */
  background:
    radial-gradient(900px 500px at 50% -8%, rgba(var(--accent-rgb),.05), transparent 62%),
    var(--bg);
  min-height: 100vh;
}
.hidden { display: none !important; }
/* The `hidden` DOM attribute must always win: author rules like
   `display: flex` on a class otherwise override the UA's [hidden]
   default, leaving "hidden" elements visible (selbar/Paste bug). */
[hidden] { display: none !important; }
.muted { color: var(--muted); }
.center { display: flex; flex-direction: column; align-items: center; justify-content: center; }
.row { display: flex; align-items: center; gap: 12px; }
.between { justify-content: space-between; }

header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.header-left { display: flex; align-items: center; gap: 28px; }
.brand { font-weight: 700; letter-spacing: 0.3px; }
.brand span { color: var(--accent); }
.nav { display: flex; gap: 4px; }
.nav-link {
  color: var(--muted); text-decoration: none;
  font-size: 14px; font-weight: 500;
  padding: 6px 12px; border-radius: 8px;
  transition: color .12s, background .12s;
}
.nav-link:hover { color: var(--text); background: var(--panel-2); }
.nav-link.active { color: var(--text); background: var(--panel-2); }
.userbar { display: flex; align-items: center; gap: 14px; }
#who { color: var(--muted); }

/* Full-bleed: the machines/audit tables are the product — let them use
   the whole window. Form-like pages re-cap themselves (e.g. support). */
main { padding: 28px 24px; }
/* The support page reads better narrow — it's a form + short list, not a
   data table. */
#support-view { max-width: 880px; margin: 0 auto; }

h1 { font-size: 22px; margin: 0 0 16px; }

/* ── Login ─────────────────────────────────────────────────────────────── */
.login {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin-top: 7vh;
}
.card {
  width: 100%;
  max-width: 400px;
  background: linear-gradient(180deg, rgba(255,255,255,.02), transparent), var(--panel);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 36px 32px;
  text-align: center;
  box-shadow: 0 24px 60px -20px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.02) inset;
}
.logo {
  width: 52px; height: 52px;
  margin: 0 auto 18px;
  display: grid; place-items: center;
  color: var(--accent);
  border-radius: 14px;
  background: rgba(var(--accent-rgb),.12);
  border: 1px solid rgba(var(--accent-rgb),.25);
}
.card h1 { font-size: 21px; margin: 0 0 6px; }
.subtitle { color: var(--muted); font-size: 14px; margin: 0 0 22px; }
.login-foot { margin: 0; opacity: .7; }

.btn {
  display: inline-block;
  border: 1px solid var(--border);
  background: var(--panel-2);
  color: var(--text);
  padding: 11px 16px;
  border-radius: 9px;
  cursor: pointer;
  font: inherit;
  font-weight: 500;
  text-decoration: none;
  text-align: center;
  white-space: nowrap;   /* a squeezed flex row must not wrap the label */
  flex: none;
  transition: background .14s, border-color .14s, transform .05s;
}
.btn:hover { border-color: var(--hover-border); background: var(--hover); }
.btn:active { transform: translateY(1px); }
.btn.block { display: block; width: 100%; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-2); border-color: var(--accent-2); }
.btn.primary:disabled, .btn:disabled { opacity: .55; cursor: default; transform: none; }
.btn.ghost { background: transparent; }
.btn.ghost:hover { background: var(--panel-2); }

/* Form fields */
.field { display: block; text-align: left; margin-bottom: 14px; }
.field-label {
  display: block;
  font-size: 12px; font-weight: 500;
  color: var(--muted);
  margin: 0 0 6px 2px;
  letter-spacing: .2px;
}
.field input, .filter {
  width: 100%;
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 9px;
  padding: 11px 13px;
  font: inherit;
  transition: border-color .14s, box-shadow .14s;
}
.field input::placeholder { color: #5a6577; }
.field input:focus, .filter:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(var(--accent-rgb),.18);
}
.code-input {
  text-align: center;
  font-size: 22px;
  letter-spacing: .5em;
  text-indent: .5em;            /* center the letter-spaced text */
  font-variant-numeric: tabular-nums;
}
.link {
  display: inline-block;
  margin-top: 12px;
  color: var(--muted);
  font-size: 13px;
  text-decoration: none;
}
.link:hover { color: var(--accent); text-decoration: underline; }

/* Dashboard filter keeps its compact sizing */
.filter { min-width: 220px; }

/* ── Tenant combobox (guest panel) ───────────────────────────────────────── */
.combo { position: relative; }
.combo-list {
  position: absolute;
  top: calc(100% + 5px); left: 0; right: 0;
  min-width: 280px;
  max-height: 288px; overflow-y: auto;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  box-shadow: 0 18px 44px -12px rgba(0,0,0,.65), 0 0 0 1px rgba(255,255,255,.02) inset;
  padding: 4px;
  z-index: 40;
}
.combo-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 14px;
}
.combo-item.active { background: rgba(var(--accent-rgb),.16); }
.combo-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.combo-name mark { background: none; color: var(--accent); font-weight: 600; }
.combo-id { color: var(--muted); font-size: 12px; flex: none; }
.combo-empty { padding: 10px 12px; color: var(--muted); font-size: 13px; }

/* ── Machines table (scales to many agents) ──────────────────────────────── */
.page-head { margin-bottom: 16px; }
.count { color: var(--muted); font-weight: 400; font-size: 15px; white-space: nowrap; }
.page-head h1 { white-space: nowrap; }

.table-wrap {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
}
.data-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.data-table thead th {
  text-align: left; font-weight: 500; color: var(--muted); font-size: 12px;
  letter-spacing: .3px; text-transform: uppercase;
  padding: 10px 16px; background: rgba(255,255,255,.02);
  border-bottom: 1px solid var(--border);
}
.data-table tbody td {
  padding: 11px 16px; border-bottom: 1px solid var(--border); vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr:hover { background: rgba(255,255,255,.025); }
.data-table tr.revoked .name { color: var(--muted); }

.col-status { width: 34px; text-align: center; }
.col-actions { text-align: right; white-space: nowrap; width: 1%; }
/* Last-contact: narrow and non-wrapping so it never pushes the action
   buttons off the panel edge. */
.col-seen { white-space: nowrap; width: 1%; font-variant-numeric: tabular-nums; }
td.col-seen.live-now { color: #4ade80; }  /* same green as .dot.on */
.col-actions .btn { margin-left: 8px; }
.cell-name .name { font-weight: 600; }
.os-ico {
  width: 14px; height: 14px;
  vertical-align: -2px; margin-right: 8px;
  color: var(--muted); flex: none;
}
.mp-os { display: inline-flex; }
.mp-os .os-ico { width: 15px; height: 15px; margin-right: 0; }

.dot {
  display: inline-block; width: 9px; height: 9px; border-radius: 50%;
  background: var(--muted);
}
.dot.on  { background: #4ade80; box-shadow: 0 0 0 3px rgba(74,222,128,.15); }
.dot.off { background: #6b7280; }

/* Filled, not outlined: a solid chip resolves faster than a tinted
   outline when scanning a column rather than reading it. */
.pill {
  display: inline-block; font-size: 11px; padding: 2px 9px; border-radius: 999px;
  border: 1px solid transparent; color: var(--chip-text);
  background: var(--chip-bg); letter-spacing: .2px;
}
.pill.warn { color: #fbbf24; background: var(--chip-warn-bg); }
/* ok/danger completed the set: the tokens existed but no rule used them,
   so a "Rollout halted" pill rendered in the same neutral grey as an
   ordinary label — the one state that must not be easy to skim past. */
.pill.ok { color: #4ade80; background: var(--chip-ok-bg); }
.pill.danger { color: #fff; background: var(--danger); }
/* Agent build version — dim, monospaced so digits line up when scanning. */
.pill.dim {
  color: var(--muted); opacity: .8;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  text-transform: none; letter-spacing: 0;
}

.empty-state { padding: 28px 16px; text-align: center; color: var(--muted); margin: 0; }

.spinner {
  width: 28px; height: 28px;
  border: 3px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .8s linear infinite;
  margin: 12vh 0;
}
@keyframes spin { to { transform: rotate(360deg); } }

.toast {
  position: fixed;
  bottom: 24px; left: 50%; transform: translateX(-50%);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 18px;
  box-shadow: 0 8px 24px rgba(0,0,0,.4);
}
.toast.error { border-color: var(--danger); }

/* ── Deploy-agent dialog ─────────────────────────────────────────────────── */
.modal-overlay {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(0, 0, 0, .55);
  display: flex; align-items: flex-start; justify-content: center;
  padding: 10vh 16px 16px;
}
.modal {
  width: 560px; max-width: 100%;
  box-shadow: 0 16px 48px rgba(0, 0, 0, .5);
}
.modal-head { margin-bottom: 4px; }
/* The deploy dialog is a three-step walkthrough, so it gets more room than
   the default confirm-style modal — and scrolls rather than overflowing on
   short screens. */
.modal-wide { width: 560px; max-height: 84vh; overflow-y: auto; }
/* Button + its build-metadata line, side by side: the metadata is a caption,
   not a second action, so it does not deserve its own row. */
.deploy-installer {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
}
.deploy-installer .btn { flex: none; }
.deploy-installer .muted { flex: 1 1 auto; min-width: 0; }
.select.block { display: block; width: 100%; }

/* Delivery method as tabs: one pane visible at a time. Stacking all three
   methods with a paragraph each is what made this dialog long — every RMM
   console (Atera, NinjaOne) shows one method at a time instead. */
.deploy-tenant { margin-bottom: 14px; }
.deploy-tabs {
  display: flex; gap: 2px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
}
.deploy-tab {
  appearance: none; background: none; border: none;
  border-bottom: 2px solid transparent;
  color: var(--muted); font: inherit; font-size: 13px;
  padding: 8px 12px; cursor: pointer; white-space: nowrap;
  margin-bottom: -1px;   /* sit the underline on the rail */
}
.deploy-tab:hover { color: var(--text); }
.deploy-tab.active { color: var(--text); border-bottom-color: var(--accent); }
/* One line of consequence copy per pane, then the action. */
.deploy-pane > * + * { margin-top: 10px; }
/* Expiry sits beside the download button: it modifies that action, so
   separating them into their own rows would overstate it. */
.deploy-ready-row { gap: 14px; }
/* Preparing a pre-configured installer re-signs ~60MB through the relay, so
   the button spins for the seconds that takes. min-width keeps the row from
   jumping as the label swaps to "Preparing…". */
.btn.is-busy {
  pointer-events: none; opacity: .8;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn.is-busy::before {
  content: ""; flex: none;
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .35);
  border-top-color: #fff;
  animation: spin .8s linear infinite;
}
/* Sized for the busy state ("Preparing…" + a 13px spinner + its 8px gap),
   not the resting "Download", so the row doesn't jump when the label
   swaps mid-download. */
#deploy-personalized-dl { min-width: 150px; text-align: center; }
@media (prefers-reduced-motion: reduce) {
  .btn.is-busy::before { animation-duration: 2.4s; }
}
.inline-field { display: flex; align-items: center; gap: 8px; }
.inline-field .field-label { margin: 0; white-space: nowrap; }
.pane-note { margin: 0; line-height: 1.45; }

/* Deploy-pane lifecycle notes. Each delivery tab states what it means for
   the machine's life, so the difference is visible at deploy time rather
   than months later. All three now say the same thing — machines stay
   maintainable — because the rebind credential closed the gap that made
   the personalized path a dead end. */
.pane-ok { margin: 0; font-size: 12.5px; color: var(--muted); }
/* Not when busy: .btn.is-busy needs inline-flex to lay out its ::before
   spinner, and this more-specific rule silently overrode it — the
   spinner rendered clipped against the button edge. */
.deploy-pane .btn.primary:not(.is-busy) { display: inline-block; }

/* Read-only value + Copy button. Used for the enrollment code and the silent
   command; the button confirms in place so the copy is unmissable. */
.copy-field .field-label { display: block; }
.copy-row { display: flex; align-items: center; gap: 8px; }
.copy-row .filter { min-width: 0; }
/* The silent-install command is longer than the dialog is wide. A one-line
   input hid its tail (the code was unreadable without scrolling the field),
   so it renders as a wrapping read-only block instead. */
.cmd-box {
  flex: 1 1 auto; min-width: 0;
  padding: 9px 11px; border-radius: 8px;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--text); font-size: 12.5px; line-height: 1.5;
  word-break: break-all; white-space: pre-wrap;
}
.copy-row .grow { flex: 1 1 auto; }
.copy-btn { flex: none; min-width: 62px; }
.copy-btn.copied {
  color: #4ade80; border-color: rgba(74,222,128,.4);
  background: rgba(74,222,128,.1);
}
.code-strong { font-size: 14px; letter-spacing: .4px; color: var(--text); }

/* ── Delete-machine modal ─────────────────────────────────────────────────── */
.row.end { display: flex; align-items: center; justify-content: flex-end; }
.btn.danger {
  background: var(--danger); border-color: var(--danger); color: #fff;
}
.btn.danger:hover:not(:disabled) { filter: brightness(1.08); }
.delete-choices { display: flex; flex-direction: column; gap: 10px; margin: 16px 0 4px; }
.delete-choice {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 12px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel-2); cursor: pointer;
}
.delete-choice:hover { border-color: var(--accent); }
.delete-choice input { margin-top: 3px; flex: none; }
.delete-choice b { display: block; font-weight: 600; font-size: 13px; }
.delete-choice em {
  display: block; font-style: normal; color: var(--muted);
  font-size: 12px; margin-top: 3px; line-height: 1.4;
}

/* ── Admin panel ─────────────────────────────────────────────────────────── */
h2 { font-size: 17px; margin: 36px 0 14px; }
h3 { font-size: 14px; margin: 0 0 12px; color: var(--text); }
/* Tabbed panes (one visible at a time). Forms and small tables read
   better narrow, so panes self-cap instead of going full-bleed. */
.admin-tabs { margin-bottom: 16px; }
.admin-pane { max-width: 860px; }
.user-form .select { flex: 0 0 130px; }
/* input.x outranks the later `.inline-form .num` 84px basis */
.user-form input.tenants-input { flex: 0 0 130px; }
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
}
.inline-form { display: flex; gap: 8px; margin-bottom: 14px; }
.inline-form input {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 8px 10px;
  font: inherit;
  flex: 1;
  min-width: 0;
}
.inline-form input:focus { outline: none; border-color: var(--accent); }
.inline-form .num { flex: 0 0 84px; }
.small-btn { padding: 8px 12px; font-size: 13px; }

/* Roles capability matrix: capabilities down, roles across. The pane cap
   (860px) stays; extra roles scroll sideways inside the wrap, and past
   ROLES_MATRIX_MAX roles the page switches to the picker below. */
.roles-matrix-wrap { overflow-x: auto; }
/* Past ROLES_MATRIX_MAX roles the custom columns collapse into one whose
   header is this dropdown; the column is tinted so it reads as "the one
   being edited" next to the pinned built-ins. */
.roles-matrix th.picked, .roles-matrix td.cap-cell.picked { background: var(--panel-2); }
.roles-matrix .role-col-select {
  width: 100%; max-width: 150px;
  font-size: 12px; padding: 4px 6px;
}
/* Keep the capability labels readable while the role columns scroll. */
.roles-matrix td.cap-label,
.roles-matrix th:first-child {
  position: sticky; left: 0; background: var(--panel);
}
.roles-matrix th.role-col { text-align: center; min-width: 96px; vertical-align: top; }
.roles-matrix th.role-col .link-btn { margin-top: 2px; }
.roles-matrix td.cap-cell { text-align: center; }
.roles-matrix td.cap-cell input {
  accent-color: var(--accent);
  cursor: pointer;
  width: 18px;
  height: 18px;
  vertical-align: middle;
}
.roles-matrix td.cap-cell input:disabled { cursor: default; }
/* Per-toggle "saved" confirmation. Absolutely placed so it never nudges the
   checkbox; fades out on its own. */
.roles-matrix td.cap-cell { position: relative; }
.roles-matrix .cap-saved {
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translate(-50%, -2px);
  font-size: 10px;
  font-weight: 600;
  color: #4ade80;   /* matches .badge.ok green */
  white-space: nowrap;
  pointer-events: none;
  animation: capSavedFade 1.6s ease-out forwards;
}
@keyframes capSavedFade {
  0% { opacity: 0; }
  12% { opacity: 1; }
  70% { opacity: 1; }
  100% { opacity: 0; }
}
.roles-matrix tr.cap-group td {
  padding-top: 14px; border-bottom: none;
  font-weight: 600; font-size: 12px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted);
}
.roles-matrix td.cap-label .mono { margin-left: 6px; }
.roles-scope { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.sso-map-panel { margin-top: 16px; }
.sso-map-panel .select { flex: 0 0 180px; }

.tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
.tbl th {
  text-align: left; font-weight: 500; color: var(--muted);
  padding: 6px 8px; border-bottom: 1px solid var(--border);
}
.tbl td { padding: 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
.tbl tr:last-child td { border-bottom: none; }
.tbl tr.inactive { opacity: .5; }
.tbl .actions { text-align: right; white-space: nowrap; }
.mono { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; }

.badge {
  font-size: 11px; padding: 1px 8px; border-radius: 999px;
  border: 1px solid transparent; color: var(--chip-text);
  background: var(--chip-bg);
}
.badge.ok { color: #4ade80; background: var(--chip-ok-bg); }

.link-btn {
  background: none; border: none; cursor: pointer;
  color: var(--accent); font: inherit; font-size: 13px;
  padding: 2px 6px; border-radius: 6px;
}
.link-btn:hover { background: var(--panel-2); }
.link-btn.danger { color: var(--danger); }

.select {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
  padding: 6px 10px;
  font: inherit; font-size: 13px;
  text-transform: capitalize;
}
.select:focus { outline: none; border-color: var(--accent); }

/* Guest-session panel (dashboard) */
.guest-panel { margin-bottom: 20px; }
.guest-panel h3 { margin: 0 0 4px; }
.guest-form { align-items: flex-end; flex-wrap: wrap; margin-top: 12px; margin-bottom: 0; }
.field.inline { margin-bottom: 0; }
.field.inline .field-label { display: block; margin-bottom: 4px; }
.guest-result {
  margin-top: 16px; padding-top: 16px;
  border-top: 1px solid var(--border);
}
.guest-result .mono { margin-left: 6px; }
.guest-code {
  font-size: 22px; font-weight: 600; letter-spacing: .18em;
  padding: 2px 10px; border: 1px dashed var(--border); border-radius: 8px;
}
.guest-sessions { margin-top: 16px; }
.guest-session-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; margin-top: 6px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 8px;
}
.guest-session-row .grow { flex: 1; min-width: 0; }
.guest-session-row .session-name {
  font-weight: 600; max-width: 220px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.seg { display: flex; gap: 2px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 8px; padding: 2px; }
.seg-btn {
  border: 0; background: transparent; color: var(--muted);
  font-size: 12.5px; font-weight: 500; padding: 3px 12px;
  border-radius: 6px; cursor: pointer;
}
.seg-btn.active { background: var(--panel); color: var(--text); }
.tenant-input { min-width: 220px; }
.tenant-name-input { padding: 6px 10px; font-size: 13px; min-width: 150px; }
td.truncated { text-align: center; padding: 10px; }
.pill.live {
  color: #4ade80; border-color: rgba(74,222,128,.3);
  background: rgba(74,222,128,.08);
}

/* Who's-connected chips: avatar + name + live duration, one per viewer. */
.v-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; padding: 2px 8px 2px 3px; border-radius: 999px;
  border: 1px solid rgba(74,222,128,.3);
  background: rgba(74,222,128,.08); color: #4ade80;
  vertical-align: middle; max-width: 220px;
  margin-left: 6px;
}
.v-chip-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500; letter-spacing: .2px;
}
.v-chip-dur {
  flex: none; font-variant-numeric: tabular-nums;
  color: rgba(74,222,128,.7);
  padding-left: 6px; border-left: 1px solid rgba(74,222,128,.22);
}
.v-chip-more { padding: 2px 9px; }

/* Initials avatar; --hue is set per identity so each technician keeps
   a stable color across rows and polls. */
.v-avatar {
  width: 18px; height: 18px; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 8.5px; font-weight: 700; letter-spacing: .3px;
  color: #fff; background: hsl(var(--hue, 210), 42%, 40%);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.12);
}
.v-avatar.lg { width: 28px; height: 28px; font-size: 11px; }

@keyframes pulse-dot {
  0%   { box-shadow: 0 0 0 0 rgba(74,222,128,.45); }
  70%  { box-shadow: 0 0 0 5px rgba(74,222,128,0); }
  100% { box-shadow: 0 0 0 0 rgba(74,222,128,0); }
}
.dot.pulse { animation: pulse-dot 2s ease-out infinite; }
.small { font-size: 12.5px; }
.filter.grow { flex: 1; min-width: 0; }
.row.between { justify-content: space-between; }

/* Divider between SSO and email-OTP */
.divider {
  display: flex; align-items: center; gap: 12px;
  color: var(--muted); font-size: 12px;
  margin: 20px 0;
}
.divider::before, .divider::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, transparent, var(--border), transparent);
}
.otp { width: 100%; }
.small { font-size: 12px; }

/* ── Machines master-detail layout ──────────────────────────────────────── */
/* Table on the left, detail side panel on the right (ScreenConnect-style).
   The panel is a sibling of .table-wrap so opening it never reflows the
   table's rows — only the table's width. */
.machines-layout {
  display: flex; gap: 16px; align-items: flex-start;
}
/* Filter sits directly above the machine list, spanning its width. */
.machines-layout .table-col {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 10px;
}
.machines-layout .table-col .filter { width: 100%; }

/* The machine list scrolls in place under a sticky header (same pattern
   as the audit log), so the filter, sidebar and detail panel stay
   visible while scrolling hundreds of rows. max-height only bites once
   the list outgrows the window — short lists are unaffected. */
#dashboard .table-wrap {
  max-height: calc(100vh - 230px);
  min-height: 240px;
  overflow-y: auto;
}
#dashboard .data-table thead th {
  position: sticky; top: 0; z-index: 2;
  /* Solid paint: the default translucent tint would let rows ghost
     through while scrolling. */
  background: linear-gradient(rgba(255,255,255,.03), rgba(255,255,255,.03)), var(--panel);
}

/* ── Tenant sidebar (session groups) ────────────────────────────────────── */
.tenant-sidebar {
  width: 210px; flex: none;
  position: sticky; top: 20px;
  display: flex; flex-direction: column; gap: 2px;
  max-height: calc(100vh - 120px); overflow-y: auto;
}
.tenant-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border: 0; background: transparent; color: var(--muted);
  font: inherit; font-size: 13.5px; font-weight: 500;
  padding: 7px 10px; border-radius: 8px;
  cursor: pointer; text-align: left;
  transition: background .12s, color .12s;
}
.tenant-item:hover { color: var(--text); background: var(--panel-2); }
.tenant-item.active { color: var(--text); background: var(--panel-2); }
.tenant-item .t-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
.tenant-item .t-counts {
  display: flex; align-items: center; gap: 6px; flex: none;
  font-size: 11.5px; font-variant-numeric: tabular-nums;
}
.tenant-item .t-total { color: var(--muted); }
.tenant-item .t-on {
  color: #4ade80;
  background: rgba(74,222,128,.10);
  border: 1px solid rgba(74,222,128,.25);
  border-radius: 999px; padding: 0 7px; line-height: 17px;
}

/* Sidebar tenant search (shown when the group list grows long) */
.tenant-search {
  min-width: 0; width: 100%;
  padding: 7px 10px; font-size: 13px;
  margin-bottom: 4px; flex: none;
}

/* Sidebar section label ("Tags") */
.side-label {
  margin: 14px 10px 4px;
  font-size: 11px; font-weight: 600; letter-spacing: .4px;
  text-transform: uppercase; color: var(--muted);
}

/* Sidebar tag entries get a # marker so they read as tags, not tenants. */
.tag-item .t-name::before {
  content: "#";
  margin-right: 5px;
  color: #93c5fd; font-weight: 600;
}

/* Tag chips on machine rows — small clickable pills that toggle the
   tag filter. Accent-tinted so they read as tags at a glance. */
.tag-chip {
  font: inherit; font-size: 11.5px; font-weight: 500;
  display: inline-block; padding: 2px 9px; margin-left: 6px;
  border-radius: 999px; cursor: pointer;
  color: #93c5fd; background: rgba(var(--accent-rgb),.12);
  border: 1px solid rgba(var(--accent-rgb),.35);
  transition: color .12s, border-color .12s, background .12s;
}
.tag-chip:hover {
  color: #bfdbfe; border-color: rgba(var(--accent-rgb),.6);
  background: rgba(var(--accent-rgb),.2);
}

/* Tag editor in the detail panel */
.mp-tags:not(:empty) { margin-bottom: 14px; }
.mp-tag-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.tag-chip-static {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 500;
  color: #93c5fd; background: rgba(var(--accent-rgb),.12);
  border: 1px solid rgba(var(--accent-rgb),.35);
}
.tag-x {
  border: 0; background: transparent; color: inherit; opacity: .7;
  font: inherit; font-size: 13px; line-height: 1;
  padding: 0 1px; cursor: pointer;
}
.tag-x:hover { opacity: 1; }
.tag-x:hover { color: var(--danger); }
.mp-tag-input { padding: 6px 10px; font-size: 12.5px; }

/* Narrow windows: the group list becomes a horizontal chip row above the
   table instead of squeezing it. */
@media (max-width: 980px) {
  .machines-layout { flex-wrap: wrap; }
  .tenant-sidebar {
    position: static;
    width: 100%; max-height: none;
    flex-direction: row; flex-wrap: nowrap; overflow-x: auto;
    padding-bottom: 4px;
  }
  .tenant-item { flex: none; }
  /* In the horizontal chip row the search becomes a fixed-width lead-in. */
  .tenant-search { width: 160px; margin-bottom: 0; }
}

/* Rows are selectable — show it. */
#agents tr { cursor: pointer; }
#agents tr.selected,
#agents tr.selected:hover { background: rgba(var(--accent-rgb),.10); }
#agents tr.selected td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

.machine-panel {
  /* Scales with the window now that the page is full-bleed. Capped at
     560px: the screen preview is a 512px-wide JPEG from the agent
     (capture-core monitors.rs thumb_w) — much past this it upscales
     visibly soft. */
  width: clamp(380px, 28vw, 560px); flex: none;
  position: sticky; top: 20px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  animation: mp-in .16s ease;
}
@keyframes mp-in {
  from { opacity: 0; transform: translateX(10px); }
  to   { opacity: 1; transform: none; }
}
.mp-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px;
}
.mp-title {
  display: flex; align-items: center; gap: 9px; min-width: 0;
}
.mp-name {
  font-weight: 650; font-size: 16px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mp-close {
  border: 0; background: transparent; color: var(--muted);
  font-size: 14px; line-height: 1; padding: 6px 8px; border-radius: 7px;
  cursor: pointer;
}
.mp-close:hover { color: var(--text); background: var(--panel-2); }
.mp-pills { margin-bottom: 12px; display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
.mp-actions { display: flex; gap: 8px; margin-bottom: 14px; }
.mp-actions .btn { flex: 1; }
/* On-demand screen preview in the machine panel. The image is a 512px
   JPEG from the agent (older agents send 360px), shown at panel width;
   aspect varies with the remote monitor, so no fixed height. */
.mp-thumb:not(:empty) { margin-bottom: 14px; }
.thumb-img {
  display: block; width: 100%;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: #000;
}
.thumb-meta {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 6px;
}
.thumb-empty {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  border: 1px dashed var(--border);
  border-radius: 8px;
  padding: 14px 12px;
}

.mp-viewers:not(:empty) { margin-bottom: 14px; }
.mp-viewer {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; padding: 6px 8px;
  border: 1px solid var(--border); border-radius: 8px;
  margin-top: 6px; background: var(--panel-2);
}
.mp-viewer .v-id {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; line-height: 1.3;
}
.mp-viewer .v-name {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 500;
}
.mp-viewer .v-email {
  font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mp-viewer .v-dur {
  flex: none; font-variant-numeric: tabular-nums;
  display: inline-flex; align-items: center; gap: 7px;
}
.mp-viewer .v-kick {
  flex: none; width: 22px; height: 22px; padding: 0;
  border: 0; border-radius: 6px; cursor: pointer;
  background: transparent; color: var(--muted);
  font-size: 13px; line-height: 1;
}
.mp-viewer .v-kick:hover { color: #f87171; background: rgba(248,113,113,.1); }
.mp-viewer .v-kick:disabled { opacity: .5; cursor: default; }
.mp-body {
  border-top: 1px solid var(--border);
  padding-top: 12px;
  max-height: calc(100vh - 300px);
  overflow-y: auto;
}

/* Recent activity: the machine's latest audit events, inside the
   scrollable panel body under the inventory. */
.mp-events:not(:empty) {
  border-top: 1px solid var(--border);
  margin-top: 14px; padding-top: 12px;
}
.mp-events-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 4px;
}
.mp-events-head .field-label { margin: 0; }
.mp-events-head a.link-btn { text-decoration: none; font-size: 12px; }
.mp-ev {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 0; font-size: 12px; min-width: 0;
}
/* Family colour comes from the ev-* rules' `color`; higher specificity
   than .ev-* so their pill background/border don't apply to the dot. */
.mp-ev .mp-ev-dot.ev {
  flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: currentColor; border: 0;
  color: var(--muted);              /* families without an ev-* rule */
}
.mp-ev-type {
  flex: none; max-width: 55%;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 11px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mp-ev-detail {
  flex: 1; min-width: 0; font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mp-ev-time { flex: none; font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Narrow windows: don't squeeze the table — float the panel over it. */
@media (max-width: 980px) {
  .machine-panel {
    position: fixed; top: 76px; right: 12px; bottom: 12px;
    width: min(360px, calc(100vw - 24px));
    z-index: 30;
    box-shadow: 0 24px 60px -18px rgba(0,0,0,.65);
    overflow-y: auto;
  }
  .mp-body { max-height: none; }
}

/* Key-value inventory grid (inside the panel) */
.kv-grid {
  display: grid; grid-template-columns: max-content 1fr;
  gap: 6px 16px; font-size: 12.5px;
}
.kv-k { color: var(--muted); white-space: nowrap; }
.kv-v { word-break: break-word; }

/* ── Audit page ─────────────────────────────────────────────────────────── */
.audit-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin: 4px 0 18px;
}
.audit-title h1 { margin: 0; }
.audit-title p { margin: 4px 0 0; }
.audit-toolbar {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  justify-content: flex-end;
}
.audit-search { flex: none; width: 240px; min-width: 0; }
.audit-tenant-input { flex: none; width: 170px; min-width: 0; }
#audit-tenant-combo .combo-list { min-width: 240px; }

/* Session rows drill into their events — the whole row is the target. */
#audit-sessions tr.clickable { cursor: pointer; }
#audit-sessions tr.clickable:hover { background: rgba(var(--accent-rgb),.07); }

/* Machine names that exist on the Machines page link to their panel. */
.machine-link { color: var(--text); text-decoration: none; }
.machine-link:hover { color: var(--accent); text-decoration: underline; }

/* Tables scroll in place under a sticky header, so the toolbar and the
   summary strip stay visible while paging through hundreds of rows. */
#audit-view .table-wrap {
  max-height: calc(100vh - 380px);
  min-height: 280px;
  overflow-y: auto;
}
#audit-view .data-table thead th {
  position: sticky; top: 0; z-index: 2;
  /* Solid paint: the default translucent tint would let rows ghost
     through while scrolling. */
  background: linear-gradient(rgba(255,255,255,.03), rgba(255,255,255,.03)), var(--panel);
}
/* Denser rows than the machines table — audit is a log. */
#audit-view .data-table tbody td { padding: 8.5px 16px; }

/* "You are looking at one session" banner above the filtered event log */
.audit-context {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: rgba(var(--accent-rgb),.08);
  border: 1px solid rgba(var(--accent-rgb),.3);
  border-radius: 10px;
  padding: 9px 14px;
  margin-bottom: 12px;
  font-size: 13.5px;
}
.audit-context .ac-label {
  font-size: 11px; font-weight: 600; letter-spacing: .5px;
  text-transform: uppercase; color: var(--accent);
}
.audit-context .btn { margin-left: auto; }

/* Summary strip */
.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}
.stat-row:empty { display: none; }
.stat {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 13px 16px 12px;
  min-width: 0;
}
.stat .s-label {
  font-size: 11.5px; color: var(--muted);
  letter-spacing: .4px; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.stat .s-value {
  font-size: 24px; font-weight: 600; color: var(--text);
  margin-top: 5px; line-height: 1.1;
  display: flex; align-items: center; gap: 8px;
}
.stat .s-value .dot { flex: none; }
.stat .s-sub { font-size: 11.5px; color: var(--muted); margin-top: 3px; }

/* Segmented Sessions|Events switch. The active segment is a solid accent
   chip — a panel-2 tint was too subtle to read as "selected". */
.seg {
  display: inline-flex; gap: 2px; padding: 3px;
  border: 1px solid var(--border); border-radius: 9px;
  background: var(--panel);
}
.seg-btn {
  background: transparent; color: var(--muted); border: none;
  padding: 5px 14px; border-radius: 6px;
  font: inherit; font-size: 13px; cursor: pointer;
  transition: background .12s, color .12s;
}
.seg-btn:hover { color: var(--text); }
.seg-btn.active { background: var(--accent); color: #fff; font-weight: 600; }

.nowrap { white-space: nowrap; }
.data-table .col-num { text-align: right; }
.data-table .col-time { width: 150px; }
.tnum { font-variant-numeric: tabular-nums; }
.detail-cell { max-width: 420px; }

/* Support-session marker in the machine column */
.pill.sup {
  color: #2dd4bf; border-color: rgba(45,212,191,.35); background: rgba(45,212,191,.08);
  text-transform: lowercase;
}

.load-more-row { display: flex; justify-content: center; margin: 14px 0 4px; }

/* Event-type pills, tinted by family (prefix before the dot) */
.pill.ev { font-family: ui-monospace, "Cascadia Code", Consolas, monospace; text-transform: none; }
.ev-session   { color: #60a5fa; border-color: rgba(96,165,250,.35);  background: rgba(96,165,250,.08); }
.ev-file      { color: #fbbf24; border-color: rgba(251,191,36,.35);  background: rgba(251,191,36,.08); }
.ev-clipboard { color: #c084fc; border-color: rgba(192,132,252,.35); background: rgba(192,132,252,.08); }
.ev-system    { color: #f87171; border-color: rgba(248,113,113,.4);  background: rgba(248,113,113,.08); }
.ev-backstage { color: #f87171; border-color: rgba(248,113,113,.4);  background: rgba(248,113,113,.08); }
.ev-admin     { color: #2dd4bf; border-color: rgba(45,212,191,.35);  background: rgba(45,212,191,.08); }
.ev-auth      { color: #fb923c; border-color: rgba(251,146,60,.35);  background: rgba(251,146,60,.08); }
.ev-screen    { color: #34d399; border-color: rgba(52,211,153,.35);  background: rgba(52,211,153,.08); }
.ev-monitor   { color: #818cf8; border-color: rgba(129,140,248,.35); background: rgba(129,140,248,.08); }
.ev-chat      { color: #f472b6; border-color: rgba(244,114,182,.35); background: rgba(244,114,182,.08); }

/* ── Console chat pane (machine panel) ─────────────────────────────── */
.mp-chat {
  margin: 14px 0 18px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-2);
  display: flex; flex-direction: column;
}
.mp-chat.hidden { display: none; }
.mp-chat-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px 4px;
}
.mp-chat-head .field-label { margin: 0; color: #f472b6; }
.mp-close.small { font-size: 12px; padding: 2px 6px; }
.mp-chat-log {
  height: 240px; overflow-y: auto;
  padding: 10px;
  display: flex; flex-direction: column; gap: 8px;
  background: var(--bg);
  border-top: 1px solid var(--border);
}
.mp-chat-empty { text-align: center; margin-top: 12px; }
.mp-chat-row { display: flex; }
.mp-chat-row.tech  { justify-content: flex-end; }
.mp-chat-row.guest { justify-content: flex-start; }
.mp-chat-bubble {
  max-width: 85%;
  padding: 6px 10px;
  border-radius: 10px;
  font-size: 13px;
  line-height: 1.35;
}
.mp-chat-bubble.tech  { background: rgba(var(--accent-rgb),.18); border: 1px solid rgba(var(--accent-rgb),.25); border-bottom-right-radius: 3px; }
.mp-chat-bubble.guest { background: var(--panel-2); border: 1px solid var(--border); border-bottom-left-radius: 3px; }
.mp-chat-meta { display: block; font-size: 10.5px; margin-bottom: 3px; white-space: nowrap; }
.mp-chat-text { display: block; white-space: pre-wrap; word-break: break-word; }
.mp-chat-sys { text-align: center; font-style: italic; padding: 2px 0; }
.mp-chat-input {
  display: flex; gap: 8px;
  padding: 8px 10px 10px;
  border-top: 1px solid var(--border);
}
.mp-chat-input .filter { flex: 1; min-width: 0; padding: 8px 10px; }

/* Thumbnail mid-refresh: keep the stale image up but visibly "busy". */
.thumb-img.thumb-loading { opacity: .45; transition: opacity .15s; }

/* Relay guardrail line under the guest-session download link */
.guest-warning {
  color: #fbbf24;
  background: rgba(251,191,36,.08);
  border: 1px solid rgba(251,191,36,.3);
  border-radius: 8px;
  padding: 8px 10px;
  margin: 10px 0 0;
}

.retention-form { display: flex; flex-direction: column; gap: 12px; align-items: flex-start; }
.retention-form .field.inline { width: 100%; }
.retention-input { display: flex; align-items: center; gap: 8px; }
.retention-input .num {
  width: 90px;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text);
  border-radius: 8px; padding: 8px 10px; font: inherit;
}
.retention-input .num:focus { outline: none; border-color: var(--accent); }
.ev-auth      { color: #4ade80; border-color: rgba(74,222,128,.35);  background: rgba(74,222,128,.08); }
.ev-agent     { color: #4ade80; border-color: rgba(74,222,128,.35);  background: rgba(74,222,128,.08); }
.ev-screen    { color: #a78bfa; border-color: rgba(167,139,250,.35); background: rgba(167,139,250,.08); }
.ev-admin     { color: #22d3ee; border-color: rgba(34,211,238,.35);  background: rgba(34,211,238,.08); }
.ev-support   { color: #2dd4bf; border-color: rgba(45,212,191,.35);  background: rgba(45,212,191,.08); }

/* ── Scrollbars ─────────────────────────────────────────────────────────── */
/* Slim, rounded, theme-matched — the stock chrome scrollbar reads as a
   foreign element on the dark surface. The transparent border +
   background-clip inset the thumb so it floats inside the gutter. */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--panel-2);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
  min-height: 40px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--hover-border);
  border: 3px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-corner { background: transparent; }

/* Firefox (no ::-webkit-scrollbar): thin native bar in matching colors. */
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: var(--panel-2) transparent; }
}

/* ── Phones ─────────────────────────────────────────────────────────────── */
/* The ≤980px rules above already collapse the tenant sidebar into a chip
   row and float the detail panel; this pass handles actual phone widths. */
@media (max-width: 640px) {
  header { padding: 10px 12px; flex-wrap: wrap; row-gap: 6px; }
  .header-left { gap: 14px; min-width: 0; }
  .nav { overflow-x: auto; }
  .nav-link { padding: 6px 9px; white-space: nowrap; }
  /* The signed-in email eats the whole bar on a phone. */
  #who { display: none; }

  main { padding: 14px 12px; }
  h1 { font-size: 19px; }
  .page-head { flex-wrap: wrap; row-gap: 10px; }

  .data-table thead th { padding: 9px 10px; }
  .data-table tbody td { padding: 10px 10px; }
  /* Machines table: status + name + actions is what matters on a phone;
     Tenant and Mode live in the detail panel anyway. */
  #agents-table th:nth-child(3), #agents-table td:nth-child(3),
  #agents-table th:nth-child(4), #agents-table td:nth-child(4),
  #agents-table th:nth-child(5), #agents-table td:nth-child(5) { display: none; }
  .col-actions .btn { margin-left: 6px; padding: 8px 11px; }

  /* Detail panel becomes a full-screen sheet (✕ closes it). */
  .machine-panel {
    top: 0; right: 0; bottom: 0; left: 0;
    width: 100%; border-radius: 0; border: 0;
  }

  /* Admin forms wrap instead of crushing four controls into one row. */
  .inline-form { flex-wrap: wrap; }
  .inline-form input { flex: 1 1 160px; }

  /* Wide log tables scroll sideways instead of crushing their columns. */
  #audit-view .table-wrap { overflow-x: auto; max-height: none; }
  #audit-view .data-table { min-width: 640px; }
  .audit-toolbar { justify-content: flex-start; }
  .audit-search, .audit-tenant-input { flex: 1 1 100%; width: 100%; }
  .detail-cell { max-width: 240px; }
}

/* ── Machine page (#/machine/<id>) — Diagnostic Tools ─────────────────── */

.mv-head {
  display: flex; align-items: center; gap: 14px;
  padding: 18px 20px; margin-bottom: 16px;
  background: linear-gradient(180deg, rgba(255,255,255,.02), transparent), var(--panel);
  border: 1px solid var(--border); border-radius: 12px;
}
.mv-head #mv-back { flex: 0 0 auto; }
.mv-head .dot { flex: 0 0 auto; }
/* OS icon in a tinted tile (Zoho-style device identity block). */
.mv-os {
  width: 44px; height: 44px; flex: 0 0 auto;
  display: grid; place-items: center;
  color: var(--accent);
  background: rgba(var(--accent-rgb),.12);
  border: 1px solid rgba(var(--accent-rgb),.25);
  border-radius: 12px;
}
.mv-os:empty { display: none; }
.mv-os .os-ico { width: 22px; height: 22px; margin: 0; color: inherit; }
.mv-titlebox { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.mv-name { font-size: 20px; margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mv-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.mv-actions { margin-left: auto; display: flex; gap: 8px; flex: 0 0 auto; }

/* Underline-style tab strip (reads as page navigation, not a toggle). */
.mv-tabs {
  background: transparent; border: 0; border-radius: 0; padding: 0;
  border-bottom: 1px solid var(--border);
  gap: 2px; margin-bottom: 16px; flex-wrap: wrap;
}
.mv-tabs .seg-btn {
  padding: 9px 14px; font-size: 13.5px;
  border-radius: 8px 8px 0 0;
}
.mv-tabs .seg-btn:hover { background: var(--panel-2); }
.mv-tabs .seg-btn.active {
  background: transparent; color: var(--accent); font-weight: 600;
  box-shadow: inset 0 -2px 0 var(--accent);
}

/* Machine view fills the viewport so its tab panel can own a real, bounded
   height. Without this the per-tab bodies stacked `vh` caps that summed to
   more than the screen, so content clipped at the top and the Files dock
   slid off the bottom. The head + tab strip are fixed-height; the panel
   takes the rest and scrolls internally per tab.

   Sized via a body→main→view flex chain rather than a calc() constant:
   the old `calc(100vh - 56px)` subtracted <main>'s padding but not the
   header bar above it, so the page was always ~60px taller than the
   window and showed a permanent scrollbar even when the tab fit. */
body:has(#machine-view:not(.hidden)) {
  height: 100vh;
  display: flex; flex-direction: column;
}
body:has(#machine-view:not(.hidden)) > header { flex: 0 0 auto; }
body:has(#machine-view:not(.hidden)) > main {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column;
}
#machine-view:not(.hidden) {
  display: flex; flex-direction: column;
  flex: 1 1 auto;
  min-height: 480px; /* short windows: overflow (and scroll) instead of crushing */
}
#machine-view > .mv-head,
#machine-view > .mv-tabs { flex: 0 0 auto; }
/* The panel takes all remaining height; min-height:0 lets its flex children
   (tables, docks) shrink and scroll instead of overflowing the panel.
   overflow-y:auto is the safety net for tabs that DON'T manage their own
   scroll (Overview's cards): if their content is taller than the panel it
   scrolls here. Tabs with an internal scroll region (Files, the inventory
   tables, Disk Usage, Console) fill the panel exactly via flex, so this
   outer scrollbar never engages for them. */
.mv-tabpanel {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column;
}
/* Tab-panel children default to their NATURAL height, so flow tabs
   (Overview, Registry) overflow and scroll via the panel's overflow-y.
   The filler regions that instead bound their own internal scroll —
   .fm, .mv-console, .mv-table-wrap (all `flex: 1 1 auto; min-height: 0`
   in their own, later rules, which win) and .du (height: 100%) — opt out.
   The old blanket `min-height: 0` was wrong: the flex shrink pass crushed
   fixed chrome to zero height (diag toolbars painted under the tab strip,
   Overview's stat tiles collapsed into the cards) instead of scrolling. */
.mv-tabpanel > * { flex: 0 0 auto; }

.mv-toolbar {
  display: flex; align-items: center; gap: 10px; margin-bottom: 10px;
}
.mv-toolbar .field-label { font-size: 13px; font-weight: 600; color: var(--text); }
.mv-filter { flex: 1 1 auto; max-width: 320px; }
.mv-toolbar #mv-refresh-processes,
.mv-toolbar [id^="mv-refresh-"] { flex: 0 0 auto; }

.mv-table-wrap {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; overflow: auto;
  /* Fill the panel below the toolbar and scroll internally, matching the
     Files tab. Falls back to a sensible cap if a tab root isn't a flex
     column (min-height:0 lets it shrink inside one). */
  flex: 1 1 auto; min-height: 160px; max-height: 100%;
}
.mv-data-table { width: 100%; }
/* Denser rows than the machines table — these lists run long. */
.mv-data-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--panel-2);
}
.mv-data-table tbody td { padding: 7px 12px; font-size: 13px; }
.mv-data-table tbody tr:hover { background: var(--panel-2); }
/* Click-to-sort headers; the active column reads solid. */
.mv-data-table th.sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.mv-data-table th.sortable:hover { color: var(--text); }
.mv-data-table th.sorted { color: var(--text); }

/* Expandable rows (software): click for the registry detail. */
.mv-data-table tr.expand { cursor: pointer; }
.mv-data-table tr.expanded td {
  border-bottom: 0;
  background: rgba(var(--accent-rgb),.08);
}
.mv-detail-row td {
  background: var(--panel-2);
  padding: 10px 14px 12px;
  border-bottom: 1px solid var(--border);
}
.sw-detail { font-size: 12.5px; gap: 7px 18px; }
.mv-detail-row .kv-v {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  word-break: break-word;   /* prose (descriptions) wraps at words… */
}
.mv-detail-row .kv-v .mono { word-break: break-all; } /* …paths anywhere */
.mv-detail-row .kv-v a { color: var(--accent); }
.sw-uninst { font-size: 12px; }
.mv-data-table .col-actions { text-align: right; white-space: nowrap; }
.mv-data-table .col-actions .btn { margin-left: 6px; }

/* Live print queue inside an expanded printer row. */
.pj-jobs { margin-top: 12px; }
.pj-title { margin-bottom: 6px; display: block; }
.pj-table { font-size: 12.5px; }
.pj-table th, .pj-table td { padding: 6px 10px; }

.mv-error { padding: 1.5rem; color: var(--danger); }

.mv-console { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; height: 100%; }
.mv-console-bar { display: flex; align-items: center; gap: 12px; flex: 0 0 auto; }
.mv-console-bar .field-label { font-weight: 600; color: var(--text); }
.mv-console-bar a { margin-left: auto; }
.mv-console-frame {
  width: 100%; flex: 1 1 auto; min-height: 380px;
  border: 1px solid var(--border); border-radius: 12px;
  background: #000;
}
.mv-console-hint { padding: 2px 2px 0; }

@media (max-width: 720px) {
  .mv-head { flex-wrap: wrap; row-gap: 10px; }
  .mv-actions { margin-left: 0; }
  .mv-table-wrap { max-height: none; }
  .mv-data-table { min-width: 560px; }
}

/* ── Overflow action menu ("⋯") ─────────────────────────────────────────── */
.act-menu-wrap { position: relative; flex: none; }
/* .mp-actions stretches its buttons (flex: 1) — the menu trigger stays
   compact instead of ballooning to a quarter of the row. */
.mp-actions .act-menu-wrap .btn,
.mv-actions .act-menu-wrap .btn { flex: none; }
.act-menu-btn { font-weight: 700; letter-spacing: 1px; }
.act-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 45;
  min-width: 200px; padding: 5px;
  background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 18px 44px -12px rgba(0,0,0,.65), 0 0 0 1px rgba(255,255,255,.02) inset;
  display: flex; flex-direction: column; gap: 1px;
}
.act-menu-item {
  display: flex; align-items: center; gap: 9px;
  border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 13.5px; text-align: left;
  padding: 8px 10px; border-radius: 7px;
  cursor: pointer; white-space: nowrap;
}
.act-menu-item:hover:not(:disabled) { background: rgba(var(--accent-rgb),.14); }
.act-menu-item:disabled { opacity: .45; cursor: default; }
.act-menu-item.danger { color: #f87171; }
.act-menu-item.danger:hover:not(:disabled) { background: rgba(248,113,113,.12); }
.act-menu-item .mi-ico { width: 18px; flex: none; text-align: center; opacity: .9; }
.act-menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* ── Machine page Overview (stat tiles + grouped cards) ─────────────────── */
.ov-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px; margin-bottom: 14px;
}
/* Tiles reuse the audit page's .stat chrome; these extend it. */
.ov-stats .stat .s-sub {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.stat .s-unit { font-size: 13px; font-weight: 500; color: var(--muted); }
.meter {
  height: 6px; border-radius: 999px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
  margin-top: 9px;
}
.meter > span { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
.meter > span.warn { background: #fbbf24; }
.meter > span.crit { background: var(--danger); }

/* Left rail (Screen + Agent) beside a main grid. Main-row cards stretch
   to equal height, so the row bottoms stay flush instead of ragged. */
.ov-layout {
  display: grid; grid-template-columns: 380px 1fr;
  gap: 14px; align-items: start;
}
.ov-side { display: flex; flex-direction: column; gap: 14px; }
.ov-main {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}
@media (max-width: 1100px) {
  .ov-layout { grid-template-columns: 1fr; }
  /* Rail cards sit side by side when the rail spans the full width. */
  .ov-side {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  }
}
.ov-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; padding: 16px 18px;
}
.ov-card-title {
  font-size: 11.5px; font-weight: 600; letter-spacing: .5px;
  text-transform: uppercase; color: var(--muted);
  margin-bottom: 12px;
}
.ov-card .kv-grid { font-size: 13px; gap: 8px 18px; }
/* Recent-activity card spans the whole main grid. */
.ov-main .ov-span { grid-column: 1 / -1; }
.ov-card .mp-viewer:first-child { margin-top: 0; }
.ov-activity-all { display: inline-block; margin-top: 6px; text-decoration: none; }
/* Screen-preview card reuses the panel's .thumb-* chrome. */
.mv-thumb .thumb-img { border-radius: 8px; }

/* Inventory-tab summary strip (.diag-stats slot between toolbar and
   table; empty for kinds without stats — .stat-row:empty hides it).
   Clickable tiles push a canned needle into the filter box. */
.diag-stats { margin: 2px 0 12px; }
.diag-stats .s-value.bad { color: var(--danger); }
.stat-click { cursor: pointer; }
.stat-click:hover { border-color: var(--accent); }

/* Hardware tab: same card chrome as the overview; .hw-cards is a plain
   auto-fit grid (no side rail). Tables inside cards use the compact
   .tbl style. */
.hw-cards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}
.hw-cards .ov-span { grid-column: 1 / -1; }
.hw-total { margin: -6px 0 8px; }
.ov-card .tbl td { font-size: 12.5px; }
.ov-card .tbl th { font-size: 11px; text-transform: uppercase; letter-spacing: .3px; }

/* ── Files tab (file manager) ──────────────────────────────────────────── */
.fm { display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; height: 100%; }
.icon-btn { padding: 5px 9px; line-height: 1; }
/* Nav buttons (back/forward/up/refresh) get a larger, square-ish hit
   area than the tiny per-row icon buttons. */
.fm-crumbbar .icon-btn {
  font-size: 17px;
  min-width: 36px;
  padding: 8px 10px;
}
.fm-svg { width: 16px; height: 16px; display: inline-block; vertical-align: -3px; }
.fm-svg-folder { color: #eab54e; }        /* manila folder */
.fm-svg-file { color: var(--muted); }
.fm-svg-drive { color: var(--muted); }
.fm-crumb .fm-svg { margin-right: 5px; color: var(--muted); }

/* Breadcrumb bar: nav buttons + clickable path segments. */
.fm-crumbbar {
  display: flex; align-items: center; gap: 4px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 5px 8px;
  flex: 0 0 auto;
}
.fm-crumbs { display: flex; align-items: center; gap: 1px; flex-wrap: wrap; margin-left: 4px; flex: 1 1 auto; min-height: 32px; cursor: text; }
.fm-crumb {
  display: inline-flex; align-items: center;
  border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 15px; padding: 5px 9px; border-radius: 7px; cursor: pointer;
}
.fm-crumb:hover { background: rgba(var(--accent-rgb),.14); }
.fm-crumb.cur { font-weight: 600; }
.fm-crumb .fm-svg { width: 18px; height: 18px; }
.fm-sep { color: var(--muted); font-size: 13px; opacity: .7; }
.fm-path-input {
  flex: 1 1 auto; margin-left: 4px; font: inherit; font-size: 15px;
  padding: 5px 9px; border-radius: 7px;
  border: 1px solid var(--accent); background: var(--panel-2); color: var(--text);
}

.fm-toolbar { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.fm-count { font-weight: 600; font-size: 13px; }
.fm-hidden-toggle { display: inline-flex; align-items: center; gap: 6px; cursor: pointer; user-select: none; }
.fm-hidden-toggle input {
  margin: 0;
  width: 16px; height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}
.fm-tspacer { flex: 1 1 auto; }
.fm-filter { max-width: 220px; }
.fm-upload.disabled { opacity: .45; pointer-events: none; }

/* Selection action bar (appears when rows are checked). */
.fm-selbar {
  display: flex; align-items: center; gap: 8px; flex: 0 0 auto;
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--border));
  border-radius: 10px; padding: 7px 12px; font-size: 13px;
}
.fm-selbar #fm-selcount { font-weight: 600; margin-right: 4px; }
.fm-selbar .btn { margin-left: 0; }
.fm-selbar #fm-sel-clear { margin-left: auto; }

/* Drive cards (the root level), Explorer's "Devices and drives". */
.fm-drives-wrap { padding: 14px 16px; }
.fm-drives-head {
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .5px;
  margin: 0 2px 12px;
}
.fm-drives {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px;
}
.fm-drive {
  display: flex; align-items: center; gap: 14px;
  text-align: left; cursor: pointer;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 12px; padding: 16px; color: var(--text); font: inherit;
  transition: border-color .12s, box-shadow .12s;
}
.fm-drive:hover { border-color: var(--accent); box-shadow: 0 2px 12px rgba(0,0,0,.18); }
.fm-drive-badge {
  flex: none; width: 48px; height: 48px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  color: var(--accent);
}
.fm-drive-badge .fm-svg { width: 28px; height: 28px; color: inherit; }
.fm-drive-body { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.fm-drive-name {
  font-size: 15px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fm-drive-letter { color: var(--muted); font-weight: 500; }
.fm-drive-body .meter { margin: 7px 0 6px; height: 7px; }
.fm-drive-sub { font-size: 12.5px; }

/* The file table. Sits in a scroll region so the dock stays visible. */
.fm-table-wrap {
  position: relative;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; overflow: auto;
  /* Grow to fill the space between the toolbars and the dock; scroll
     internally. min-height:0 is required so it can shrink below content
     size inside the flex column instead of pushing the dock off-screen. */
  flex: 1 1 auto; min-height: 120px;
}
/* border-collapse: separate — NOT collapse — is what makes the sticky
   header paint correctly: Chrome mis-renders sticky th in collapsed
   tables (rows bleed over/under the header while scrolling), and the
   th's bottom border scrolls away with the rows. */
.fm-data-table { width: 100%; border-collapse: separate; border-spacing: 0; }
/* thead th, not bare th: the shared `.data-table thead th` rule outranks
   `.fm-data-table th` and would repaint the sticky header with its 2%-
   alpha background — rows ghost straight through it while scrolling. */
.fm-data-table thead th {
  position: sticky; top: 0; z-index: 2; background: var(--panel-2);
  text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .4px;
  color: var(--muted); padding: 10px 12px; border-bottom: 1px solid var(--border);
  white-space: nowrap; user-select: none;
}
.fm-data-table th.fm-sortable { cursor: pointer; }
.fm-data-table th.fm-sortable:hover { color: var(--text); }
.fm-sortarrow { font-size: 9px; margin-left: 3px; color: var(--accent); }
.fm-data-table td { padding: 7px 12px; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: middle; }
.fm-data-table tbody tr { transition: background .08s; }
.fm-data-table tbody tr:hover { background: rgba(var(--accent-rgb),.07); }
.fm-data-table tbody tr.fm-sel { background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* Reveal-from-Disk-Usage: brief pulse on the row that was scrolled to, so
   the eye lands on it even in a long listing. */
.fm-data-table tbody tr.fm-flash { animation: fm-flash 1.6s ease-out; }
@keyframes fm-flash {
  0% { background: color-mix(in srgb, var(--accent) 45%, transparent); }
  100% { background: color-mix(in srgb, var(--accent) 12%, transparent); }
}
.fm-data-table tbody tr:hover .fm-row-actions,
.fm-data-table tbody tr.fm-sel .fm-row-actions { opacity: 1; }
.fm-col-type, .fm-col-size, .fm-col-date { color: var(--muted); }
.fm-col-size { text-align: right; font-variant-numeric: tabular-nums; }
.fm-check { width: 42px; text-align: center; cursor: pointer; }
.fm-check input {
  cursor: pointer;
  width: 16px; height: 16px;
  accent-color: var(--accent);
  vertical-align: middle;
}
.fm-name-cell { cursor: default; max-width: 0; }
.fm-row-dir .fm-name-cell { cursor: pointer; }
.fm-row-dir .fm-name-txt { font-weight: 500; }
.fm-name { display: inline-flex; align-items: center; gap: 8px; max-width: 100%; }
.fm-name-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fm-dim { opacity: .5; }
.fm-row-actions { text-align: right; white-space: nowrap; opacity: 0; transition: opacity .1s; width: 78px; }
.fm-row-actions .fm-act { margin-left: 1px; }
.fm-rename-input, .fm-newfolder-input {
  width: 100%; max-width: 340px; font: inherit; font-size: 13px;
  padding: 3px 6px; border-radius: 6px;
  border: 1px solid var(--accent); background: var(--panel-2); color: var(--text);
}
.fm-creating .fm-name { width: 100%; }
/* Items sitting on the clipboard as a pending cut render ghosted,
   Explorer-style. */
.fm-cutrow { opacity: .45; }

/* Drag-and-drop upload overlay. */
.fm-drop-overlay {
  position: absolute; inset: 0; display: none;
  align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--accent) 14%, var(--panel));
  border: 2px dashed var(--accent); border-radius: 12px;
  color: var(--accent); font-weight: 600; font-size: 15px; pointer-events: none; z-index: 3;
}
.fm-table-wrap.fm-dragover .fm-drop-overlay { display: flex; }

/* Right-click / ⋮ context menu. */
.fm-menu {
  position: fixed; z-index: 200; min-width: 172px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 5px; box-shadow: 0 8px 28px rgba(0,0,0,.22);
}
.fm-menu-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  border: 0; background: transparent; color: var(--text);
  font: inherit; font-size: 13px; text-align: left;
  padding: 7px 10px; border-radius: 7px; cursor: pointer;
}
.fm-menu-item:hover:not(:disabled) { background: rgba(var(--accent-rgb),.14); }
.fm-menu-item:disabled { opacity: .4; cursor: default; }
.fm-menu-item.danger:hover { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.fm-menu-item .fm-svg { color: var(--muted); }
.fm-menu-item.danger .fm-svg { color: inherit; }
.fm-menu-sep { height: 1px; background: var(--border); margin: 4px 6px; }

/* Properties dialog. */
.fm-props { width: 460px; }
.fm-props-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.fm-props-title .fm-svg { flex: none; }
.fm-props-table { width: 100%; border-collapse: collapse; margin-top: 6px; }
.fm-props-table td { padding: 6px 8px; font-size: 13px; vertical-align: top; border-bottom: 1px solid var(--border); }
.fm-props-table tr:last-child td { border-bottom: 0; }
.fm-props-table td:first-child { width: 120px; white-space: nowrap; }
.fm-props-table td:last-child { word-break: break-all; }
.fm-props-foot { margin-top: 14px; }

/* Bottom dock: Event Log / Job Queue. */
.fm-dock { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; flex: 0 0 auto; }
.fm-dock-tabs { display: flex; align-items: center; gap: 2px; background: var(--panel-2); border-bottom: 1px solid var(--border); padding: 4px 6px; }
.fm-dock-tab {
  border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 12.5px;
  font-weight: 600; padding: 6px 12px; border-radius: 7px; cursor: pointer;
}
.fm-dock-tab.active { background: var(--panel); color: var(--text); box-shadow: 0 0 0 1px var(--border); }
.fm-dock-body { max-height: 22vh; min-height: 64px; overflow: auto; }

.fm-ev { display: flex; gap: 10px; padding: 6px 12px; font-size: 12.5px; border-bottom: 1px solid var(--border); }
.fm-ev:last-child { border-bottom: 0; }
.fm-ev-time { flex: none; width: 52px; }
.fm-ev-ok .fm-ev-text::before { content: "✓ "; color: #34d399; }
.fm-ev-info .fm-ev-text::before { content: "• "; color: var(--muted); }
.fm-ev-err .fm-ev-text { color: var(--danger); }

.fm-job { display: flex; align-items: center; gap: 10px; padding: 8px 12px; font-size: 12.5px; border-bottom: 1px solid var(--border); }
.fm-job:last-child { border-bottom: 0; }
.fm-job-dir { flex: 0 0 auto; color: var(--muted); font-size: 13px; width: 12px; text-align: center; }
.fm-job-name { flex: 0 0 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.fm-job-meter { flex: 1 1 auto; height: 6px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border); overflow: hidden; }
.fm-job-meter > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; transition: width .15s; }
.fm-job.done .fm-job-meter > span { background: #34d399; }
.fm-job.err .fm-job-meter > span { background: var(--danger); }
.fm-job.cancel .fm-job-meter > span { background: var(--muted); }
.fm-job-stat { flex: 0 0 auto; color: var(--muted); min-width: 118px; text-align: right; font-variant-numeric: tabular-nums; }
.fm-job-eta { flex: 0 0 auto; min-width: 128px; text-align: right; font-variant-numeric: tabular-nums; }
.fm-job-cancel {
  flex: 0 0 auto; border: 0; background: transparent; color: var(--muted);
  cursor: pointer; font-size: 12px; padding: 2px 6px; border-radius: 6px; line-height: 1;
}
.fm-job-cancel:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); }
.fm-job-cancel-spacer { flex: 0 0 auto; width: 24px; }

/* ── Registry tab (remote regedit) ──────────────────────────────────────── */
.reg {
  display: grid; grid-template-columns: 300px 1fr; gap: 12px;
  align-items: start;
}
.reg-tree-pane, .reg-val-pane { min-width: 0; }
.reg-tree-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
}
.reg-tree-head .field-label { font-size: 13px; font-weight: 600; color: var(--text); }
.reg-tree {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; overflow: auto; max-height: 66vh; padding: 6px 4px;
}
.reg-node {
  display: flex; align-items: center; gap: 4px;
  padding: 4px 6px; border-radius: 7px; cursor: pointer;
  font-size: 13px; white-space: nowrap; user-select: none;
}
.reg-node:hover { background: var(--panel-2); }
.reg-node.sel { background: rgba(var(--accent-rgb),.16); }
.reg-node.sel .reg-node-label { font-weight: 600; }
.reg-node-label { overflow: hidden; text-overflow: ellipsis; }

/* Twisty: a small triangle that rotates open; leaf nodes reserve the space
   but draw nothing; a loading node spins. */
.reg-twisty {
  flex: 0 0 auto; width: 14px; height: 14px; position: relative;
  cursor: pointer;
}
.reg-twisty.closed::before, .reg-twisty.open::before {
  content: ""; position: absolute; top: 3px; left: 4px;
  border-left: 5px solid var(--muted); border-top: 4px solid transparent;
  border-bottom: 4px solid transparent; transition: transform .12s;
}
.reg-twisty.open::before { transform: rotate(90deg); transform-origin: 2px 4px; }
.reg-twisty.spin::before {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 9px; height: 9px; border: 2px solid var(--border);
  border-top-color: var(--accent); border-radius: 50%;
  animation: reg-spin .7s linear infinite;
}
@keyframes reg-spin { to { transform: rotate(360deg); } }

.reg-node-ico {
  flex: 0 0 auto; width: 15px; height: 15px;
  background: currentColor; color: var(--muted);
  -webkit-mask: center / contain no-repeat; mask: center / contain no-repeat;
}
.reg-node-ico.hive {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect x='2' y='2' width='12' height='12' rx='2' fill='none' stroke='black' stroke-width='1.4'/><path d='M2 6h12' stroke='black' stroke-width='1.2'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><rect x='2' y='2' width='12' height='12' rx='2' fill='none' stroke='black' stroke-width='1.4'/><path d='M2 6h12' stroke='black' stroke-width='1.2'/></svg>");
  color: var(--accent);
}
.reg-node-ico.key {
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M1.5 3.4c0-.5.4-.9.9-.9h3.3c.3 0 .5.1.7.3l1 1h6.2c.5 0 .9.4.9.9v7.4c0 .5-.4.9-.9.9H2.4a.9.9 0 0 1-.9-.9z' fill='black'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path d='M1.5 3.4c0-.5.4-.9.9-.9h3.3c.3 0 .5.1.7.3l1 1h6.2c.5 0 .9.4.9.9v7.4c0 .5-.4.9-.9.9H2.4a.9.9 0 0 1-.9-.9z' fill='black'/></svg>");
  color: #eab54e;
}

/* Value pane: breadcrumb, toolbar, table. */
.reg-crumb {
  font-size: 13px; margin-bottom: 10px; word-break: break-all;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 10px; padding: 8px 12px; min-height: 34px;
}
.reg-crumb-seg { color: var(--muted); }
.reg-crumb-seg.cur { color: var(--text); font-weight: 600; }
.reg-crumb-sep { color: var(--muted); margin: 0 3px; }
.reg-val-toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.reg-val-toolbar .filter { flex: 1 1 auto; max-width: 320px; }
.reg-val-toolbar #reg-add-value { flex: 0 0 auto; margin-left: auto; }
.reg-val-table .reg-vname { font-weight: 500; }
.reg-default { font-style: italic; color: var(--muted); }
.reg-type-pill {
  font-size: 11px; font-family: var(--mono, ui-monospace, monospace);
  color: var(--muted); background: var(--panel-2);
  border: 1px solid var(--border); border-radius: 6px; padding: 1px 6px;
}
.reg-vdata { font-family: var(--mono, ui-monospace, monospace); font-size: 12.5px; word-break: break-all; }
.tiny-btn { padding: 3px 8px; font-size: 12px; line-height: 1.2; }

/* Add/edit value modal fields. */
.reg-modal { width: 460px; }
.reg-field { display: block; margin-bottom: 12px; }
.reg-field > span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.reg-field .input, .reg-field .select { width: 100%; box-sizing: border-box; }
.reg-field textarea.input { resize: vertical; font-family: var(--mono, ui-monospace, monospace); }
.reg-m-hint { min-height: 16px; }

/* Right-click key menu: an absolutely-positioned .act-menu placed at the
   cursor (fixed, not anchored to a wrapper like the "⋯" overflow menu). */
.reg-ctx { position: fixed; top: 0; left: 0; right: auto; }

@media (max-width: 720px) {
  .reg { grid-template-columns: 1fr; }
  .reg-tree { max-height: 40vh; }
}

/* ── Disk Usage tab (built-in WinDirStat/WizTree) ───────────────────── */
.du { display: flex; flex-direction: column; height: 100%; }
.du-toolbar { flex: 0 0 auto; flex-wrap: wrap; row-gap: 8px; }

/* Drive-picker landing view reuses the Files tab's .fm-drive cards; only
   the footnote under the grid is du-specific. */
.du-drives-note { margin-top: 16px; max-width: 640px; line-height: 1.5; }

/* Live scan readout: accent phase chip + one stat chip per figure. */
.du-status { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.du-phase {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 3px 11px; border-radius: 999px;
  background: rgba(var(--accent-rgb),.13);
  border: 1px solid rgba(var(--accent-rgb),.35);
  color: var(--text); font-size: 12px; font-weight: 600;
  white-space: nowrap;
}
.du-stat {
  padding: 3px 10px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border);
  color: var(--muted); font-size: 12px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.du-stat b { color: var(--text); font-weight: 600; }
.du-spin {
  width: 11px; height: 11px; border-radius: 50%;
  border: 2px solid rgba(var(--accent-rgb),.3); border-top-color: var(--accent);
  animation: du-spinner .7s linear infinite;
  flex: none;
}
@keyframes du-spinner { to { transform: rotate(360deg); } }

.du-method { font-variant-numeric: tabular-nums; }

.du-progress { flex: 0 0 auto; margin: 0 0 10px; }
.du-bar {
  height: 6px; border-radius: 3px; overflow: hidden;
  background: var(--panel-2); border: 1px solid var(--border);
}
.du-bar-fill {
  height: 100%; width: 0; background: var(--accent);
  transition: width .25s ease;
}
/* Indeterminate sweep for the walk fallback (no known total). */
.du-bar-fill.indeterminate {
  width: 35% !important; transition: none;
  animation: du-indet 1.1s ease-in-out infinite;
}
@keyframes du-indet {
  0%   { margin-left: -35%; }
  100% { margin-left: 100%; }
}

.du-scanning { padding: 2rem 1.5rem; }
.du-scanning-phase { font-size: 15px; font-weight: 600; margin-bottom: 6px; }

/* Folder / Overall mode toggle (compact segmented control). */
.du-modeseg { display: inline-flex; }
.du-modeseg .seg-btn { padding: 3px 12px; font-size: 12px; }

/* Overall-view canvas fills the map area; the canvas itself is sized in JS
   to the wrapper's client box × devicePixelRatio. */
.du-overall { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.du-ov-wrap { padding: 0; }
.du-ov-wrap canvas { display: block; width: 100%; height: 100%; cursor: crosshair; }

/* overflow-y engages only for flow content (the drive grid on a short
   window); the treemap views size themselves to fill exactly. */
.du-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; overflow-y: auto; }

.du-crumbbar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 4px;
  padding: 6px 2px; margin-bottom: 8px;
}
.du-crumb {
  background: none; border: 0; color: var(--accent); cursor: pointer;
  font-size: 13px; padding: 2px 4px; border-radius: 4px;
}
.du-crumb:hover { background: var(--panel-2); }
.du-crumb:last-of-type { color: var(--text); font-weight: 600; }
.du-crumb-sep { color: var(--muted); }
.du-crumb-total { margin-left: auto; padding-left: 12px; font-variant-numeric: tabular-nums; }

.du-main {
  flex: 1 1 auto; display: grid; grid-template-columns: 1fr 240px; gap: 12px;
  min-height: 0;
}
.du-map {
  position: relative; min-height: 200px; height: 100%;
  border: 1px solid var(--border); border-radius: 6px; overflow: hidden;
  background: var(--panel);
}
.du-cell {
  position: absolute; box-sizing: border-box; overflow: hidden;
  border-radius: 2px; padding: 2px 4px;
  outline: 1px solid rgba(0,0,0,.35); outline-offset: -1px;
  display: flex; flex-direction: column; justify-content: flex-start;
  color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.6);
}
.du-cell.du-clickable { cursor: pointer; }
.du-cell.du-clickable:hover { outline: 2px solid #fff; outline-offset: -2px; z-index: 2; }
.du-cell.is-dir { font-weight: 600; }
.du-cell.is-folded { opacity: .78; }
.du-cell-label {
  font-size: 11px; line-height: 1.2; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.du-cell-size { font-size: 10px; opacity: .9; font-variant-numeric: tabular-nums; }

.du-side {
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--panel); padding: 10px; overflow-y: auto;
}
.du-side-h { font-size: 12px; font-weight: 600; color: var(--muted); margin-bottom: 8px; }
.du-legend { display: flex; flex-direction: column; gap: 5px; }
.du-leg-row { display: flex; align-items: center; gap: 7px; }
.du-leg-swatch { width: 11px; height: 11px; border-radius: 2px; flex: 0 0 auto; }
.du-leg-ext { font-size: 12px; font-variant-numeric: tabular-nums; }
.du-leg-size { margin-left: auto; }

.du-tip {
  position: absolute; z-index: 20; pointer-events: none;
  max-width: 260px; padding: 6px 9px; border-radius: 5px;
  background: rgba(10,14,20,.95); color: var(--text);
  border: 1px solid var(--border); font-size: 12px; line-height: 1.4;
  box-shadow: 0 6px 20px rgba(0,0,0,.4);
}
.du-tip-path { color: var(--muted); font-size: 11px; word-break: break-all; }

@media (max-width: 720px) {
  .du-main { grid-template-columns: 1fr; }
  .du-side { max-height: 30vh; }
}
