/* PIKS Manager 5 — workspace shell and component layer.
   Loaded last, after style.css and any page stylesheet, so it owns the shared
   surfaces (frame, sidebar, topbar, cards, tables, controls) while the older
   feature stylesheets keep their behavioural selectors.

   Composition rules this file encodes:
     · the app is a rounded frame floating on a canvas, never edge-to-edge
     · cards are borderless and separated by shadow and space, not by rules
     · one green accent; status is carried by soft tinted pills, never by
       saturated fills behind body text
     · numbers are the loudest thing on a page; labels are quiet and small */

/* ─────────────────────────────  base  ───────────────────────────── */

html {
  -webkit-text-size-adjust: 100%;
}

html body {
  margin: 0;
  background: var(--ui-canvas);
  color: var(--ui-text);
  font-family: Montserrat, "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: var(--ui-font-size-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

/* The `hidden` attribute must win over any component `display`. Several
   controls here (Stop, Clear filters, the offline chip) are toggled by
   attribute, and a class-level `display: inline-flex` would otherwise keep
   them on screen. */
[hidden] {
  display: none !important;
}

:where(a) {
  color: var(--ui-accent);
  text-decoration: none;
}

:where(a):hover {
  color: var(--ui-accent-hover);
}

/* One focus treatment for the whole app. :focus-visible only, so pointer
   users never see a ring on click. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: var(--ui-focus-ring-width) solid var(--ui-focus-ring);
  outline-offset: 2px;
  border-radius: var(--ui-radius-xs);
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ─────────────────────────────  frame  ───────────────────────────── */

.app-layout {
  display: flex;
  margin: var(--ui-frame-inset);
  height: calc(100dvh - (var(--ui-frame-inset) * 2));
  border-radius: var(--ui-radius-frame);
  background: var(--ui-shell);
  box-shadow: var(--ui-shadow-frame);
  overflow: hidden;
  isolation: isolate;
}

/* ─────────────────────────────  sidebar  ───────────────────────────── */

.app-layout .sidebar {
  display: flex;
  flex-direction: column;
  width: var(--ui-sidebar-width);
  flex: 0 0 var(--ui-sidebar-width);
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  transition: width .18s ease, flex-basis .18s ease;
}

.sidebar-brand-wrap {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: 18px 14px 6px 16px;
  border: 0;
}

.sidebar-brand {
  display: flex;
  align-items: center;
  min-width: 0;
  flex: 1;
}

.sidebar-brand img,
.brand-lockup-mark img {
  max-height: 26px;
  width: auto;
}

.brand-lockup {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
}

.brand-lockup-name {
  font-size: var(--ui-font-size-title);
  font-weight: 650;
  letter-spacing: -0.02em;
  color: var(--ui-text);
  white-space: nowrap;
}

.sidebar-collapse-toggle {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-sm);
  background: transparent;
  color: var(--ui-text-faint);
  font-size: 11px;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.sidebar-collapse-toggle:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.sidebar-scroll {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: var(--ui-space-2) var(--ui-space-3) var(--ui-space-3);
  scrollbar-width: thin;
}

.sidebar .nav-section {
  padding: 0;
}

/* Section labels: sentence case and quiet. Small-caps tracking-out reads as
   decoration at this size and fights the nav items for attention. */
.sidebar .nav-label {
  padding: 0 10px 6px;
  margin: 0;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  color: var(--ui-text-faint);
}

.sidebar .nav-group {
  margin-top: var(--ui-space-5);
}

.sidebar .nav-item {
  display: flex;
  align-items: center;
  gap: 0;
  min-height: 32px;
  margin-bottom: 2px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: transparent;
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition: background .15s, color .15s;
}

.sidebar .nav-item-main {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1;
}

.sidebar .nav-icon {
  flex-shrink: 0;
  color: var(--ui-text-faint);
  transition: color .15s;
}

.sidebar .nav-item-text {
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar .nav-item:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.sidebar .nav-item:hover .nav-icon {
  color: var(--ui-text-secondary);
}

.sidebar .nav-item.active {
  background: var(--ui-accent-on-fill);
  color: var(--ui-accent-fill-text);
  font-weight: 600;
  box-shadow: none;
}

.sidebar .nav-item.active .nav-icon,
.sidebar .nav-item.active svg {
  color: currentColor;
}

/* Trailing count on a nav row — the fleet size, pending jobs. Sits on the
   right and inverts inside the active pill. */
.sidebar .nav-count {
  flex-shrink: 0;
  min-width: 18px;
  padding: 1px 5px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-surface-3);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

.sidebar .nav-item.active .nav-count {
  background: rgba(255, 255, 255, 0.22);
  color: var(--ui-accent-fill-text);
}

[data-theme="dark"] .sidebar .nav-item.active .nav-count {
  background: rgba(255, 255, 255, 0.20);
}

.sidebar .nav-count:empty {
  display: none;
}

/* ── sidebar footer ── */

.sidebar-footer {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-2);
  padding: var(--ui-space-3) var(--ui-space-3) var(--ui-space-4);
  border: 0;
  border-top: 1px solid var(--ui-border-soft);
  margin: 0 var(--ui-space-3);
  font-size: var(--ui-font-size-caption);
}

.sidebar-footer .sidebar-link,
.sidebar-logout-form button {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  width: 100%;
  min-height: 30px;
  padding: 0 10px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: transparent;
  color: var(--ui-text-secondary);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.sidebar-footer .sidebar-link:hover,
.sidebar-logout-form button:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.sidebar-logout-form {
  margin: 0;
}

.sidebar-userline {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--ui-space-2);
  padding: 0 10px;
  min-width: 0;
  overflow: hidden;
}

.sidebar-user-avatar {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent-soft-strong);
  color: var(--ui-accent);
  font-size: var(--ui-font-size-micro);
  font-weight: 700;
  text-transform: uppercase;
}

.sidebar-userline-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  line-height: 1.3;
}

.sidebar-user-prefix {
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
}

.sidebar-user-email {
  font-size: var(--ui-font-size-caption);
  font-weight: 500;
  color: var(--ui-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar-version {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px;
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
}

.sidebar-build-label {
  padding: 1px 5px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-warning-soft);
  color: var(--ui-warning);
  font-weight: 600;
}

/* ── theme toggle ── */

.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  min-height: 30px;
  padding: 0 10px;
  border-radius: var(--ui-radius-md);
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  cursor: pointer;
  transition: background .15s;
}

.theme-toggle:hover {
  background: var(--ui-surface-2);
}

.toggle-track {
  position: relative;
  width: 30px;
  height: 17px;
  flex-shrink: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-surface-3);
  transition: background .18s;
}

.toggle-knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
  transition: transform .18s;
}

[data-theme="dark"] .toggle-track {
  background: var(--ui-accent-on-fill);
}

[data-theme="dark"] .toggle-knob {
  transform: translateX(13px);
}

/* ── collapsed rail (desktop only) ──
   An intentional icon rail for expert users. Collapsing is a choice, not a
   hover state, so nothing shifts under the pointer. Scoped to wide layouts:
   at phone widths the same class drives the nav drawer instead. */
@media (min-width: 861px) {
.app-layout.sidebar-collapsed .sidebar {
  width: var(--ui-sidebar-collapsed);
  flex-basis: var(--ui-sidebar-collapsed);
}

.app-layout.sidebar-collapsed .sidebar .nav-item-text,
.app-layout.sidebar-collapsed .sidebar .nav-label,
.app-layout.sidebar-collapsed .sidebar .nav-count,
.app-layout.sidebar-collapsed .sidebar-userline-text,
.app-layout.sidebar-collapsed .sidebar-link-text,
.app-layout.sidebar-collapsed .sidebar-version,
.app-layout.sidebar-collapsed .theme-toggle-label,
.app-layout.sidebar-collapsed .brand-lockup-text {
  display: none;
}

.app-layout.sidebar-collapsed .sidebar .nav-item,
.app-layout.sidebar-collapsed .sidebar-footer .sidebar-link,
.app-layout.sidebar-collapsed .sidebar-logout-form button,
.app-layout.sidebar-collapsed .theme-toggle,
.app-layout.sidebar-collapsed .sidebar-userline {
  justify-content: center;
  padding: 0;
}

.app-layout.sidebar-collapsed .sidebar .nav-item-main {
  flex: 0;
  justify-content: center;
}

.app-layout.sidebar-collapsed .sidebar .nav-group {
  margin-top: var(--ui-space-3);
  border-top: 1px solid var(--ui-border-soft);
  padding-top: var(--ui-space-3);
}

.app-layout.sidebar-collapsed .sidebar-brand-wrap {
  flex-direction: column;
  padding: 16px 0 6px;
}
}

