/* Premium Styling System - Firebrand Characterisation Database Viewer */

:root {
  /* Dark Mode Variables (Default) */
  --bg-app: #080b11;
  --bg-sidebar: #0f131c;
  --bg-card: #151c28;
  --bg-card-hover: #1c2637;
  --bg-input: #101622;
  --border-color: #242f44;
  --border-color-glow: rgba(124, 92, 246, 0.2);

  --text-main: #f3f4f6;
  --text-muted: #9ca3af;
  --text-inverse: #0f172a;

  --primary: #7c3aed;
  --primary-glow: rgba(124, 58, 237, 0.4);
  --primary-light: #a78bfa;

  --secondary: #3b82f6;
  --secondary-glow: rgba(59, 130, 246, 0.3);

  --accent: #f97316;
  --accent-glow: rgba(249, 115, 22, 0.3);

  --info: #06b6d4;
  --info-glow: rgba(6, 182, 212, 0.3);

  --scrollbar-track: #0f131c;
  --scrollbar-thumb: #2d3b55;
  --scrollbar-thumb-hover: #3d5073;

  --transition-speed: 0.25s;
  --border-radius: 12px;
  --font-family-title: 'Outfit', 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;
  --font-family-body: 'Plus Jakarta Sans', system-ui, -apple-system, sans-serif;

  --bg-canvas-start: #1b263a;
  --bg-canvas-end: #0d121c;
  --bg-canvas-loading: rgba(13, 18, 28, 0.85);
  --bg-hud: rgba(21, 28, 40, 0.85);
  --bg-legend: rgba(21, 28, 40, 0.75);
}

/* Light Mode Variables override */
body.light-mode {
  --bg-app: #f4f6f9;
  --bg-sidebar: #ffffff;
  --bg-card: #ffffff;
  --bg-card-hover: #f8fafc;
  --bg-input: #f1f5f9;
  --border-color: #e2e8f0;
  --border-color-glow: rgba(124, 92, 246, 0.08);

  --text-main: #0f172a;
  --text-muted: #64748b;
  --text-inverse: #f8fafc;

  --primary: #6d28d9;
  --primary-glow: rgba(109, 40, 217, 0.15);
  --primary-light: #7c3aed;

  --secondary: #2563eb;
  --secondary-glow: rgba(37, 99, 235, 0.12);

  --scrollbar-track: #f1f5f9;
  --scrollbar-thumb: #cbd5e1;
  --scrollbar-thumb-hover: #94a3b8;

  --bg-canvas-start: #e2e8f0;
  --bg-canvas-end: #cbd5e1;
  --bg-canvas-loading: rgba(241, 245, 249, 0.85);
  --bg-hud: rgba(255, 255, 255, 0.85);
  --bg-legend: rgba(255, 255, 255, 0.75);
}

/* Base Styles */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background-color: var(--bg-app);
  color: var(--text-main);
  font-family: var(--font-family-body);
  font-size: 14px;
  line-height: 1.5;
  overflow: hidden;
  transition: background-color var(--transition-speed), color var(--transition-speed);
}

h1,
h2,
h3,
h4,
h5,
h6 {
  font-family: var(--font-family-title);
  font-weight: 600;
  letter-spacing: -0.01em;
}

/* Scrollbar Customization */
.scrollbar::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.scrollbar::-webkit-scrollbar-track {
  background: var(--scrollbar-track);
}

.scrollbar::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border-radius: 4px;
}

.scrollbar::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

/* App Container Layout */
.app-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
}

/* Top Header */
.header {
  height: 64px;
  background-color: var(--bg-sidebar);
  border-bottom: 1px solid var(--border-color);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 24px;
  z-index: 10;
  transition: background-color var(--transition-speed), border-color var(--transition-speed);
}

.logo-area {
  display: flex;
  align-items: center;
  gap: 12px;
}

.logo-icon {
  font-size: 24px;
  animation: pulse-fire 2s infinite alternate;
}

@keyframes pulse-fire {
  0% {
    transform: scale(1);
    filter: drop-shadow(0 0 2px var(--accent));
  }

  100% {
    transform: scale(1.1);
    filter: drop-shadow(0 0 8px var(--accent));
  }
}

.title-wrap h1 {
  font-size: 18px;
  font-weight: 700;
  background: linear-gradient(135deg, var(--text-main) 30%, var(--primary-light));
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.sub-title {
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 16px;
}

.global-stats {
  display: flex;
  gap: 8px;
}

/* Main Content Wrapper */
.content-wrapper {
  display: flex;
  flex: 1;
  overflow: hidden;
  height: calc(100vh - 64px);
}

/* Sidebar Styling */
.sidebar {
  width: 320px;
  background-color: var(--bg-sidebar);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  flex-shrink: 0;
  overflow: hidden;
  transition: background-color var(--transition-speed), border-color var(--transition-speed);
}

.search-filter-panel {
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  gap: 16px;
  background: rgba(0, 0, 0, 0.05);
}

.panel-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.section-title {
  font-size: 14px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: 4px;
}

.search-box {
  position: relative;
  width: 100%;
}

#search-input {
  width: 100%;
  padding: 10px 32px 10px 12px;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  color: var(--text-main);
  font-family: var(--font-family-body);
  outline: none;
  transition: border-color var(--transition-speed), box-shadow var(--transition-speed);
}

#search-input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-glow);
}

.clear-search {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  font-size: 18px;
  color: var(--text-muted);
}

.clear-search:hover {
  color: var(--text-main);
}

.form-select {
  width: 100%;
  padding: 10px 12px;
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  color: var(--text-main);
  outline: none;
  cursor: pointer;
  font-family: var(--font-family-body);
  transition: border-color var(--transition-speed);
}

.form-select:focus {
  border-color: var(--primary);
}

.filter-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--text-muted);
  letter-spacing: 0.02em;
}

.group-navigation {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
}

.group-nav-header {
  padding: 16px 20px 10px;
}

.group-nav-header h2 {
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
}

.runs-list {
  flex: 1;
  overflow-y: auto;
  padding: 0 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Run List Item / Card */
.run-item {
  padding: 14px;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: transform 0.15s ease, background-color var(--transition-speed), border-color var(--transition-speed), box-shadow 0.2s ease;
}

.run-item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 4px;
  background: var(--primary);
  transform: scaleY(0);
  transition: transform 0.2s ease;
}

.run-item.active::before {
  transform: scaleY(1);
}

.run-item:hover {
  transform: translateY(-2px);
  background-color: var(--bg-card-hover);
  border-color: var(--primary-light);
  box-shadow: 0 4px 12px rgba(124, 58, 237, 0.15);
}

