/* LP Onboarding — application styles */

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

/* ===================== DARK MODE TOKEN OVERRIDES =====================
   colors_and_type.css defines the semantic tokens for light mode.
   All app text/surfaces MUST reference --fg-1/--fg-2/--fg-3/--bg-1/--bg-2/--bg-3
   (never --lp-ink or other raw brand colors directly) so this override flips
   them correctly instead of leaving dark-mode text invisible.
   ======================================================================= */
html.dark {
  --fg-1: var(--lp-white);
  --fg-2: #C7D3E0;
  --fg-3: var(--lp-fog);
  --bg-1: #0B2038;
  --bg-2: #10314F;
  --bg-3: #163F63;
  --border-1: #2A4A68;
  --border-2: #35597C;
}

/* ===================== LOGIN PAGE ===================== */

.login-page {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--lp-dreaming);
  overflow: hidden;
  padding: var(--sp-5);
}

.login-bg-pattern {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1px);
  background-size: 22px 22px;
  pointer-events: none;
}

.login-shape {
  position: absolute;
  border-radius: var(--radius-lg);
  opacity: 0.12;
  pointer-events: none;
}
.login-shape-1 {
  width: 340px;
  height: 340px;
  background: var(--lp-sapphire);
  top: -120px;
  right: -80px;
  transform: rotate(18deg);
}
.login-shape-2 {
  width: 260px;
  height: 260px;
  background: var(--lp-teal-time);
  bottom: -100px;
  left: -60px;
  transform: rotate(-24deg);
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.login-card {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 380px;
  background: var(--bg-1);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: var(--sp-7) var(--sp-6);
  text-align: center;
  animation: slideUp var(--dur-slow) var(--ease-out);
}

.login-logo {
  height: 48px;
  width: auto;
  margin-bottom: var(--sp-4);
}

.login-title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  color: var(--fg-1);
  margin: 0 0 var(--sp-1);
}

.login-subtitle {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--fg-2);
  margin: 0 0 var(--sp-5);
}

.login-divider {
  border: none;
  border-top: 1px solid var(--border-1);
  margin: 0 0 var(--sp-5);
}

.btn-microsoft {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  background: var(--lp-sapphire);
  color: var(--fg-inverse);
  border: none;
  border-radius: var(--radius-md);
  padding: var(--sp-3) var(--sp-4);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-body);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.btn-microsoft:hover {
  background: var(--fg-link-hover);
}

.login-footer {
  margin: var(--sp-5) 0 0;
  font-size: var(--fs-caption);
  color: var(--fg-3);
}

/* ===================== TOP NAV ===================== */

.topnav {
  position: sticky;
  top: 0;
  z-index: 50;
  height: 52px;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: 0 var(--sp-4);
  background: var(--lp-dreaming);
  box-shadow: var(--shadow-sm);
}

.topnav-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}

.topnav-logo {
  height: 24px;
  width: auto;
  display: block;
}

.topnav-divider {
  width: 1px;
  height: 24px;
  background: rgba(255, 255, 255, 0.2);
  flex-shrink: 0;
}

.topnav-titles {
  display: flex;
  flex-direction: column;
  line-height: var(--lh-tight);
  overflow: hidden;
}

.topnav-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.95);
  white-space: nowrap;
}

.topnav-subtitle {
  font-size: 11px;
  color: rgba(255, 255, 255, 0.55);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topnav-spacer {
  flex: 1;
}

.topnav-user {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.user-avatar {
  width: 28px;
  height: 28px;
  border-radius: var(--radius-pill);
  background: var(--lp-sapphire);
  color: var(--lp-white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  flex-shrink: 0;
}

.user-name {
  font-size: 13px;
  color: rgba(255, 255, 255, 0.85);
  white-space: nowrap;
}

.icon-btn {
  background: none;
  border: none;
  padding: var(--sp-2);
  cursor: pointer;
  color: rgba(255, 255, 255, 0.85);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease-std);
}
.icon-btn:hover {
  background: rgba(255, 255, 255, 0.08);
}

.theme-toggle .icon-moon {
  display: none;
}
html.dark .theme-toggle .icon-sun {
  display: none;
}
html.dark .theme-toggle .icon-moon {
  display: block;
}

.hamburger,
.hamburger::before,
.hamburger::after {
  content: "";
  display: block;
  height: 2px;
  width: 18px;
  background: rgba(255, 255, 255, 0.85);
  border-radius: 2px;
}
.hamburger {
  position: relative;
}
.hamburger::before {
  position: absolute;
  top: -6px;
  left: 0;
}
.hamburger::after {
  position: absolute;
  top: 6px;
  left: 0;
}

.btn-signout {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: rgba(255, 255, 255, 0.9);
  font-size: 12px;
  font-family: var(--font-body);
  padding: var(--sp-1) var(--sp-3);
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.btn-signout:hover {
  background: rgba(255, 255, 255, 0.1);
}

/* ===================== SIDEBAR ===================== */

.sidebar {
  position: fixed;
  top: 52px;
  left: 0;
  bottom: 0;
  width: 260px;
  max-width: 80vw;
  background: var(--bg-1);
  border-right: 1px solid var(--border-1);
  box-shadow: var(--shadow-lg);
  transform: translateX(-100%);
  transition: transform var(--dur-base) var(--ease-std);
  z-index: 40;
  overflow-y: auto;
}
.sidebar.open {
  transform: translateX(0);
}

.sidebar-backdrop {
  position: fixed;
  top: 52px;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-std);
  z-index: 30;
}
.sidebar-backdrop.open {
  opacity: 1;
  pointer-events: auto;
}

.sidebar-nav {
  padding: var(--sp-4);
}

.sidebar-section {
  margin-bottom: var(--sp-5);
}

.sidebar-heading {
  display: block;
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--fg-3);
  margin: 0 0 var(--sp-2) var(--sp-2);
}

.nav-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: var(--sp-2) var(--sp-3);
  margin-bottom: 2px;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--fg-2);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std), color var(--dur-fast) var(--ease-std);
}
.nav-item:hover {
  background: var(--bg-2);
  color: var(--fg-1);
}
.nav-item.active {
  background: var(--lp-sapphire);
  color: var(--fg-inverse);
  font-weight: 600;
}
/* The neutral, non-revealing retry control shown in the System section when the storage-independent Settings-access check itself is unavailable — deliberately styled smaller/muted (never like a real destination) so it never reads as an actual nav item. */
.nav-item--retry {
  font-size: var(--fs-caption, 14px);
  color: var(--fg-3);
  font-style: italic;
}

/* ===================== MAIN CONTENT ===================== */

.main-content {
  width: 100%;
  max-width: 1600px;
  margin: 0 auto;
  padding: clamp(16px, 2vw, 32px);
}

.view-placeholder h2 {
  font-family: var(--font-display);
  color: var(--fg-1);
  text-transform: capitalize;
}
.view-placeholder p {
  color: var(--fg-2);
}

/* ===================== DASHBOARD HOME ===================== */

:root {
  --dash-cyan: #2FB8C4;
  --dash-orange: #E8792B;
  --dash-blue-light: #6FA8E0;
}

