/* responsive + polish fixes */
.page-header h1 { white-space: nowrap; }
.page-header .subtitle {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex-shrink: 1;
}
.page-header { gap: 12px; flex-wrap: wrap; }
.status-pip span { white-space: nowrap; }
.status-pip { white-space: nowrap; }
.rail-item { min-width: 0; }
.rail-item > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.rail-item > span.rail-count, .rail-item > .rail-color-dot { overflow: visible; flex-shrink: 0; min-width: auto; }

/* 2026-08-05 zgaetano bin columns replaced tree: gap:0 on bin items for tight layout. */
.library-controls-strip .rail-list .rail-item--bin,
.bin-column .rail-item--bin { gap: 0 !important; }

@media (max-width: 1100px) {
  .dash-stat-row { grid-template-columns: repeat(2, 1fr); }
  .jobs-stats { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 1280px) {
  .recorder-row {
    grid-template-columns: 180px 1fr;
    grid-template-rows: auto auto;
  }
  .recorder-stats { grid-column: 2 / 3; grid-row: 2; }
  .recorder-actions { grid-column: 1 / 3; grid-row: 3; justify-content: flex-end; padding-top: 4px; border-top: 1px solid var(--border); }
}

.capture-stat-label, .recorder-stat .stat-label, .dash-stat-label, .dash-stat-sub {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar > * { flex-shrink: 0; }
.topbar .crumb { min-width: 0; overflow: hidden; }
.topbar .crumb > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar .spacer { flex: 1; min-width: 8px; }

@media (max-width: 1100px) {
  .topbar .search-wrap { display: none; }
}
@media (max-width: 900px) {
  .topbar .status-pip span:not(.dot) { display: none; }
}

.library-toolbar { flex-wrap: wrap; }
.library-toolbar .search { width: 200px; }

@media (max-width: 1280px) {
  .page-body > div[style*="grid-template-columns: 440px"] {
    grid-template-columns: 1fr !important;
  }
}

.audio-meter.v {
  border-radius: 99px;
  background: rgba(255,255,255,0.04);
  padding: 3px;
}

.recorder-preview { min-height: 56px; }

.activity-text .target { word-break: break-word; }

.asset-card .meta .sub { overflow: hidden; min-width: 0; flex-wrap: wrap; }
/* #52 - duration mono badge in the meta row had no shrink behaviour, so on
   narrow cards it overlapped the project text. Force the duration column to
   never overflow and let the project label ellipsize. */
.asset-card .meta .sub > .duration { flex-shrink: 0; margin-left: auto; }
.asset-card .meta .sub > :not(.duration) { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

.dash-stat-label, .dash-stat-mono, .dash-stat-sub { position: relative; z-index: 1; }
.dash-sparkline { z-index: 0; }

/* ============================================================
   Search bar polish - give it a real container so it doesn't
   read as floating text on the topbar background.
   ============================================================ */
.topbar .search,
.search-wrap .search {
  background: var(--bg-2);
  border: 1px solid var(--border-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.03),
    0 1px 0 rgba(0, 0, 0, 0.25);
  color: var(--text-1);
  transition: background 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}
.topbar .search:hover,
.search-wrap .search:hover {
  background: var(--bg-3);
  border-color: var(--border-stronger);
}
.topbar .search:focus-within,
.search-wrap .search:focus-within,
.topbar .search.is-open,
.search-wrap .search.is-open {
  background: var(--bg-2);
  border-color: var(--accent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 0 0 3px var(--accent-soft);
}
.topbar .search input::placeholder,
.search-wrap .search input::placeholder {
  color: var(--text-3);
}
.topbar .search .search-icon,
.search-wrap .search .search-icon {
  color: var(--text-2);
}
.topbar .search:focus-within .search-icon,
.search-wrap .search:focus-within .search-icon {
  color: var(--accent-text);
}
.topbar .search .kbd,
.search-wrap .search .kbd {
  background: var(--bg-1);
  border-color: var(--border-stronger);
  color: var(--text-2);
}

/* Library-local "Filter assets" search - same container treatment,
   keep its compact width. */
.library-toolbar .search {
  background: var(--bg-2);
  border: 1px solid var(--border-strong);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.03),
    0 1px 0 rgba(0, 0, 0, 0.25);
}
.library-toolbar .search:hover { background: var(--bg-3); border-color: var(--border-stronger); }
.library-toolbar .search:focus-within {
  border-color: var(--accent);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 0 0 3px var(--accent-soft);
}

/* Open-state dropdown: visually connect it to the input. */
.search-wrap .search.is-open {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.search-results {
  background: var(--bg-2);
  border-color: var(--border-stronger);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  margin-top: -1px;
  padding: 6px;
}
.search-result {
  padding: 8px 10px;
}
.search-result + .search-result { margin-top: 1px; }
.search-result:hover { background: var(--hover-strong); }
.search-result.active {
  background: var(--accent-soft);
  outline: 1px solid var(--accent-soft-2);
  outline-offset: -1px;
}

/* ============================================================
   Right-click context menu - pop it forward off the page so it
   reads as a menu, not a floating list.
   ============================================================ */
.ctx-menu {
  background: var(--bg-2);
  border: 1px solid var(--border-stronger);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset,
    0 18px 40px rgba(0, 0, 0, 0.55),
    0 4px 10px rgba(0, 0, 0, 0.35);
  padding: 6px;
  min-width: 240px;
  /* Tall menus (many actions + the move-to-bin list) used to overflow the
     viewport, hiding lower items like Transcode below the screen edge with no
     way to reach them. Cap the height and scroll instead. */
  max-height: calc(100vh - 16px);
  overflow-y: auto;
  animation: ctxFadeIn 90ms ease-out both;
}
@keyframes ctxFadeIn {
  from { opacity: 0; transform: translateY(-2px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.ctx-menu .ctx-header {
  padding: 8px 10px 8px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-3);
  border-bottom: 1px solid var(--border);
  margin: 0 -2px 6px;
}
.ctx-menu .ctx-divider {
  background: var(--border-strong);
  margin: 6px 2px;
}
.ctx-menu .ctx-section-label {
  font-size: 9.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--text-4);
  padding: 8px 10px 4px;
}
.ctx-menu button {
  padding: 7px 10px;
  border-radius: 5px;
  gap: 10px;
  color: var(--text-1);
}
.ctx-menu button + button { margin-top: 1px; }
.ctx-menu button:hover:not(:disabled) {
  background: var(--accent-soft);
  color: var(--accent-text);
}
.ctx-menu button:hover:not(:disabled) svg { color: var(--accent); }
.ctx-menu button:disabled { color: var(--text-3); }
.ctx-menu button:disabled svg { color: var(--text-4); }
.ctx-menu button.danger:hover:not(:disabled) {
  background: var(--danger-soft);
  color: var(--danger);
}
.ctx-menu button.danger:hover:not(:disabled) svg { color: var(--danger); }

/* Row-popover menu (Users page etc.) - match the same polish so the
   app feels consistent. */
.row-menu {
  background: var(--bg-2);
  border: 1px solid var(--border-stronger);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.04) inset,
    0 14px 32px rgba(0, 0, 0, 0.5);
  padding: 6px;
}
.row-menu button { padding: 7px 10px; border-radius: 5px; }
.row-menu button:hover { background: var(--accent-soft); color: var(--accent-text); }
.row-menu button.danger:hover { background: var(--danger-soft); color: var(--danger); }

/* Project card right-click context menu — self-contained (was reusing .row-menu
   which is sized/positioned for an inline dropdown, making the fixed context
   menu render oversized). Compact fixed popover at the cursor. */
.proj-ctx-menu {
  position: fixed;
  z-index: 9999;
  min-width: 184px;
  max-width: 240px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px;
  background: var(--bg-2);
  border: 1px solid var(--border-stronger);
  border-radius: 8px;
  box-shadow: 0 14px 32px rgba(0, 0, 0, 0.5);
}
.proj-ctx-menu button {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  background: transparent;
  border: 0;
  color: var(--text-1);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.2;
  padding: 8px 10px;
  border-radius: 5px;
  cursor: pointer;
  text-align: left;
}
.proj-ctx-menu button:hover { background: var(--accent-soft); color: var(--accent-text); }
.proj-ctx-menu button.danger { color: var(--danger); }
.proj-ctx-menu button.danger:hover { background: var(--danger-soft); color: var(--danger); }

/* ============================================================
   Sidebar brand logo - replace the gradient "D" tile with the
   actual dragon-coiled-D logo. mix-blend-mode: screen drops the
   light-gray PNG background so only the black silhouette + blue
   flame remain over the dark sidebar.
   ============================================================ */
.brand-logo {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  object-fit: contain;
  /* Rainbow dragon on transparent bg — no filter needed on dark sidebar. */
}
.sidebar-header:hover .brand-logo {
  opacity: 1;
}
/* Light mode: darken the white outline so the logo reads on light bg. */
[data-theme="light"] .brand-logo {
  filter: drop-shadow(0 0 1px rgba(0,0,0,0.3));
}

/* ============================================================
   Launcher home - full-bleed landing page with the logo as hero
   and big section tiles.
   ============================================================ */
.launcher {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  background: var(--bg-0);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 32px 64px;
}
.launcher-inner {
  width: 100%;
  max-width: 1160px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 40px;
}

.launcher-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  margin-top: 8px;
}
/* Logo wrapper — quiet hero mark with a soft pulse halo (restored per user request). */
.launcher-logo-wrap {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 120px;
  height: 120px;
  flex-shrink: 0;
}
.launcher-logo-pulse {
  position: absolute;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  background: radial-gradient(circle, var(--accent-soft) 0%, transparent 70%);
  animation: logoPulse 3s ease-in-out infinite;
  z-index: 0;
}
@keyframes logoPulse {
  0%, 100% { transform: scale(1); opacity: 0.6; }
  50%      { transform: scale(1.15); opacity: 1; }
}
.launcher-logo {
  position: relative;
  z-index: 1;
  width: 110px;
  height: 110px;
  object-fit: contain;
  /* Rainbow dragon — show colors as-is. */
}
/* Light mode: subtle shadow so the logo reads on white ground. */
[data-theme="light"] .launcher-logo {
  filter: drop-shadow(0 0 2px rgba(0,0,0,0.25));
}
@keyframes launcherLogoIn {
  from { opacity: 0; transform: scale(0.88); }
  to   { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .launcher-logo-pulse { animation: none; opacity: 0.6; }
  .launcher-logo { animation: none; }
}

.launcher-wordmark {
  margin: 0;
  font-size: 44px;
  font-weight: 700;
  letter-spacing: 0.12em;
  line-height: 1;
  color: var(--text-1);
  text-shadow: none;
}
.launcher-kicker {
  margin: 2px 0 0;
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.launcher-tagline {
  margin: 0;
  color: var(--text-3);
  font-size: 13.5px;
  letter-spacing: 0.02em;
}
@media (max-width: 480px) {
  .launcher-tagline { font-size: 11.5px; letter-spacing: 0; }
}

.launcher-tagline-motto {
  margin-top: 6px;
  color: var(--accent);
  font-style: italic;
  font-size: 15px;
  letter-spacing: 0.04em;
}

.launcher-grid {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}
@media (max-width: 960px) { .launcher-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .launcher-grid { grid-template-columns: 1fr; } }

/* Settings sits on its own centered row beneath the main grid. */
.launcher-tile-secondary {
  min-height: 120px;
  padding: 16px 18px 18px;
}
.launcher-tile-secondary .launcher-tile-icon {
  width: 34px;
  height: 34px;
  border-radius: 8px;
  margin-bottom: 4px;
}
.launcher-tile-secondary .launcher-tile-icon svg {
  width: 17px;
  height: 17px;
}
.launcher-tile-secondary .launcher-tile-label {
  font-size: 15px;
}
.launcher-tile-secondary .launcher-tile-desc {
  font-size: 12px;
}

/* Settings row: holds the 4 secondary tiles. */
.launcher-settings-row {
  width: 100%;
  display: flex;
  justify-content: center;
}
.launcher-tile-settings {
  width: 100%;
  max-width: calc((100% - 28px) / 3);
}
@media (max-width: 960px) { .launcher-tile-settings { max-width: calc((100% - 14px) / 2); } }
@media (max-width: 620px) { .launcher-tile-settings { max-width: 100%; } }

.launcher-tile {
  position: relative;
  display: grid;
  grid-template-areas:
    "icon arrow"
    "label label"
    "sub sub"
    "desc desc";
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: 6px;
  text-align: left;
  padding: 20px 22px 22px;
  border-radius: var(--r-lg);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.04), transparent 45%),
    var(--bg-1);
  border: 1px solid var(--border);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.03),
    0 12px 28px rgba(0, 0, 0, 0.28);
  color: var(--text-1);
  cursor: pointer;
  transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease, background 140ms ease;
  min-height: 168px;
  overflow: hidden;
  isolation: isolate;
}
.launcher-tile::before {
  /* Tinted accent halo that brightens on hover. Sits behind content
     (z-index lower than children which inherit 1). */
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(120% 80% at 0% 0%, var(--tile-tint, transparent), transparent 60%);
  opacity: 0;
  transition: opacity 160ms ease;
  z-index: 0;
}
.launcher-tile > * { position: relative; z-index: 1; }
.launcher-tile:hover {
  transform: translateY(-2px);
  border-color: var(--border-stronger);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.05),
    0 18px 40px rgba(0, 0, 0, 0.42);
}
.launcher-tile:hover::before { opacity: 1; }
.launcher-tile:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.launcher-tile:active { transform: translateY(0); }

.launcher-tile-icon {
  grid-area: icon;
  width: 44px; height: 44px;
  border-radius: 10px;
  display: grid;
  place-items: center;
  background: var(--tile-icon-bg, var(--bg-3));
  color: var(--tile-icon-fg, var(--text-1));
  border: 1px solid var(--tile-icon-border, var(--border-strong));
  margin-bottom: 6px;
}
.launcher-tile-icon svg { width: 22px; height: 22px; }

.launcher-tile-label {
  grid-area: label;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.launcher-tile-sub {
  grid-area: sub;
  font-size: 11.5px;
  font-family: var(--font-mono);
  color: var(--tile-sub-fg, var(--text-3));
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.launcher-tile-desc {
  grid-area: desc;
  font-size: 12.5px;
  color: var(--text-3);
  line-height: 1.5;
  margin-top: 4px;
}
.launcher-tile-arrow {
  grid-area: arrow;
  align-self: start;
  color: var(--text-4);
  transform: translateX(-4px);
  transition: transform 140ms ease, color 140ms ease;
}
.launcher-tile:hover .launcher-tile-arrow {
  transform: translateX(0);
  color: var(--tile-icon-fg, var(--accent-text));
}

/* Tone variants - colour the icon tile + halo, leave the body text
   neutral so the tile reads as a button, not a banner. */
.launcher-tile.tone-accent {
  --tile-tint: rgba(236, 19, 19, 0.14);
  --tile-icon-bg: var(--accent-soft);
  --tile-icon-fg: var(--accent-text);
  --tile-icon-border: rgba(236, 19, 19, 0.28);
}
.launcher-tile.tone-live {
  --tile-tint: rgba(255, 59, 48, 0.18);
  --tile-icon-bg: var(--live-soft);
  --tile-icon-fg: var(--live);
  --tile-icon-border: rgba(255, 59, 48, 0.30);
}
.launcher-tile.tone-purple {
  --tile-tint: rgba(181, 124, 250, 0.18);
  --tile-icon-bg: var(--purple-soft);
  --tile-icon-fg: var(--purple);
  --tile-icon-border: rgba(181, 124, 250, 0.30);
}
.launcher-tile.tone-success {
  --tile-tint: rgba(45, 212, 168, 0.16);
  --tile-icon-bg: var(--success-soft);
  --tile-icon-fg: var(--success);
  --tile-icon-border: rgba(45, 212, 168, 0.30);
}
.launcher-tile.tone-warn {
  --tile-tint: rgba(245, 166, 35, 0.18);
  --tile-icon-bg: var(--warning-soft);
  --tile-icon-fg: var(--warning);
  --tile-icon-border: rgba(245, 166, 35, 0.30);
}
.launcher-tile.tone-neutral {
  --tile-tint: rgba(255, 255, 255, 0.06);
  --tile-icon-bg: var(--bg-3);
  --tile-icon-fg: var(--text-1);
  --tile-icon-border: var(--border-stronger);
}
.launcher-tile.tone-ghost {
  --tile-tint: rgba(255, 255, 255, 0.04);
  --tile-icon-bg: transparent;
  --tile-icon-fg: var(--text-2);
  --tile-icon-border: var(--border);
  background:
    linear-gradient(180deg, rgba(255,255,255,0.02), transparent 50%),
    var(--bg-1);
}

.launcher-status {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-start;
  margin-top: 4px;
}

/* ── Current version panel (below bento tiles) ── */
.launcher-version {
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--bg-1);
  padding: 12px 16px;
  margin-top: 4px;
}
.launcher-version-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--text-2);
  font-weight: 600;
}
.launcher-version-num {
  color: var(--accent);
  font-size: 12px;
}
.launcher-version-head .muted {
  color: var(--text-4);
  font-size: 11px;
  margin-left: auto;
}
.launcher-version-notes {
  margin: 8px 0 0;
  padding-left: 18px;
  font-size: 11.5px;
  color: var(--text-3);
  line-height: 1.7;
}
.launcher-status-pip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  font-family: var(--font-mono);
  color: var(--text-3);
  letter-spacing: 0.02em;
  padding: 6px 12px;
  border-radius: 99px;
  border: 1px solid var(--border);
  background: var(--bg-1);
}
.launcher-status-pip .dot {
  width: 6px; height: 6px; border-radius: 50%;
  box-shadow: 0 0 0 3px var(--success-soft);
}
.launcher-status-pip .muted { color: var(--text-4); margin-left: 2px; }
.launcher-status-pip.live .dot {
  box-shadow: 0 0 0 3px var(--live-soft);
}