/* ─────────────────────────────  main column  ───────────────────────────── */

.main-content {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  min-height: 0;
  padding: 0;
  background: transparent;
  overflow: hidden;
}

/* ── topbar ──
   Page identity on the left, global tools on the right. Sticky within the
   scrolling content so the title and search stay reachable on long pages. */
.topbar {
  display: flex;
  align-items: center;
  gap: var(--ui-space-4);
  flex-shrink: 0;
  padding: 16px 20px 14px;
}

.topbar-identity {
  min-width: 0;
  flex: 1;
}

/* A back link above the title, for pages you drill into. Quiet by default so
   the page name stays the loudest thing in the topbar. */
.topbar-back {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin: 0 0 2px -2px;
  font-size: var(--ui-font-size-caption);
  font-weight: 500;
  color: var(--ui-text-muted);
  text-decoration: none;
}

.topbar-back:hover {
  color: var(--ui-text);
}

/* Title and its status pill on one line; the pill keeps its size and the
   title takes the slack. */
.topbar-title-row {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
}

.topbar-title-row h1 {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.topbar-title-row .pill {
  flex-shrink: 0;
}

.topbar-identity h1,
.main-content .page-header h1 {
  margin: 0;
  font-size: var(--ui-font-size-heading);
  font-weight: 650;
  letter-spacing: -0.035em;
  line-height: 26px;
  color: var(--ui-text);
}

.topbar-identity p,
.main-content .page-header p {
  margin: 3px 0 0;
  font-size: var(--ui-font-size-caption);
  line-height: 16px;
  font-weight: 400;
  color: var(--ui-text-muted);
}

.topbar-tools {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  flex-shrink: 0;
}

/* Global search with a keyboard hint. The hint is decorative — the shortcut
   is bound in JS and announced on the input's label. */
.global-search {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  width: 210px;
  height: 32px;
  padding: 0 8px 0 11px;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
  color: var(--ui-text-faint);
  transition: box-shadow .15s;
}

.global-search:focus-within {
  box-shadow: 0 0 0 2px var(--ui-focus-ring);
}

.global-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
}

.global-search input::placeholder {
  color: var(--ui-text-faint);
}

.global-search input:focus {
  outline: 0;
}

.global-search kbd {
  flex-shrink: 0;
  padding: 2px 5px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-surface-2);
  color: var(--ui-text-faint);
  font-family: inherit;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

.icon-btn {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
  color: var(--ui-text-secondary);
  cursor: pointer;
  transition: color .15s, background .15s;
}

.icon-btn:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

/* ── page header (pages that keep the older markup) ── */

.main-content > .page-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--ui-space-4);
  flex-shrink: 0;
  padding: 16px 20px 14px;
  border: 0;
  background: transparent;
}

.page-header-kicker {
  margin-bottom: 4px;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  color: var(--ui-text-faint);
}

.page-header-title-row {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  flex-wrap: wrap;
}

.page-header-actions {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  flex-shrink: 0;
  flex-wrap: wrap;
}

/* The scrolling body of a page. Everything below the topbar lives here so the
   frame itself never scrolls. */
.page-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 20px 20px;
  scrollbar-width: thin;
}

/* A page whose main surface must fill the frame (a table that scrolls inside
   its own card) opts out of body scrolling. */
.page-body-fill {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ─────────────────────────────  buttons  ───────────────────────────── */

.main-content .btn,
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 11px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}

.btn:hover:not(:disabled) {
  background: var(--ui-surface-2);
  border-color: var(--ui-border-strong);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .5;
  cursor: not-allowed;
}

/* The single most important action on a page: a near-black pill (a light one
   in dark mode) so it outranks the green accent used for state. */
.main-content .btn-primary,
.btn-primary {
  border-color: var(--ui-solid);
  background: var(--ui-solid);
  color: var(--ui-solid-text);
  font-weight: 600;
}

.btn-primary:hover:not(:disabled) {
  border-color: var(--ui-solid-hover);
  background: var(--ui-solid-hover);
  color: var(--ui-solid-text);
}

.btn-accent {
  border-color: var(--ui-accent-on-fill);
  background: var(--ui-accent-on-fill);
  color: var(--ui-accent-fill-text);
  font-weight: 600;
}

.btn-accent:hover:not(:disabled) {
  border-color: var(--ui-accent-on-fill-hover);
  background: var(--ui-accent-on-fill-hover);
  color: var(--ui-accent-fill-text);
}

.btn-secondary {
  background: var(--ui-surface-1);
  color: var(--ui-text);
}

.btn-danger {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
  font-weight: 600;
}

.btn-danger:hover:not(:disabled) {
  border-color: var(--ui-danger);
  background: var(--ui-danger-soft);
}

/* Quiet button: no chrome until hovered. For clear/reset affordances that
   should not compete with real actions. */
.btn-quiet {
  border-color: transparent;
  background: transparent;
  color: var(--ui-text-muted);
}

.btn-quiet:hover:not(:disabled) {
  border-color: transparent;
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.btn-sm {
  min-height: 26px;
  padding: 0 8px;
  font-size: var(--ui-font-size-caption);
}

.btn-group {
  display: inline-flex;
  gap: 6px;
  flex-wrap: wrap;
}

/* ─────────────────────────────  form controls  ───────────────────────────── */

.main-content input[type="text"],
.main-content input[type="password"],
.main-content input[type="number"],
.main-content input[type="email"],
.main-content input[type="search"],
.main-content select,
.main-content textarea,
.form-control,
.sender-input,
.sender-textarea {
  width: 100%;
  min-height: 30px;
  padding: 6px 9px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-sm);
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  transition: border-color .15s, box-shadow .15s;
}

.main-content input:focus,
.main-content select:focus,
.main-content textarea:focus,
.form-control:focus {
  outline: 0;
  border-color: var(--ui-accent-on-fill);
  box-shadow: 0 0 0 3px var(--ui-focus-ring);
}

/* A search affordance draws its own bordered box around the icon, the field and
   the shortcut hint, so the field inside it must not draw a second one. The
   generic rule above is `.main-content input[type="text"]` — specificity
   (0,2,1), which outranks a plain `.search-box input` (0,1,1) — so the reset
   has to carry `.main-content` too and sit after it, or the field keeps its own
   border, radius and padding and shows as a box within a box. */
.main-content .global-search input,
.main-content .search-box input {
  min-height: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
}

/* The wrapper takes the focus ring on :focus-within, so the field stays flat —
   otherwise focusing it draws a second ring inside the first. */
.main-content .global-search input:focus,
.main-content .search-box input:focus {
  border: 0;
  box-shadow: none;
}

.main-content textarea,
.sender-textarea {
  min-height: 74px;
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  line-height: 1.6;
  resize: vertical;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}

.field > label,
.field-label {
  font-size: var(--ui-font-size-caption);
  font-weight: 600;
  color: var(--ui-text-secondary);
}

.field-hint {
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
  line-height: 1.5;
}

/* Checkbox / radio: the accent colour is the only place a saturated fill
   appears inside a form. */
.main-content input[type="checkbox"],
.main-content input[type="radio"] {
  width: 14px;
  height: 14px;
  min-height: 0;
  margin: 0;
  accent-color: var(--ui-accent-on-fill);
  cursor: pointer;
}

.toolbar-check,
.sender-check-label,
.check-all-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 9px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.toolbar-check:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.toolbar-check:has(input:checked) {
  border-color: var(--ui-accent-soft-strong);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

/* ─────────────────────────────  cards  ───────────────────────────── */

.main-content .card,
.card,
.panel {
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
  overflow: hidden;
}

.card-header,
.panel-head {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 14px 16px 0;
  border: 0;
  background: transparent;
}

.card-title,
.panel-head h2 {
  margin: 0;
  flex: 1;
  min-width: 0;
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ui-text);
}

/* The small rounded glyph tile that precedes a card title. Dark and neutral
   so it reads as a marker, not a status. */
.card-glyph,
.panel-glyph {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: 7px;
  background: var(--ui-surface-3);
  color: var(--ui-text-secondary);
}