/* ---------- Page header ---------- */

.page-header {
  margin-bottom: var(--sp-5);
}

.page-header-label {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-3);
  margin-bottom: var(--sp-1);
}

.page-header-title {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  color: var(--fg-1);
  margin: 0 0 var(--sp-1);
}

.page-header-subtitle {
  font-size: var(--fs-body);
  color: var(--fg-3);
  margin: 0;
}

/* ---------- Loading / error states ---------- */

.loading-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding: var(--sp-8) var(--sp-4);
  background: rgba(0, 0, 0, 0.45);
  border-radius: var(--radius-md);
}

/* ---------- Branded "LP loader" busy-state overlay ----------
   Reused by web/js/ui/zoom.js for every busy state: the dashboard's own initial-load panel
   (.loading-container above, a normal-flow swap) and two true absolute-positioned overlays
   (.lp-loader-overlay, over #zoom-content for Refresh/Reset and over the Add Users panel for its
   own two busy states). All three share this icon/text/animation styling. The dark backdrop color
   reuses the exact rgba(0, 0, 0, 0.45) scrim already established by .sidebar-backdrop. */

.lp-loader-overlay {
  display: none;
  position: absolute;
  inset: 0;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  background: rgba(0, 0, 0, 0.45);
  border-radius: var(--radius-md);
  z-index: 5;
  opacity: 1;
  /* Deliberately 700ms (not the shared --dur-slow token) — must match .lp-loader-icon-wrap-exit's
     own 700ms shrink animation (and JS's LP_LOADER_EXIT_MS) exactly, so the backdrop can never
     fade to fully invisible before the icon's shrink has visibly finished. */
  transition: opacity 700ms var(--ease-std);
}

.lp-loader-overlay.lp-loader-overlay-exiting {
  opacity: 0;
}

.lp-loader-icon-wrap {
  display: inline-block;
  /* Resting state matches the entrance keyframes' own 0% frame (small, transparent) — so simply
     making the overlay visible already paints this exact frame before any animation class is
     ever added, satisfying "the browser paints the small starting state before beginning the
     animation." */
  opacity: 0;
  transform: scale(0.05);
}

.lp-loader-icon {
  display: block;
  width: 112px;
  height: 112px;
  animation: lpLoaderSpin 2s linear infinite;
}

@keyframes lpLoaderSpin {
  to {
    transform: rotate(360deg);
  }
}

/* Entrance: ~5% and transparent -> grows prominently, slightly overshooting full size -> settles
   at full size. Rotation during the growth comes from .lp-loader-icon's own always-running spin
   above — composited on a separate inner element specifically so this wrap's scale/opacity
   keyframes never fight a rotation on the same transform. */
.lp-loader-icon-wrap-enter {
  animation: lpLoaderGrow 1050ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes lpLoaderGrow {
  0% {
    opacity: 0;
    transform: scale(0.05);
  }
  55% {
    opacity: 1;
  }
  80% {
    transform: scale(1.08);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* Completion: rotate (still via .lp-loader-icon's continuous spin) while shrinking from full
   size back to ~5%, fading out over the same span. */
.lp-loader-icon-wrap-exit {
  animation: lpLoaderShrink 700ms ease-in both;
}

@keyframes lpLoaderShrink {
  from {
    opacity: 1;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(0.05);
  }
}

.lp-loader-text {
  font-family: var(--font-display);
  font-size: var(--fs-body-lg);
  font-weight: 700;
  color: var(--fg-inverse);
  text-align: center;
  padding: 0 var(--sp-4);
}

@media (prefers-reduced-motion: reduce) {
  .lp-loader-overlay {
    transition: none;
  }
  .lp-loader-icon {
    animation: none;
  }
  /* No scale/rotation animation — but the icon must still show, centered, at full size (never
     stuck at the small/transparent resting state above, which only exists to seed the animation
     that reduced motion is turning off here). */
  .lp-loader-icon-wrap,
  .lp-loader-icon-wrap-enter,
  .lp-loader-icon-wrap-exit {
    animation: none;
    opacity: 1;
    transform: scale(1);
  }
  /* Results ticker (Home dashboard) — defensive backstop only: home.js's own prefersReducedMotion()
     check already renders the static stacked list instead of ever creating a walking procession in
     the first place; this only guards the rare case of the OS setting changing while one is already
     mid-walk, freezing it in place rather than leaving it animating. */
  .home-ticker-procession {
    animation: none;
    position: static;
    transform: none;
    margin: 0 auto;
  }
  .home-ticker-placard {
    animation: none;
  }
}

.error-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-3);
  padding: var(--sp-8) var(--sp-4);
  text-align: center;
}

.error-message {
  font-size: var(--fs-body);
  color: var(--color-danger);
}

/* Positioning context for #zoom-content's own .lp-loader-overlay (Refresh/Reset busy state). */
.dashboard-content-area {
  position: relative;
}

.stats-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-bottom: var(--sp-5);
}

.stat-card {
  flex: 1 1 180px;
  background: var(--bg-2);
  border-left: 4px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--sp-4) var(--sp-5);
}