.launcher-footer {
  margin-top: 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--text-4);
}
.launcher-footer-logo {
  width: 16px; height: 16px;
  object-fit: contain;
  opacity: 0.75;
  flex-shrink: 0;
}

/* Tactile press feedback on high-stakes operational buttons. */
.btn-record:active,
button.btn.primary:active {
  transform: scale(0.97);
  transition: transform 80ms ease-out;
}

/* Smooth active-item transition in sidebar nav. */
.nav-item {
  transition: background 150ms ease-out, color 150ms ease-out;
}

/* ============================================================
   Recorder row - signal indicator with a pulsing dot when
   actually receiving frames. Closes part of #2.
   ============================================================ */
.signal-val {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.signal-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.04);
}
.signal-dot.receiving {
  /* static ring — signal, not beacon (impeccable) */
  box-shadow: 0 0 0 2px rgba(45, 212, 168, 0.5);
}

/* ============================================================
   BMD card diagram - rendered inside the Cluster node panel.
   The SVG is generated by bmd-card.js; styles live here so
   they inherit the app CSS custom properties at render time.
   ============================================================ */
.bmd-card-diagram {
  width: 100%;
  overflow: hidden;
}
.bmd-card-svg {
  width: 100%;
  height: auto;
  display: block;
}
.bmd-card-body {
  fill: var(--bg-3, #1e2130);
  stroke: var(--border, #2d3147);
  stroke-width: 1;
}
.bmd-card-bracket {
  fill: var(--bg-1, #13151f);
  stroke: var(--border, #2d3147);
  stroke-width: 1.5;
}
.bmd-card-trace {
  stroke: rgba(236, 19, 19, 0.12);
  stroke-width: 0.5;
  fill: none;
}
.bmd-port-group {
  transition: opacity 0.15s;
}
.bmd-port-group:hover {
  opacity: 0.85;
}
.bmd-port-ring {
  fill: var(--bg-1, #13151f);
  stroke: var(--border, #2d3147);
  stroke-width: 1.5;
}
.bmd-port-pin {
  fill: var(--text-4, #4a4f61);
}
.bmd-port-label {
  fill: var(--text-1, #e8eaf6);
  font-size: 10px;
  font-weight: 600;
  font-family: var(--font-mono, monospace);
}
.bmd-port-sublabel {
  fill: var(--text-3, #7a8194);
  font-size: 8.5px;
  font-family: var(--font-mono, monospace);
}
.bmd-card-model {
  fill: var(--text-4, #4a4f61);
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.08em;
  font-family: var(--font-mono, monospace);
}
/* Signal presence dot overlaid on each BNC connector */
.bmd-port-signal {
  opacity: 0.95;
  filter: drop-shadow(0 0 2px currentColor);
}
.bmd-port-signal--pulse {
  /* static — signal, not beacon (impeccable) */
  opacity: 0.95;
}

/* ========== Mobile sidebar (issue #134) ========== */
.topbar-menu { display: none; }
/* Mobile (<=768px) layout is now owned entirely by styles-mobile.css
   (loaded last). The previous block here set a conflicting 220px grid
   column and a duplicate ::before scrim that left content blank in
   portrait, so it has been removed. Only the hamburger toggle stays. */
@media (max-width: 768px) {
  .topbar-menu { display: grid; place-items: center; }
}

/* ========== Sidebar collapse/expand (issue #142) ========== */
.sidebar-header { gap: 8px; }
.sidebar-toggle {
  flex-shrink: 0;
  margin-left: auto;
  width: 28px; height: 28px;
  display: grid; place-items: center;
}
.app[data-sidebar="collapsed"] .brand-name,
.app[data-sidebar="collapsed"] .brand-sub,
.app[data-sidebar="collapsed"] .nav-item > span,
.app[data-sidebar="collapsed"] .nav-section-label,
.app[data-sidebar="collapsed"] .nav-badge,
.app[data-sidebar="collapsed"] .nav-item.has-children > .nav-caret,
.app[data-sidebar="collapsed"] .nav-children,
.app[data-sidebar="collapsed"] .user-meta {
  display: none !important;
}
.app[data-sidebar="collapsed"] .brand-link { gap: 0; justify-content: center; flex: 0; }
/* Logo centering fix (2026-07-23): .sidebar-header's collapsed width is only
   56px (--sidebar-w) minus padding = ~44px available. The logo alone (32px,
   see .brand-logo above) fits and centers fine, but .sidebar-toggle (28px) +
   its 8px gap was STILL sharing this same centered flex row — 32+8+28=68px
   into a 44px box, and .sidebar{overflow:hidden} silently clipped ~24px of
   that off both edges, cutting the logo instead of centering it. The toggle
   chevron is redundant here anyway — Topbar has its own onToggleSidebar
   button (shell.jsx ~line 470) that expands the sidebar back — so hide THIS
   one in collapsed mode and let the logo alone own the centered row. */
/* Collapsed header: stack the logo and the toggle vertically so the expand
   button is ALWAYS reachable. Previously the toggle was display:none in
   collapsed mode, relying on the Topbar's toggle to expand — but the Topbar
   is hidden on the Home screen and on the asset-detail view, leaving NO way
   to re-expand a collapsed sidebar (2026-07-24 bug). Keep the toggle visible. */
.app[data-sidebar="collapsed"] .sidebar-header {
  padding: 6px 6px 0;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.app[data-sidebar="collapsed"] .sidebar-toggle {
  display: grid;
  margin-left: 0;
}
.app[data-sidebar="collapsed"] .nav-item { justify-content: center; padding: 0; }
.app[data-sidebar="collapsed"] .sidebar-footer { padding: 10px 6px; justify-content: center; }
.app[data-sidebar="collapsed"] .sidebar-footer .icon-btn:not(.theme-toggle-btn) { display: none; }
.app[data-sidebar="collapsed"] .nav-item { position: relative; }
.app[data-sidebar="collapsed"] .nav-item:hover::after {
  content: attr(data-tip);
  position: absolute;
  left: 100%;
  margin-left: 8px;
  top: 50%;
  transform: translateY(-50%);
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-1);
  font-size: 12px;
  padding: 4px 8px;
  radius: var(--r-sm);
  white-space: nowrap;
  z-index: 100;
  pointer-events: none;
}

/* ── Resource utilization cards (screens-resources.jsx) ── */
.res-nodes-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 12px;
}
.res-node-card {
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.res-node-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-1);
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
}
.res-node-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--success);
  box-shadow: 0 0 0 3px var(--success-soft);
  flex-shrink: 0;
}
.res-metric {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.res-metric-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-3);
  font-family: var(--font-mono);
  display: flex;
  align-items: baseline;
  gap: 6px;
}
.res-metric-sub {
  color: var(--text-4);
  font-weight: 400;
}
.res-bar-wrap {
  display: flex;
  align-items: center;
  gap: 8px;
}
.res-bar {
  flex: 1;
  height: 6px;
  background: var(--bg-4);
  border-radius: 99px;
  overflow: hidden;
}
.res-bar-fill {
  height: 100%;
  border-radius: 99px;
  transition: width 0.6s ease;
}
.res-bar-pct {
  font-size: 11px;
  font-family: var(--font-mono);
  color: var(--text-3);
  min-width: 32px;
  text-align: right;
}
.res-mock-note {
  font-size: 11px;
  color: var(--warning);
  background: var(--warning-soft);
  border-radius: var(--r-sm);
  padding: 6px 10px;
  margin-bottom: 10px;
  font-family: var(--font-mono);
}

/* ============================================================
   Recorder menu — production redesign.
   Recorders are PHYSICAL capture ports grouped under their
   node (a hardware "rack"). Lifecycle: DISABLED (dormant) →
   ENABLED/armed (live standby) → RECORDING (on air). Built on
   the existing design tokens, badges and .btn classes — no new
   design language, just elevated rhythm and signal.
   ============================================================ */

/* ---- Rack (node group) ---- */
.recorder-rack {
  background: linear-gradient(180deg, var(--bg-1), var(--bg-0));
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: 6px 6px 8px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-card);
  transition: opacity 120ms ease, border-color 120ms ease;
}
.recorder-rack.is-offline {
  opacity: 0.5;
  filter: saturate(0.55);
}

.recorder-rack-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px 9px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border);
}
.recorder-rack-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: var(--r-sm);
  background: var(--bg-2);
  border: 1px solid var(--border);
  color: var(--text-3);
  flex-shrink: 0;
}
.recorder-rack-id {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}
.recorder-rack-host {
  font-size: 14px;
  font-weight: 650;
  letter-spacing: 0.01em;
  color: var(--text-1);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.recorder-rack-state {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-family: var(--font-mono);
  flex-shrink: 0;
}
.recorder-rack-state.online { color: var(--success); }
.recorder-rack-state.offline { color: var(--text-4); }
.recorder-rack-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
}
.recorder-rack-state.online .recorder-rack-dot {
  box-shadow: 0 0 0 3px var(--success-soft);
}
.recorder-rack-ports {
  font-size: 11px;
  color: var(--text-4);
  letter-spacing: 0.02em;
  flex-shrink: 0;
}

.recorders-list { gap: 8px; padding: 0 4px; }

/* ---- Row + lifecycle states ----
   Lifecycle state reads from the status badge (icon + text + color), the
   preview thumbnail/icon, and the row's own border + background tint below —
   deliberately NOT a colored left-edge rail (impeccable: side-stripe accent
   border is banned; it was also fully redundant with the badge here). */
.recorder-row {
  position: relative;
  padding: 12px 14px;
  transition: border-color 120ms ease, background 120ms ease, opacity 120ms ease;
}

/* DISABLED — dormant. Muted, recedes. Enable is the CTA. */
.recorder-row.is-disabled {
  background: transparent;
  border-color: var(--border);
  opacity: 0.82;
}
.recorder-row.is-disabled .recorder-name { color: var(--text-2); }
.recorder-row.is-disabled .recorder-preview { opacity: 0.7; }

/* ENABLED / armed — ready, live standby up. Calm but present. */
.recorder-row.is-armed {
  border-color: var(--border-strong);
}

/* RECORDING — on air. Hot. Full-ring pulse (not a one-sided stripe) carries
   the same "state cue, not decoration" role the old rail had. */
.recorder-row.recording {
  border-color: rgba(255,59,48,0.4);
  background:
    linear-gradient(90deg, rgba(255,59,48,0.06), transparent 38%);
  /* static ring — signal, not beacon (impeccable) */
  box-shadow: 0 0 0 1px rgba(255,59,48,0.45);
}

.recorder-row.error { border-color: rgba(232,106,106,0.4); }

/* ---- Info column ---- */
.recorder-titleline {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.recorder-name {
  font-weight: 600;
  font-size: 13.5px;
  color: var(--text-1);
  letter-spacing: 0.01em;
}
.recorder-hw {
  font-size: 10.5px;
  color: var(--text-4);
}
.recorder-badges {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 2px;
}
/* Capture port chip — the physical input identity. Reads as a
   precise hardware tag, not a generic badge. */
.badge.recorder-port-chip {
  background: var(--accent-soft);
  border: 1px solid var(--accent-soft-2);
  color: var(--accent-text);
  font-weight: 650;
}
.recorder-sub {
  font-size: 11.5px;
  color: var(--text-3);
  font-family: var(--font-mono);
  letter-spacing: 0.01em;
}
.recorder-sub-sep { color: var(--text-4); opacity: 0.7; }

/* ---- Stats ---- */
.recorder-stats { grid-template-columns: 96px 1fr; gap: 16px; }
.recorder-stat .stat-val { color: var(--text-2); font-family: var(--font-mono); }
.recorder-row.recording .recorder-stat .stat-val.mono { color: var(--text-1); }

/* ---- Actions ---- */
.recorder-actions { gap: 8px; }
.recorder-take {
  display: flex;
  align-items: center;
  gap: 6px;
}
.recorder-take-project,
.recorder-take-clip {
  height: 26px;
  padding: 0 8px;
  font-size: 12px;
}
.recorder-take-project { width: 140px; }
.recorder-take-clip { width: 152px; }
.recorder-controls {
  display: flex;
  align-items: center;
  gap: 6px;
}
.recorder-rec-btn { min-width: 84px; justify-content: center; }
/* Enable is the primary lifecycle CTA on dormant ports. */
.recorder-life-btn { min-width: 90px; justify-content: center; }
.recorder-life-btn.is-enable { font-weight: 600; }
.recorder-cfg-btn { color: var(--text-3); }
.recorder-cfg-btn:hover { color: var(--text-1); }

/* ---- Empty state ---- */
.recorder-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 64px 24px;
  text-align: center;
  color: var(--text-4);
  background: var(--bg-0);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-lg);
}
.recorder-empty-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-2);
}
.recorder-empty-sub {
  font-size: 12px;
  color: var(--text-4);
  max-width: 420px;
}