.card-glyph-solid {
  background: linear-gradient(160deg, #3b423e, #1d2321);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
}

.card-meta {
  flex-shrink: 0;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

.card-subtitle,
.card-intro,
.panel-note {
  margin: 4px 0 0;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
  line-height: 1.55;
  text-align: left;
}

/* The sign-in card is the one place centred copy is right. */
.card-box .card-subtitle {
  text-align: center;
}

.card-body {
  padding: 12px 16px 16px;
}

.card-footer {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: 12px 16px;
  border-top: 1px solid var(--ui-border-soft);
  background: var(--ui-surface-inset);
}

/* A card that holds a scrolling table: no padding, header flush, body fills. */
.card-flush {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.card-flush > .card-body {
  padding: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

/* ─────────────────────────────  metric strip  ───────────────────────────── */

/* One row of headline numbers, hairline-divided inside a single card. Reads
   as a unit rather than four competing tiles. */
.metric-strip {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  margin-bottom: var(--ui-space-4);
  padding: 14px 4px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
}

.metric {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 2px 16px;
  border-right: 1px solid var(--ui-border-soft);
}

.metric:last-child {
  border-right: 0;
}

.metric-glyph {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 12px;
  background: linear-gradient(160deg, #454c48, #1d2321);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

[data-theme="dark"] .metric-glyph {
  background: linear-gradient(160deg, #3c443f, #232926);
}

.metric-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.metric-label {
  font-size: var(--ui-font-size-body);
  line-height: 16px;
  font-weight: 500;
  color: var(--ui-text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.metric-value {
  font-size: 27px;
  font-weight: 650;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--ui-text);
}

/* ─────────────────────────────  pills and chips  ───────────────────────────── */

/* One pill component, five tones. Soft tinted background plus a text-safe
   foreground — never a saturated fill behind small text. */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-neutral-soft);
  color: var(--ui-neutral-text);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.pill-success,
.status-badge.on {
  background: var(--ui-success-soft);
  color: var(--ui-success);
}

.pill-warning {
  background: var(--ui-warning-soft);
  color: var(--ui-warning);
}

.pill-danger,
.status-badge.off {
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

.pill-info {
  background: var(--ui-info-soft);
  color: var(--ui-info);
}

.pill-accent {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.pill-dot::before {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  border: 0;
  border-radius: var(--ui-radius-xs);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

/* Live dot: a small solid dot with a soft ring. The ring is what makes 6px of
   green read as "connected" rather than as a stray pixel. */
.live-dot {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--ui-text-faint);
}

.live-dot.on {
  background: var(--ui-success-dot);
  box-shadow: 0 0 0 3px var(--ui-success-dot-glow);
}

.live-dot.off {
  background: var(--ui-text-faint);
  box-shadow: 0 0 0 3px var(--ui-neutral-soft);
}

/* An offline device in the rail is an exception to look at, not a neutral
   row — amber, the tone the closing insight banner used to carry. */
.live-dot.warn {
  background: var(--ui-warning-dot);
  box-shadow: 0 0 0 3px var(--ui-warning-soft);
}

/* Avatar-style initial chip used in device/name cells. */
.name-chip {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex-shrink: 0;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-accent-soft-strong);
  color: var(--ui-accent);
  font-size: var(--ui-font-size-micro);
  font-weight: 700;
  text-transform: uppercase;
}

.name-chip.off {
  background: var(--ui-neutral-soft);
  color: var(--ui-text-muted);
}

/* ─────────────────────────────  meters  ───────────────────────────── */

.meter {
  height: 6px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-surface-3);
  overflow: hidden;
}

.meter > span {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: var(--ui-accent-on-fill);
  transition: width .25s ease;
}

.meter-warning > span { background: var(--ui-warning-dot); }
.meter-danger > span { background: var(--ui-danger-dot); }

/* Stacked meter: several tones in one bar, with a legend underneath. */
.meter-stack {
  display: flex;
  gap: 2px;
  height: 6px;
  border-radius: var(--ui-radius-pill);
  overflow: hidden;
  background: var(--ui-surface-3);
}

.meter-stack > span {
  height: 100%;
  min-width: 0;
  transition: flex-grow .25s ease;
}

.legend {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-top: 11px;
}

.legend-row {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-secondary);
}

.legend-row i {
  width: 6px;
  height: 6px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--ui-accent-on-fill);
}

.legend-row span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.legend-row strong {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ui-text);
}

/* ─────────────────────────────  toolbars  ───────────────────────────── */

.operator-toolbar {
  flex-shrink: 0;
  padding: 12px 14px;
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
  background: transparent;
}

.operator-toolbar-row {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}

.search-box {
  display: flex;
  align-items: center;
  gap: 7px;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  color: var(--ui-text-faint);
  transition: border-color .15s, box-shadow .15s;
}

.search-box:focus-within {
  border-color: var(--ui-accent-on-fill);
  box-shadow: 0 0 0 3px var(--ui-focus-ring);
}

.search-box svg {
  flex-shrink: 0;
}

.search-box input {
  width: 100%;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
}

.search-box-wide {
  flex: 1 1 190px;
  min-width: 150px;
  max-width: 300px;
}

/* Segmented control — one row of mutually exclusive scopes, each with its
   count, so the filter and the tally are the same control. */
.status-filter,
.segmented {
  display: inline-flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-2);
}

.status-filter-btn,
.segmented > button {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 26px;
  padding: 0 9px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ui-text-secondary);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.status-filter-btn:hover,
.segmented > button:hover {
  color: var(--ui-text);
}

.status-filter-btn.active,
.segmented > button.active {
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-weight: 600;
  box-shadow: var(--ui-shadow-sm);
}

.status-filter-btn span,
.segmented > button span {
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
}

.status-filter-btn.active span,
.segmented > button.active span {
  color: var(--ui-accent);
}

/* ── company filter popover ── */

.company-filter {
  position: relative;
}

.company-filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  cursor: pointer;
  transition: background .15s, border-color .15s;
}

.company-filter-toggle:hover {
  background: var(--ui-surface-2);
  border-color: var(--ui-border-strong);
}

.company-filter-toggle-label {
  color: var(--ui-text-secondary);
}

.company-filter-toggle-summary {
  max-width: 130px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-weight: 600;
}

.company-filter-toggle-icon {
  color: var(--ui-text-faint);
  font-size: 9px;
}

.company-filter-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 40;
  width: 258px;
  max-height: 330px;
  display: flex;
  flex-direction: column;
  padding: 10px;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
}

.company-filter-panel[hidden] {
  display: none;
}

.company-filter-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-2);
  margin-bottom: var(--ui-space-2);
}

.company-filter-meta {
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-muted);
}

.company-filter-options {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: var(--ui-space-2);
  scrollbar-width: thin;
}

.company-filter-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--ui-radius-sm);
  font-size: var(--ui-font-size-label);
  cursor: pointer;
  transition: background .12s;
}

.company-filter-option:hover {
  background: var(--ui-surface-2);
}

.company-filter-option-copy {
  display: flex;
  align-items: baseline;
  gap: 6px;
  flex: 1;
  min-width: 0;
}

.company-filter-option-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.company-filter-option-count {
  flex-shrink: 0;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
}

.company-filter-empty {
  padding: 14px 8px;
  text-align: center;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

/* ── columns menu ── */

.table-options {
  position: relative;
}

.table-options > summary {
  list-style: none;
}

.table-options > summary::-webkit-details-marker {
  display: none;
}

.table-options-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 172px;
  padding: 8px;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
}

.table-options-panel label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: var(--ui-radius-sm);
  font-size: var(--ui-font-size-label);
  cursor: pointer;
}

.table-options-panel label:hover {
  background: var(--ui-surface-2);
}

/* ─────────────────────────────  tables  ───────────────────────────── */

.table-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  scrollbar-width: thin;
}

.device-table,
.sender-device-table,
.data-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--ui-font-size-label);
}

.device-table thead th,
.data-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  padding: 9px 12px;
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
  background: var(--ui-surface-1);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  text-align: left;
  white-space: nowrap;
}

.device-table tbody td,
.data-table tbody td {
  padding: 10px 12px;
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
  vertical-align: middle;
  color: var(--ui-text-secondary);
}

.device-table tbody tr:last-child td,
.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.device-table tbody tr,
.data-table tbody tr {
  transition: background .12s;
}

.device-table tbody tr:hover,
.data-table tbody tr:hover {
  background: var(--ui-surface-inset);
}

.table-sort-button {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: color .15s;
}

.table-sort-button:hover {
  color: var(--ui-text);
}

.device-table th.sorted .table-sort-button {
  color: var(--ui-accent);
}

.sort-indicator {
  font-size: 9px;
}

/* Device identity cell: initial chip, name, then the quiet company line. */
.dev-name-link {
  display: flex;
  align-items: center;
  gap: 9px;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}

.dev-name-text {
  display: block;
  min-width: 0;
  flex: 1;
}

.dev-name {
  display: block;
  font-size: var(--ui-font-size-body);
  line-height: 20px;
  font-weight: 600;
  color: var(--ui-text);
  letter-spacing: -0.01em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dev-name-link:hover .dev-name {
  color: var(--ui-accent);
}

.dev-brand {
  display: block;
  margin-top: 1px;
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}

.dev-os {
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-secondary);
  white-space: nowrap;
}