.stat-card-total { border-left-color: var(--lp-sapphire); }
.stat-card-pending { border-left-color: var(--lp-sun-glow); }
.stat-card-completed { border-left-color: var(--color-success); }
.stat-card-offboarded { border-left-color: #7c5cff; }
.stat-card-cancelled { border-left-color: var(--fg-3); }
.stat-card-attention { border-left-color: var(--dash-orange); }

.stat-card-zoom-total { border-left-color: var(--lp-sapphire); }
.stat-card-zoom-zra { border-left-color: var(--dash-cyan); }

.stat-number {
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  font-weight: 700;
  line-height: var(--lh-tight);
  color: var(--fg-1);
}

.stat-label {
  font-size: var(--fs-caption);
  color: var(--fg-3);
  margin-top: var(--sp-1);
}

.stat-sub {
  font-size: var(--fs-caption);
  margin-top: var(--sp-1);
}

.stat-sub-danger {
  color: var(--color-danger);
}

/* ---------- Filter bar ---------- */

.filter-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.filter-input,
.filter-select,
.filter-date {
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  color: var(--fg-1);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  padding: var(--sp-2) var(--sp-3);
}

.filter-input {
  flex: 1 1 220px;
  min-width: 160px;
}

.filter-date {
  color-scheme: dark;
}
html:not(.dark) .filter-date {
  color-scheme: light;
}

.filter-input:focus,
.filter-select:focus,
.filter-date:focus {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.filter-input:disabled,
.filter-select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.auto-refresh-indicator {
  margin-left: auto;
  font-size: var(--fs-caption);
  color: var(--fg-3);
  white-space: nowrap;
}

/* ---------- Zoom dashboard filter-bar additions (single-row, matching Home) ---------- */

/* Shrinks only the Zoom search field so Technician and Date Range fit alongside it on normal
   desktop widths — the shared .filter-input's flex-grow would otherwise let it consume all
   remaining row space. Home's search field is untouched (it uses .filter-input alone). */
.zoom-search-input {
  flex: 0 1 220px;
  max-width: 260px;
}

/* Display is toggled inline by updateCustomRangeVisibility() ('none'/'flex') — only the internal
   layout is set here. */
.zoom-custom-range-group {
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

/* ---------- Date-range trigger + anchored popover ---------- */

/* Positioning context for the absolutely-positioned popover below. */
.date-range-field {
  position: relative;
  display: inline-flex;
}

/* Fixed width so switching presets never reflows Refresh/Reset/Last Refreshed; overflow handling
   is defensive only — every label formatDateRangeLabel() produces fits comfortably. */
.date-range-trigger {
  width: 200px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}

.date-range-popover {
  position: absolute;
  top: calc(100% + var(--sp-2));
  left: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  min-width: 240px;
  max-width: calc(100vw - var(--sp-6));
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  padding: var(--sp-3);
}

.date-range-popover-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
}

.scope-filter-message {
  font-size: var(--fs-caption);
  color: var(--color-danger);
  margin: calc(-1 * var(--sp-2)) 0 var(--sp-4);
}

/* ---------- Buttons ---------- */

.btn-neutral-outline {
  background: transparent;
  border: 1px solid var(--border-1);
  color: var(--fg-1);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  padding: var(--sp-2) var(--sp-4);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.btn-neutral-outline:hover {
  background: var(--bg-3);
}
.btn-neutral-outline:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.btn-neutral-outline:disabled:hover {
  background: transparent;
}

.btn-remove-services {
  background: transparent;
  border: 1px solid var(--color-danger);
  color: var(--color-danger);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  padding: var(--sp-2) var(--sp-4);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.btn-remove-services:hover {
  background: rgba(214, 69, 69, 0.1);
}
/* Home dashboard Remove Services only (web/js/onboarding-cleanup-view.mjs adds .home-remove-services) —
   the shared .btn-remove-services used by Zoom is intentionally unchanged. Visual only: the `disabled`
   attribute and home.js's click-time recheck are what actually block the action. */
.home-remove-services:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.home-remove-services:disabled:hover {
  background: transparent;
}

.btn-onboard {
  background: var(--lp-sapphire);
  border: 1px solid var(--lp-sapphire);
  color: var(--fg-inverse);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  padding: var(--sp-2) var(--sp-4);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.btn-onboard:hover {
  background: var(--fg-link-hover);
}
.btn-onboard:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.btn-onboard:disabled:hover {
  background: var(--lp-sapphire);
}

/* ---------- Data table ---------- */

.table-container {
  overflow-x: auto;
  background: var(--bg-1);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
}

.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-caption);
}

.data-table thead th {
  position: sticky;
  top: 0;
  background: var(--bg-2);
  color: var(--fg-3);
  text-align: left;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border-1);
  white-space: nowrap;
}

.data-table th.sortable {
  cursor: pointer;
  user-select: none;
}
.data-table th.sortable::after {
  content: '';
  display: inline-block;
  width: 8px;
  margin-left: var(--sp-1);
}
.data-table th.sortable.sort-asc::after {
  content: '\25B2';
  font-size: 8px;
  opacity: 0.7;
}
.data-table th.sortable.sort-desc::after {
  content: '\25BC';
  font-size: 8px;
  opacity: 0.7;
}

.data-table td {
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--border-1);
  color: var(--fg-1);
  vertical-align: middle;
}

.data-table tbody tr.data-row {
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.data-table tbody tr.data-row:hover {
  background: var(--bg-2);
}

.data-table tbody tr.detail-row td {
  padding: 0;
  border-bottom: 1px solid var(--border-1);
}

/* ---------- Zoom directory table (fixed column widths) ---------- */

.zoom-table {
  table-layout: fixed;
}

.zoom-table th:nth-child(1),
.zoom-table tbody tr.data-row td:nth-child(1) {
  width: 40px;
}
.zoom-table th:nth-child(2),
.zoom-table tbody tr.data-row td:nth-child(2) {
  width: 20%;
}
.zoom-table th:nth-child(3),
.zoom-table tbody tr.data-row td:nth-child(3) {
  width: 30%;
}
.zoom-table th:nth-child(4),
.zoom-table tbody tr.data-row td:nth-child(4) {
  width: 25%;
}
.zoom-table th:nth-child(5),
.zoom-table tbody tr.data-row td:nth-child(5) {
  width: 25%;
}

/* ---------- Row selection (checkbox column, selected-row state) ---------- */

.checkbox-col {
  text-align: center;
}

.data-table td.checkbox-col,
.data-table th.checkbox-col {
  width: 36px;
  padding-left: var(--sp-3);
  padding-right: var(--sp-3);
}

.zoom-table td.checkbox-col {
  padding-left: var(--sp-3);
  padding-right: var(--sp-3);
}

.zoom-table tbody tr.data-row.selected {
  background: rgba(48, 118, 229, 0.12);
}
.zoom-table tbody tr.data-row.selected:hover {
  background: rgba(48, 118, 229, 0.18);
}

/* ---------- Selection bar ---------- */

.selection-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3);
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
}

.selection-bar-count {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--fg-1);
}

.selection-bar-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  flex: 1 1 auto;
}

/* ---------- Pagination bar ---------- */

.pagination-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-4);
}

.pagination-info {
  font-size: var(--fs-caption);
  color: var(--fg-3);
  white-space: nowrap;
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.pagination-pages {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
}

.pagination-page-btn {
  background: transparent;
  border: 1px solid var(--border-1);
  color: var(--fg-1);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  font-weight: 600;
  min-width: 30px;
  padding: var(--sp-1) var(--sp-2);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.pagination-page-btn:hover {
  background: var(--bg-3);
}
.pagination-page-btn.active {
  background: var(--lp-sapphire);
  border-color: var(--lp-sapphire);
  color: var(--fg-inverse);
}

.pagination-ellipsis {
  color: var(--fg-3);
  padding: 0 var(--sp-1);
}

.pagination-size {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-caption);
  color: var(--fg-3);
  white-space: nowrap;
}

.pagination-size select {
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  color: var(--fg-1);
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  padding: var(--sp-1) var(--sp-2);
}

/* ---------- Expanded detail panel ---------- */

@keyframes detailSlideDown {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.detail-panel {
  background: var(--bg-2);
  border-top: 1px solid var(--border-1);
  border-bottom: 1px solid var(--border-1);
  padding: var(--sp-4) var(--sp-5);
  animation: detailSlideDown var(--dur-base) var(--ease-out);
}

.detail-subtitle {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--fg-1);
  margin-bottom: var(--sp-3);
}

.detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(160px, 1fr));
  gap: var(--sp-3) var(--sp-5);
  margin-bottom: var(--sp-4);
}

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

.detail-label {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-3);
}

.detail-value {
  font-size: var(--fs-body);
  color: var(--fg-1);
}

/* Offboarding overlay detail (web/js/home-dashboard-stats.mjs describeOffboardingDetail) — the
   verbatim Entra marker text, shown as secondary/muted text alongside the descriptive sentence. */
.detail-raw-marker {
  color: var(--fg-3);
  font-size: 11px;
}

/* Collapsed by default (native <details>/<summary> — no JS needed) — raw Entra/Zoom/First Orion
   identifiers are troubleshooting-only, never part of the primary detail presentation. */