.run-item.active {
  background-color: var(--bg-card-hover);
  border-color: var(--primary);
  box-shadow: 0 4px 16px var(--primary-glow);
}

.run-item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}

.run-item-title {
  font-family: var(--font-family-title);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 170px;
}

.run-item-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.run-item-count {
  font-size: 11px;
  color: var(--text-muted);
}

/* Badges & Buttons */
.badge {
  display: inline-block;
  padding: 3px 8px;
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  border-radius: 20px;
}

.badge-primary {
  background-color: var(--primary-glow);
  color: var(--primary-light);
  border: 1px solid rgba(124, 58, 237, 0.3);
}

.badge-secondary {
  background-color: rgba(59, 130, 246, 0.15);
  color: #60a5fa;
  border: 1px solid rgba(59, 130, 246, 0.3);
}

.badge-accent {
  background-color: var(--accent-glow);
  color: #fdba74;
  border: 1px solid rgba(249, 115, 22, 0.3);
}

.badge-info {
  background-color: var(--info-glow);
  color: #67e8f9;
  border: 1px solid rgba(6, 182, 212, 0.3);
}

.stat-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  padding: 6px 12px;
  border-radius: 30px;
  font-size: 12px;
  color: var(--text-muted);
}

.stat-badge strong {
  color: var(--text-main);
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 16px;
  font-family: var(--font-family-body);
  font-weight: 600;
  font-size: 13px;
  border-radius: var(--border-radius);
  cursor: pointer;
  outline: none;
  border: none;
  transition: all var(--transition-speed);
}

.btn-primary {
  background-color: var(--primary);
  color: #ffffff;
}

.btn-primary:hover {
  background-color: var(--primary-light);
  box-shadow: 0 0 12px var(--primary-glow);
}

.btn-secondary {
  background-color: var(--bg-input);
  border: 1px solid var(--border-color);
  color: var(--text-main);
}

.btn-secondary:hover {
  border-color: var(--primary-light);
}

.btn-icon {
  padding: 8px;
  border-radius: 50%;
}

.btn-small {
  padding: 4px 10px;
  font-size: 11px;
}

/* Workspace Layout */
.workspace {
  flex: 1;
  height: 100%;
  overflow-y: auto;
  padding: 24px;
  display: flex;
  flex-direction: column;
}

.workspace-centered-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1;
}

.empty-state {
  text-align: center;
  max-width: 460px;
  padding: 40px;
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 20px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
}

.empty-state-icon {
  font-size: 54px;
  margin-bottom: 20px;
}

.empty-state h3 {
  font-size: 20px;
  margin-bottom: 12px;
}

.empty-state p {
  color: var(--text-muted);
}

/* Grid layout for selected workspace items */
.workspace-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto 1fr;
  gap: 24px;
  height: 100%;
  min-height: 700px;
}

/* Cards Base */
.card {
  background-color: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  transition: background-color var(--transition-speed), border-color var(--transition-speed);
}

.card-header {
  padding: 20px;
  border-bottom: 1px solid var(--border-color);
}

.card-header.space-between {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.card-header h2 {
  font-size: 18px;
  font-weight: 700;
}

.subtitle-text {
  font-size: 11px;
  color: var(--text-muted);
  margin-top: 4px;
}

/* Section specific styling */
.details-card {
  grid-column: 1 / 2;
  grid-row: 1 / 2;
}

.viewport-card {
  grid-column: 2 / 3;
  grid-row: 1 / 3;
  min-height: 500px;
  height: 100%;
}

.table-card {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
  height: 100%;
  min-height: 300px;
}

/* Bages Row on details card */
.badge-row {
  display: flex;
  gap: 6px;
  margin-bottom: 10px;
}

/* Video Section */
.video-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.video-tab-header {
  display: flex;
  background-color: var(--bg-input);
  border-bottom: 1px solid var(--border-color);
}

.tab-btn {
  flex: 1;
  padding: 12px;
  font-family: var(--font-family-body);
  font-weight: 600;
  font-size: 12px;
  text-transform: uppercase;
  color: var(--text-muted);
  background: none;
  border: none;
  cursor: pointer;
  transition: color var(--transition-speed), background-color var(--transition-speed);
}

.tab-btn.active {
  color: var(--text-main);
  background-color: var(--bg-card);
  border-bottom: 2px solid var(--primary);
}

.video-viewports {
  padding: 16px;
  background-color: var(--bg-input);
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-wrapper {
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: var(--border-radius);
  overflow: hidden;
  position: relative;
  background-color: #000000;
}

.video-wrapper video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  outline: none;
}

.video-empty-state {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px;
  color: var(--text-muted);
  font-weight: 500;
  background-color: #0b0f19;
}

/* Three.js viewport styling */
.viewport-body {
  flex: 1;
  position: relative;
}

.three-canvas-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  outline: none;
  background: radial-gradient(circle at center, var(--bg-canvas-start) 0%, var(--bg-canvas-end) 100%);
}

.canvas-loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: var(--bg-canvas-loading);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 5;
  gap: 16px;
}

.spinner {
  width: 48px;
  height: 48px;
  border: 4px solid var(--border-color);
  border-top-color: var(--primary);
  border-radius: 50%;
  animation: spin 1s infinite linear;
}

@keyframes spin {
  100% {
    transform: rotate(360deg);
  }
}