.dev-agent {
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
}

.last-seen-primary {
  display: block;
  font-size: var(--ui-font-size-label);
  color: var(--ui-text);
  white-space: nowrap;
}

.last-seen-online .last-seen-primary {
  color: var(--ui-success);
  font-weight: 600;
}

.last-seen-detail {
  display: block;
  margin-top: 1px;
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
  white-space: nowrap;
}

.td-status {
  display: flex;
  align-items: center;
}

.td-ip {
  font-variant-numeric: tabular-nums;
}

/* Copyable value: reads as text until hovered, then offers the copy glyph. */
.ip-copy {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 6px;
  border: 1px solid transparent;
  border-radius: var(--ui-radius-xs);
  background: transparent;
  color: var(--ui-text-secondary);
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  /* It is a button, so the UA centres it. Long values (DNS labels) wrap, and
     centred wrapped text does not line up with the label above it. */
  text-align: left;
  cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}

.ip-copy:hover {
  border-color: var(--ui-border);
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.ip-copy-icon {
  opacity: 0;
  color: var(--ui-text-faint);
  transition: opacity .12s;
}

.ip-copy:hover .ip-copy-icon {
  opacity: 1;
}

.td-actions {
  display: flex;
  align-items: center;
  gap: 5px;
  justify-content: flex-end;
}

/* Row actions are quiet by default and only gain chrome on hover of the row,
   so four buttons per row do not shout across a long table. */
.td-actions .btn {
  min-height: 26px;
  padding: 0 8px;
  font-size: var(--ui-font-size-caption);
  border-color: transparent;
  background: transparent;
  color: var(--ui-text-secondary);
}

.device-table tbody tr:hover .td-actions .btn:not(:disabled) {
  border-color: var(--ui-border);
  background: var(--ui-surface-1);
  color: var(--ui-text);
}

.td-actions .btn:hover:not(:disabled) {
  border-color: var(--ui-accent-soft-strong) !important;
  background: var(--ui-accent-soft) !important;
  color: var(--ui-accent) !important;
}

/* Row overflow menu — keeps the less-used file downloads out of the row
   without hiding the two actions operators use every day. */
.row-menu {
  position: relative;
}

.row-menu > summary {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  list-style: none;
  border-radius: var(--ui-radius-sm);
  color: var(--ui-text-faint);
  cursor: pointer;
  transition: background .12s, color .12s;
}

.row-menu > summary::-webkit-details-marker {
  display: none;
}

.row-menu > summary:hover,
.row-menu[open] > summary {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.row-menu-panel {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  gap: 1px;
  width: 196px;
  padding: 6px;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
}

.row-menu-panel button,
.row-menu-panel a {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-height: 28px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--ui-radius-sm);
  background: transparent;
  color: var(--ui-text-secondary);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background .12s, color .12s;
}

.row-menu-panel button:hover:not(:disabled),
.row-menu-panel a:hover {
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

.row-menu-panel button:disabled {
  opacity: .45;
  cursor: not-allowed;
}

.row-menu-label {
  padding: 5px 8px 3px;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  color: var(--ui-text-faint);
}

/* Device time is data with a refresh affordance, not a button that happens to
   contain a timestamp. */
.device-time-cell {
  display: flex;
  align-items: center;
  gap: 6px;
}

.device-time-value {
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.device-time-value.muted {
  font-family: inherit;
  color: var(--ui-text-faint);
}

.device-time-refresh {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  padding: 0;
  border: 0;
  border-radius: var(--ui-radius-xs);
  background: transparent;
  color: var(--ui-text-faint);
  cursor: pointer;
  transition: background .12s, color .12s;
}

.device-time-refresh:hover:not(:disabled) {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.device-time-refresh:disabled {
  opacity: .4;
  cursor: not-allowed;
}

.state-message {
  padding: 40px 16px !important;
  text-align: center;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-label);
}

/* Empty state with a heading and a suggested next step. */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 38px 20px;
  text-align: center;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-label);
}

/* The same class is used on `td colspan="n"` cells. `display: flex` takes a
   cell out of the table layout, so the colspan is ignored and the message
   collapses into the first column one character wide — it has to stay a cell
   and keep the centred padding by hand, as .state-message does. */
td.empty-state {
  display: table-cell;
  padding: 38px 20px;
  text-align: center;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-label);
}

.empty-state strong {
  font-size: var(--ui-font-size-body);
  font-weight: 600;
  color: var(--ui-text);
}

/* ─────────────────────────────  tabs  ───────────────────────────── */

.tabs,
.tab-nav,
.sender-tab-bar {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-wrap: wrap;
  padding: 3px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-2);
  width: fit-content;
  max-width: 100%;
}

.tab-btn,
.tab-button,
.sender-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 27px;
  padding: 0 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ui-text-secondary);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: background .15s, color .15s;
}

.tab-btn:hover,
.tab-button:hover,
.sender-tab:hover {
  color: var(--ui-text);
}

.tab-btn.active,
.tab-button.active,
.sender-tab.active,
.tab-btn[aria-selected="true"],
.tab-button[aria-selected="true"],
.sender-tab[aria-selected="true"] {
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-weight: 600;
  box-shadow: var(--ui-shadow-sm);
}

/* Count badge inside a tab. Distinguishes "no findings" from "not analysed":
   an empty badge renders nothing at all. */
.tab-count {
  padding: 1px 5px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-surface-3);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.tab-count:empty {
  display: none;
}

.tab-btn.active .tab-count,
.tab-button.active .tab-count {
  background: rgba(255, 255, 255, 0.22);
  color: var(--ui-accent-fill-text);
}

[data-theme="dark"] .tab-btn.active .tab-count,
[data-theme="dark"] .tab-button.active .tab-count {
  background: rgba(255, 255, 255, 0.20);
}

.tab-content {
  display: none;
}

.tab-content.active {
  display: block;
}

/* ─────────────────────────────  toasts  ───────────────────────────── */

.toast {
  position: fixed;
  inset: auto 22px 22px auto;
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 330px;
  padding: 10px 13px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-solid);
  color: var(--ui-solid-text);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  box-shadow: var(--ui-shadow-lg);
}

.toast.error {
  background: var(--ui-danger);
  color: #fff;
}

.toast.success {
  background: var(--ui-accent-on-fill);
  color: #fff;
}

/* ─────────────────────────────  misc shared  ───────────────────────────── */

.help-tip {
  display: inline-grid;
  place-items: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: var(--ui-surface-3);
  color: var(--ui-text-muted);
  font-size: 9px;
  font-weight: 700;
  cursor: help;
  vertical-align: middle;
}

.help-tip:hover {
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.text-muted {
  color: var(--ui-text-muted);
}

.mono {
  font-family: var(--ui-font-mono);
  font-variant-numeric: tabular-nums;
}

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--ui-font-size-caption);
  font-weight: 500;
  color: var(--ui-text-muted);
}

.back-link:hover {
  color: var(--ui-accent);
}

/* Section heading used between cards on a long page. */
.section-head {
  display: flex;
  align-items: baseline;
  gap: var(--ui-space-2);
  margin: var(--ui-space-5) 0 var(--ui-space-3);
}

.section-head h2 {
  margin: 0;
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.section-head p {
  margin: 0;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

/* Definition list for fact panels (device detail, review summaries). */
.detail-list {
  display: grid;
  grid-template-columns: minmax(96px, auto) 1fr;
  gap: 9px var(--ui-space-4);
  margin: 0;
  font-size: var(--ui-font-size-label);
}

.detail-list dt {
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-caption);
}

.detail-list dd {
  margin: 0;
  color: var(--ui-text);
  font-weight: 500;
  min-width: 0;
}

.detail-value-mono,
.detail-value-ip {
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  font-variant-numeric: tabular-nums;
}

.detail-value-ip {
  white-space: nowrap;
}

.detail-value-wrap {
  overflow-wrap: anywhere;
}

/* ─────────────────────────────  workspace grid  ───────────────────────────── */

/* The dashboard composition: a wide primary surface and a narrower rail of
   supporting panels. The rail is where "what needs attention" lives, so the
   main table never has to carry both the list and its summary. */
.workspace {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 240px;
  gap: var(--ui-space-4);
  flex: 1;
  min-height: 0;
}

.workspace-main {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}

.workspace-rail {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-3);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  padding-bottom: 2px;
}

.rail-panel {
  flex-shrink: 0;
  padding: 15px;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
}