.detail-technical {
  border-top: 1px solid var(--border-1);
  padding-top: var(--sp-3);
  margin-bottom: var(--sp-4);
}

.detail-technical-summary {
  display: block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-3);
  margin-bottom: var(--sp-2);
  cursor: pointer;
}
.detail-technical-summary:hover,
.detail-technical-summary:focus-visible {
  color: var(--fg-2);
}
.detail-technical[open] .detail-technical-summary {
  margin-bottom: var(--sp-2);
}

.detail-system-caption {
  font-size: var(--fs-caption);
  color: var(--fg-3);
  margin-bottom: var(--sp-2);
}

.detail-system-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(120px, 1fr));
  gap: var(--sp-3);
}

.detail-system-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.detail-system-label {
  font-size: var(--fs-caption);
  color: var(--fg-3);
}

.detail-system-value {
  font-size: var(--fs-body);
  color: var(--fg-1);
}

.detail-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.detail-actions-bordered {
  border-top: 1px solid var(--border-1);
  padding-top: var(--sp-4);
}

/* ---------- Onboarding lifecycle panel (Home dashboard Onboard action) ---------- */

.onboarding-panel {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  background: var(--bg-1);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  padding: var(--sp-3) var(--sp-4);
  margin-bottom: var(--sp-4);
  overflow-wrap: anywhere; /* a long typed address wraps instead of running past the panel */
}

.onboarding-panel-status {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-body);
  color: var(--fg-1);
}

.onboarding-panel-message {
  font-size: var(--fs-caption);
  color: var(--fg-2);
}

.onboarding-panel-message-danger {
  color: var(--color-danger);
}

.onboarding-panel-details {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.onboarding-panel-form {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-width: 320px;
}

/* In this column-direction form, .filter-input's 220px flex basis would become the input's height. */
.onboarding-panel-form .filter-input {
  flex: none;
}

/* An expanded Home row spans the table's full scroll width, which on a narrow screen is wider than
   the visible table. Keep its onboarding content within the visible width, pinned to the left, so
   text wraps instead of running offscreen; the data columns still scroll horizontally. */
.dashboard-home .table-container {
  container-type: inline-size;
}

.dashboard-home .detail-row .onboarding-panel,
.dashboard-home .detail-row .detail-panel > .batch-progress-detail,
.dashboard-home .detail-row .detail-panel > .batch-progress-unavailable-note {
  position: sticky;
  left: var(--sp-5);
  max-width: calc(100cqi - 2 * var(--sp-5));
}

.onboarding-panel-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.onboarding-panel-trace {
  font-size: 11px;
  color: var(--fg-3);
}

/* ---------- Results ticker (Home dashboard onboarding completions) ----------
   web/js/ui/home.js's bottom results ticker — a full-width procession lane (.home-ticker-bar/
   .home-ticker-stage) in which one small walking character pushes a large result "placard" left to
   right at a time, plus a static expandable Details view (.home-ticker-panel). Reduced motion is
   decided in JS (home.js's prefersReducedMotion()) — the character/walk markup is never even
   created in that case, replaced by an equally prominent static stacked list instead; the small
   @media (prefers-reduced-motion: reduce) override below is only a defensive backstop for the OS
   setting changing while a walk is already mid-flight. Narrow-viewport handling lives in the shared
   @media (max-width: 640px) block below — never duplicated here. */

.home-content-with-ticker {
  padding-bottom: 180px;
}

.home-ticker-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 15;
  display: flex;
  align-items: stretch;
  gap: var(--sp-3);
  height: clamp(112px, 11vw, 150px);
  background: var(--bg-2);
  color: var(--fg-1);
  border-top: 1px solid var(--border-1);
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-body);
  box-shadow: var(--shadow-md);
}
.home-ticker-bar[hidden] {
  display: none;
}
.home-ticker-bar.home-ticker-static {
  height: auto;
  min-height: clamp(112px, 11vw, 150px);
  align-items: center;
}

.home-ticker-stage {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
}
.home-ticker-bar.home-ticker-static .home-ticker-stage {
  position: static;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  overflow-y: auto;
  max-height: 100%;
  padding: var(--sp-1) 0;
}

/* ---- Normal motion: the approved robot performance + placard crossing the lane together ---- */
/*
   The robot's own crossing position AND which pre-rendered frame is showing are both driven by ONE
   JS elapsed-time clock (web/js/ui/home-ticker.mjs's startProcession()/tick loop — see
   robotTravelFraction/robotFrameIndex/robotProcessionBoxLeft in web/js/home-onboarding-results.mjs),
   sampling the exact approved 41s timeline (assets-source/home-ticker/robot-performance/motion.mjs),
   never a CSS keyframe — a flip-book of 329 individual baked frames can't be expressed as a CSS
   transform/position keyframe, and completion is likewise decided directly by that same clock
   (elapsedSeconds >= ROBOT_ROUTINE_DURATION), not a separate CSS animation timer. Pause (manual,
   hover, focus-within) and page-visibility backgrounding are read directly off the DOM each tick —
   see isPausedNow() in home-ticker.mjs — so there is exactly one source of truth for whether time is
   advancing, not a CSS animation-play-state mirrored by a second JS check.
*/

.home-ticker-procession {
  position: absolute;
  top: 50%;
  left: 0; /* JS (home-ticker.mjs) overwrites this every tick with a measured pixel position — see
    robotProcessionBoxLeft; this is only the pre-first-tick fallback. */
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 0;
}

.home-ticker-robot {
  /* Downscaled from the exported 140×190 frames (assets-source/home-ticker/robot-performance/
     frames/manifest.json) to fit the lane's own height with room for the placard beside it. */
  width: 94px;
  height: 128px;
  flex: none;
  position: relative;
  z-index: 2; /* paints in FRONT of the placard — the slight overlap/depth Jesse asked to keep */
  /* (140 - anchorPixel.x) * (128/190) ≈ 28px — the manifest's card-contact anchor, scaled to this
     display size: how far the robot's own rendered content extends PAST where the card's left
     edge sits, so the placard tucks in behind by exactly that amount rather than a guessed value. */
  margin-right: -28px;
  pointer-events: none;
}

.home-ticker-placard,
.home-ticker-static-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  background: var(--bg-1);
  border: 2px solid var(--color-success);
  border-radius: var(--radius-md);
  padding: var(--sp-2) var(--sp-4);
  box-shadow: var(--shadow-sm);
}
.home-ticker-placard {
  min-width: 14rem;
  max-width: 34rem;
  /* A restrained, ONE-SHOT entrance — never a repeating flash. Runs once per new procession
     (each is a freshly-inserted element); it never restarts on its own. */
  animation: home-ticker-glow-in 0.6s ease-out;
}
.home-ticker-static-card {
  max-width: 100%;
}
.home-ticker-placard-warning {
  border-color: var(--color-warning);
}
.home-ticker-placard-danger {
  border-color: var(--color-danger);
}

@keyframes home-ticker-glow-in {
  0% {
    opacity: 0;
    transform: scale(0.92);
  }
  60% {
    box-shadow: 0 0 16px 2px rgba(31, 168, 138, 0.35);
  }
  100% {
    opacity: 1;
    transform: scale(1);
    box-shadow: var(--shadow-sm);
  }
}