.loading-text {
  font-weight: 600;
  color: var(--text-main);
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Head-Up-Display HUD Overlay */
.hud-overlay {
  position: absolute;
  top: 16px;
  right: 16px;
  background-color: var(--bg-hud);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
  padding: 14px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 8px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
  pointer-events: none;
  animation: fade-in 0.2s ease;
}

@keyframes fade-in {
  from {
    opacity: 0;
    transform: translateY(-5px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.hud-item {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  font-size: 12px;
}

.hud-label {
  color: var(--text-muted);
  font-weight: 500;
}

.hud-val {
  font-family: var(--font-family-title);
  font-weight: 600;
  color: var(--text-main);
}

.legend-overlay {
  position: absolute;
  bottom: 16px;
  left: 16px;
  background-color: var(--bg-legend);
  backdrop-filter: blur(8px);
  border: 1px solid var(--border-color);
  border-radius: 8px;
  padding: 8px 12px;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: 4px;
  pointer-events: none;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11px;
  color: var(--text-muted);
  font-weight: 500;
}

.color-box {
  width: 12px;
  height: 12px;
  border-radius: 2px;
}

.scale-box {
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: repeating-linear-gradient(45deg, transparent, transparent 2px, rgba(255, 255, 255, 0.1) 2px, rgba(255, 255, 255, 0.1) 4px);
}

.box-box {
  border: 1.5px solid var(--accent);
  background-color: transparent;
}

/* Firebrand Table styling */
.table-wrapper {
  flex: 1;
  overflow-y: auto;
}

table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

th {
  background-color: var(--bg-sidebar);
  position: sticky;
  top: 0;
  z-index: 2;
  font-weight: 600;
  color: var(--text-muted);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-color);
}

td {
  padding: 10px 16px;
  font-size: 13px;
  border-bottom: 1px solid var(--border-color);
  transition: background-color 0.1s ease;
}

tr {
  cursor: pointer;
  transition: all 0.15s ease;
}

tr:hover td {
  background-color: var(--bg-card-hover);
}

tr.active-row td {
  background-color: var(--primary-glow);
  color: var(--text-main);
  font-weight: 500;
}

/* Responsive Viewports */
@media (max-width: 1024px) {
  .content-wrapper {
    flex-direction: column;
  }

  .sidebar {
    width: 100%;
    height: 320px;
    border-right: none;
    border-bottom: 1px solid var(--border-color);
  }

  .workspace-grid {
    grid-template-columns: 1fr;
    grid-template-rows: auto auto auto;
    overflow-y: auto;
  }

  .viewport-card {
    grid-column: 1 / 2;
    grid-row: 2 / 3;
    height: 450px;
  }

  .table-card {
    grid-column: 1 / 2;
    grid-row: 3 / 4;
  }
}

/* Floating dimension labels on the 3D viewport */
.dimension-label {
  background-color: var(--bg-hud);
  border: 1px solid var(--border-color);
  color: var(--info);
  padding: 4px 8px;
  border-radius: 6px;
  font-size: 11px;
  font-weight: 700;
  font-family: var(--font-family-body);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
  backdrop-filter: blur(8px);
  user-select: none;
  white-space: nowrap;
  z-index: 2;
  transition: background-color var(--transition-speed), border-color var(--transition-speed), color var(--transition-speed);
}

/* Card details-body flex expand rule */
.detail-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* Focused layout swap: moves video details to the large right pane, and mesh to the small top-left pane */
.workspace-grid.video-focused .details-card {
  grid-column: 2 / 3;
  grid-row: 1 / 3;
  height: 100%;
}

.workspace-grid.video-focused .viewport-card {
  grid-column: 1 / 2;
  grid-row: 1 / 2;
  min-height: 250px;
  height: 100%;
}

.workspace-grid.video-focused .table-card {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}

/* Sidebar Authors Section */
.authors-section {
  padding: 16px 20px;
  border-top: 1px solid var(--border-color);
  background-color: rgba(0, 0, 0, 0.08);
  margin-top: auto;
  flex-shrink: 0;
}

.authors-section .filter-label {
  margin-bottom: 6px;
  color: var(--text-main);
}

.authors-org {
  font-size: 10px;
  font-weight: 700;
  color: var(--primary-light);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.3;
  margin-bottom: 4px;
}

.authors-names {
  font-size: 11px;
  color: var(--text-muted);
  line-height: 1.4;
}

/* Thermal Scale Legend Overlay */
.thermal-legend {
  position: absolute;
  bottom: 12px;
  left: 90%;
  transform: translateX(-5%);
  background: rgba(15, 23, 42, 0.85);
  backdrop-filter: blur(8px);
  border: 1px solid var(--border-color);
  border-radius: 20px;
  padding: 6px 16px;
  display: flex;
  align-items: center;
  gap: 12px;
  z-index: 2;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
  pointer-events: none;
}

.legend-temp {
  font-size: 11px;
  font-weight: 700;
  color: #f3f4f6;
}

.thermal-legend .color-bar {
  width: 10px;
  height: 200px;
  border-radius: 4px;
  background: linear-gradient(to top, #000000 0%, #999999 50%, #ffffff 100%);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* ==========================================================================
   Remediation additions
   Appended rather than merged so the existing design language is untouched.
   Selectors below are scoped to new class names, except the responsive block
   at the end, which deliberately overrides the fixed geometry above.
   ========================================================================== */

/* --- Sidebar tree ------------------------------------------------------- */
.tree-family { margin-bottom: 6px; }
.tree-header,
.tree-subheader {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 9px 10px; background: transparent; border: none; cursor: pointer;
  color: var(--text-main); font-family: var(--font-family-title);
  font-size: 0.86rem; font-weight: 600; text-align: left;
  border-radius: 8px; transition: background var(--transition-speed);
}
.tree-subheader { font-weight: 500; font-size: 0.8rem; padding-left: 20px; color: var(--text-muted); }
.tree-header:hover, .tree-subheader:hover { background: var(--bg-card-hover); }
.tree-caret { width: 10px; flex: none; opacity: 0.7; font-size: 0.7rem; }
.tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tree-count {
  flex: none; font-size: 0.68rem; font-variant-numeric: tabular-nums;
  padding: 2px 7px; border-radius: 999px;
  background: var(--bg-input); color: var(--text-muted); border: 1px solid var(--border-color);
}
.tree-subbody .run-item { margin-left: 12px; }
.empty-list-msg { padding: 24px 16px; text-align: center; color: var(--text-muted); font-size: 0.85rem; }

/* --- Video segments ----------------------------------------------------- */
/* Runs carry up to eleven recordings; the viewer previously reached only the first. */
.segment-strip {
  display: none; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 10px; border-bottom: 1px solid var(--border-color); background: var(--bg-input);
}
.segment-hint { font-size: 0.72rem; color: var(--text-muted); margin-right: 2px; }
.segment-btn {
  padding: 4px 10px; font-size: 0.72rem; font-family: var(--font-family-body);
  border-radius: 6px; cursor: pointer; background: var(--bg-card);
  color: var(--text-muted); border: 1px solid var(--border-color);
  transition: all var(--transition-speed);
}
.segment-btn:hover { color: var(--text-main); border-color: var(--accent); }
.segment-btn.active { background: var(--accent); color: #fff; border-color: var(--accent); }

/* --- Data-quality flags ------------------------------------------------- */
.flag-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px; margin-left: 7px; padding: 0 4px;
  border-radius: 999px; font-size: 0.62rem; font-weight: 700; cursor: help;
  background: rgba(249, 115, 22, 0.16); color: var(--accent);
  border: 1px solid rgba(249, 115, 22, 0.45);
}
.flag-summary { margin: 6px 0 0; font-size: 0.76rem; color: var(--accent); }
td.suspect { color: var(--accent); font-style: italic; }
td .na, .na { color: var(--text-muted); font-size: 0.76rem; font-style: italic; }
.hud-flags {
  margin-top: 8px; padding: 7px 9px; border-radius: 7px; max-width: 260px;
  font-size: 0.7rem; line-height: 1.45;
  background: rgba(249, 115, 22, 0.12); color: var(--accent);
  border: 1px solid rgba(249, 115, 22, 0.35);
}
.table-empty, .table-more { text-align: center; padding: 18px; color: var(--text-muted); }
.row-dl { text-decoration: none; color: var(--text-muted); font-weight: 700; }
.row-dl:hover { color: var(--accent); }
.mono, .detail-id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
#firebrands-table td { font-variant-numeric: tabular-nums; }

/* --- Run identity ------------------------------------------------------- */
.detail-heading { min-width: 0; }
.detail-id-row { display: flex; align-items: center; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
.detail-id {
  font-size: 0.7rem; color: var(--text-muted); background: var(--bg-input);
  padding: 3px 8px; border-radius: 6px; border: 1px solid var(--border-color);
  overflow-wrap: anywhere;
}
.btn-tiny { padding: 3px 9px; font-size: 0.68rem; border-radius: 6px; }
.hud-uid { border-bottom: 1px solid var(--border-color); padding-bottom: 6px; margin-bottom: 4px; }
.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;
}

/* --- Thermal legend ----------------------------------------------------- */
.legend-note { font-size: 0.62rem; color: var(--text-muted); width: 100%; margin-top: 3px; }

/* --- Landing panel ------------------------------------------------------ */
.intro-card {
  max-width: 760px; margin: 0 auto; padding: 34px 32px;
  background: var(--bg-card); border: 1px solid var(--border-color);
  border-radius: var(--border-radius);
}
.intro-card h1 {
  font-family: var(--font-family-title); font-size: 1.75rem; line-height: 1.2;
  margin: 0 0 14px; text-wrap: balance;
}
.intro-lead { font-size: 0.95rem; line-height: 1.65; color: var(--text-muted); margin: 0 0 22px; max-width: 62ch; }
.intro-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 24px; }
.intro-stat {
  padding: 14px 16px; background: var(--bg-input);
  border: 1px solid var(--border-color); border-radius: 10px;
}
.intro-stat strong {
  display: block; font-family: var(--font-family-title); font-size: 1.5rem;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.intro-stat span { font-size: 0.76rem; color: var(--text-muted); }
.intro-card h3 { font-family: var(--font-family-title); font-size: 0.95rem; margin: 0 0 10px; }
.intro-list { margin: 0 0 20px; padding-left: 18px; color: var(--text-muted); font-size: 0.86rem; line-height: 1.75; }
.intro-hint { font-size: 0.82rem; color: var(--text-muted); font-style: italic; margin: 0; }

/* --- Mobile sidebar ----------------------------------------------------- */
.sidebar-toggle { display: none; margin-right: 4px; }
.sidebar-scrim {
  display: none; position: fixed; inset: 0; z-index: 40;
  background: rgba(0, 0, 0, 0.5);
}
body.sidebar-open .sidebar-scrim { display: block; }

/* ==========================================================================
   Responsive tiers. The stylesheet previously had one breakpoint (1024px) and
   fixed geometry underneath it: a 320px sidebar and a 700px minimum workspace
   height, neither of which fits a phone.
   ========================================================================== */

/* Wide monitors: give the 3D panel the room a 27-inch display has to spare. */
@media (min-width: 1600px) {
  .workspace-grid { grid-template-columns: 1.1fr 1fr; gap: 20px; }
  .sidebar { width: 360px; }
  .intro-card { max-width: 860px; }
}

/* Tablet and small laptop. */
@media (max-width: 1100px) {
  .sidebar { width: 280px; }
}

/* Phone and small tablet: the sidebar becomes an overlay drawer. */
@media (max-width: 900px) {
  .sidebar-toggle { display: inline-flex; }
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 50;
    width: min(88vw, 340px); height: 100dvh;
    transform: translateX(-100%);
    transition: transform var(--transition-speed) ease;
    box-shadow: 0 0 40px rgba(0, 0, 0, 0.4);
    overflow-y: auto;
  }
  body.sidebar-open .sidebar { transform: translateX(0); }

  .workspace-grid {
    grid-template-columns: 1fr;
    min-height: 0;            /* 700px forced a scroll on every phone */
  }
  .workspace { padding: 12px; }
  .header { flex-wrap: wrap; height: auto; padding: 10px 14px; gap: 10px; }
  .header-actions { gap: 8px; }
  .content-wrapper { height: auto; flex: 1; }
  .intro-card { padding: 22px 18px; }
  .intro-card h1 { font-size: 1.35rem; }
}

@media (max-width: 640px) {
  /* A ten-column table cannot fit; let it scroll inside its own container so the
     page body never scrolls sideways. */
  .table-wrapper { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #firebrands-table { min-width: 720px; }
  .three-canvas-wrapper { min-height: 260px; }
  .hud-overlay { font-size: 0.68rem; max-width: 60%; }
  .hud-flags { max-width: 100%; }
  .stat-badge { display: none; }
  .intro-grid { grid-template-columns: 1fr; }
  .detail-id { max-width: 100%; }
}

/* Respect a reduced-motion preference for the drawer and hover transitions. */
@media (prefers-reduced-motion: reduce) {
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* Present in the original markup but never styled. */
.viewport-title { font-size: 0.95rem; margin: 0; }
.viewport-controls { display: flex; gap: 6px; flex-wrap: wrap; }

/* Injected facets sit inside .search-filter-panel; match its column rhythm. */
#dynamic-facets { display: flex; flex-direction: column; gap: 16px; }
/* The sidebar is a flex column with overflow hidden; the filter panel must not be squeezed
   out when the run tree is long. */
.search-filter-panel { flex: none; }
.group-navigation { display: flex; flex-direction: column; min-height: 0; flex: 1; }

/* A flex item defaults to min-width:auto, so it refuses to shrink below its content's
   preferred width. The intro card's 760px max-width therefore pushed the workspace wider
   than a phone viewport and the text ran off the right edge. */
.content-wrapper > * { min-width: 0; }
.workspace, .workspace-centered-screen { min-width: 0; }
.intro-card { width: 100%; }
.workspace-grid > .card { min-width: 0; }

/* ==========================================================================
   Desktop layout: give the firebrand table the full width.
   It carries ten columns of measurements and was confined to one grid column,
   which pushed height, mass and density out of view behind a scrollbar.
   ========================================================================== */
@media (min-width: 1025px) {
  .workspace-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-rows: auto minmax(320px, auto);
    height: auto;
    min-height: 0;
  }
  .details-card  { grid-column: 1 / 2; grid-row: 1 / 2; }
  .viewport-card { grid-column: 2 / 3; grid-row: 1 / 2; min-height: 460px; }
  .table-card    { grid-column: 1 / -1; grid-row: 2 / 3; min-height: 0; }

  /* Focus mode: the video takes the full width, the mesh and table share the row below. */
  .workspace-grid.video-focused { grid-template-rows: auto minmax(320px, auto); }
  .workspace-grid.video-focused .details-card  { grid-column: 1 / -1; grid-row: 1 / 2; }
  .workspace-grid.video-focused .viewport-card { grid-column: 1 / 2; grid-row: 2 / 3; }
  .workspace-grid.video-focused .table-card    { grid-column: 2 / 3; grid-row: 2 / 3; }

  /* Ten columns still need room on a laptop; let the table scroll rather than the page. */
  .table-wrapper { overflow-x: auto; }
}

/* --- HUD: compact, and clickable where it needs to be ------------------- */
/* The panel was wide enough to cover the mesh it annotates. The firebrand_uid is the long
   part, so it gets its own line at a smaller size and truncates rather than stretching the
   panel. */
.hud-overlay {
  max-width: 230px;
  padding: 10px 12px;
  gap: 5px;
}
.hud-item { gap: 12px; font-size: 11px; }
.hud-uid {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}
.hud-uid .hud-val {
  font-size: 9.5px;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  direction: rtl;            /* keep the distinctive tail visible when it truncates */
  text-align: left;
}
/* The overlay is pointer-events:none so orbiting works through it; the download link is the
   one thing inside it that must stay clickable. */
.hud-overlay a, .hud-overlay button { pointer-events: auto; }
#hud-download { margin-top: 4px; text-align: center; text-decoration: none; }

@media (max-width: 1024px) {
  .hud-overlay { max-width: 190px; }
}

/* ==========================================================================
   Mobile and tablet: the video card collapsed to nothing.
   .detail-body is flex:1, i.e. flex-basis:0. On desktop the grid row gives the
   card a definite height so the item grows into it; below 1025px the rows are
   content-sized, there is no free space, and a zero basis stays zero — taking
   the tab header and the video with it.
   ========================================================================== */
@media (max-width: 1024px) {
  .details-card    { height: auto; }
  .detail-body     { flex: 0 0 auto; overflow: visible; }
  .video-container { height: auto; }
  .video-viewports { flex: 0 0 auto; padding: 12px; }
  .video-wrapper   { aspect-ratio: 16 / 9; }   /* now the height source */
  .card            { overflow: visible; }      /* was clipping the collapsed card */
  .workspace-grid  { align-items: start; }
}

@media (max-width: 640px) {
  /* Two tabs must stay legible and tappable rather than truncating. */
  .video-tab-header { flex-wrap: wrap; }
  .tab-btn { flex: 1 1 50%; font-size: 0.74rem; padding: 10px 6px; min-height: 42px; }
  .segment-strip { padding: 6px 8px; }
  .segment-btn { min-height: 30px; }
  .viewport-controls { width: 100%; }
  .viewport-controls .btn { flex: 1 1 auto; }
}

/* ==========================================================================
   Video sizing — never crop, and take the shape of whatever loaded.
   The wrapper was fixed at 16:9 with object-fit: cover. RGB is 1920x1080 and
   fits, but the thermal camera is 1024x768, so a quarter of every thermal
   frame was being cut off — in a recording where a firebrand may be in the
   lost strip. --vid-aspect is set from the video's own dimensions as soon as
   metadata arrives, so any future source is handled too.
   ========================================================================== */
.video-wrapper {
  aspect-ratio: var(--vid-aspect, 16 / 9);
  max-height: min(56vh, 520px);
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: center;
}
.video-wrapper video {
  width: 100%;
  height: 100%;
  object-fit: contain;      /* was cover: it cropped the 4:3 thermal frames */
  display: block;
}
/* The wrapper keeps the video's ratio, so the letterbox only appears while the
   height cap is binding; the surrounding black then reads as intentional. */
.video-viewports { min-width: 0; }

@media (max-width: 1024px) {
  .video-wrapper { max-height: min(48vh, 420px); }
}
@media (max-width: 640px) {
  .video-wrapper { max-height: 42vh; }
}
/* A short, wide window is the case that pushed the player off screen entirely. */
@media (max-height: 700px) {
  .video-wrapper { max-height: 40vh; }
}

/* ==========================================================================
   Thermal colour scale — rebuilt.
   It was anchored at left:90% with only a -5% shift, so it hung off the right
   edge, and its bar was a fixed 200px inside a player that can be 250px tall.
   Now a compact vertical scale pinned inside the frame, sized relative to it,
   reading high at the top to match the gradient.
   ========================================================================== */
.thermal-legend {
  left: auto;
  right: 12px;
  bottom: 12px;
  transform: none;
  flex-direction: column-reverse;   /* markup is low, bar, high; show high on top */
  align-items: center;
  gap: 6px;
  padding: 8px 9px;
  border-radius: 12px;
  max-height: calc(100% - 24px);
  cursor: help;
}
.thermal-legend .color-bar {
  width: 8px;
  height: clamp(48px, 18vh, 140px);
}
.legend-temp { font-size: 10px; line-height: 1.2; white-space: nowrap; }
/* The explanation is long and does not belong inside a small overlay; it is set
   as the element's tooltip instead. */
#legend-note { display: none; }

@media (max-width: 640px) {
  .thermal-legend { right: 8px; bottom: 8px; padding: 6px 7px; }
  .thermal-legend .color-bar { height: clamp(40px, 14vh, 90px); }
}

/* ==========================================================================
   Fitting the detail panel to narrow windows
   ========================================================================== */

/* A badge is a label, not a paragraph: let the row wrap between badges rather
   than breaking "FIBROUS BARK" across two lines inside its own pill. */
.badge { white-space: nowrap; }
.badge-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }

/* The legend is absolutely positioned inside the player, so it must be sized
   against the player and not the viewport — 18vh overflowed a short frame. */
.thermal-legend .color-bar { height: clamp(40px, 9vh, 96px); }
.thermal-legend { max-height: calc(100% - 20px); overflow: hidden; }

/* The metrics panel annotates the mesh and must not bury it. Capped as a share
   of the panel it floats over, so a narrow 3D pane keeps the model visible. */
.hud-overlay {
  max-width: min(210px, 42%);
  font-size: 10.5px;
  background: color-mix(in srgb, var(--bg-hud) 92%, transparent);
}
.hud-item { gap: 10px; }
@media (max-width: 1280px) {
  .hud-overlay { max-width: min(180px, 46%); padding: 8px 9px; }
  .hud-uid { display: none; }        /* the id is in the table; the model is not */
}

/* ==========================================================================
   Make the frame hug the recording.
   With width:100% and only a max-height, a height cap leaves the box wider
   than the video and object-fit:contain letterboxes it. Driving the height
   instead lets aspect-ratio compute the width, so the frame matches the
   recording at any window size and the black surround disappears.
   ========================================================================== */
.video-wrapper {
  height: min(56vh, 520px);
  width: auto;
  max-width: 100%;
  max-height: none;
}
@media (max-width: 1024px) { .video-wrapper { height: min(46vh, 420px); } }
@media (max-width: 640px)  { .video-wrapper { height: 40vh; } }
/* A short window is the awkward case: keep the player usable without letting it
   push the table off the screen. */
@media (max-height: 760px) { .video-wrapper { height: min(46vh, 340px); } }
@media (max-height: 560px) { .video-wrapper { height: 44vh; } }

/* ==========================================================================
   Video pane: the segment strip stacks above the frame.
   The strip used to live inside .video-wrapper, so once that became a flex row
   sized to the recording's aspect ratio the strip was laid out beside the
   video and pushed out of the card.
   ========================================================================== */
.video-pane {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  width: 100%;
  min-width: 0;
}
.video-pane .segment-strip { flex: none; border-radius: 8px; border-bottom: none; }
.video-pane .video-wrapper { flex: none; align-self: center; }
.video-viewports { flex-direction: column; align-items: stretch; }

/* ==========================================================================
   The card must grow to the video, not clip it.
   Giving .video-wrapper a fixed height made it taller than the space the card
   allowed, and .detail-body's overflow:hidden then cut the bottom off — losing
   the end of the frame and the playback controls with it. The height now
   follows the width through aspect-ratio, .detail-body sizes to its content
   instead of being a flex:1 box that clips, and the grid row grows to suit.
   ========================================================================== */
.video-wrapper {
  height: auto;
  width: 100%;
  max-width: 100%;
  max-height: none;
  aspect-ratio: var(--vid-aspect, 16 / 9);
}
.detail-body {
  flex: 0 0 auto;
  overflow: visible;
  min-height: 0;
}
.video-container { height: auto; }
.video-viewports { flex: 0 0 auto; }
.details-card { height: auto; align-self: start; }

/* Keep the player from dominating a very wide window, where a 4:3 frame at full
   column width would be taller than the screen. Applied as a width cap so the
   frame still matches the recording exactly — no letterboxing. */
.video-wrapper { max-width: min(100%, calc((100vh - 300px) * var(--vid-ar-num, 1.78))); }

/* ==========================================================================
   Final sizing rule: the video is driven by the height available, not by its
   own width.
   Letting the frame set its own height made the card 637px inside a 460px grid
   row, so it painted over the table; capping by viewport height instead made it
   taller than the card, so overflow:hidden cut the controls off. Both failed for
   the same reason — the frame was sizing itself without reference to the space
   it had. Now the card fills its row, each wrapper passes the remaining height
   down, and the frame takes 100% of it with the width computed from the
   recording's aspect ratio. It cannot overflow, cannot be clipped, and hugs the
   image whenever the column is wide enough.
   ========================================================================== */
@media (min-width: 1025px) {
  .details-card    { height: 100%; align-self: stretch; }
  .detail-body     { flex: 1 1 auto; min-height: 0; overflow: hidden; }
  .video-container { height: 100%; min-height: 0; }
  .video-viewports { flex: 1 1 auto; min-height: 0; }
  .video-pane      { height: 100%; min-height: 0; }
  .video-wrapper {
    height: 100%;
    width: auto;
    max-width: 100%;
    max-height: none;
    align-self: center;
  }
  /* Row 1 is sized by the 3D panel's minimum; give the video room to be useful. */
  .viewport-card { min-height: 520px; }
}

/* The frame must take the height LEFT OVER after the segment strip, not 100% of
   the pane that also contains the strip — that overshot by exactly the strip's
   height and clipped the bottom of the controls. */
@media (min-width: 1025px) {
  .video-pane .video-wrapper { height: auto; flex: 1 1 auto; min-height: 0; }
}

/* ==========================================================================
   Thermal scale beside the frame, not over it.
   As an overlay pinned inside .video-wrapper it covered the right-hand edge of
   the thermal image — part of the recording was simply not visible. It is now a
   sibling of the frame in a row, so the image is never obscured, and the markup
   runs high-to-low so no flex reversal is needed.
   ========================================================================== */
.thermal-stage {
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 10px;
  min-height: 0;
  min-width: 0;
  flex: 1 1 auto;
}
.thermal-stage .video-wrapper { flex: 0 1 auto; min-width: 0; }

#thermal-scale-legend {
  position: static;                 /* was absolute, pinned over the video */
  flex: none;
  display: flex;
  flex-direction: column;           /* markup is high, bar, low */
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 8px 10px;
  max-height: none;
  align-self: center;
  background: var(--bg-legend);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  cursor: help;
}
#thermal-scale-legend .color-bar {
  width: 10px;
  height: clamp(60px, 100%, 220px);
  flex: 1 1 auto;
  min-height: 40px;
}
#thermal-scale-legend .legend-temp { font-size: 10px; white-space: nowrap; }

@media (max-width: 640px) {
  .thermal-stage { gap: 6px; }
  #thermal-scale-legend { padding: 6px 7px; }
  #thermal-scale-legend .color-bar { width: 8px; }
}

/* ==========================================================================
   Expand video: the row needs a definite height.
   In focused mode row 1 was `auto`, so a card told to fill 100% of a row that
   was itself sized by its content had nothing to resolve against and the player
   collapsed to a sliver.
   ========================================================================== */
@media (min-width: 1025px) {
  .workspace-grid.video-focused { grid-template-rows: minmax(0, 62vh) minmax(280px, auto); }
  .workspace-grid.video-focused .details-card  { height: 100%; align-self: stretch; }
  .workspace-grid.video-focused .viewport-card { min-height: 280px; }
}
@media (max-width: 1024px) {
  .workspace-grid.video-focused .details-card { height: auto; }
}

/* Inside the thermal stage the frame is a row item, so it must take its height
   from the stage and compute its width from the ratio — otherwise it grows to
   fill the row's width and derives a height taller than the space, which the
   card then clips. */
.thermal-stage .video-wrapper {
  height: 100%;
  width: auto;
  max-width: 100%;
  flex: 0 1 auto;
}

/* Expand video: the row needs a FIXED height, not a content-sized one.
   With `auto` or `minmax(..., auto)` the row is sized by its content, the card
   fills the row, and the frame fills the card — a loop with no definite value,
   which resolves to zero and collapses the player. In normal mode the 3D
   panel's min-height breaks that loop; in focused mode it moves to row 2, so
   nothing does. A fixed track breaks it directly. */
@media (min-width: 1025px) {
  /* Expanding should actually enlarge the player: the frame is height-driven, so the
     row has to be generous or the video stays small in a very wide card. */
  .workspace-grid.video-focused { grid-template-rows: min(78vh, 820px) minmax(280px, auto); }
}
/* Below the desktop breakpoint the cards stack and size to content, so the frame
   must not try to fill a parent that has no definite height. */
@media (max-width: 1024px) {
  .workspace-grid.video-focused .video-wrapper { height: auto; flex: 0 0 auto; }
  .workspace-grid.video-focused .thermal-stage .video-wrapper { height: auto; }
}

/* The identifier is long for candlebark and wrapped onto a second line, pushing
   the copy button below it and making the header taller than it needs to be.
   One line with an ellipsis; the full value is still what gets copied, and it
   is in the tooltip. */
.detail-id-row { flex-wrap: nowrap; }
.detail-id {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow-wrap: normal;
  min-width: 0;
  flex: 0 1 auto;
}
.detail-id-row .btn { flex: none; }

/* ==========================================================================
   Compact detail header, taller thermal scale
   Expand mode is gone — double-clicking the video gives full screen — so the
   header loses its button and can tighten up, handing the room to the video.
   ========================================================================== */
.detail-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 16px 10px;
}
.detail-header .detail-heading { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.detail-header h2 { font-size: 1.05rem; line-height: 1.2; margin: 0; }
.detail-header .badge-row { gap: 5px; }
.detail-header .badge { font-size: 0.62rem; padding: 2px 8px; }
.detail-header .detail-id-row { margin-top: 0; }
.detail-header .detail-id { font-size: 0.65rem; padding: 2px 7px; }
.video-tab-header .tab-btn { padding: 9px 14px; }

/* A tall scale reads a temperature range far better than a short one, and there
   is now room for it. */
#thermal-scale-legend {
  align-self: stretch;
  justify-content: space-between;
  padding: 10px 10px;
}
#thermal-scale-legend .color-bar {
  width: 12px;
  height: auto;
  flex: 1 1 auto;
  min-height: 80px;
  max-height: none;
}
#thermal-scale-legend .legend-temp { font-size: 10.5px; font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  #thermal-scale-legend { padding: 8px 7px; }
  #thermal-scale-legend .color-bar { width: 9px; min-height: 60px; }
}