.rail-panel > h2 {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 4px;
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.rail-note {
  margin: 0;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
  line-height: 1.55;
}

.rail-figure {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 12px 0 10px;
}

.rail-figure strong {
  font-size: var(--ui-font-size-metric);
  font-weight: 650;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.rail-figure span {
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

/* A compact list of rows in the rail — offline devices, stock-style alerts.
   Each row is a link to the thing it names. */
.rail-list {
  display: flex;
  flex-direction: column;
  margin-top: 10px;
}

.rail-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 0;
  border-bottom: 1px solid var(--ui-border-soft);
  color: inherit;
  text-decoration: none;
  min-width: 0;
}

.rail-item:last-child {
  border-bottom: 0;
  padding-bottom: 0;
}

.rail-item-text {
  flex: 1;
  min-width: 0;
}

.rail-item strong {
  display: block;
  font-size: var(--ui-font-size-label);
  font-weight: 600;
  color: var(--ui-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-item small {
  display: block;
  margin-top: 1px;
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.rail-item:hover strong {
  color: var(--ui-accent);
}

.rail-item-trail {
  flex-shrink: 0;
  align-self: flex-start;
  margin-top: 1px;
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.rail-empty {
  padding: 14px 0 2px;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

/* ─────────────────────────────  page: sender  ───────────────────────────── */

.sender-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--ui-space-4);
  align-items: start;
}

.sender-devices,
.sender-panel {
  display: flex;
  flex-direction: column;
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
  overflow: hidden;
}

.sender-devices-header,
.sender-section-title {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 15px;
  margin: 0;
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
  background: transparent;
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ui-text);
}

.sender-tab-content {
  padding: 15px;
}

.sender-upload-section,
.sender-run-section,
.sender-log-section {
  padding: 15px;
  border-top: 1px solid var(--ui-border-soft);
}

/* File drop area: one interactive element, not a button inside a button. */
.sender-file-row,
.sender-drop {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 20px 15px;
  border: 1px dashed var(--ui-border-strong);
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-inset);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-label);
  text-align: center;
  transition: border-color .15s, background .15s;
}

.sender-drop.dragover,
.sender-file-row.dragover {
  border-color: var(--ui-accent-on-fill);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.sender-log {
  max-height: 260px;
  overflow-y: auto;
  padding: 11px 13px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-inset);
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  line-height: 1.65;
  scrollbar-width: thin;
}

.log-line {
  display: flex;
  gap: 8px;
}

.log-time {
  flex-shrink: 0;
  color: var(--ui-text-faint);
  font-variant-numeric: tabular-nums;
}

.log-error { color: var(--ui-danger); }
.log-success { color: var(--ui-success); }
.log-info { color: var(--ui-text-secondary); }

.cmd-list {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.cmd-card {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: 10px 12px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-inset);
}

.cmd-card-label {
  font-size: var(--ui-font-size-label);
  font-weight: 600;
}

.cmd-card-body {
  flex: 1;
  min-width: 0;
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
  overflow-wrap: anywhere;
}

/* ─────────────────────────────  page: diagnostics  ───────────────────────────── */

.epos-log-tool,
.audit-tool {
  display: flex;
  flex-direction: column;
  min-height: 0;
  flex: 1;
}

.epos-log-main-content,
.audit-emulate-main-content {
  overflow: hidden;
}

.upload-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: var(--ui-space-3);
}

.upload-panel,
.definition-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 15px;
  border: 0;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-inset);
}

.upload-panel h3,
.definition-card h3 {
  margin: 0;
  font-size: var(--ui-font-size-label);
  font-weight: 600;
}

/* Neutral until something is actually wrong: an unloaded file is "No file
   selected", not a red failure. */
.definition-status,
.file-status {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 7px;
  width: fit-content;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-neutral-soft);
  color: var(--ui-neutral-text);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

.definition-status.loaded,
.file-status.loaded {
  background: var(--ui-success-soft);
  color: var(--ui-success);
}

.definition-status.error,
.file-status.error {
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

.definition-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.progress-container {
  margin-top: var(--ui-space-3);
}

.progress-bar-bg {
  height: 6px;
  border-radius: var(--ui-radius-pill);
  background: var(--ui-surface-3);
  overflow: hidden;
}

.progress-bar-fill {
  height: 100%;
  border-radius: inherit;
  background: var(--ui-accent-on-fill);
  transition: width .25s ease;
}

/* ─────────────────────────────  page: device detail  ───────────────────────────── */

.device-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: var(--ui-space-4);
  align-items: start;
}

.deployment-history-row,
.deployment-session {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  padding: 10px 0;
  border-bottom: 1px solid var(--ui-border-soft);
  font-size: var(--ui-font-size-label);
}

.deployment-history-row:last-child {
  border-bottom: 0;
}

.deployment-status-pill {
  padding: 2px 7px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-neutral-soft);
  color: var(--ui-neutral-text);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

.deployment-empty,
.device-meta-note {
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
  line-height: 1.6;
}

/* ─────────────────────────────  page: settings  ───────────────────────────── */

.settings-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--ui-space-4);
  align-items: start;
}

.settings-card {
  max-width: none;
}

.settings-form-grid,
.settings-pref-grid {
  display: grid;
  gap: var(--ui-space-3);
}

.settings-form-grid {
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}

.settings-actions {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  flex-wrap: wrap;
  margin-top: var(--ui-space-4);
}

/* ─────────────────────────────  page: login  ───────────────────────────── */

.card-page {
  display: grid;
  place-items: center;
  min-height: 100dvh;
  padding: var(--ui-space-5);
  background: var(--ui-canvas);
}

.card-box {
  width: 100%;
  max-width: 356px;
  padding: var(--ui-space-6);
  border: 0;
  border-radius: var(--ui-radius-frame);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
  text-align: center;
}

.card-box .brand-lockup,
.brand-lockup-auth {
  justify-content: center;
  margin-bottom: var(--ui-space-4);
}

.card-subtitle {
  margin-bottom: var(--ui-space-5);
  font-size: var(--ui-font-size-label);
  color: var(--ui-text-muted);
  line-height: 1.6;
}

.login-btn,
.auth-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 38px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-solid);
  color: var(--ui-solid-text);
  font-family: inherit;
  font-size: var(--ui-font-size-body);
  font-weight: 600;
  cursor: pointer;
  transition: background .15s;
}

.login-btn:hover,
.auth-btn:hover {
  background: var(--ui-solid-hover);
}

/* Shown while sign-in is happening in a child window. It replaces the button
   rather than sitting beside it, so the card does not jump. */
.sign-in-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--ui-space-2);
  min-height: 38px;
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
}

.sign-in-status[hidden] {
  display: none;
}

.sign-in-spinner {
  flex-shrink: 0;
  width: 13px;
  height: 13px;
  border: 2px solid var(--ui-border-strong);
  border-top-color: var(--ui-accent);
  border-radius: 50%;
  animation: sign-in-spin .8s linear infinite;
}

@keyframes sign-in-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .sign-in-spinner { animation: none; }
}

/* Why the window went away, when it went away without finishing. */
.sign-in-note {
  margin: var(--ui-space-3) 0 0;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-caption);
  line-height: 1.5;
}

.sign-in-note[hidden] {
  display: none;
}

.card-theme-toggle {
  position: fixed;
  top: var(--ui-space-5);
  right: var(--ui-space-5);
}

/* ─────────────────────────────  page: terminal  ───────────────────────────── */

.term-wrap {
  display: flex;
  flex-direction: column;
  height: 100dvh;
  padding: var(--ui-frame-inset);
  background: var(--ui-canvas);
}

.term-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--ui-space-3);
  padding: 10px 14px;
  border-radius: var(--ui-radius-lg) var(--ui-radius-lg) 0 0;
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
}

.term-titlebar-left,
.term-titlebar-right {
  display: flex;
  align-items: center;
  gap: var(--ui-space-2);
  min-width: 0;
}

.term-title {
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  color: var(--ui-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.term-content {
  position: relative;
  flex: 1;
  min-height: 0;
  padding: 10px;
  border-radius: 0 0 var(--ui-radius-lg) var(--ui-radius-lg);
  background: #0f1311;
  box-shadow: var(--ui-shadow-card);
}

/* ─────────────────────────────  modals  ───────────────────────────── */

.auth-overlay {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: grid;
  place-items: center;
  padding: var(--ui-space-4);
  background: rgba(10, 14, 12, 0.55);
  backdrop-filter: blur(3px);
}

.auth-card {
  width: 100%;
  max-width: 356px;
  padding: var(--ui-space-5);
  border: 0;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
}

.auth-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-bottom: var(--ui-space-3);
  text-align: left;
  font-size: var(--ui-font-size-caption);
  font-weight: 600;
  color: var(--ui-text-secondary);
}

.auth-field input {
  width: 100%;
  min-height: 32px;
  padding: 6px 9px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-sm);
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 400;
}