.home-ticker-placard-primary {
  font-size: var(--fs-body-lg);
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.home-ticker-static-card .home-ticker-placard-primary {
  white-space: normal;
}

.home-ticker-placard-secondary {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.home-ticker-static-card .home-ticker-placard-secondary {
  white-space: normal;
}

.home-ticker-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: var(--radius-pill);
  flex: none;
}
.home-ticker-dot-success {
  background: var(--color-success);
}
.home-ticker-dot-warning {
  background: var(--color-warning);
}
.home-ticker-dot-danger {
  background: var(--color-danger);
}

.home-ticker-controls {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: none;
}

.home-ticker-count {
  font-weight: 600;
  font-size: var(--fs-caption);
  margin-right: 2px;
  white-space: nowrap;
}

.home-ticker-controls button {
  background: transparent;
  border: 1px solid var(--border-2);
  color: inherit;
  border-radius: var(--radius-sm);
  padding: var(--sp-1) var(--sp-3);
  font-size: var(--fs-caption);
  cursor: pointer;
  white-space: nowrap;
}
.home-ticker-controls button:hover,
.home-ticker-controls button:focus-visible {
  background: var(--bg-3);
}

.home-ticker-panel {
  position: fixed;
  left: 0;
  right: 0;
  /* Fallback only, matching the ticker bar's own tallest clamp() value — home.js's
     syncTickerPanelOffset() overwrites this with the bar's REAL measured height (which varies: the
     clamp() below in normal motion, auto/content-driven height in the reduced-motion static view,
     and again across the narrow-viewport breakpoint) so this panel always floats immediately above
     the bar instead of a stale fixed offset overlapping/being covered by it. */
  bottom: 150px;
  z-index: 15;
  max-height: 42vh;
  overflow-y: auto;
  background: var(--bg-1);
  color: var(--fg-1);
  border-top: 1px solid var(--border-1);
  padding: var(--sp-3) var(--sp-4);
  box-shadow: var(--shadow-lg);
}
.home-ticker-panel[hidden] {
  display: none;
}

.home-ticker-panel-empty {
  color: var(--fg-3);
}

.home-ticker-panel-item {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid var(--color-success);
  border-bottom: 1px solid var(--border-1);
}
.home-ticker-panel-item-warning {
  border-left-color: var(--color-warning);
}
.home-ticker-panel-item-danger {
  border-left-color: var(--color-danger);
}
.home-ticker-panel-item:last-child {
  border-bottom: none;
}

.home-ticker-panel-item-body {
  flex: 1 1 auto;
  min-width: 0;
}

.home-ticker-panel-item-title {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  font-weight: 600;
}

.home-ticker-panel-item-detail {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  margin-top: 2px;
}

.home-ticker-panel-dismiss {
  background: transparent;
  border: none;
  color: var(--fg-2);
  cursor: pointer;
  font-size: var(--fs-body-lg);
  line-height: 1;
  padding: 2px var(--sp-2);
  flex: none;
}
.home-ticker-panel-dismiss:hover,
.home-ticker-panel-dismiss:focus-visible {
  color: var(--fg-1);
}

/* ---------- Batch onboarding panel (Home dashboard) ----------
   The expanded panel above the Home table (web/js/ui/home.js's renderBatchPanel()) — visually
   consistent with the existing .add-users-panel shell (Zoom's own expanded bulk-action panels) but
   with its own row-grid shape (Expand | Name | Entra | Zoom | First Orion | Status), which nothing
   in the existing Zoom panels needed. */

.batch-panel {
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-4);
}
.batch-panel[hidden] {
  display: none;
}

.batch-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--sp-3);
}

.batch-panel-title {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--fg-1);
}

.batch-panel-close {
  padding: 2px var(--sp-2);
  line-height: 1;
}

.batch-confirm-summary {
  font-weight: 600;
  margin-bottom: var(--sp-2);
}

.batch-confirm-list {
  list-style: none;
  margin: 0 0 var(--sp-3);
  padding: 0;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
}
.batch-confirm-row {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-1);
}
.batch-confirm-row:last-child {
  border-bottom: none;
}

.batch-panel-actions {
  display: flex;
  gap: var(--sp-2);
}

.batch-row-list {
  max-height: 420px;
  overflow-y: auto;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
}

.batch-row-grid {
  display: grid;
  grid-template-columns: 32px 1fr 1fr 1fr 1fr 1fr;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-1);
}
.batch-row-grid:last-child {
  border-bottom: none;
}
.batch-row-grid-header {
  position: sticky;
  top: 0;
  background: var(--bg-2);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 11px;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-3);
}

.batch-row-expand-toggle {
  background: transparent;
  border: none;
  color: var(--fg-2);
  cursor: pointer;
  font-size: 11px;
  padding: 2px;
}
.batch-row-expand-toggle:hover,
.batch-row-expand-toggle:focus-visible {
  color: var(--fg-1);
}

.batch-row-detail {
  grid-column: 1 / -1;
  padding: var(--sp-3);
  border-bottom: 1px solid var(--border-1);
  background: var(--bg-1);
}

.batch-progress-detail {
  margin-bottom: var(--sp-3);
}

.batch-progress-system {
  margin-bottom: var(--sp-2);
}

.batch-progress-steps {
  list-style: none;
  margin: var(--sp-1) 0 0;
  padding: 0;
}
.batch-progress-steps li {
  font-size: var(--fs-caption);
  padding: 2px 0;
}

.batch-progress-stale-note {
  color: #8a5c00;
  font-size: var(--fs-caption);
  margin-bottom: var(--sp-2);
}
html.dark .batch-progress-stale-note {
  color: var(--lp-sun-glow);
}

.batch-progress-unavailable-note {
  color: var(--fg-3);
  font-size: var(--fs-caption);
  margin-bottom: var(--sp-2);
}

@media (max-width: 640px) {
  /* Four status pills (Entra/Zoom/First Orion/Status) don't fit legibly beside a 24px expand-arrow
     column — that column is reserved for the arrow alone; every pill instead spans two full-width
     tracks across two rows below the name, never squeezed into the arrow's own narrow track (which
     produced overlapping/garbled pill text before this fix — verified via a real <640px browser
     screenshot). */
  .batch-row-grid {
    grid-template-columns: 24px 1fr 1fr;
    grid-template-areas:
      'expand name  name'
      '.      entra zoom'
      '.      fo    status';
    row-gap: var(--sp-1);
  }
  .batch-row-grid-header {
    display: none;
  }
  /* The grid-template-areas above only take effect once each cell is actually assigned to one —
     without this, cells simply flow in DOM order through the narrow column track and overlap. */
  .batch-cell-expand {
    grid-area: expand;
  }
  .batch-cell-name {
    grid-area: name;
  }
  .batch-cell-entra {
    grid-area: entra;
  }
  .batch-cell-zoom {
    grid-area: zoom;
  }
  .batch-cell-fo {
    grid-area: fo;
  }
  .batch-cell-status {
    grid-area: status;
  }
}