/* ---- Responsive: keep take controls coherent when the row stacks ---- */
@media (max-width: 1280px) {
  .recorder-take { flex: 1; }
  .recorder-take-project,
  .recorder-take-clip { width: auto; flex: 1; min-width: 110px; }
}

/* ── Recorder config modal — recording-mode segmented control + grid ───────── */
.rec-mode-seg {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.rec-mode-opt {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--bg-2, rgba(255,255,255,0.02));
  color: var(--text-2);
  cursor: pointer;
  text-align: left;
  transition: border-color .12s ease, background .12s ease, color .12s ease;
}
.rec-mode-opt:hover:not(:disabled) { border-color: var(--accent, #4a9eff); }
.rec-mode-opt.active {
  border-color: var(--accent, #4a9eff);
  background: var(--accent-soft, rgba(74,158,255,0.12));
  color: var(--text-1);
}
.rec-mode-opt:disabled { opacity: .55; cursor: default; }
.rec-mode-opt .icon { flex-shrink: 0; opacity: .85; }
.rec-mode-txt { display: flex; flex-direction: column; line-height: 1.25; }
.rec-mode-name { font-size: 13px; font-weight: 600; }
.rec-mode-desc { font-size: 10.5px; color: var(--text-3); }
.rec-mode-hint {
  margin-top: 8px;
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
}
.rec-cfg-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.rec-cfg-grid .field:only-child { grid-column: 1 / -1; }

/* ── Home / launcher — console-dashboard redesign ──────────────────────────── */
/* Tighter hero: horizontal logo lockup instead of a giant stacked block.       */
.launcher { padding: 28px 28px 56px; }
.launcher-inner { max-width: 1200px; gap: 26px; }

/* Centered hero: big stacked logo lockup, text centered under it. */
.launcher-hero {
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  width: 100%;
  max-width: 720px;
  margin: 8px auto 0;
}
/* Hero: centred mark over the wordmark. Large enough to read as a hero image,
   but with no tagline/kicker under it — the copy is what made this a landing
   page, not the logo size. */
.launcher-hero {
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  width: 100%;
  max-width: none;
  margin: 0 auto 22px;
  text-align: center;
}
.launcher-logo-wrap { width: 156px; height: 156px; }
.launcher-logo { width: 148px; height: 148px; }
.launcher-hero .launcher-logo-pulse { display: none; }
.launcher-hero .launcher-wordmark {
  font-size: 30px;
  letter-spacing: 0.18em;
  margin: 0;
  line-height: 1;
}

/* The grid: even, auto-fit cards. No random spans — rhythm over novelty. */
.launcher-grid {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(232px, 1fr));
  gap: 14px;
}

/* Card: flat surface, left accent rail by tone, generous click target. */
.launcher-tile {
  position: relative;
  display: grid;
  grid-template-areas: "icon arrow" "label label" "sub sub" "desc desc";
  grid-template-columns: 1fr auto;
  align-items: start;
  gap: 6px;
  text-align: left;
  padding: 18px 18px 20px 22px;
  min-height: 168px;
  border-radius: 14px;
  background: var(--bg-1, #15171c);
  border: 1px solid var(--border, #262a31);
  box-shadow: 0 1px 0 rgba(255,255,255,0.02) inset, 0 8px 24px rgba(0,0,0,0.22);
  color: var(--text-1, #e8eaed);
  cursor: pointer;
  overflow: hidden;
  transition: transform 160ms cubic-bezier(.2,.7,.2,1), border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}
/* Per-section color cue lives on the leading icon (background tint + fg
   color below) rather than a left-edge rail — impeccable bans side-stripe
   accent borders, and a rail here would only duplicate the icon's signal. */
.launcher-tile.tone-accent  { --tile-accent: var(--accent, #EC1313); }
.launcher-tile.tone-live    { --tile-accent: var(--live, #FF3B30); }
.launcher-tile.tone-purple  { --tile-accent: #8B7DFF; }
.launcher-tile.tone-success { --tile-accent: #5FBF97; }
.launcher-tile.tone-warn    { --tile-accent: #E6A93C; }
.launcher-tile.tone-neutral { --tile-accent: #5b616b; }
.launcher-tile.tone-ghost   { --tile-accent: #3a3f47; }

.launcher-tile:hover {
  transform: none;
  border-color: color-mix(in srgb, var(--tile-accent) 45%, var(--border));
  box-shadow: none;
  background: var(--bg-2);
}
.launcher-tile:focus-visible { outline: 2px solid var(--tile-accent); outline-offset: 2px; }

.launcher-tile-icon {
  grid-area: icon;
  display: inline-grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 11px;
  background: color-mix(in srgb, var(--tile-accent) 16%, transparent);
  color: var(--tile-accent);
  margin-bottom: 8px;
}
.launcher-tile-icon svg { width: 20px; height: 20px; }
.launcher-tile-arrow {
  grid-area: arrow;
  color: var(--text-3, #6b7079);
  opacity: 0;
  transform: translateX(-4px);
  transition: opacity 160ms ease, transform 160ms ease;
}
.launcher-tile:hover .launcher-tile-arrow { opacity: 1; transform: translateX(0); color: var(--tile-accent); }
.launcher-tile-label { grid-area: label; font-size: 16px; font-weight: 650; letter-spacing: -0.01em; }
.launcher-tile-sub {
  grid-area: sub;
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--tile-accent);
  text-transform: none;
}
.launcher-tile-desc { grid-area: desc; font-size: 12px; line-height: 1.45; color: var(--text-3, #8a8f98); margin-top: 2px; }

/* Settings row mirrors the grid so its card lines up with the columns above. */
.launcher-settings-row { width: 100%; display: grid; grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 14px; justify-content: start; }
.launcher-tile-settings { max-width: none; min-height: 140px; }
.launcher-tile-secondary { min-height: 168px; }

/* Responsive: cards reflow naturally; the hero mark scales down so it stays a
   hero on a phone without eating the whole first screen. */
@media (max-width: 640px) {
  .launcher-hero { gap: 10px; margin-bottom: 16px; }
  .launcher-logo-wrap { width: 92px; height: 92px; }
  .launcher-logo { width: 88px; height: 88px; }
  .launcher-hero .launcher-wordmark { font-size: 20px; letter-spacing: 0.14em; }
  .launcher-grid { grid-template-columns: 1fr; }
}

/* ===== Ported from feat/gui-facelift: Xbox-dashboard bento home ===== */
/* ============================================================
   Xbox-dashboard home — one big "spotlight" tile beside an
   asymmetric bento of supporting tiles. Replaces the old flat
   3-col launcher grid. Live-data wiring is unchanged; this is
   purely the presentation layer.
   ============================================================ */
.dash-bento {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  /* Was 1.55fr : 1fr with a 340px spotlight — the featured card ran ~75% empty
     because it was sized for a hero image that no longer renders. Even columns,
     content-sized rows. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  display: grid;
  gap: 16px;
  align-items: start;
}
@media (max-width: 980px) { .dash-bento { grid-template-columns: 1fr; } }

/* ── Spotlight ── */
.dash-spotlight {
  position: relative;
  display: block;
  text-align: left;
  /* Sized to its content. When a live feed IS attached the art fills it; idle
     it is a normal card, not a 340px placeholder. */
  min-height: 0;
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  cursor: pointer;
  border: 1px solid var(--border-strong);
  background: var(--bg-1);
  color: var(--text-1);
  /* A dense tool does not float its panels off the page. Flat surface, border
     for definition; the drop shadow + lift belonged to a marketing card. */
  transition: border-color 160ms ease, background 160ms ease;
}
.dash-spotlight:hover {
  border-color: var(--tile-spot, var(--accent));
}
.dash-spotlight:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

/* live preview / faux art fills the tile, dimmed under a gradient veil */
.dash-spotlight-art { position: absolute; inset: 0; z-index: 0; }
.dash-spotlight-art .thumb-svg,
.dash-spotlight-art video,
.dash-spotlight-art canvas { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.dash-spotlight-veil {
  position: absolute; inset: 0;
  background:
    linear-gradient(105deg, rgba(11,13,17,0.94) 0%, rgba(11,13,17,0.78) 38%, rgba(11,13,17,0.28) 100%),
    linear-gradient(0deg, rgba(11,13,17,0.85), transparent 55%);
}

.dash-spotlight-body {
  position: relative; z-index: 2;
  display: flex; flex-direction: column;
  gap: 8px;
  /* Padding matched a 340px hero card. The 78% cap existed to keep text off the
     watermark glyph, which is gone. */
  padding: 16px 18px;
}
/* When a live feed IS attached the card grows to hold it and the text overlays. */
.dash-spotlight:has(.dash-spotlight-art) .dash-spotlight-body {
  min-height: 240px;
  justify-content: flex-end;
  max-width: 78%;
}
.dash-spotlight-kicker {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tile-spot, var(--accent-text));
}
.dash-onair-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--live);
  box-shadow: 0 0 0 3px var(--live-soft);
  /* static ring — live color is enough signal */
}
.dash-spotlight-title {
  font-size: 36px; font-weight: 650; line-height: 1.05; letter-spacing: -0.028em;
  margin-top: auto;
  text-shadow: none;
}
.dash-spotlight-desc {
  font-size: 14px; line-height: 1.55; color: var(--text-2); max-width: 46ch;
}
.dash-spotlight-foot {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 6px;
}
.dash-spotlight-sub {
  font-size: 12px; letter-spacing: 0.02em;
  color: var(--text-3);
  padding: 5px 11px; border-radius: 99px;
  background: rgba(0,0,0,0.35); border: 1px solid var(--border-strong);
}
.dash-spotlight-cta {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 13px; font-weight: 600; color: var(--text-1);
  padding: 8px 16px; border-radius: 99px;
  background: var(--tile-spot, var(--accent));
  color: #0B0D11;
  transition: gap 140ms ease, filter 140ms ease;
}
.dash-spotlight:hover .dash-spotlight-cta { gap: 11px; filter: brightness(1.08); }

/* oversized brand glyph bleeding off the right edge */
/* Decorative 120px watermark glyph — removed. It carried no information and
   is the stock "big translucent icon in the corner" template flourish. */
.dash-spotlight-glyph { display: none; }

.dash-spotlight.tone-accent { --tile-spot: var(--accent); }
.dash-spotlight.tone-live   { --tile-spot: var(--live); }
.dash-spotlight.tone-purple { --tile-spot: var(--purple); }
.dash-spotlight.is-onair    { border-color: color-mix(in oklab, var(--tile-spot) 50%, transparent); }

/* ── Supporting bento grid ── */
.dash-bento-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  align-content: stretch;
}
@media (max-width: 540px) { .dash-bento-grid { grid-template-columns: 1fr; } }

.dash-bento-tile {
  position: relative;
  display: grid;
  grid-template-areas: "icon arrow" "label label" "sub sub" "desc desc";
  grid-template-columns: 1fr auto;
  gap: 3px;
  text-align: left;
  padding: 14px 15px 15px;
  border-radius: var(--r-lg);
  background: var(--bg-1);
  border: 1px solid var(--border);
  color: var(--text-1);
  cursor: pointer;
  overflow: hidden;
  isolation: isolate;
  /* Flat, bordered surface. The sheen gradient + drop shadow + hover lift is
     the stock "SaaS feature card" treatment; broadcast panels sit on the page. */
  transition: border-color 130ms ease, background 130ms ease;
}
.dash-bento-tile::before {
  content: ""; position: absolute; inset: -1px; border-radius: inherit; z-index: 0;
  pointer-events: none; opacity: 0; transition: opacity 150ms ease;
  background: radial-gradient(120% 90% at 100% 0%, var(--tile-tint, transparent), transparent 62%);
}
.dash-bento-tile > * { position: relative; z-index: 1; }
.dash-bento-tile:hover {
  border-color: var(--border-stronger);
  background: var(--bg-2);
}
.dash-bento-tile:hover::before { opacity: 1; }
.dash-bento-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.dash-bento-icon {
  grid-area: icon;
  width: 36px; height: 36px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--tile-icon-bg, var(--bg-3));
  color: var(--tile-icon-fg, var(--text-1));
  border: 1px solid var(--tile-icon-border, var(--border-strong));
  margin-bottom: 4px;
}
.dash-bento-label { grid-area: label; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.dash-bento-sub {
  grid-area: sub; font-size: 10.5px; color: var(--tile-sub-fg, var(--text-3));
  text-transform: uppercase; letter-spacing: 0.05em;
}
.dash-bento-desc { grid-area: desc; font-size: 12px; color: var(--text-3); line-height: 1.45; margin-top: 3px; }
.dash-bento-arrow {
  grid-area: arrow; align-self: start; color: var(--text-4);
  transform: translateX(-3px); transition: transform 130ms ease, color 130ms ease;
}
.dash-bento-tile:hover .dash-bento-arrow { transform: translateX(0); color: var(--tile-icon-fg, var(--accent-text)); }

/* reuse the launcher tone tints for the bento icon chips */
.dash-bento-tile.tone-accent  { --tile-tint: rgba(236,19,19,0.14); --tile-icon-bg: var(--accent-soft);  --tile-icon-fg: var(--accent-text); --tile-icon-border: rgba(236,19,19,0.28); }
.dash-bento-tile.tone-live    { --tile-tint: rgba(255,59,48,0.18);  --tile-icon-bg: var(--live-soft);    --tile-icon-fg: var(--live);        --tile-icon-border: rgba(255,59,48,0.30); }
.dash-bento-tile.tone-purple  { --tile-tint: rgba(181,124,250,0.18);--tile-icon-bg: var(--purple-soft);  --tile-icon-fg: var(--purple);      --tile-icon-border: rgba(181,124,250,0.30); }
.dash-bento-tile.tone-success { --tile-tint: rgba(45,212,168,0.16); --tile-icon-bg: var(--success-soft); --tile-icon-fg: var(--success);     --tile-icon-border: rgba(45,212,168,0.30); }
.dash-bento-tile.tone-warn    { --tile-tint: rgba(245,166,35,0.18); --tile-icon-bg: var(--warning-soft); --tile-icon-fg: var(--warning);     --tile-icon-border: rgba(245,166,35,0.30); }
.dash-bento-tile.tone-neutral { --tile-tint: rgba(255,255,255,0.06);--tile-icon-bg: var(--bg-3);         --tile-icon-fg: var(--text-1);      --tile-icon-border: var(--border-stronger); }
.dash-bento-tile.tone-ghost   { --tile-tint: rgba(255,255,255,0.05);--tile-icon-bg: transparent;         --tile-icon-fg: var(--text-2);      --tile-icon-border: var(--border); }

/* entry stagger removed (impeccable) — instant paint, no cascade delay */

/* ============================================================
   Dashboard — statistics board (.statboard / .stat-*)
   Top row of stat cards, two list panels, storage summary.
   ============================================================ */
.statboard {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 24px 28px 56px;
  max-width: 1280px;
  margin: 0 auto;
  width: 100%;
}

/* ── Stat-card grid ── */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}
/* Dashboard stat cards are CLICKABLE (they navigate), so they get the accent
   rail + hover affordance. Scoped to `.stat-grid` on purpose: the canonical
   `.stat-card` base lives in styles-rest.css and is shared with the Jobs and
   Admin screens, where the cards are static readouts and must NOT look
   interactive. This used to be an unscoped second `.stat-card` definition that
   won by load order and leaked a pointer cursor + accent bar + hover lift onto
   every non-interactive stat card in the app. */
.stat-grid .stat-card {
  position: relative;
  align-items: flex-start;
  text-align: left;
  padding: 16px 16px 18px;
  cursor: pointer;
  overflow: hidden;
  transition: border-color var(--t-fast, 140ms) var(--ease, ease);
}
/* No left-edge accent rail (impeccable: side-stripe accent border banned) —
   the icon below already carries the tone color as a tinted background. */
/* Border-only hover. No lift, no shadow bloom (impeccable: flat signals). */
.stat-grid .stat-card:hover {
  border-color: color-mix(in srgb, var(--stat-accent, var(--accent)) 50%, var(--border));
}
.stat-grid .stat-card:focus-visible { outline: 2px solid var(--stat-accent, var(--accent)); outline-offset: 2px; }
.stat-card-ic {
  display: inline-grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: 10px;
  margin-bottom: 4px;
  background: color-mix(in srgb, var(--stat-accent, var(--accent)) 16%, transparent);
  color: var(--stat-accent, var(--accent));
}
.stat-card-label {
  font-size: 11px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--text-3, #8a8f98);
}
.stat-card-value {
  font-size: 28px; font-weight: 700; line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--text-1, #e8eaed);
}
.stat-card-unit { font-size: 13px; font-weight: 600; color: var(--text-3, #8a8f98); margin-left: 4px; }
.stat-card-foot { font-size: 11.5px; color: var(--text-3, #8a8f98); margin-top: 2px; }

.stat-card.tone-accent  { --stat-accent: var(--accent, #EC1313); }
.stat-card.tone-live    { --stat-accent: var(--live, #ff3b30); }
.stat-card.tone-purple  { --stat-accent: var(--purple, #b57cfa); }
.stat-card.tone-success { --stat-accent: var(--success, #2dd4a8); }
.stat-card.tone-warn    { --stat-accent: var(--warning, #f5a623); }
.stat-card.tone-neutral { --stat-accent: #5b616b; }

/* ── Two list panels ── */
.stat-panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
@media (max-width: 860px) { .stat-panels { grid-template-columns: 1fr; } }

.stat-panel {
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  background: var(--bg-1, #15171c);
  border: 1px solid var(--border, #262a31);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.02), 0 8px 22px rgba(0,0,0,0.18);
  overflow: hidden;
}
.stat-panel-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border, #262a31);
}
.stat-panel-ic { display: inline-grid; place-items: center; color: var(--accent); }
.stat-panel-title { font-size: 13px; font-weight: 650; letter-spacing: -0.01em; }
.stat-panel-head .btn { margin-left: auto; }

.stat-list { display: flex; flex-direction: column; padding: 4px 0; }
.stat-empty { padding: 16px 14px; font-size: 12px; color: var(--text-3, #8a8f98); }
.stat-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  font-size: 12.5px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 45%, transparent);
  cursor: default;
}
.stat-row:last-child { border-bottom: none; }
.stat-row[onclick], .stat-list .stat-row:hover { cursor: pointer; }
.stat-row:hover { background: color-mix(in srgb, var(--accent) 5%, transparent); }
.stat-row-ic { display: inline-grid; place-items: center; color: var(--text-3, #8a8f98); flex-shrink: 0; }
.stat-row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-1, #e8eaed);
}
.stat-row-size { color: var(--text-3, #8a8f98); font-size: 11.5px; flex-shrink: 0; }
.stat-row-meta { color: var(--text-4, #6b7079); font-size: 11px; flex-shrink: 0; min-width: 56px; text-align: right; }

/* ── Storage summary ── */
.stat-storage {
  border-radius: 14px;
  background: var(--bg-1, #15171c);
  border: 1px solid var(--border, #262a31);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.02), 0 8px 22px rgba(0,0,0,0.18);
  overflow: hidden;
}
.stat-storage-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--border, #262a31);
}
.stat-storage-body { display: flex; align-items: stretch; }
.stat-storage-cell {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 18px 20px;
}
.stat-storage-div { width: 1px; background: var(--border, #262a31); }
.stat-storage-v { font-size: 26px; font-weight: 700; letter-spacing: -0.02em; color: var(--text-1, #e8eaed); }
.stat-storage-l { font-size: 11px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-3, #8a8f98); }
.stat-storage-s { font-size: 11.5px; color: var(--text-4, #6b7079); margin-top: 2px; }

/* Auth screen background — dark by default, light variant for light mode. */
.auth-screen {
  background:
    radial-gradient(900px 520px at 50% 28%, rgba(236,19,19,0.035), transparent 60%),
    radial-gradient(1200px 1000px at 50% 50%, #0C0E12 0%, #08090C 60%, #050609 100%);
}
[data-theme="light"] .auth-screen {
  background:
    radial-gradient(900px 520px at 50% 28%, rgba(51,85,224,0.06), transparent 60%),
    var(--bg-0, #FFFFFF);
}
[data-theme="light"] .auth-screen .auth-card,
[data-theme="light"] .auth-screen .card {
  box-shadow: var(--shadow-raise);
}
@media (max-width: 540px) {
  .stat-storage-body { flex-direction: column; }
  .stat-storage-div { width: auto; height: 1px; }
}