.auth-actions {
  display: flex;
  gap: var(--ui-space-2);
  margin-top: var(--ui-space-4);
}

.auth-error {
  margin-top: var(--ui-space-3);
  font-size: var(--ui-font-size-caption);
  color: var(--ui-danger);
}

.auth-error:empty {
  display: none;
}

/* ─────────────────────────────  responsive  ───────────────────────────── */

@media (max-width: 1240px) {
  .workspace {
    grid-template-columns: minmax(0, 1fr) 224px;
  }

  .sender-layout {
    grid-template-columns: minmax(0, 1fr) 300px;
  }
}

@media (max-width: 1080px) {
  /* Below this the rail stops being a rail: the table needs the full width,
     so supporting panels move under it and the page scrolls as one column. */
  .workspace {
    grid-template-columns: minmax(0, 1fr);
    overflow-y: auto;
  }

  .workspace-main {
    min-height: 420px;
  }

  .workspace-rail {
    flex-direction: row;
    flex-wrap: wrap;
    overflow: visible;
  }

  .workspace-rail > * {
    flex: 1 1 260px;
  }

  .sender-layout {
    grid-template-columns: minmax(0, 1fr);
  }

  .metric-strip {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: var(--ui-space-4);
  }

  .metric:nth-child(2n) {
    border-right: 0;
  }
}

@media (max-width: 860px) {
  :root {
    --ui-frame-inset: 0px;
  }

  html body {
    background: var(--ui-shell);
  }

  .app-layout {
    flex-direction: column;
    height: 100dvh;
    border-radius: 0;
    box-shadow: none;
  }

  /* Mobile navigation is a bounded drawer, not a full-height takeover: the
     current task stays visible behind it. base.js toggles .sidebar-collapsed
     on .app-layout, so that is what opens and closes the drawer here. */
  .app-layout .sidebar {
    width: 100%;
    flex: 0 0 auto;
    max-height: 58dvh;
    overflow: hidden;
    border-bottom: 1px solid var(--ui-border-soft);
    background: var(--ui-surface-1);
    transition: max-height .2s ease;
  }

  .app-layout.sidebar-collapsed .sidebar {
    max-height: 62px;
  }

  .app-layout .sidebar-brand-wrap {
    min-height: 62px;
  }

  .brand-lockup-name {
    line-height: 1.3;
  }

  /* The footer belongs to the drawer, not to the collapsed bar. */
  .app-layout.sidebar-collapsed .sidebar-scroll,
  .app-layout.sidebar-collapsed .sidebar-footer {
    display: none;
  }

  .sidebar-brand-wrap {
    padding: 14px 16px;
  }

  .sidebar-collapse-toggle {
    width: auto;
    height: 30px;
    padding: 0 10px;
    gap: 6px;
    border-radius: var(--ui-radius-md);
    background: var(--ui-surface-2);
    color: var(--ui-text);
    font-size: var(--ui-font-size-label);
    font-weight: 600;
  }

  .sidebar-collapse-icon-desktop {
    display: none;
  }

  .sidebar-collapse-toggle-mobile {
    display: inline-flex;
    align-items: center;
    gap: 6px;
  }

  .topbar,
  .main-content > .page-header {
    flex-wrap: wrap;
    padding: 14px 16px 12px;
  }

  .topbar-tools {
    width: 100%;
  }

  .global-search {
    flex: 1;
    width: auto;
  }

  .page-body {
    padding: 0 16px 16px;
  }

  .device-detail-grid,
  .settings-grid,
  .upload-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 620px) {
  .metric-strip {
    grid-template-columns: minmax(0, 1fr);
    padding: 6px 4px;
  }

  .metric {
    border-right: 0;
    border-bottom: 1px solid var(--ui-border-soft);
    padding: 10px 14px;
  }

  .metric:last-child {
    border-bottom: 0;
  }

  .topbar-identity h1 {
    font-size: 18px;
  }
}

/* The desktop collapse control is hidden on touch layouts and vice versa. */
.sidebar-collapse-toggle-mobile {
  display: none;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition-duration: .01ms !important;
    animation-duration: .01ms !important;
  }
}

@media print {
  .app-layout .sidebar,
  .topbar-tools,
  .operator-toolbar {
    display: none;
  }

  .app-layout {
    margin: 0;
    height: auto;
    box-shadow: none;
  }
}

/* ── column visibility (Columns menu) ── */

.device-table.hide-system-column .col-system,
.device-table.hide-time-column .col-time {
  display: none;
}

/* ── scroll containers for pages that keep their own wrapper ──
   .main-content no longer scrolls (the frame must never grow), so each page's
   own wrapper becomes the scrolling surface. */

.epos-log-tool,
.audit-tool,
.setup-builder-page {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 0 20px 20px;
  scrollbar-width: thin;
}

.setup-builder-page {
  padding-top: var(--ui-space-4);
}

/* The browser-processing reassurance, demoted to a quiet pill: it is
   supporting information, not the status of an analysis. */
.privacy-chip {
  flex-shrink: 0;
  align-self: center;
  padding: 3px 8px;
  border: 0;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-neutral-soft);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 500;
  white-space: nowrap;
}

/* Diagnostics pages stack cards; give them consistent separation. */
.epos-log-tool .tab-content > .card,
.audit-tool .tab-content > .card,
.epos-log-tool > .tabs,
.audit-tool > .tab-nav {
  margin-bottom: var(--ui-space-4);
}

.epos-log-tool .card + .card,
.audit-tool .card + .card {
  margin-top: var(--ui-space-4);
}

/* ── sender: corrections for rules written against the old flex layout ── */

/* sender.css pins this to 50% from when the page was a flex row; in the v5
   grid the column already has its width. */
.sender-layout .sender-devices {
  width: auto;
  min-width: 0;
}

/* Four target/file/reboot/session facts do not fit across a 340px rail, so
   they read two-up and stay legible instead of truncating to "0 selec…". */
.sender-action-summary {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-bottom: 1px solid var(--ui-border-soft);
  background: var(--ui-surface-inset);
}

.sender-action-summary-item {
  border: 0;
  border-radius: var(--ui-radius-sm);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
}

.sender-action-summary-item strong {
  font-size: var(--ui-font-size-label);
  font-weight: 600;
}

.sender-action-summary-item span,
.sender-selected-count {
  font-size: var(--ui-font-size-micro);
  color: var(--ui-text-muted);
}

/* The device list owns the page's vertical space; the panel stays at the top. */
.sender-layout {
  min-width: 0;
  align-items: start;
}

.sender-devices .table-scroll {
  max-height: 58dvh;
}

/* ── deploy: run command ──
   A saved command is a label plus a multi-line shell body. In the 340px rail
   it wrapped a character at a time, so this page stacks instead: the picker and
   the library each get the page's full width. */

.sender-stacked {
  display: flex;
  flex-direction: column;
  gap: var(--ui-space-4);
}

/* Each stacked section keeps the height its own content asks for; letting the
   column shrink them squeezed the device table down to four rows regardless of
   its max-height. The page scrolls instead. */
.sender-stacked > * {
  flex: none;
}

.sender-stacked .sender-devices {
  width: auto;
  min-width: 0;
}

/* The picker is the first half of the task, not the whole page, so it shows a
   workable slice of the fleet and yields the rest to the library below it. */
.sender-stacked .sender-devices .table-scroll {
  min-height: 232px;
  max-height: 38dvh;
}

.sender-stacked .sender-action-summary {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
}

.sender-command-library .cmd-list {
  gap: var(--ui-space-2);
}

/* Label, body and actions each get their own column, and the body keeps its
   own line breaks instead of being reflowed into a paragraph. */
.sender-command-library .cmd-card {
  display: grid;
  grid-template-columns: minmax(110px, 180px) minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--ui-space-4);
  padding: 13px 15px;
}

.sender-command-library .cmd-card-label {
  padding-top: 2px;
  overflow-wrap: anywhere;
}

.sender-command-library .cmd-card-body {
  flex: none;
  color: var(--ui-text);
  font-size: var(--ui-font-size-label);
  line-height: 1.6;
  white-space: pre-wrap;
}

.sender-command-library .cmd-card-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Deleting a saved command is destructive, but a red button in every row reads
   as a warning about the row rather than about the action. It stays quiet until
   you go for it. */
.sender-command-library .btn-delete-cmd {
  border: 1px solid var(--ui-border);
  background: var(--ui-surface-1);
  color: var(--ui-text-secondary);
}