/* ---------- Batch onboarding results ticker (approved multi-card conveyor) ----------
   web/js/ui/home-batch-ticker-dom.mjs's own moving lane — a SEPARATE stage from the single-hire
   .home-ticker-bar/.home-ticker-stage above (which stays completely untouched), so multiple result
   cards can be visually on-screen at once without competing for the same lane. Positioning/frame
   selection are driven entirely by JS (web/js/home-batch-ticker.mjs's motion math), exactly like the
   single-hire ticker — never a CSS keyframe for the crossing itself. */

.home-batch-ticker-bar {
  position: relative;
  overflow: hidden;
  height: clamp(112px, 11vw, 150px);
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  margin-bottom: var(--sp-4);
  box-shadow: var(--shadow-sm);
}
.home-batch-ticker-bar[hidden] {
  display: none;
}
.home-batch-ticker-bar.home-batch-ticker-static {
  height: auto;
  min-height: clamp(112px, 11vw, 150px);
}

.home-batch-ticker-stage {
  position: relative;
  width: 100%;
  height: 100%;
}
.home-batch-ticker-bar.home-batch-ticker-static .home-batch-ticker-stage {
  position: static;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
}

.home-batch-ticker-card {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 0;
  /* Cards from adjacent slots must never visually merge/obscure each other's text — the approved
     handoff spacing (web/js/home-batch-ticker.mjs's SPACING constant) already keeps a full card
     width of clearance at every handoff; z-index here only breaks ties consistently (later-arriving
     cards paint on top), never masks a still-readable neighboring card. */
  z-index: 1;
}

.home-batch-ticker-robot {
  width: 94px;
  height: 128px;
  flex: none;
  position: relative;
  z-index: 2;
  margin-right: -28px;
  pointer-events: none;
}

.home-batch-ticker-placard,
.home-batch-ticker-static-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  background: var(--bg-1);
  border: 2px solid var(--color-success);
  border-radius: var(--radius-md);
  padding: var(--sp-2) var(--sp-4);
  box-shadow: var(--shadow-sm);
  min-width: 12rem;
  max-width: 28rem;
}
.home-batch-ticker-static-card {
  max-width: 100%;
}

/* Re-asserted here (not just relying on the existing .home-ticker-placard-warning/-danger rules
   defined earlier in this file) because CSS cascades by source order when specificity ties — the
   base border-color set on .home-batch-ticker-placard/.home-batch-ticker-static-card above comes
   AFTER those earlier rules, so without this it would always win regardless of severity. */
.home-ticker-placard-warning {
  border-color: var(--color-warning);
}
.home-ticker-placard-danger {
  border-color: var(--color-danger);
}

@media (prefers-reduced-motion: reduce) {
  .home-batch-ticker-card {
    position: static;
    transform: none;
  }
}

@media (max-width: 640px) {
  .home-batch-ticker-bar {
    height: auto;
    min-height: 96px;
  }
  .home-batch-ticker-robot {
    width: 72px;
    height: 98px;
    margin-right: -20px;
  }
  .home-batch-ticker-placard {
    min-width: 0;
    max-width: 60vw;
    padding: var(--sp-1) var(--sp-3);
  }
}

/* ---------- Detail sections (Zoom expanded detail) ---------- */

.detail-section {
  margin-bottom: 16px;
}

.detail-section-label {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 10px;
  color: var(--fg-3);
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-1);
  margin-bottom: 12px;
}

.detail-field-label {
  font-size: 11px;
  color: var(--fg-3);
  margin-bottom: 4px;
}

.detail-field-value {
  font-size: 13px;
  color: var(--fg-1);
}

.detail-chip {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--radius-pill);
  background: var(--bg-1);
  border: 1px solid var(--border-1);
  font-size: 11px;
  color: var(--fg-2);
  margin: 2px 4px 2px 0;
}

.detail-chips-container {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

/* Interactive existing-group chips (Manage Groups entry point) — a real <button>, reusing
   .detail-chip's own look, with hover/focus affordance so it visibly reads as clickable. Never
   used for Monitoring Groups chips, which remain the plain read-only .detail-chip. */
.detail-chip-interactive {
  cursor: pointer;
  font: inherit;
  transition: background var(--dur-fast) var(--ease-std), border-color var(--dur-fast) var(--ease-std);
}
.detail-chip-interactive:hover:not(:disabled) {
  background: var(--bg-2);
  border-color: var(--lp-sapphire);
  color: var(--fg-link);
}
.detail-chip-interactive:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}
.detail-chip-interactive:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

/* ---------- Status badges ---------- */

.badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: var(--radius-pill);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.badge-completed {
  background: rgba(31, 168, 138, 0.15);
  color: var(--color-success);
}
.badge-pre-registered {
  background: rgba(47, 184, 196, 0.15);
  color: var(--dash-cyan);
}
.badge-needs-attention {
  background: rgba(255, 190, 36, 0.2);
  color: #8a5c00;
}
html.dark .badge-needs-attention {
  color: var(--lp-sun-glow);
}
.badge-failed {
  background: rgba(214, 69, 69, 0.15);
  color: var(--color-danger);
}
.badge-in-progress {
  background: rgba(48, 118, 229, 0.15);
  color: var(--lp-sapphire);
}
.badge-queued {
  background: rgba(111, 168, 224, 0.2);
  color: var(--dash-blue-light);
}
.badge-cancelled {
  background: var(--bg-3);
  color: var(--fg-3);
}
.badge-offboarded {
  background: rgba(124, 92, 255, 0.15);
  color: #5b3fd6;
}
html.dark .badge-offboarded {
  color: #b7a6ff;
}

.badge-zra-licensed {
  background: rgba(31, 168, 138, 0.15);
  color: var(--color-success);
}
.badge-zra-none {
  background: var(--bg-3);
  color: var(--fg-3);
}
.badge-zra-scope-error {
  background: rgba(255, 190, 36, 0.2);
  color: #8a5c00;
}
html.dark .badge-zra-scope-error {
  color: var(--lp-sun-glow);
}
.badge-zra-api-error {
  background: rgba(214, 69, 69, 0.15);
  color: var(--color-danger);
}

/* ---------- Batch onboarding per-system progress pills (web/js/onboarding-progress-presentation.mjs) ----------
   A SEPARATE small vocabulary from the .badge-* overall-status pills above (waiting/skipped/
   unavailable have no equivalent in that set) — reused visually via the shared .badge shell, never
   the overall-status classes themselves. The loading dot (.badge-progress-spinner) only ever appears
   on a badge carrying .is-live (set in JS ONLY when the backend reports state:"running" AND the
   attempt's freshness is "current" — see describeOnboardingProgress's own isRunning rule); the
   visible/accessible TEXT already states the real status regardless, so color/motion is never the
   only signal (WCAG 1.4.1). */