/* Expand mode is gone; drop the rules that positioned it. */
.workspace-grid.video-focused .details-card,
.workspace-grid.video-focused .viewport-card,
.workspace-grid.video-focused .table-card { grid-column: auto; grid-row: auto; }

/* ==========================================================================
   Expand video, restored.
   The header goes back to a row so the button sits beside the heading without
   costing a line, and the focused layout gets a FIXED row height — the value
   that made it work before. A content-sized row is what collapsed the player to
   zero: the card fills the row, the frame fills the card, and the row is sized
   by the frame, so nothing has a definite value to resolve against.
   ========================================================================== */
.detail-header {
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.detail-header > .btn { flex: none; }

/* Undo the neutralising rules added when the mode was removed. */
@media (min-width: 1025px) {
  .workspace-grid.video-focused { grid-template-rows: min(78vh, 820px) minmax(280px, auto); }
  .workspace-grid.video-focused .details-card  { grid-column: 1 / -1; grid-row: 1 / 2; height: 100%; align-self: stretch; }
  .workspace-grid.video-focused .viewport-card { grid-column: 1 / 2; grid-row: 2 / 3; min-height: 280px; }
  .workspace-grid.video-focused .table-card    { grid-column: 2 / 3; grid-row: 2 / 3; }
}
@media (max-width: 1024px) {
  .workspace-grid.video-focused .details-card,
  .workspace-grid.video-focused .viewport-card,
  .workspace-grid.video-focused .table-card { grid-column: 1 / -1; grid-row: auto; }
  .workspace-grid.video-focused .details-card { height: auto; }
  .workspace-grid.video-focused .video-wrapper { height: auto; flex: 0 0 auto; }
  .workspace-grid.video-focused .thermal-stage .video-wrapper { height: auto; }
}

/* ==========================================================================
   Pass the available height all the way down to the frame.
   flex: 1 1 auto sizes an item to its content first and only then lets it grow,
   so each level of the chain measured the frame instead of telling it how much
   room it had — the video ended up 300x225 inside a 1132px card when expanded.
   A zero basis makes each level take the free space outright, which gives the
   frame a definite height to compute its width from.
   ========================================================================== */
@media (min-width: 1025px) {
  .detail-body     { flex: 1 1 0; min-height: 0; }
  .video-container { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
  .video-viewports { flex: 1 1 0; min-height: 0; }
  .video-pane      { flex: 1 1 0; min-height: 0; height: auto; }
  .thermal-stage   { flex: 1 1 0; min-height: 0; }
  .video-pane .video-wrapper,
  .thermal-stage .video-wrapper { height: 100%; width: auto; max-width: 100%; flex: 0 1 auto; }
}

/* height:100% needs a parent with a *definite* height. Through a flex chain that
   is not guaranteed, and when it fails the frame falls back to the video's
   intrinsic size — 1024x768, overflowing the card. Taking the height from the
   flex line instead (stretch in the row, a zero basis in the column) always
   resolves, and aspect-ratio then computes the width. */
@media (min-width: 1025px) {
  .thermal-stage > .video-wrapper {
    align-self: stretch;
    flex: 0 1 auto;
    height: auto;
    max-height: 100%;
    width: auto;
    max-width: 100%;
  }
  .video-pane > .video-wrapper {
    flex: 1 1 0;
    min-height: 0;
    height: auto;
    max-height: 100%;
    width: auto;
    max-width: 100%;
    align-self: center;
  }
}

/* ==========================================================================
   FINAL: the frame fills its area; the video letterboxes inside it.
   Sizing the box itself to the recording's aspect ratio through three nested
   flex containers proved unreliable — height:100% needs a definite parent, a
   zero basis and stretch each resolved differently, and the frame came out
   either 300x225 or its full 1024x768 depending on which rule won. The box now
   simply fills the space it is given and the video is positioned to fill that
   box with object-fit: contain, which shows the entire frame at the right
   proportions whatever the window does. Any spare room reads as black around
   the image, the way every video player behaves. Correctness over hugging: the
   fire and the firebrands are in the lower half of every thermal frame, so
   losing the bottom is the one outcome that must not happen.
   ========================================================================== */
.video-wrapper {
  position: relative;
  aspect-ratio: auto;
  height: auto;
  width: 100%;
  max-width: 100%;
  max-height: none;
  min-height: 0;
  background: #000;
  overflow: hidden;
  display: block;
}
.video-wrapper video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.video-wrapper .video-empty-state { position: absolute; inset: 0; }

/* Give that box a definite area to fill. */
@media (min-width: 1025px) {
  .video-pane > .video-wrapper,
  .thermal-stage > .video-wrapper { flex: 1 1 0; min-height: 120px; align-self: stretch; height: auto; width: auto; }
  .thermal-stage > .video-wrapper { flex: 1 1 auto; }
}
@media (max-width: 1024px) {
  /* Stacked layout has no row height to inherit, so the box needs one of its own. */
  .video-wrapper { aspect-ratio: var(--vid-aspect, 16 / 9); }
  .thermal-stage > .video-wrapper { flex: 1 1 auto; }
}

/* ==========================================================================
   Give the video area an explicit height per mode.
   Propagating height through pane -> stage -> frame depended on three flex
   containers each resolving a definite height, and they did not: the frame came
   out 300x225, then 1024x768, then a 139px strip, depending on which rule won.
   The card's height is known in each mode, so the video area is simply given
   the room that is left after the header, tabs and segment strip. The video
   fills that box with object-fit: contain, so the whole frame is always visible
   whatever the window size.
   ========================================================================== */
@media (min-width: 1025px) {
  /* Normal: the row is 520px (set by the 3D panel's minimum). */
  .video-wrapper { height: 330px; flex: 0 0 auto; align-self: stretch; }
  .thermal-stage > .video-wrapper { flex: 1 1 auto; width: auto; }
  .video-pane > .video-wrapper { width: 100%; }

  /* Expanded: the row is min(78vh, 820px), so the video gets that less the chrome. */
  .workspace-grid.video-focused .video-wrapper { height: calc(min(78vh, 820px) - 185px); }
}
@media (max-width: 1024px) {
  .video-wrapper { height: auto; aspect-ratio: var(--vid-aspect, 16 / 9); flex: 0 0 auto; }
  .thermal-stage > .video-wrapper { flex: 1 1 auto; width: auto; }
}
#thermal-scale-legend { align-self: stretch; }

/* The height above lost to an earlier `.video-pane > .video-wrapper { height: auto }`:
   two classes beat one, whatever the order. Set at matching specificity. */
@media (min-width: 1025px) {
  .video-pane > .video-wrapper,
  .thermal-stage > .video-wrapper {
    height: 330px;
    min-height: 0;
    flex: 0 0 auto;
    align-self: stretch;
  }
  .thermal-stage > .video-wrapper { flex: 1 1 auto; width: auto; }
  .video-pane > .video-wrapper { width: 100%; }

  .workspace-grid.video-focused .video-pane > .video-wrapper,
  .workspace-grid.video-focused .thermal-stage > .video-wrapper {
    height: calc(min(78vh, 820px) - 185px);
  }
}

/* ==========================================================================
   Denser layout — reclaim the space the chrome was taking.
   The three panels were separated by 24px gaps, 16px radii, shadows and their
   own borders, which together cost more room than the gaps between them were
   worth. Panels now sit flush and are divided by a single hairline: the grid's
   own background shows through 1px gaps, so no panel needs a border of its own
   and adjacent borders cannot double up. Type goes up rather than down.
   ========================================================================== */

/* --- Type ---------------------------------------------------------------- */
body { font-size: 15px; }
.sidebar .filter-label { font-size: 12px; }
.section-title { font-size: 15px; }
.tree-header { font-size: 0.92rem; }
.tree-subheader { font-size: 0.86rem; }
.run-item-title { font-size: 0.88rem; }
.run-item-count { font-size: 0.74rem; }
#firebrands-table { font-size: 13.5px; }
#firebrands-table th { font-size: 11.5px; }
.detail-header h2 { font-size: 1.2rem; }
.viewport-title, .table-card h2 { font-size: 1.05rem; }
.hud-overlay { font-size: 11.5px; }
.group-nav-header h2 { font-size: 12px; }

/* --- Panels divided by a line, not a gap --------------------------------- */
.workspace { padding: 0; }
.workspace-grid {
  gap: 1px;
  background: var(--border-color);
  border-top: 1px solid var(--border-color);
}
.workspace-grid > .card {
  border: none;
  border-radius: 0;
  box-shadow: none;
}
.card-header, .detail-header { padding: 10px 14px; }
.table-card .card-header { padding: 10px 14px 8px; }
.subtitle-text { font-size: 12px; margin-top: 2px; }
.video-viewports { padding: 8px; }
.viewport-body { padding: 0; }

/* The landing panel keeps breathing room; it is prose, not a workspace. */
.workspace-centered-screen { padding: 24px; }

/* --- Sidebar: the freed space goes to the experiment list ---------------- */
.search-filter-panel { padding: 14px 16px; gap: 12px; }
.group-nav-header { padding: 10px 16px 6px; }
.runs-list { padding: 0 12px 12px; }
.tree-header, .tree-subheader { padding: 7px 9px; }
.run-item { padding: 8px 10px; }

/* --- Authors in the header ----------------------------------------------- */
.header-authors {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.25;
  margin-right: 4px;
  cursor: help;
  min-width: 0;
}
.header-authors-label {
  font-size: 9.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  font-weight: 700;
}
.header-authors-names {
  font-size: 11.5px;
  color: var(--text-main);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 34ch;
}
/* Names are the first thing to go when the header runs out of room. */
@media (max-width: 1280px) { .header-authors-names { max-width: 22ch; } }
@media (max-width: 1100px) { .header-authors { display: none; } }

/* The video sits normally in its frame again. Absolute positioning was a
   workaround from when the frame had no definite height; the frame now has one,
   so the video can simply fill it. Fewer moving parts, and it removes the other
   thing that changed when thermal playback stopped working. */
.video-wrapper video {
  position: static;
  inset: auto;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