.sender-command-library .btn-delete-cmd:hover {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

.cmd-add-form {
  display: grid;
  gap: 8px;
  margin-top: var(--ui-space-4);
  padding: var(--ui-space-4);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-inset);
}

@media (max-width: 860px) {
  .sender-command-library .cmd-card {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--ui-space-2);
  }
}

/* ── account menu ──
   One placement on every page: the sidebar footer. It was briefly in the topbar
   on the pages that have one, which made the same control look like two
   different things depending on where you were. The trigger is a full row, so
   it says who you are; the address is allowed to ellipsis there because the
   panel one click away shows it whole. */

.account-menu {
  position: relative;
  width: 100%;
}

.account-trigger {
  display: flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-height: 38px;
  padding: 4px 8px;
  border-radius: var(--ui-radius-md);
  background: transparent;
  cursor: pointer;
  list-style: none;
  text-align: left;
  transition: background .15s;
}

.account-trigger::-webkit-details-marker {
  display: none;
}

.account-trigger:hover,
.account-menu[open] > .account-trigger {
  background: var(--ui-surface-2);
}

.account-trigger:focus-visible {
  outline: 2px solid var(--ui-accent);
  outline-offset: 1px;
}

.account-avatar {
  display: grid;
  flex: none;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-size: var(--ui-font-size-caption);
  font-weight: 650;
  text-transform: uppercase;
}

.account-trigger-text {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.account-trigger-label {
  color: var(--ui-text-faint);
  font-size: var(--ui-font-size-micro);
  font-weight: 500;
  line-height: 1.2;
}

.account-trigger-email {
  overflow: hidden;
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-caption);
  font-weight: 550;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-caret {
  margin-left: auto;
  flex: none;
  color: var(--ui-text-faint);
  font-size: 9px;
  line-height: 1;
}

/* Nothing sits below the footer, so the panel opens upward. */
.account-panel {
  position: absolute;
  z-index: 40;
  bottom: calc(100% + 6px);
  left: 0;
  width: max(100%, 216px);
  max-width: 300px;
  padding: var(--ui-space-4);
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-lg);
}

.account-panel-label {
  margin: 0 0 2px;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.account-panel-email {
  margin: 0 0 var(--ui-space-4);
  color: var(--ui-text);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.account-signout {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: 100%;
  min-height: 30px;
  padding: 0 11px;
  border: 1px solid var(--ui-border);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-1);
  color: var(--ui-text-secondary);
  font-family: inherit;
  font-size: var(--ui-font-size-label);
  font-weight: 500;
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}

.account-signout:hover {
  border-color: var(--ui-danger-border);
  background: var(--ui-danger-soft);
  color: var(--ui-danger);
}

/* Collapsed to the icon rail, the avatar is the whole control again. */
.sidebar-collapsed .account-trigger-text,
.sidebar-collapsed .account-caret {
  display: none;
}

.sidebar-collapsed .account-trigger {
  justify-content: center;
  padding: 4px;
}

/* ── sender: activity ──
   The log left the 340px rail because a transcript of device names, paths and
   SSH output cannot wrap usefully at that width. It spans both columns, keeps
   a real height when empty so the panel reads as ready rather than broken,
   and can be dragged taller during a long run. */

.sender-activity {
  margin-top: var(--ui-space-4);
}

.sender-activity .sender-log {
  height: 232px;
  max-height: none;
  margin-top: 11px;
  border-radius: 0 0 var(--ui-radius-card) var(--ui-radius-card);
  resize: vertical;
}

.sender-activity .sender-log:empty::before {
  content: "Nothing yet. Uploads and commands report here line by line as they run.";
  color: var(--ui-text-faint);
  font-family: var(--ui-font-sans);
  font-size: var(--ui-font-size-label);
}

/* ── sender: target review ──
   A count cannot be checked against intent; names and sites can. */

.sender-confirm-targets {
  max-height: 210px;
  overflow-y: auto;
  margin-top: var(--ui-space-4);
  padding: var(--ui-space-3) var(--ui-space-4);
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-inset);
  scrollbar-width: thin;
}

.sender-confirm-group + .sender-confirm-group {
  margin-top: var(--ui-space-3);
}