.badge-progress-waiting {
  background: var(--bg-3);
  color: var(--fg-3);
}
.badge-progress-running {
  background: rgba(48, 118, 229, 0.15);
  color: var(--lp-sapphire);
}
.badge-progress-completed {
  background: rgba(31, 168, 138, 0.15);
  color: var(--color-success);
}
.badge-progress-failed {
  background: rgba(214, 69, 69, 0.15);
  color: var(--color-danger);
}
.badge-progress-needs-attention {
  background: rgba(255, 190, 36, 0.2);
  color: #8a5c00;
}
html.dark .badge-progress-needs-attention {
  color: var(--lp-sun-glow);
}
.badge-progress-skipped {
  background: var(--bg-3);
  color: var(--fg-3);
}
.badge-progress-unavailable {
  background: transparent;
  border: 1px dashed var(--border-1);
  color: var(--fg-3);
}

.badge-progress-spinner {
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-radius: var(--radius-pill);
  border: 2px solid currentColor;
  border-top-color: transparent;
  animation: batch-progress-spin 0.9s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .badge-progress-spinner {
    animation: none;
    /* Still visibly distinct from a static/non-live badge even without motion. */
    opacity: 0.6;
  }
}
@keyframes batch-progress-spin {
  to {
    transform: rotate(360deg);
  }
}

/* ---------- Empty state ---------- */

.empty-state {
  text-align: center;
  color: var(--fg-3);
  padding: var(--sp-8) var(--sp-4);
}

/* ---------- Add Users picker (Zoom dashboard) ---------- */

.add-users-panel {
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--sp-4) var(--sp-5);
  margin-bottom: var(--sp-4);
}

/* Positioning context for the panel's own .lp-loader-overlay — scoped to this modifier class
   (rather than added to .add-users-panel itself) so the shared ZRA panel, which also uses
   .add-users-panel, is never affected. */
.add-users-panel-loader-host {
  position: relative;
}

.add-users-panel-header {
  margin-bottom: var(--sp-3);
}

.add-users-panel-title {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--fg-1);
}

.add-users-search {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: var(--sp-3);
}

.add-users-results {
  max-height: 260px;
  overflow-y: auto;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
  margin-bottom: var(--sp-3);
}

.add-users-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-1);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-std);
}
.add-users-row:last-child {
  border-bottom: none;
}
.add-users-row:hover {
  background: var(--bg-2);
}

.add-users-checkbox {
  flex: 0 0 auto;
}

.add-users-row-name {
  flex: 1 1 40%;
  color: var(--fg-1);
  font-size: var(--fs-caption);
}

.add-users-row-email {
  flex: 1 1 60%;
  color: var(--fg-3);
  font-size: var(--fs-caption);
}

.add-users-empty {
  padding: var(--sp-4);
  text-align: center;
  color: var(--fg-3);
  font-size: var(--fs-caption);
}

.add-users-message {
  font-size: var(--fs-caption);
  color: var(--color-success);
  margin-bottom: var(--sp-3);
}

.add-users-message-error {
  color: var(--color-danger);
}

.add-users-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* ---------- Manage ZRA action panel (Zoom dashboard) ---------- */

.zra-action-summary {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  margin-bottom: var(--sp-3);
}

.zra-action-choice {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  margin-bottom: var(--sp-3);
}

.zra-action-radio {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-caption);
  color: var(--fg-1);
  cursor: pointer;
}

.zra-results-summary {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--fg-1);
  margin-bottom: var(--sp-2);
}

.zra-results-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-sm);
  background: var(--bg-1);
}

.zra-results-list li {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--border-1);
  font-size: var(--fs-caption);
  color: var(--fg-2);
}
.zra-results-list li:last-child {
  border-bottom: none;
}

/* ---------- Manage Groups action panel (Zoom dashboard) ---------- */
/* Reuses .zra-action-panel/.zra-action-summary/.zra-results-* and .add-users-* tokens/classes
   directly (see the ZRA block above and the Add Users block further above) — only the few
   elements unique to this panel (the action fieldset reset, the cardinality note, and the
   ambiguous-group marker) get their own rules here. */

.group-action-choice {
  /* Reset the browser's default <fieldset> chrome so it lays out identically to .zra-action-choice
     (a plain <div> in the ZRA panel) — this panel uses <fieldset>/<legend> instead for a proper
     accessible group label. */
  border: 0;
  margin: 0;
  padding: 0;
}

.group-action-cardinality-note {
  font-size: var(--fs-caption);
  color: var(--fg-3);
  margin-bottom: var(--sp-3);
}

.group-action-row-ambiguous {
  opacity: 0.6;
}

.group-action-ambiguous-badge {
  margin-left: auto;
  font-size: var(--fs-caption);
  color: var(--color-danger);
  white-space: nowrap;
}

/* Assignment-state label shown beside every group in the picker ("Assigned"/"Not assigned",
   "Assigned to all/some/none", "Already assigned to all", "Will be added first", the longer
   multi-user Set Primary labels — "Assigned to some · remaining users will be added first",
   "Assigned to none · all users will be added first" — etc.) — informational text, not a
   warning, so it reuses the same neutral tone as .group-action-cardinality-note rather than the
   ambiguous badge's danger color. Deliberately no white-space: nowrap (unlike the ambiguous
   badge above) — the multi-user Set Primary labels are long enough to need to wrap onto a
   second line in a narrow picker rather than overflow or clip. */
.group-action-assignment-label {
  margin-left: auto;
  font-size: var(--fs-caption);
  color: var(--fg-3);
}

/* Manage Groups picker rows: the "Assigned to some" details expansion is a SIBLING of the
   checkbox <label> (see renderGroupActionResults() in zoom.js), never nested inside it — a
   <details>/<summary> inside a <label> would incorrectly toggle the checkbox itself. This
   wrapper carries the row separator so the label and its optional details sit together inside
   one visually undivided row, matching the picker's existing per-row look. */
.group-action-row-container {
  border-bottom: 1px solid var(--border-1);
}
.group-action-row-container:last-child {
  border-bottom: none;
}
.group-action-row-container .add-users-row {
  border-bottom: none;
}

.group-action-assigned-details summary {
  cursor: pointer;
  font-size: var(--fs-caption);
  color: var(--fg-link);
  padding: 0 var(--sp-3) var(--sp-2);
}

.group-action-assigned-details-content {
  font-size: var(--fs-caption);
  color: var(--fg-2);
  padding: 0 var(--sp-3) var(--sp-2) var(--sp-6);
}

/* Visually hidden but still reachable by screen readers/keyboard — used for the Manage Groups
   search field's <label> and the action fieldset's <legend>, whose meaning is already conveyed
   visually (a placeholder, and the radio labels themselves). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ===================== RESPONSIVE ===================== */

@media (max-width: 640px) {
  .topnav-subtitle {
    display: none;
  }
  .user-name {
    display: none;
  }
  .login-card {
    padding: var(--sp-6) var(--sp-4);
  }
  .sidebar {
    width: 240px;
  }
  .stats-row {
    flex-direction: column;
  }
  .filter-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .auto-refresh-indicator {
    margin-left: 0;
    text-align: right;
  }
  .zoom-search-input {
    max-width: none;
    flex: 1 1 auto;
  }
  .date-range-field {
    display: flex;
  }
  .date-range-trigger {
    width: 100%;
  }
  .date-range-popover {
    left: 0;
    right: 0;
    min-width: 0;
    max-width: none;
  }
  .pagination-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .pagination-controls {
    justify-content: center;
  }
  .detail-grid,
  .detail-system-grid {
    grid-template-columns: 1fr;
  }
  .add-users-row {
    flex-direction: column;
    align-items: flex-start;
  }
  .group-action-ambiguous-badge {
    margin-left: 0;
  }
  .group-action-assignment-label {
    margin-left: 0;
  }
  .home-ticker-bar {
    height: clamp(96px, 26vw, 116px);
    padding: var(--sp-2) var(--sp-3);
  }
  .home-ticker-bar.home-ticker-static {
    min-height: clamp(96px, 26vw, 116px);
  }
  .home-ticker-count {
    display: none;
  }
  .home-ticker-robot {
    width: 70px;
    height: 95px;
    margin-right: -21px; /* same anchor ratio as the desktop size above, scaled down */
  }
  .home-ticker-placard {
    min-width: 0;
    max-width: 72vw;
    white-space: normal;
  }
  .home-ticker-placard .home-ticker-placard-primary,
  .home-ticker-placard .home-ticker-placard-secondary {
    white-space: normal;
  }
  .home-ticker-panel-item {
    flex-direction: column;
  }
  .home-ticker-panel-dismiss {
    align-self: flex-end;
  }
}

/* ---------- Offboarding dashboard (web/js/offboarding-page.mjs) ----------
   Form card + results card side by side on wide screens, stacked below 900px. Reuses the shared
   .page-header, .filter-input, .btn-onboard, .badge-*, .error-state, .loading-container and
   .lp-loader-overlay; only the layout, field, banner, service-row and callout pieces are new. */

.offboarding-battle {
  grid-column: 1 / -1;
  position: relative;
  overflow: hidden;
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  background: #153b50;
  margin-top: var(--sp-2);
  isolation: isolate;
}

.offboarding-battle[hidden] { display: none; }

/* A faded print treatment stays inside the decorative scene. */
.offboarding-battle::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.48;
  background-image:
    radial-gradient(ellipse at 50% 48%, transparent 35%, #33271980 100%),
    linear-gradient(115deg, #d6b87c38, #e8dfbf16 48%, #6a594a24),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='grain'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.72' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Cpath fill='%23c4ae83' opacity='.2' d='M0 0h220v220H0z' filter='url(%23grain)'/%3E%3C/svg%3E");
}

.offboarding-battle-heading {
  position: absolute;
  z-index: 3;
  inset: 0 0 auto;
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5) var(--sp-5);
  background: linear-gradient(#0b2432b3, transparent);
  color: #d2e5e9;
  pointer-events: none;
  font-size: var(--fs-caption);
}

.offboarding-battle-heading > :first-child {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #b8d8dc;
}

.offboarding-battle-canvas {
  display: block;
  width: 100%;
  height: clamp(320px, 34vw, 480px);
  filter: sepia(0.34) saturate(0.68) contrast(0.9) brightness(1.06);
}

.offboarding-layout {
  display: grid;
  grid-template-columns: minmax(280px, 380px) minmax(0, 1fr);
  gap: var(--sp-5);
  align-items: start;
}

.offboarding-card {
  position: relative; /* positioning context for the results card's .lp-loader-overlay */
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  background: var(--bg-2);
  border: 1px solid var(--border-1);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
  padding: var(--sp-4) var(--sp-5);
  min-width: 0;
  overflow-wrap: anywhere;
}

.offboarding-card-title {
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  color: var(--fg-3);
  margin: 0;
}

.offboarding-results-card {
  min-height: 220px;
}

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

.offboarding-label {
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--fg-2);
}

/* Column-direction field: stop .filter-input's 220px flex basis from becoming its height. */
.offboarding-field .filter-input {
  flex: none;
  min-width: 0;
  width: 100%;
  box-sizing: border-box;
}

.offboarding-input--valid {
  border-color: var(--color-success);
}

.offboarding-input--invalid {
  border-color: var(--color-danger);
}

.offboarding-hint {
  min-height: 1em;
  font-size: var(--fs-caption);
  color: var(--color-danger);
}

.offboarding-toggle {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--fs-body);
  color: var(--fg-1);
  cursor: pointer;
}

.offboarding-toggle input {
  margin-top: 4px;
}

.offboarding-toggle small {
  display: block;
  font-size: var(--fs-caption);
  color: var(--fg-3);
}

.offboarding-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.offboarding-note {
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--fg-3);
}

.offboarding-placeholder {
  margin: 0;
  font-size: var(--fs-body);
  color: var(--fg-3);
}

.offboarding-banner {
  border-radius: var(--radius-sm);
  border-left: 4px solid var(--border-1);
  background: var(--bg-1);
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--fg-1);
}

.offboarding-banner--ok { border-left-color: var(--color-success); }
.offboarding-banner--dry { border-left-color: var(--lp-sun-glow); }
.offboarding-banner--fail { border-left-color: var(--color-danger); }
.offboarding-banner--review { border-left-color: var(--dash-orange); }

.offboarding-summary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

.offboarding-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  margin: var(--sp-3) 0;
}

.offboarding-meta dt {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--fg-3);
}

.offboarding-meta dd {
  margin: 2px 0 0;
  font-size: var(--fs-body);
  color: var(--fg-1);
}

.offboarding-service-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.offboarding-service-row {
  display: grid;
  grid-template-columns: minmax(80px, 140px) auto minmax(0, 1fr);
  align-items: baseline;
  gap: var(--sp-3);
  background: var(--bg-1);
  border: 1px solid var(--border-1);
  border-left: 4px solid var(--border-1);
  border-radius: var(--radius-sm);
  padding: var(--sp-2) var(--sp-3);
}

.offboarding-service-row--success { border-left-color: var(--color-success); }
.offboarding-service-row--failed { border-left-color: var(--color-danger); }
.offboarding-service-row--dryrun { border-left-color: var(--dash-blue-light); }
.offboarding-service-row--skipped { border-left-color: var(--fg-3); }
.offboarding-service-row--unrecognized { border-left-color: var(--dash-orange); }

.offboarding-service-name {
  font-weight: 600;
  color: var(--fg-1);
}

.offboarding-service-message {
  font-size: var(--fs-caption);
  color: var(--fg-2);
}

.offboarding-service-phone {
  color: var(--fg-1);
}

.offboarding-callout {
  margin-top: var(--sp-4);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border-1);
  border-left: 4px solid var(--border-1);
  background: var(--bg-1);
  padding: var(--sp-3) var(--sp-4);
}

.offboarding-callout--warning { border-left-color: var(--lp-sun-glow); }
.offboarding-callout--manual { border-left-color: var(--lp-sapphire); }

.offboarding-callout-title {
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wide);
  color: var(--fg-2);
  margin: 0 0 var(--sp-2);
}

.offboarding-callout-list {
  margin: 0;
  padding-left: var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--fs-caption);
  color: var(--fg-1);
}

@media (max-width: 900px) {
  .offboarding-layout {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 640px) {
  .offboarding-card {
    padding: var(--sp-3);
  }
  .offboarding-service-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .offboarding-service-message {
    grid-column: 1 / -1;
  }
}