.sender-confirm-group-name {
  display: block;
  margin-bottom: 4px;
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.sender-confirm-names {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.sender-confirm-names li {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-sm);
  color: var(--ui-text);
  font-size: var(--ui-font-size-caption);
}

/* Reachable through NetBird is not the same as "the SSH login will work", and
   a manually added target is not known either way. Both are said out loud. */
.sender-confirm-names li.is-offline,
.sender-confirm-names li.is-unknown {
  color: var(--ui-text-muted);
}

.sender-confirm-names li.is-offline::after {
  content: " · offline";
  color: var(--ui-warning);
}

.sender-confirm-names li.is-unknown::after {
  content: " · not seen yet";
  color: var(--ui-text-faint);
}

.sender-filter-note {
  margin-left: auto;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

.sender-mobile-sticky {
  background: transparent;
}

.sender-add-device-panel {
  padding: 14px;
  border-bottom: 1px solid var(--ui-border-soft);
  background: var(--ui-surface-inset);
}

.sender-add-device-panel h2 {
  margin: 0 0 3px;
  font-size: var(--ui-font-size-label);
  font-weight: 600;
}

.sender-add-device-panel p {
  margin: 0;
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

.sender-add-row-inline {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.sender-add-row-inline .sender-input {
  flex: 1 1 140px;
  width: auto;
}

/* ── diagnostics pages: scoped overrides ──
   epos-log-analyser.css and audit-emulate.css scope their rules under
   .epos-log-tool / .audit-tool, so the v5 versions have to match that
   specificity rather than rely on load order. */

.epos-log-tool .tabs,
.audit-tool .tab-nav {
  gap: 2px;
  padding: 3px;
  border: 0;
  border-radius: var(--ui-radius-md);
  background: var(--ui-surface-2);
}

.epos-log-tool .tab-btn,
.audit-tool .tab-button {
  min-height: 27px;
  padding: 0 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
}

/* The selected tab is the same filled green pill the sidebar uses for the
   current page, so "where am I" reads identically at both levels. */
.epos-log-tool .tab-btn.active,
.audit-tool .tab-button.active {
  border: 0;
  border-radius: 7px;
  background: var(--ui-accent-on-fill);
  color: var(--ui-accent-fill-text);
  font-weight: 600;
  box-shadow: none;
}

.epos-log-tool .tab-btn:hover:not(.active),
.audit-tool .tab-button:hover:not(.active) {
  background: transparent;
  color: var(--ui-text);
}

.epos-log-tool .card,
.audit-tool .card {
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
}

.epos-log-tool .upload-area,
.audit-tool .upload-area {
  border: 1px dashed var(--ui-border-strong);
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-inset);
  color: var(--ui-text-muted);
}

.epos-log-tool .upload-area:hover,
.audit-tool .upload-area:hover {
  border-color: var(--ui-accent-on-fill);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
}

.epos-log-tool .definition-card,
.audit-tool .upload-panel {
  border: 0;
  border-radius: var(--ui-radius-lg);
  background: var(--ui-surface-inset);
}

/* "No file loaded" is a neutral starting state, not a failure. */
.epos-log-tool .definition-status,
.audit-tool .file-status,
.audit-tool .status-indicator {
  border: 0;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-neutral-soft);
  color: var(--ui-neutral-text);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

.epos-log-tool .definition-status.loaded,
.audit-tool .file-status.loaded,
.audit-tool .status-indicator.loaded {
  background: var(--ui-success-soft);
  color: var(--ui-success);
}

.epos-log-tool table,
.audit-tool table {
  font-size: var(--ui-font-size-label);
}

.epos-log-tool thead th,
.audit-tool thead th {
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
  background: var(--ui-surface-1);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.epos-log-tool tbody td,
.audit-tool tbody td {
  border: 0;
  border-bottom: 1px solid var(--ui-border-soft);
}

/* An unselected file is a neutral starting state; red is for a parse failure
   or invalid content (review finding 8). */
.audit-tool .status-empty {
  background: var(--ui-neutral-soft);
  color: var(--ui-neutral-text);
}

.audit-tool .status-badge,
.epos-log-tool .status-badge {
  padding: 2px 7px;
  border: 0;
  border-radius: var(--ui-radius-xs);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

/* Step headings on the audit page: a section label, not a second page title. */
.audit-tool .step-header h2,
.audit-tool .card > h2,
.audit-tool .card-header h2 {
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
}

/* ── diagnostics: source switch ──
   Two independent paths, not five steps. The switch picks the source; the tab
   strip below it is the stage within that source. */

.diagnostic-modes {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--ui-space-3);
  flex-wrap: wrap;
  margin-bottom: var(--ui-space-1);
}

.audit-tool .segmented > button,
.audit-tool .segmented > button:not(.tab-button) {
  min-height: 28px;
  padding: 0 12px;
  border: 0;
  background: transparent;
  color: var(--ui-text-secondary);
  font-size: var(--ui-font-size-label);
  font-weight: 500;
}

.audit-tool .segmented > button.active,
.audit-tool .segmented > button.active:not(.tab-button) {
  background: var(--ui-surface-1);
  color: var(--ui-text);
  font-weight: 600;
  box-shadow: var(--ui-shadow-sm);
}

/* The legacy strip sized five numbered tabs at `flex: 1 1 150px`. Three short
   stage labels at that basis overflow the strip's fit-content width and wrap
   onto a second row, so the stages size to their own labels instead. */
.audit-tool > .tab-nav {
  /* `.audit-tool` is a column flex container. Scrolling the strip sideways
     forces overflow-y off `visible`, which makes its automatic minimum height
     zero and lets the column shrink it away, so the strip opts out of
     shrinking and clips vertically instead. */
  flex: none;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}

.audit-tool > .tab-nav::-webkit-scrollbar {
  display: none;
}

.audit-tool > .tab-nav .tab-button {
  flex: 0 0 auto;
}

/* Panel titles sit between the page title and the card titles, and are not
   section rules. */
.audit-tool .tab-content > header > h2 {
  margin: 0 0 5px;
  border: 0;
  padding: 0;
  color: var(--ui-text);
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.02em;
}

/* `.audit-tool button:not(.tab-button)` fills every button on this page with
   the accent colour and outranks `.btn`, which is why secondary actions here
   need naming explicitly. Clearing an input you loaded is a reset, not a
   destructive action, so red stays reserved for parse failures and invalid
   content. */
.audit-tool .btn-reset,
.audit-tool button.btn-reset:not(.tab-button),
.audit-tool .btn-secondary,
.audit-tool button.btn-secondary:not(.tab-button) {
  border: 1px solid var(--ui-border);
  background: var(--ui-surface-1);
  color: var(--ui-text-secondary);
  font-weight: 500;
}

.audit-tool .btn-reset:hover,
.audit-tool button.btn-reset:not(.tab-button):hover,
.audit-tool .btn-secondary:hover,
.audit-tool button.btn-secondary:not(.tab-button):hover {
  border-color: var(--ui-border-strong);
  background: var(--ui-surface-2);
  color: var(--ui-text);
}

/* One place to load a site, with the three single pickers kept below it for
   replacing an individual file. */

.audit-tool .config-bulk {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--ui-space-4);
  flex-wrap: wrap;
  margin-bottom: 10px;
}

.audit-tool .config-bulk-label {
  display: grid;
  gap: 6px;
  font-size: var(--ui-font-size-label);
  font-weight: 600;
  color: var(--ui-text);
}

.audit-tool .config-bulk-label input[type="file"] {
  max-width: 100%;
}

.audit-tool .config-bulk-feedback {
  margin: 0 0 var(--ui-space-4);
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-caption);
}

.audit-tool .config-bulk-feedback:empty {
  display: none;
}

.audit-tool .config-bulk-feedback.is-warning {
  color: var(--ui-warning);
}

/* The two reference summaries are lookups, so they collapse by default and
   stop pushing the screen table below the fold. */

.audit-tool details.config-summary {
  padding: 0;
}

.audit-tool details.config-summary > summary {
  padding: 14px var(--ui-space-5);
  color: var(--ui-text);
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
  cursor: pointer;
  list-style: none;
}

.audit-tool details.config-summary > summary::-webkit-details-marker {
  display: none;
}

.audit-tool details.config-summary > summary::before {
  content: "▸";
  display: inline-block;
  width: 14px;
  color: var(--ui-text-faint);
  font-size: 10px;
  transition: transform .15s;
}

.audit-tool details.config-summary[open] > summary::before {
  transform: rotate(90deg);
}

.audit-tool details.config-summary > summary:hover {
  color: var(--ui-accent);
}

.audit-tool details.config-summary > div {
  padding: 0 var(--ui-space-5) var(--ui-space-5);
}

/* ── device detail: fact lists ──
   Labels are quiet captions in sentence case; small-caps tracking-out reads as
   decoration at this size and competes with the values it describes. */

.detail-list {
  grid-template-columns: minmax(92px, auto) 1fr;
  column-gap: var(--ui-space-4);
  row-gap: 10px;
  font-size: var(--ui-font-size-label);
}

.detail-list dt {
  color: var(--ui-text-muted);
  font-size: var(--ui-font-size-caption);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}

.detail-list dd {
  color: var(--ui-text);
  font-weight: 500;
}

.detail-list-stacked {
  grid-template-columns: 1fr;
  row-gap: 2px;
}

.detail-list-stacked dt {
  margin-top: 12px;
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ui-text-faint);
}

.detail-list-stacked dt:first-child {
  margin-top: 0;
}

.detail-list-stacked dd {
  margin-bottom: 0;
}

.detail-list code {
  font-family: var(--ui-font-mono);
  font-size: var(--ui-font-size-caption);
}

/* The device's group chips read as companies, not as actions. */
.device-detail-grid .group-chip {
  display: inline-flex;
  padding: 2px 7px;
  border: 0;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
}

.detail-note-actions {
  display: flex;
  gap: 6px;
  margin-top: var(--ui-space-2);
  flex-wrap: wrap;
}

/* ── setup builder ──
   setup-builder.css consumes the --sb-* aliases, so it inherits the v5 palette
   already. These rules bring its distinctive pieces into the same language:
   borderless cards on shadow, and a selected state that rings rather than
   outlines in heavy accent. */

.sb-profile-card {
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
  padding: 16px;
  min-height: 0;
  transition: box-shadow .15s, background .15s;
}

.sb-profile-card:hover {
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-md);
}

/* A recommended template gets a quiet accent ring, not a 2px green outline. */
.sb-profile-card-builtin {
  border: 0;
  box-shadow: var(--ui-shadow-card), inset 0 0 0 1px var(--ui-accent-soft-strong);
}

.sb-profile-pill {
  top: 12px;
  right: 12px;
  padding: 2px 7px;
  border-radius: var(--ui-radius-xs);
  background: var(--ui-accent-soft);
  color: var(--ui-accent);
  font-size: var(--ui-font-size-micro);
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
}

.sb-profile-card-name {
  font-size: var(--ui-font-size-title);
  font-weight: 600;
  letter-spacing: -0.015em;
}

.sb-profile-card-caption,
.sb-profile-card-meta {
  font-size: var(--ui-font-size-caption);
  color: var(--ui-text-muted);
}

/* Builder surfaces: same card treatment as the rest of the app. */
.sb-card,
.sb-panel,
.sb-section {
  border: 0 !important;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-1);
  box-shadow: var(--ui-shadow-card);
}

.sb-step-title,
.sb-screen-title {
  font-size: var(--ui-font-size-heading);
  font-weight: 650;
  letter-spacing: -0.035em;
}

.sb-help-panel {
  border: 0;
  border-radius: var(--ui-radius-card);
  background: var(--ui-surface-inset);
  box-shadow: none;
}

/* ── fleet table density ──
   At 1440 with the nav expanded and the context rail in place, the device
   table has roughly 760px. Trim the cheap width first — cell padding, the
   action buttons and the repeated absolute timestamp — so the Actions column
   stays on screen instead of scrolling out of reach. */

.fleet-table {
  min-width: 0;
}

.fleet-table thead th,
.fleet-table tbody td {
  padding-left: 10px;
  padding-right: 10px;
}

.fleet-table .td-actions .btn {
  padding: 0 7px;
}

.fleet-table .dev-brand {
  max-width: 150px;
}

/* The relative time carries the meaning; the absolute one is on the title
   attribute and returns when there is room for it. */
@media (max-width: 1560px) {
  .fleet-table .last-seen-wrap .last-seen-detail,
  .fleet-table .td-device-time .last-seen-detail {
    display: none;
  }
}



/* ── merged status column ──
   The dot and the reading sit on one line; the absolute timestamp drops below
   it when there is room. */
.last-seen-head {
  display: flex;
  align-items: center;
  gap: 7px;
}

.last-seen-wrap {
  display: block;
}

/* Row actions keep their words at wide widths and fall back to the icon alone
   when the table is tight. The label stays in the DOM either way, so the
   accessible name never changes. */
@media (max-width: 1620px) {
  .fleet-table .td-actions .btn-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .fleet-table .td-actions .btn {
    padding: 0 6px;
  }
}
