:root {
  /* UI overhaul Phase 4 (specs/ui-overhaul.md): the 6-step type scale.
     New styles use these; existing rules migrate value-for-value (no
     visual change) and collapse onto the scale as pages get their
     redesign pass. */
  --fs-xs: 0.68rem;
  --fs-sm: 0.74rem;
  --fs-base: 0.82rem;
  --fs-md: 0.95rem;
  --fs-lg: 1.15rem;
  --fs-xl: 1.45rem;

  --bg: #071014;
  --panel: rgba(11, 20, 26, 0.92);
  --panel-soft: rgba(15, 27, 35, 0.72);
  --ink: #edf8f8;
  --muted: #90a9ad;
  --line: rgba(163, 185, 188, 0.16);
  --accent: #32d0bd;
  --accent-2: #7dd3fc;
  --warn: #f6b15e;
  --bad: #fb7185;
  --ok: #55d38a;
  --shadow: 0 28px 80px rgba(0, 0, 0, 0.42);
  --radius: 22px;
}

* {
  box-sizing: border-box;
}

html,
body {
  min-height: 100%;
  margin: 0;
}

body {
  color: var(--ink);
  background:
    radial-gradient(circle at 15% 0%, rgba(50, 208, 189, 0.18), transparent 28%),
    radial-gradient(circle at 80% 12%, rgba(125, 211, 252, 0.14), transparent 26%),
    linear-gradient(180deg, #061014 0%, #09161d 46%, #081117 100%);
  font-family: "IBM Plex Sans", "Segoe UI", sans-serif;
  overflow-x: hidden;
}

button,
input,
select,
textarea {
  font: inherit;
}

[hidden] {
  display: none !important;
}

.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;
}

a {
  color: inherit;
  text-decoration: none;
}

.app-shell {
  width: min(1920px, 100%);
  height: 100vh;
  height: 100dvh;
  margin: 0 auto;
  padding: 14px;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  overflow: hidden;
}

.app-header {
  display: grid;
  grid-template-columns: minmax(190px, 0.52fr) minmax(500px, 1.18fr) minmax(340px, 0.78fr);
  gap: 14px;
  align-items: center;
  min-height: 86px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 24px;
  background: rgba(7, 16, 20, 0.84);
  box-shadow: var(--shadow);
  backdrop-filter: blur(20px);
}

.brand-block {
  display: flex;
  align-items: center;
  gap: 10px;
}
.brand-logo {
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  object-fit: contain;
  display: block;
}
.brand-block .brand-wordmark {
  margin: 0;
  font-size: 1.18rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--accent);
}

.brand-block h1,
.page-head h2,
.map-topline h2,
.side-panel h2,
.context-drawer h2,
h3,
p {
  margin-top: 0;
}

.brand-block h1 {
  margin-bottom: 4px;
  font-size: clamp(1.35rem, 2vw, 2.25rem);
  line-height: 0.95;
}

.brand-block p:last-child,
.page-head p,
.muted {
  color: var(--muted);
}

.brand-block p:last-child {
  margin: 0;
  max-width: 42rem;
  font-size: 0.9rem;
}

.eyebrow {
  margin: 0 0 5px;
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.primary-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
  gap: 6px;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
}

.nav-button,
.button {
  min-height: 40px;
  border: 1px solid transparent;
  border-radius: 13px;
  color: var(--ink);
  background: transparent;
  cursor: pointer;
  transition: transform 160ms ease, background 160ms ease, border-color 160ms ease;
}

.nav-button {
  padding: 0 8px;
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 700;
}

.nav-button:hover,
.button:hover {
  transform: translateY(-1px);
}

.nav-button.is-active {
  color: #041312;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
}

/* Live status badge anchored to the top-right corner of a nav button.
   Updated by _refreshNavBadges() on a 5s timer. Colors:
     default (cyan)  — informational count (e.g. fresh tiles, neighbors)
     .is-warn (amber) — degraded (stale data, sparse neighbors)
     .is-alert (red)  — at least one watch alerting / a real problem */
.nav-button {
  position: relative;
}
.nav-badge {
  position: absolute;
  top: -2px;
  right: -2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 9px;
  font-size: 9.5px;
  font-weight: 700;
  line-height: 16px;
  text-align: center;
  background: rgba(50, 208, 189, 0.92);
  color: #041312;
  border: 1.5px solid rgba(7, 18, 24, 0.9);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
  pointer-events: none;
  z-index: 2;
  transition: background 0.18s, transform 0.18s;
}
.nav-badge.is-warn { background: rgba(245, 158, 11, 0.94); color: #1a0f00; }
.nav-badge.is-alert {
  background: rgba(251, 113, 133, 0.96);
  color: #2d0000;
  animation: nav-badge-pulse 1.4s ease-in-out infinite;
}
.nav-badge.is-hidden { display: none; }
@keyframes nav-badge-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(251, 113, 133, 0.6); transform: scale(1); }
  50%      { box-shadow: 0 0 0 4px rgba(251, 113, 133, 0); transform: scale(1.08); }
}

.header-controls {
  display: grid;
  grid-template-columns: 1fr 1fr auto auto;
  gap: 8px;
  align-items: end;
}

.header-metrics {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 0 0 auto;
}

.header-metric {
  display: flex;
  align-items: center;
  gap: 6px;
}

.header-metric > span {
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

.header-metric select {
  width: auto;
  min-width: 120px;
  max-width: 190px;
  min-height: 34px;
  padding: 0 9px;
  font-size: var(--fs-base);
}

.control {
  display: grid;
  gap: 6px;
  min-width: 0;
}

.control span {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

select,
input,
textarea {
  width: 100%;
  min-height: 40px;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  background: rgba(6, 13, 17, 0.86);
  outline: none;
  padding: 0 11px;
}

textarea {
  min-height: 120px;
  padding-block: 10px;
  resize: vertical;
}

select:focus,
input:focus,
textarea:focus {
  border-color: rgba(50, 208, 189, 0.72);
  box-shadow: 0 0 0 3px rgba(50, 208, 189, 0.13);
}

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 14px;
  font-weight: 700;
}

.button-primary {
  color: #031413;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
}

.button-secondary {
  color: var(--ink);
  border-color: var(--line);
  background: rgba(255, 255, 255, 0.045);
}

.button.is-active {
  color: #041312;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
}

.console-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(360px, 420px);
  grid-template-areas: "map side";
  gap: 14px;
  min-height: 0;
  height: calc(100% - 14px);
  margin-top: 14px;
  overflow: hidden;
}

body[data-route="observe"] .app-shell {
  width: 100%;
  max-width: none;
  padding: 0;
  grid-template-rows: minmax(0, 1fr);
}

body[data-route="observe"] .app-header {
  position: fixed;
  left: 16px;
  right: 16px;
  top: 16px;
  z-index: 80;
  grid-template-columns: minmax(180px, 0.7fr) minmax(280px, 0.72fr) minmax(320px, 0.82fr);
  min-height: 0;
  background: rgba(7, 16, 20, 0.66);
}

body[data-route="observe"] .brand-block p:last-child {
  display: none;
}

body[data-route="observe"] .console-grid {
  height: 100%;
  margin: 0;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "map";
}

body[data-route="observe"] .map-plane {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  grid-template-rows: minmax(0, 1fr);
}

body[data-route="observe"] .map-stage {
  margin: 0;
  grid-area: 1 / 1;
}

body[data-route="observe"] #map,
body[data-route="observe"] .globe-canvas {
  border-radius: 0;
}

body[data-route="observe"] .map-topline {
  position: absolute;
  left: 16px;
  right: 16px;
  top: 118px;
  z-index: 45;
  padding: 12px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 18px;
  background: rgba(7, 16, 20, 0.58);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(16px);
}

body[data-route="observe"] .map-utility-strip {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 14px;
  z-index: 44;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 18px;
  background: rgba(7, 16, 20, 0.58);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(16px);
}

body[data-route="observe"] .map-status {
  position: absolute;
  left: 18px;
  bottom: 82px;
  z-index: 44;
  max-width: min(720px, calc(100% - 36px));
  padding: 8px 12px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 999px;
  background: rgba(7, 16, 20, 0.58);
  backdrop-filter: blur(14px);
}

body[data-route="observe"] .map-coordinate-tools {
  bottom: 248px;
}

body[data-route="observe"] .map-overlay-controls {
  top: 206px;
  bottom: auto;
  width: min(360px, 92vw) !important;
  max-height: calc(100vh - 248px) !important;
}

body[data-route="observe"] .map-overlay-controls.dock-top-left,
body[data-route="observe"] .map-overlay-controls.dock-top-right {
  top: 206px;
}

body[data-route="observe"] .map-viz-dock {
  bottom: 248px;
}

body[data-route="observe"] .dto-temporal-control {
  bottom: 92px;
}

body[data-route="observe"] .context-drawer {
  top: 206px;
  right: 16px;
  bottom: 228px;
  max-height: calc(100% - 434px);
}

body[data-route="observe"] .side-panel,
body[data-route="observe"] #map-page {
  display: none;
}

.map-plane,
.side-panel,
.page-panel {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
}

.map-plane {
  grid-area: map;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  min-height: 0;
  height: 100%;
  overflow: hidden;
}

.map-stage {
  position: relative;
  isolation: isolate;
  display: grid;
  min-height: 0;
  overflow: hidden;
  margin: 12px 14px;
}

.map-topline {
  position: relative;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 16px 0;
}

.map-topline h2,
.page-head h2,
.side-panel h2 {
  margin-bottom: 0;
}

.map-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.map-utility-strip {
  position: relative;
  z-index: 5;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 0 16px 8px;
}

.map-layer-status {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  min-width: 0;
}

.map-layer-status span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.045);
  font-size: var(--fs-sm);
  font-weight: 700;
}

.map-layer-status span.ok {
  color: var(--ink);
  border-color: rgba(50, 208, 189, 0.24);
  background: rgba(50, 208, 189, 0.09);
}

.map-layer-status span.warn {
  color: #ffe5bd;
  border-color: rgba(246, 177, 94, 0.28);
  background: rgba(246, 177, 94, 0.1);
}

.map-layer-status b {
  color: var(--ink);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.map-quick-actions {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  justify-content: flex-end;
}

.map-quick-actions .button,
.hardware-card-actions .button,
.section-actions .button {
  min-height: 30px;
  padding: 0 10px;
  font-size: 0.76rem;
}

/* Map Overlays popover (1/N) — anchored to the Overlays button in
   the map-quick-actions strip. Three category groups (Radar /
   Satellite Imagery / Weather), each with toggle + opacity slider
   per active layer. The popover sits ABOVE the map so the operator
   can see overlays appear as they toggle. */
.map-overlay-picker-wrap {
  position: relative;
  display: inline-flex;
}
.map-overlays-popover {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 340px;
  max-width: 420px;
  max-height: 70vh;
  overflow-y: auto;
  z-index: 1050;
  background: var(--panel, rgba(15, 22, 28, 0.96));
  border: 1px solid var(--line, rgba(255, 255, 255, 0.12));
  border-radius: 10px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.50);
  backdrop-filter: blur(20px);
  padding: 12px;
}
.map-overlays-popover-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.map-overlays-popover-close {
  background: none;
  border: none;
  color: rgba(255, 255, 255, 0.7);
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 4px;
}
.map-overlays-popover-close:hover {
  background: rgba(255, 255, 255, 0.08);
  color: var(--ink);
}
.map-overlays-popover-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.map-overlay-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.map-overlay-group-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: rgba(207, 232, 216, 0.55);
}
.map-overlay-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 8px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.02);
  transition: border-color 0.15s, background 0.15s;
}
.map-overlay-item.is-active {
  background: rgba(108, 183, 255, 0.10);
  border-color: rgba(108, 183, 255, 0.30);
}
.map-overlay-item-head {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
}
.map-overlay-item-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  font-size: 12px;
  font-weight: 600;
  flex: 1;
}
.map-overlay-item-toggle input[type="checkbox"] {
  width: 14px;
  height: 14px;
  cursor: pointer;
}
.map-overlay-item-cadence {
  font-size: 10px;
  color: rgba(207, 232, 216, 0.5);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.map-overlay-item-desc {
  font-size: 11px;
  color: rgba(207, 232, 216, 0.65);
  line-height: 1.35;
}
.map-overlay-item-opacity {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  color: rgba(207, 232, 216, 0.5);
}
.map-overlay-item-opacity input[type="range"] {
  flex: 1;
  height: 4px;
}
.map-overlay-empty {
  font-size: 11px;
  color: rgba(207, 232, 216, 0.5);
  text-align: center;
  padding: 10px;
}

.view-toggle {
  display: inline-flex;
  gap: 5px;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.035);
}

#map {
  position: relative;
  z-index: 0;
  grid-area: 1 / 1;
  min-height: 0;
  height: 100%;
  margin: 0;
  border-radius: 18px;
  background: #08141a;
  overflow: hidden;
}

.globe-canvas {
  grid-area: 1 / 1;
  display: block;
  width: 100%;
  min-height: 0;
  height: 100%;
  border: 1px solid rgba(125, 211, 252, 0.16);
  border-radius: 18px;
  background:
    radial-gradient(circle at 50% 46%, rgba(56, 189, 248, 0.12), transparent 36%),
    radial-gradient(circle at 50% 55%, #0b1e26 0%, #061016 54%, #02070a 100%);
  box-shadow: inset 0 0 80px rgba(125, 211, 252, 0.08), 0 28px 90px rgba(0, 0, 0, 0.42);
  cursor: grab;
  touch-action: none;
}

.globe-canvas:active {
  cursor: grabbing;
}

.map-stage.is-globe #map {
  display: none;
}

.map-stage.is-globe .globe-canvas {
  position: relative;
  z-index: 1;
  display: block;
  box-shadow:
    inset 0 0 0 1px rgba(125, 211, 252, 0.18),
    inset 0 -90px 120px rgba(3, 12, 18, 0.18),
    0 28px 90px rgba(0, 0, 0, 0.42);
}

.map-stage.is-globe::after {
  content: "3D globe mode projects stations, overlays, and research footprints";
  position: absolute;
  left: 18px;
  bottom: 18px;
  z-index: 620;
  padding: 7px 10px;
  border: 1px solid rgba(125, 211, 252, 0.22);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(6, 16, 22, 0.76);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  pointer-events: none;
}

.globe-legend {
  position: absolute;
  left: 16px;
  top: 16px;
  z-index: 690;
  width: min(310px, calc(100% - 32px));
  display: grid;
  gap: 10px;
  padding: 14px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 20px;
  background: rgba(7, 18, 24, 0.82);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.36);
  backdrop-filter: blur(18px);
  pointer-events: auto;
}

.leaflet-map-overlay-field {
  mix-blend-mode: screen;
  will-change: transform;
}

.globe-legend h3 {
  margin: 0;
  font-size: 1rem;
}

.globe-legend-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 6px 12px;
  align-items: center;
}

.globe-legend-grid span {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.globe-legend-grid strong {
  overflow: hidden;
  text-align: right;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.globe-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  pointer-events: auto;
}

.map-coordinate-tools {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 42;
  display: grid;
  gap: 9px;
  width: min(360px, calc(100% - 32px));
  padding: 12px;
  border: 1px solid rgba(125, 211, 252, 0.2);
  border-radius: 18px;
  background:
    linear-gradient(145deg, rgba(8, 20, 26, 0.92), rgba(3, 10, 13, 0.76)),
    rgba(4, 14, 19, 0.82);
  box-shadow: 0 22px 50px rgba(0, 0, 0, 0.34);
  backdrop-filter: blur(14px);
}

.map-coordinate-tools.is-collapsed {
  width: auto;
  max-width: min(340px, calc(100% - 32px));
  max-height: none;
  overflow: visible;
  padding: 9px;
}

.map-coordinate-tools.is-collapsed .coordinate-readout-grid,
.map-coordinate-tools.is-collapsed .map-point-list,
.map-coordinate-tools.is-collapsed .coordinate-input-grid,
.map-coordinate-tools.is-collapsed .coordinate-action-row,
.map-coordinate-tools.is-collapsed #map-coordinate-status {
  display: none;
}

.map-stage.is-globe .map-coordinate-tools {
  display: none;
}

.map-coordinate-tools.is-free-floating,
.dto-temporal-control.is-free-floating,
.ocean-viewer-panel.is-free-floating,
.context-drawer.is-free-floating,
.globe-legend.is-free-floating,
.page-panel.is-free-floating {
  right: auto !important;
  bottom: auto !important;
  transform: none !important;
}

.dto-temporal-control.is-free-floating {
  width: min(780px, calc(100% - 16px));
}

.context-drawer.is-free-floating {
  max-height: min(72vh, calc(100% - 16px));
}

.coordinate-head,
.coordinate-action-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.coordinate-head-actions,
.route-picker-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
  justify-content: flex-end;
}

.coordinate-head,
.temporal-head,
.context-drawer-head,
.map-overlay-head,
.ocean-viewer-head,
.globe-legend,
body[data-route="plan"] #command-page .page-head {
  cursor: move;
}

.coordinate-head h3 {
  margin: 0;
  font-size: 0.98rem;
}

.coordinate-readout-grid {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 5px 9px;
  font-size: 0.78rem;
}

.coordinate-readout-grid span,
.overlay-product-insight span {
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.coordinate-readout-grid strong {
  min-width: 0;
  color: var(--ink);
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.coordinate-input-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.map-point-list {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  max-height: 70px;
  overflow: auto;
}

.map-point-list.empty {
  min-height: 52px;
  padding: 8px;
  font-size: var(--fs-base);
}

.map-point-list span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 26px;
  padding: 0 8px;
  border: 1px solid rgba(125, 211, 252, 0.2);
  border-radius: 999px;
  color: var(--muted);
  background: rgba(125, 211, 252, 0.07);
  font-size: 0.73rem;
  font-weight: 700;
}

.map-point-list b {
  color: var(--ink);
}

.map-point-remove {
  min-height: 20px;
  border: 1px solid rgba(251, 113, 133, 0.24);
  border-radius: 999px;
  color: #ffd0d8;
  background: rgba(251, 113, 133, 0.12);
  cursor: pointer;
  font-size: 0.66rem;
  font-weight: 800;
}

.coordinate-action-row {
  flex-wrap: wrap;
}

.coordinate-action-row .button {
  min-height: 32px;
  flex: 1 1 74px;
  padding: 0 9px;
  font-size: 0.75rem;
}

.map-tool-pin {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 2px solid #dffffa;
  border-radius: 999px;
  color: #031413;
  background: radial-gradient(circle, var(--accent) 0 32%, rgba(50, 208, 189, 0.12) 34% 100%);
  box-shadow:
    0 0 0 8px rgba(50, 208, 189, 0.12),
    0 0 22px rgba(50, 208, 189, 0.42);
  font-size: 0.66rem;
  font-weight: 900;
  line-height: 1;
  pointer-events: none;
}

.dto-temporal-control {
  position: absolute;
  left: 50%;
  bottom: 18px;
  z-index: 43;
  display: grid;
  gap: 9px;
  width: min(780px, calc(100% - 420px));
  min-width: 380px;
  padding: 12px;
  border: 1px solid rgba(232, 255, 122, 0.2);
  border-radius: 20px;
  background:
    linear-gradient(145deg, rgba(9, 20, 24, 0.9), rgba(5, 12, 15, 0.72)),
    radial-gradient(circle at 8% 0%, rgba(232, 255, 122, 0.14), transparent 35%);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.36);
  backdrop-filter: blur(16px);
  transform: translateX(-50%);
}

.map-stage.is-globe .dto-temporal-control {
  z-index: 50;
}

.ocean-viewer-panel {
  position: absolute;
  right: 16px;
  top: 206px;
  z-index: 57;
  display: grid;
  gap: 10px;
  width: min(430px, calc(100% - 32px));
  max-height: min(64vh, calc(100% - 300px));
  overflow: auto;
  padding: 14px;
  border: 1px solid rgba(50, 208, 189, 0.24);
  border-radius: 22px;
  background:
    linear-gradient(155deg, rgba(7, 18, 24, 0.92), rgba(3, 10, 13, 0.78)),
    radial-gradient(circle at 92% 0%, rgba(125, 211, 252, 0.16), transparent 38%);
  box-shadow: 0 26px 76px rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(18px);
}

.map-stage.is-globe .ocean-viewer-panel {
  z-index: 700;
}

.ocean-viewer-panel.is-free-floating {
  right: auto !important;
  bottom: auto !important;
  transform: none !important;
}

.ocean-viewer-panel.is-collapsed {
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 9px;
}

.ocean-viewer-panel.is-collapsed .ocean-viewer-body,
.ocean-viewer-panel.is-collapsed .ocean-viewer-head .eyebrow,
.ocean-viewer-panel.is-collapsed .ocean-viewer-head h3 {
  display: none;
}

.ocean-viewer-head,
.ocean-viewer-actions,
.ocean-viewer-action-row {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
}

.ocean-viewer-head {
  cursor: move;
  user-select: none;
}

.ocean-viewer-head h3 {
  margin: 0;
  font-size: 1rem;
}

.ocean-viewer-actions,
.ocean-viewer-action-row {
  flex-wrap: wrap;
  justify-content: flex-end;
}

.ocean-viewer-body {
  display: grid;
  gap: 10px;
}

.ocean-product-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}

.ocean-product-chip {
  min-height: 34px;
  padding: 0 8px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 12px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.045);
  cursor: pointer;
  font-size: var(--fs-sm);
  font-weight: 800;
}

.ocean-product-chip.is-active {
  color: #041312;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
}

.ocean-viewer-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}

.ocean-viewer-action-row .button {
  flex: 1 1 86px;
  min-height: 32px;
  padding: 0 9px;
  font-size: var(--fs-sm);
}

.ocean-time-depth-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 8px;
  border: 1px solid rgba(163, 185, 188, 0.15);
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.035);
}

.ocean-time-depth-row > span {
  margin-right: auto;
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ocean-time-depth-row .map-overlay-button {
  min-height: 28px;
  padding: 0 8px;
  font-size: 0.7rem;
}

.ocean-viewer-stack {
  display: grid;
  gap: 7px;
}

.ocean-layer-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 5px 10px;
  align-items: center;
  padding: 9px 10px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.04);
}

.ocean-layer-card strong {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ocean-layer-card span,
.ocean-layer-card small {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.ocean-layer-card small {
  grid-column: 1 / -1;
  letter-spacing: 0;
  text-transform: none;
}

.ocean-layer-card.is-sample {
  border-color: rgba(232, 255, 122, 0.24);
  background: rgba(232, 255, 122, 0.08);
}

.ocean-profile-card {
  display: grid;
  gap: 8px;
  min-height: 126px;
  padding: 10px;
  border: 1px solid rgba(232, 255, 122, 0.2);
  border-radius: 16px;
  background:
    radial-gradient(circle at 8% 10%, rgba(232, 255, 122, 0.12), transparent 42%),
    rgba(255, 255, 255, 0.035);
}

.ocean-profile-card.empty {
  place-items: center;
  min-height: 86px;
  color: var(--muted);
  text-align: center;
  font-size: 0.78rem;
  font-weight: 700;
}

.ocean-profile-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.ocean-profile-head div:first-child {
  display: grid;
  gap: 3px;
}

.ocean-profile-head strong {
  color: var(--ink);
}

.ocean-profile-head span,
.ocean-profile-stats span {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 800;
}

.ocean-profile-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}

.ocean-profile-actions .button {
  min-height: 28px;
  padding: 0 8px;
  font-size: 0.7rem;
}

.ocean-profile-chart {
  width: 100%;
  height: 84px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.045), transparent),
    repeating-linear-gradient(90deg, rgba(163, 185, 188, 0.08) 0 1px, transparent 1px 20%);
}

.ocean-profile-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 6px;
}

.ocean-profile-stats span {
  min-width: 0;
  overflow: hidden;
  padding: 6px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 10px;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: rgba(255, 255, 255, 0.035);
}

.ocean-viewer-inspect-active #map,
.ocean-viewer-transect-active #map {
  cursor: crosshair;
}

.temporal-head,
.temporal-actions,
.temporal-grid {
  display: flex;
  align-items: center;
  gap: 10px;
}

.temporal-head {
  justify-content: space-between;
}

.temporal-head span,
.depth-readout span {
  color: var(--muted);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.temporal-head strong {
  display: block;
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.92rem;
}

.temporal-grid {
  display: grid;
  grid-template-columns: minmax(180px, 1.1fr) minmax(190px, 0.95fr) minmax(160px, 0.9fr) auto;
  align-items: end;
}

.dto-temporal-control input[type="range"] {
  accent-color: var(--accent);
}

.depth-readout {
  display: grid;
  gap: 6px;
  min-height: 40px;
  align-content: center;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 13px;
  background: rgba(255, 255, 255, 0.045);
}

.depth-readout strong {
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  white-space: nowrap;
}

.dto-temporal-control p {
  margin: 0;
  font-size: 0.78rem;
}

.map-overlay-controls {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 40;
  width: min(360px, calc(100% - 32px));
  max-height: min(62vh, calc(100% - 32px));
  overflow: auto;
  display: grid;
  gap: 10px;
  padding: 12px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 20px;
  background: rgba(7, 18, 24, 0.86);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(18px);
}

.map-overlay-controls.dock-top-left {
  inset: 16px auto auto 16px;
}

.map-overlay-controls.dock-top-right {
  inset: 16px 16px auto auto;
}

.map-overlay-controls.dock-bottom-left {
  inset: auto auto 16px 16px;
}

.map-overlay-controls.dock-bottom-right {
  inset: auto 16px 16px auto;
}

.map-overlay-controls.is-free {
  right: auto;
  bottom: auto;
}

.map-overlay-controls.is-collapsed {
  width: min(188px, calc(100% - 32px));
  max-height: none;
  overflow: visible;
  padding: 9px;
}

.map-overlay-controls.is-collapsed .map-overlay-body {
  display: none;
}

.map-overlay-controls.is-collapsed .map-overlay-head {
  align-items: center;
}

.map-overlay-controls.is-collapsed .map-overlay-head .eyebrow,
.map-overlay-controls.is-collapsed .map-overlay-head h3,
.map-overlay-controls.is-collapsed #move-map-overlay-button {
  display: none;
}

.map-overlay-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  user-select: none;
}

.map-overlay-head h3 {
  margin-bottom: 0;
  font-size: 1rem;
}

.map-overlay-head-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
}

.map-overlay-body {
  display: grid;
  gap: 10px;
}

.overlay-product-insight {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 10px;
  border: 1px solid rgba(50, 208, 189, 0.18);
  border-radius: 16px;
  background:
    radial-gradient(circle at 12% 0%, rgba(50, 208, 189, 0.14), transparent 42%),
    rgba(255, 255, 255, 0.035);
}

.overlay-product-insight div {
  display: grid;
  gap: 3px;
}

.overlay-product-insight strong {
  color: var(--ink);
  font-size: 0.86rem;
}

.overlay-product-insight p {
  grid-column: 1 / -1;
  margin: 0;
}

.map-overlay-primary {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
  gap: 10px;
  align-items: end;
}

.overlay-action-row {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  align-items: center;
}

.overlay-action-row .button {
  flex: 1 1 110px;
}

.overlay-action-row-wide {
  grid-column: 1 / -1;
}

.overlay-advanced {
  border: 1px solid var(--line);
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.035);
}

.overlay-advanced summary {
  min-height: 38px;
  display: flex;
  align-items: center;
  padding: 0 12px;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.overlay-advanced[open] {
  padding-bottom: 8px;
}

.overlay-advanced .map-overlay-scope {
  margin: 8px 8px 0;
}

.map-overlay-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.map-overlay-buttons.compact {
  gap: 5px;
}

.overlay-preset-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
}

.overlay-preset-grid .map-overlay-button {
  min-height: 34px;
  border-radius: 12px;
  text-align: center;
}

/* Discoverable entry point to the searchable Layer Catalog. */
.browse-layers-button {
  width: 100%;
  margin-top: 7px;
  justify-content: center;
  text-align: center;
}

/* Named saved-views row (save current scene + restore/delete). */
.saved-views-row {
  display: flex;
  gap: 6px;
  align-items: center;
  margin-top: 6px;
}
.saved-views-row #save-view-button { flex: none; }
.saved-views-select {
  flex: 1 1 auto;
  min-width: 0;
  padding: 5px 8px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: rgba(7, 16, 20, 0.7);
  color: var(--text);
  font-size: var(--fs-sm);
}
.saved-views-row #delete-view-button { flex: none; }

.map-overlay-scope {
  display: grid;
  gap: 6px;
  padding: 8px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.035);
}

.map-overlay-scope > span {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.provider-cache-status {
  display: grid;
  gap: 6px;
  padding: 10px;
  border: 1px solid rgba(125, 211, 252, 0.18);
  border-radius: 14px;
  background: rgba(10, 24, 32, 0.56);
}

.provider-cache-status strong {
  color: var(--ink);
}

.provider-cache-status .section-row {
  gap: 8px;
}

.map-overlay-button {
  min-height: 32px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.045);
  cursor: pointer;
  font-weight: 700;
}

.map-overlay-button.is-active {
  color: #041312;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent-2), #d5fbff);
}

.overlay-layer-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: 7px;
  align-items: end;
}

.overlay-layer-select,
.overlay-wide-select {
  min-width: 0;
}

.overlay-layer-select select,
.overlay-wide-select select {
  width: 100%;
  max-width: 260px;
}

.heat-overlay-label {
  padding: 2px 7px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(4, 14, 19, 0.9);
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.01em;
  white-space: nowrap;
  box-shadow: 0 8px 18px rgba(0, 0, 0, 0.34);
}

.mini-select {
  min-height: 32px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.045);
}

.mini-select span {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.mini-select select {
  min-height: 26px;
  border: 0;
  color: var(--text);
  background: transparent;
  font-weight: 800;
}

.map-viz-dock {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 35;
  width: min(420px, calc(100% - 32px));
  max-height: min(46vh, 430px);
  display: grid;
  gap: 10px;
  padding: 14px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 20px;
  background: rgba(7, 18, 24, 0.86);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(18px);
}

.side-panel .map-viz-dock {
  position: static;
  z-index: auto;
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 14px;
  border-radius: 18px;
  background: var(--panel-soft);
  box-shadow: none;
  backdrop-filter: none;
}

.side-panel .map-overlay-controls {
  position: static;
  z-index: auto;
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 14px;
  border-radius: 18px;
  background: var(--panel-soft);
  box-shadow: none;
  backdrop-filter: none;
}

.side-panel .map-overlay-controls.is-collapsed {
  width: auto;
}

.side-panel .map-viz-dock.is-collapsed {
  width: auto;
}

.map-viz-dock.is-collapsed {
  width: auto;
  max-height: none;
}

.map-viz-dock.is-collapsed .map-viz-modes,
.map-viz-dock.is-collapsed #map-viz-summary,
.map-viz-dock.is-collapsed #map-viz-chart {
  display: none;
}

.map-viz-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.map-viz-head h3 {
  margin-bottom: 0;
  font-size: 1rem;
}

.map-viz-head-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.map-viz-modes {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.map-viz-mode {
  min-height: 24px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.045);
  cursor: pointer;
  font-weight: 700;
  font-size: 0.72rem;
}

.map-viz-mode.is-active {
  color: #041312;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
}

#map-viz-chart {
  min-height: 190px;
  max-height: min(28vh, 250px);
  overflow: auto;
}

.vector-overlay,
.wave-overlay,
.temp-overlay {
  position: relative;
  display: block;
  width: 86px;
  height: 72px;
  pointer-events: none;
}

.overlay-scale-shell {
  display: block;
  width: 86px;
  height: 72px;
  opacity: var(--overlay-opacity, 1);
  transform: scale(var(--overlay-zoom-scale, 1));
  transform-origin: center center;
  pointer-events: none;
  will-change: transform;
}

.vector-motion {
  position: absolute;
  inset: 6px 10px 18px;
  transform: rotate(var(--vector-rotation, 0deg));
  transform-origin: center center;
}

.vector-core {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 10px;
  height: 10px;
  border-radius: 999px;
  background: var(--vector-color, var(--accent-2));
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--vector-color, var(--accent-2)) 20%, transparent);
  transform: translate(-50%, -50%);
  animation: overlay-pulse 1.8s ease-out infinite;
}

.vector-tail {
  position: absolute;
  left: 12px;
  top: 50%;
  width: calc(18px + (18px * var(--vector-scale, 1)));
  height: 6px;
  border-radius: 999px;
  background:
    linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--vector-color, var(--accent-2)) 55%, transparent) 36%, var(--vector-color, var(--accent-2)) 100%);
  transform: translateY(-50%);
  transform-origin: left center;
  animation: overlay-flow 1.05s linear infinite;
}

.vector-arrow {
  position: absolute;
  right: 8px;
  top: 50%;
  color: var(--vector-color, var(--accent-2));
  font-size: calc(16px + (8px * var(--vector-scale, 1)));
  line-height: 1;
  transform: translateY(-50%);
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--vector-color, var(--accent-2)) 55%, transparent));
}

.overlay-label {
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  padding: 2px 6px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 999px;
  color: var(--ink);
  background: rgba(4, 14, 19, 0.86);
  font-size: var(--fs-xs);
  font-weight: 700;
  white-space: nowrap;
}

.wave-ring,
.wave-ring.is-second {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(18px + (16px * var(--wave-scale, 1)));
  height: calc(18px + (16px * var(--wave-scale, 1)));
  border: 2px solid var(--wave-color, var(--warn));
  border-radius: 999px;
  transform: translate(-50%, -50%);
  opacity: 0.72;
  animation: overlay-wave 2.2s ease-out infinite;
}

.wave-ring.is-second {
  animation-delay: 0.9s;
}

.wave-arrow {
  position: absolute;
  left: 50%;
  top: 50%;
  color: var(--wave-color, var(--warn));
  font-size: 19px;
  line-height: 1;
  transform: translate(-50%, -50%) rotate(var(--vector-rotation, 0deg));
  filter: drop-shadow(0 0 10px color-mix(in srgb, var(--wave-color, var(--warn)) 55%, transparent));
}

.temp-core {
  position: absolute;
  left: 50%;
  top: 50%;
  min-width: calc(18px + (18px * var(--temp-scale, 1)));
  height: calc(18px + (18px * var(--temp-scale, 1)));
  padding: 0 9px;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--temp-color, var(--accent-2)) 35%, transparent);
  color: #051416;
  background: color-mix(in srgb, var(--temp-color, var(--accent-2)) 82%, white 18%);
  display: grid;
  place-items: center;
  font-size: 0.72rem;
  font-weight: 800;
  transform: translate(-50%, -50%);
  box-shadow:
    0 0 0 10px color-mix(in srgb, var(--temp-color, var(--accent-2)) 18%, transparent),
    0 0 26px color-mix(in srgb, var(--temp-color, var(--accent-2)) 45%, transparent);
  animation: overlay-pulse 2s ease-out infinite;
}

@keyframes overlay-flow {
  0% {
    opacity: 0.55;
    transform: translateY(-50%) scaleX(0.72);
  }
  50% {
    opacity: 1;
    transform: translateY(-50%) scaleX(1.04);
  }
  100% {
    opacity: 0.55;
    transform: translateY(-50%) scaleX(0.72);
  }
}

@keyframes overlay-pulse {
  0% {
    opacity: 0.95;
    transform: translate(-50%, -50%) scale(0.92);
  }
  70% {
    opacity: 0.28;
    transform: translate(-50%, -50%) scale(1.28);
  }
  100% {
    opacity: 0.08;
    transform: translate(-50%, -50%) scale(1.44);
  }
}

@keyframes overlay-wave {
  0% {
    opacity: 0.82;
    transform: translate(-50%, -50%) scale(0.72);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.55);
  }
}

.data-layer-div-icon {
  background: transparent;
  border: 0;
}

.dynamic-field-canvas {
  z-index: 430;
  pointer-events: none;
  image-rendering: auto;
}

.data-layer-marker {
  position: relative;
  display: block;
  width: 48px;
  height: 48px;
  color: var(--marker-color, var(--accent-2));
  filter: drop-shadow(0 10px 18px rgba(0, 0, 0, 0.42));
  pointer-events: auto;
}

.data-layer-marker-ring,
.data-layer-marker-core,
.data-layer-marker-wake,
.data-layer-marker-value {
  position: absolute;
  left: 50%;
  top: 50%;
}

.data-layer-marker-ring {
  width: 38px;
  height: 38px;
  border: 1px solid color-mix(in srgb, var(--marker-color, var(--accent-2)) 62%, transparent);
  border-radius: 999px;
  background:
    radial-gradient(circle, color-mix(in srgb, var(--marker-color, var(--accent-2)) 18%, transparent) 0 32%, transparent 62%);
  transform: translate(-50%, -50%) scale(0.8);
  animation: data-marker-pulse 2.35s ease-out infinite;
}

.data-layer-marker-core {
  display: grid;
  place-items: center;
  width: 25px;
  height: 25px;
  border: 1px solid color-mix(in srgb, var(--marker-color, var(--accent-2)) 70%, white 20%);
  border-radius: 8px;
  color: #021012;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--marker-color, var(--accent-2)) 92%, white 8%), #e8ff7a);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-xs);
  font-weight: 900;
  transform: translate(-50%, -50%);
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--marker-color, var(--accent-2)) 16%, transparent),
    0 0 20px color-mix(in srgb, var(--marker-color, var(--accent-2)) 38%, transparent);
}

.data-layer-marker-wake {
  width: 34px;
  height: 4px;
  border-radius: 999px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--marker-color, var(--accent-2)) 72%, transparent), transparent);
  opacity: 0.7;
  transform: translate(-50%, -50%);
  animation: data-marker-wake 1.7s ease-in-out infinite;
}

.data-layer-marker-value {
  min-width: 24px;
  padding: 1px 5px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 999px;
  color: rgba(237, 248, 248, 0.9);
  background: rgba(3, 10, 13, 0.82);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.56rem;
  font-weight: 800;
  text-align: center;
  transform: translate(-50%, 15px);
}

.data-layer-marker-argo .data-layer-marker-core,
.data-layer-marker-array .data-layer-marker-core {
  border-radius: 999px;
}

.data-layer-marker-glider .data-layer-marker-core,
.data-layer-marker-flow .data-layer-marker-core {
  border-radius: 6px;
  transform: translate(-50%, -50%) rotate(45deg);
}

.data-layer-marker-glider .data-layer-marker-core,
.data-layer-marker-flow .data-layer-marker-core {
  font-size: 0.62rem;
}

.data-layer-marker-buoy .data-layer-marker-core,
.data-layer-marker-seamark .data-layer-marker-core {
  background:
    linear-gradient(180deg, #e8ff7a 0 48%, color-mix(in srgb, var(--marker-color, var(--accent-2)) 88%, #ffffff 12%) 50% 100%);
}

.data-layer-marker-bio .data-layer-marker-ring {
  border-style: dashed;
}

@keyframes data-marker-pulse {
  0% {
    opacity: 0.78;
    transform: translate(-50%, -50%) scale(0.65);
  }
  72% {
    opacity: 0.16;
    transform: translate(-50%, -50%) scale(1.28);
  }
  100% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(1.42);
  }
}

@keyframes data-marker-wake {
  0%,
  100% {
    opacity: 0.34;
    transform: translate(-58%, -50%) scaleX(0.7);
  }
  50% {
    opacity: 0.78;
    transform: translate(-42%, -50%) scaleX(1.08);
  }
}

.map-status {
  position: relative;
  z-index: 5;
  padding: 0 16px 14px;
  color: var(--muted);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.78rem;
}

/* The status strip is a transient toast Ã¢â‚¬â€ when setStatus clears it, keep it
   off the map edge regardless of the display rules above. */
#map-status[hidden] {
  display: none !important;
}

.context-drawer {
  position: absolute;
  top: 16px;
  right: 16px;
  bottom: 16px;
  z-index: 70;
  width: min(440px, calc(100% - 32px));
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  gap: 12px;
  min-height: 0;
  padding: 14px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 24px;
  background:
    radial-gradient(circle at 0% 0%, rgba(50, 208, 189, 0.16), transparent 32%),
    rgba(7, 16, 20, 0.82);
  box-shadow: 0 28px 90px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(22px);
  animation: context-drawer-in 180ms ease-out both;
}

.context-drawer-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
}

.context-drawer-head h2 {
  /* Was clamp(1.2rem, 2.2vw, 1.85rem) — 30px+ font wrapped station
     labels like "San Diego tide and met station" to 3 lines, pushing
     the head to 142px. Cap smaller so labels stay 1-2 lines. */
  margin-bottom: 2px;
  font-size: clamp(1rem, 1.4vw, 1.25rem);
  line-height: 1.2;
}
.context-drawer-head .eyebrow {
  margin: 0;
  font-size: 10px;
}
.context-drawer-head .muted {
  margin-top: 0;
  font-size: var(--fs-sm);
}

.context-drawer-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.context-drawer-body {
  display: grid;
  gap: 12px;
  min-height: 0;
  overflow: auto;
  padding-right: 2px;
}

.context-drawer .map-viz-dock,
body[data-route="observe"] .context-drawer .map-viz-dock {
  position: static;
  z-index: auto;
  width: auto;
  max-height: none;
  overflow: visible;
  padding: 14px;
  border-radius: 18px;
  background: var(--panel-soft);
  box-shadow: none;
  backdrop-filter: none;
}

.context-drawer .map-viz-dock.is-collapsed {
  width: auto;
}

@keyframes context-drawer-in {
  from {
    opacity: 0;
    transform: translateX(18px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.side-panel {
  position: relative;
  z-index: 6;
  grid-area: side;
  display: grid;
  gap: 12px;
  align-content: start;
  min-height: 0;
  max-height: 100%;
  overflow: auto;
  padding: 14px;
}

.hardware-feed-list {
  display: grid;
  gap: 9px;
}

.hardware-card {
  display: grid;
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 15px;
  background: rgba(255, 255, 255, 0.04);
}

.hardware-card header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.hardware-card strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hardware-card-actions,
.section-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 7px;
}

.hardware-card-actions {
  justify-content: stretch;
}

.hardware-card-actions .button {
  flex: 1 1 92px;
}

.hardware-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.hardware-metrics span {
  padding: 4px 7px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  font-size: var(--fs-sm);
  font-weight: 700;
}

.panel-section,
.insight-card {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel-soft);
}

.section-row,
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
}
/* Compact the page-head eyebrow + h2 chrome — the picker dropdown
   already shows what page you're on, and on community pages the nav
   button highlight is the indicator. Tighter line-height + smaller
   bottom margin saves ~20px per page. */
.page-head h2 { margin: 2px 0 0; }
.page-head .eyebrow { margin-bottom: 0; }
.page-head > p.muted { margin-top: 4px; font-size: 0.78rem; }

/* Hide the live-tile-icon — it was always an emoji ("📊") and contributed
   nothing once we strip emoji elsewhere. The category-colored left
   border + label + value carry the same identity signal. */
.live-tile-icon:empty,
.live-tile-icon { display: none; }

/* Helper paragraphs in section-row chrome explain what a section does
   ("Stand up the physical gateway...", "Save your paid-account ngrok
   authtoken...", "AI-assisted research notes..."). Once the user has
   landed on the right section they don't need a paragraph telling
   them what it's for. Hide them globally — surfaces with truly
   essential context can opt back in with .keep-helper-text. */
section.system-check-panel > p.muted:not(.keep-helper-text):not([id]),
section.report-panel > p.muted:not(.keep-helper-text):not([id]),
.community-shell > p.muted:not(.keep-helper-text):not([id]),
.community-shell + p.muted:not(.keep-helper-text):not([id]) {
  display: none;
}

.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 28px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.78rem;
  font-weight: 700;
}

.pill.ok {
  color: #ccffe1;
  background: rgba(85, 211, 138, 0.14);
  border-color: rgba(85, 211, 138, 0.28);
}

.pill.warn {
  color: #ffe0b4;
  background: rgba(246, 177, 94, 0.14);
  border-color: rgba(246, 177, 94, 0.28);
}

.pill.bad,
.pill.planned {
  color: #ffd0d8;
  background: rgba(251, 113, 133, 0.14);
  border-color: rgba(251, 113, 133, 0.28);
}

.page-panel {
  display: none;
  min-height: 0;
  overflow: auto;
}

/* Unified floating "glass bridge" drawer: every page's content panel renders as
   the same right-docked panel over the persistent map, so pages stay consistent. */
.page-panel.is-active {
  position: absolute;
  top: 76px;
  right: 16px;
  bottom: 308px;
  z-index: 60;
  display: grid;
  /* Single content column pinned to the panel width. Without this the
     implicit grid column sizes to content and balloons whenever a child
     has wide intrinsic content (e.g. an un-wrapped file path), pushing
     the whole page off-screen. */
  grid-template-columns: minmax(0, 1fr);
  align-content: start;
  gap: 14px;
  width: min(720px, calc(100vw - 360px));
  padding: 16px;
  border: 1px solid rgba(50, 208, 189, 0.24);
  border-radius: 20px;
  background: rgba(7, 18, 24, 0.94);
  box-shadow: 0 26px 70px rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(20px);
  overflow: auto;
}

.page-head p {
  max-width: 48rem;
  margin: 0;
}

.command-snippet {
  margin: 10px 0 14px;
  padding: 12px 14px;
  overflow-x: auto;
  border: 1px solid rgba(125, 211, 252, 0.2);
  border-radius: 14px;
  color: #c9fff6;
  background: rgba(2, 8, 12, 0.62);
  font-size: 0.88rem;
  white-space: pre;
}

.workspace-tabs {
  position: sticky;
  top: -18px;
  z-index: 20;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
  gap: 8px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: rgba(6, 13, 17, 0.94);
  backdrop-filter: blur(18px);
}

.compact-tabs {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.workspace-tab {
  min-height: 42px;
  border: 1px solid var(--line);
  border-radius: 14px;
  color: var(--muted);
  background: rgba(255, 255, 255, 0.04);
  cursor: pointer;
  font-weight: 800;
}

.workspace-tab:hover,
.workspace-tab.is-active {
  color: #041312;
  border-color: transparent;
  background: linear-gradient(135deg, var(--accent), #9df6e9);
}

.community-page.is-active {
  width: min(920px, calc(100vw - 320px));
  bottom: 120px;
  /* Lay out community pages as a flex column so the inner layout grid can
     flex-grow into the available height and the detail panels can scroll
     independently instead of pushing the whole page-panel past viewport. */
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* Hide the verbose page-head on community pages — the nav button + the
   consolidated summary-strip already tell the user where they are.
   Was 49-61px per page across forum/wiki/blog/marketplace. */
.community-page > .page-head { display: none; }

/* Briefings page: the AI briefing list is the primary content. Let it
   flex-grow into available height and scroll internally so long
   briefing batches don't push the page-panel past viewport. */
#blog-briefing-list {
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
}

/* ── Briefings main grid (News Queue + Editorial Queue) ────────────────
   Two-column layout: News Queue on the left, Editorial Queue on the
   right. Both are first-class — the editorial queue is no longer hidden
   behind a details element. On a narrow viewport the columns stack. */
.blog-main-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 14px;
  margin-top: 8px;
  min-height: 0;
  flex: 1 1 auto;
}
.blog-main-col {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  padding: 10px 12px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 10px;
  background: rgba(7, 18, 24, 0.42);
}
.blog-col-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.blog-col-head h3 {
  margin: 0;
  font-size: 0.86rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #dff8ff;
}
.blog-col-sub {
  margin: 0 0 4px;
  font-size: 0.7rem;
  line-height: 1.5;
}
.blog-main-col-news .blog-briefing-list {
  /* Make the news queue scroll inside its own column so the editorial
     side stays visible at the same time. */
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding-right: 4px;
}
.blog-main-col-editorial .blog-layout {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  overflow: hidden;
}
.blog-main-col-editorial .blog-card-grid {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 200px;
  overflow-y: auto;
  padding-right: 4px;
}
.blog-main-col-editorial .blog-featured {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(163, 185, 188, 0.1);
  font-size: 0.78rem;
  line-height: 1.55;
}
@media (max-width: 980px) {
  .blog-main-grid { grid-template-columns: 1fr; }
}

/* Source catalog list (collapsed details) — every configured feed as a
   compact row showing name + kind + trust + default-enabled state, plus
   topic + note + URL. Answers "where do these items come from?". */
.blog-source-catalog { margin-top: 12px; }
.blog-source-catalog > summary {
  cursor: pointer;
  padding: 8px 12px;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 10px;
  background: rgba(125, 211, 252, 0.06);
  border: 1px solid rgba(125, 211, 252, 0.14);
  border-radius: 8px;
}
.blog-source-catalog > summary::-webkit-details-marker { display: none; }
.blog-source-catalog[open] > summary { background: rgba(125, 211, 252, 0.12); }
.blog-source-catalog-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 8px;
  padding: 10px 0 4px;
}
.blog-source-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
  font-size: var(--fs-sm);
}
.blog-source-row-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px;
}
.blog-source-row-head strong { font-size: 0.78rem; color: #dff8ff; }
.blog-source-row-head .pill { font-size: 0.58rem; padding: 2px 6px; }
.blog-source-row-head .pill.is-high { background: rgba(50, 208, 189, 0.16); color: #b8f5e8; }
.blog-source-row-head .pill.is-med  { background: rgba(255, 214, 106, 0.16); color: #ffe18a; }
.blog-source-row-head .pill.is-low  { background: rgba(239, 68, 68, 0.16); color: #fda4af; }
.blog-source-row-topic { margin: 0; font-size: 0.7rem; line-height: 1.5; color: rgba(218, 234, 240, 0.75); }
.blog-source-row-note { margin: 0; font-size: 0.66rem; line-height: 1.45; }
.blog-source-row-url {
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.62rem;
  word-break: break-all;
  color: rgba(125, 211, 252, 0.55);
}
.blog-source-row-url:hover { color: rgba(125, 211, 252, 0.9); }

/* "How this page works" explainer at the top of the Briefings page —
   short numbered list so a first-time visitor knows what the controls do
   and how to get more items into the queue. Deliberately understated
   styling so it doesn't compete with the actual data below. */
.blog-explainer {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid rgba(125, 211, 252, 0.18);
  background: linear-gradient(135deg, rgba(125, 211, 252, 0.08), rgba(50, 208, 189, 0.04));
  margin-bottom: 8px;
}
.blog-explainer > strong {
  font-size: 0.72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #dff8ff;
}
.blog-explainer-steps {
  margin: 0;
  padding-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.blog-explainer-steps li {
  font-size: 0.78rem;
  color: rgba(218, 234, 240, 0.85);
  line-height: 1.55;
}
.blog-explainer-steps strong {
  color: #eafcff;
}

/* Editorial Queue (hardcoded blog posts) is a secondary view — fold it
   behind a details summary. When opened, it gets its own scroll. */
.blog-editorial-queue { flex: 0 0 auto; }
.blog-editorial-queue > summary {
  cursor: pointer;
  padding: 6px 4px;
  list-style: none;
}
.blog-editorial-queue > summary::-webkit-details-marker { display: none; }
.blog-editorial-queue[open] > summary { color: var(--accent); }
.blog-editorial-queue[open] .blog-layout {
  max-height: 360px;
  overflow: auto;
}

.community-shell,
.knowledge-layout,
.blog-layout,
.marketplace-layout {
  display: grid;
  gap: 12px;
  min-width: 0;
  /* Flex-grow into remaining viewport height after the summary-strip and
     outcome chips, then let inner panels scroll. */
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
}

.forum-shell {
  grid-template-columns: minmax(150px, 0.8fr) minmax(220px, 1.1fr) minmax(260px, 1.4fr);
}

.knowledge-layout,
.blog-layout,
.marketplace-layout {
  grid-template-columns: minmax(240px, 0.9fr) minmax(300px, 1.3fr);
  /* Single row that takes all available height but clips to 1fr — child
     panels then internally scroll instead of overflowing. */
  grid-template-rows: minmax(0, 1fr);
}

.forum-shell {
  grid-template-rows: minmax(0, 1fr);
}

.community-rail,
.community-list-panel,
.community-detail-panel,
.knowledge-detail,
.blog-featured,
.bounty-detail-panel {
  min-width: 0;
  min-height: 0;
  padding: 12px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.035);
  /* Each panel scrolls itself so long articles / message stacks don't
     push the page-panel beyond viewport. `block-size:100%` pins it to
     the grid track height so overflow:auto can actually clip. */
  block-size: 100%;
  overflow: auto;
}

.community-rail h3,
.community-list-panel h3,
.community-detail h3,
.knowledge-detail h3,
.blog-featured h3 {
  margin: 0;
}

.community-toolbar {
  display: grid;
  grid-template-columns: minmax(220px, 1fr) minmax(180px, 0.4fr);
  gap: 10px;
  align-items: end;
}

/* Collapsible community composers (Marketplace "Post a listing", Wiki "New page"). */
.marketplace-composer,
.community-composer {
  border: 1px solid rgba(120, 150, 170, 0.25);
  border-radius: 12px;
  padding: 4px 12px;
  margin-bottom: 12px;
  background: rgba(12, 24, 32, 0.35);
}
.marketplace-composer > summary,
.community-composer > summary {
  cursor: pointer;
  padding: 8px 2px;
  font-weight: 600;
  list-style: none;
}
.marketplace-composer[open] > summary,
.community-composer[open] > summary { margin-bottom: 8px; }
.marketplace-composer-body,
.community-composer-body { display: flex; flex-direction: column; gap: 10px; padding-bottom: 10px; }
.marketplace-composer-row,
.community-composer-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px;
}
.marketplace-composer-actions,
.community-composer-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.marketplace-composer textarea,
.community-composer textarea { width: 100%; resize: vertical; font-family: inherit; }
.wiki-doc-actions { display: flex; gap: 8px; margin-top: 10px; }
.bbs-mod-danger { color: #fb7185; border-color: rgba(251, 113, 133, 0.4); }
.bbs-mod-danger:hover { background: rgba(251, 113, 133, 0.15); }

.community-channel-list,
.community-thread-list,
.knowledge-list,
.blog-card-grid,
.bounty-list,
.message-stack {
  display: grid;
  gap: 8px;
}

.community-channel,
.community-thread,
.knowledge-list-item,
.blog-card,
.bounty-card {
  display: grid;
  gap: 5px;
  min-width: 0;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 12px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.035);
  text-align: left;
  cursor: pointer;
}

.community-channel {
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
}

.community-channel > span:not(.community-channel-hash) {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.community-channel:hover,
.community-thread:hover,
.knowledge-list-item:hover,
.blog-card:hover,
.bounty-card:hover,
.community-channel.is-active,
.community-thread.is-active,
.knowledge-list-item.is-active,
.blog-card.is-active,
.bounty-card.is-active {
  border-color: rgba(50, 208, 189, 0.36);
  background: rgba(50, 208, 189, 0.09);
}

.community-channel strong,
.community-thread strong,
.knowledge-list-item strong,
.blog-card strong,
.bounty-card strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.community-channel small,
.community-thread small,
.knowledge-list-item small,
.blog-card small,
.bounty-card small,
.community-channel span span,
.community-thread span,
.knowledge-list-item span,
.blog-card span,
.bounty-card span {
  color: var(--muted);
  font-size: 0.76rem;
  line-height: 1.35;
}

.community-channel-hash {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border: 1px solid rgba(125, 211, 252, 0.2);
  border-radius: 8px;
  color: var(--accent);
  font-weight: 900;
}

.community-channel b {
  min-width: 24px;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(7, 16, 20, 0.72);
  color: var(--ink);
  font-size: var(--fs-xs);
  text-align: center;
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.mini-tag {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0 7px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 999px;
  color: rgba(218, 234, 240, 0.84);
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.66rem;
  font-weight: 800;
}

.community-detail {
  display: grid;
  gap: 10px;
  min-width: 0;
}

.community-detail-head {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  justify-content: space-between;
}

.forum-message {
  display: grid;
  grid-template-columns: 32px minmax(0, 1fr);
  gap: 10px;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 12px;
  background: rgba(3, 10, 13, 0.42);
}

.forum-avatar {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--accent), #7dd3fc);
  color: #041312;
  font-weight: 900;
}

.forum-message p {
  margin: 0 0 4px;
}

.forum-message p span {
  color: var(--muted);
  font-size: 0.72rem;
}

.forum-composer {
  display: grid;
  gap: 8px;
  margin-top: 10px;
}

.forum-composer textarea {
  resize: vertical;
  min-height: 82px;
}

.knowledge-step-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding-left: 18px;
  color: rgba(218, 234, 240, 0.86);
}

body[data-page="wiki"] .page-panel.is-active {
  /* Wiki keeps its scroll behavior; background gets a translucent dark tone
     so the map shows faintly through. The position/size rules in the
     map-backed section above take precedence. */
  overflow: auto;
}

body[data-page="wiki"] .page-head {
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.16);
}

body[data-page="wiki"] .knowledge-layout {
  grid-template-columns: minmax(280px, 0.34fr) minmax(0, 1fr);
  align-items: start;
}

body[data-page="wiki"] .knowledge-list {
  position: sticky;
  top: 0;
  align-content: start;
  max-height: calc(100vh - 306px);
  overflow: auto;
  padding-right: 6px;
}

body[data-page="wiki"] .knowledge-list-item,
body[data-page="wiki"] .knowledge-detail {
  border-radius: 8px;
}

body[data-page="wiki"] .knowledge-list-item {
  border-color: rgba(163, 185, 188, 0.13);
  background: rgba(255, 255, 255, 0.025);
}

body[data-page="wiki"] .knowledge-list-item.is-active {
  border-left: 3px solid var(--accent);
  background: rgba(50, 208, 189, 0.08);
}

body[data-page="wiki"] .knowledge-list-item strong {
  white-space: normal;
}

.wiki-doc-page {
  display: grid;
  gap: 16px;
  min-width: 0;
}

.wiki-doc-header {
  display: grid;
  gap: 7px;
  padding-bottom: 12px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.14);
}

.wiki-doc-header h3 {
  font-size: clamp(1.35rem, 2vw, 2rem);
  line-height: 1.12;
}

.wiki-article-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.wiki-article-meta span,
.wiki-doc-index span {
  padding: 3px 7px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 6px;
  color: rgba(218, 234, 240, 0.82);
  background: rgba(255, 255, 255, 0.035);
  font-size: var(--fs-xs);
  font-weight: 800;
}

.wiki-doc-index {
  display: grid;
  gap: 8px;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}

.wiki-doc-index strong {
  color: rgba(236, 248, 250, 0.94);
  font-size: var(--fs-sm);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.wiki-doc-index div {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.wiki-article-body {
  display: grid;
  gap: 16px;
  min-width: 0;
  color: rgba(218, 234, 240, 0.88);
}

.wiki-lead,
.wiki-paragraph,
.wiki-callout p {
  margin: 0;
  line-height: 1.62;
}

.wiki-lead {
  padding: 12px 14px;
  border-left: 3px solid var(--accent);
  background: rgba(50, 208, 189, 0.08);
  color: rgba(236, 248, 250, 0.94);
}

.wiki-section-heading {
  margin: 8px 0 0;
  color: rgba(236, 248, 250, 0.96);
  font-size: 1rem;
  letter-spacing: 0;
}

.wiki-step-list,
.wiki-bullet-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding-left: 20px;
  line-height: 1.54;
}

.wiki-metric-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}

.wiki-metric {
  display: grid;
  gap: 4px;
  min-width: 0;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}

.wiki-metric strong {
  color: var(--accent);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-md);
}

.wiki-metric span {
  color: rgba(236, 248, 250, 0.9);
  font-size: 0.76rem;
  font-weight: 900;
}

.wiki-metric small,
.wiki-bar-row small,
.wiki-code-block figcaption small,
.wiki-bar-chart figcaption small,
.wiki-line-chart figcaption small {
  color: var(--muted);
  font-size: var(--fs-xs);
}

.wiki-flow-diagram,
.wiki-picture,
.wiki-code-block,
.wiki-bar-chart,
.wiki-line-chart,
.wiki-callout {
  margin: 0;
  min-width: 0;
}

.wiki-flow-diagram,
.wiki-picture,
.wiki-code-block,
.wiki-bar-chart,
.wiki-line-chart {
  display: grid;
  gap: 9px;
}

.wiki-flow-diagram figcaption,
.wiki-picture figcaption,
.wiki-code-block figcaption,
.wiki-bar-chart figcaption,
.wiki-line-chart figcaption {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: space-between;
  color: rgba(236, 248, 250, 0.9);
  font-size: 0.75rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.wiki-picture {
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}

.wiki-picture figcaption {
  align-items: flex-start;
  text-transform: none;
  letter-spacing: 0;
}

.wiki-picture figcaption span {
  color: rgba(236, 248, 250, 0.94);
  font-size: var(--fs-base);
  font-weight: 900;
}

.wiki-picture figcaption small {
  max-width: 58ch;
  color: var(--muted);
  font-size: 0.72rem;
  line-height: 1.45;
  text-align: right;
}

.wiki-picture-canvas {
  overflow: hidden;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 8px;
  background: #031014;
}

.wiki-picture-canvas svg {
  display: block;
  width: 100%;
  height: auto;
}

.wiki-picture-canvas rect {
  fill: #041115;
}

.wiki-picture-water {
  fill: rgba(50, 208, 189, 0.12);
}

.wiki-picture-coast,
.wiki-picture-line {
  fill: none;
  stroke: var(--wiki-picture-accent, var(--accent));
  stroke-linecap: round;
  stroke-width: 3;
}

.wiki-picture-coast {
  opacity: 0.7;
}

.wiki-picture-line {
  opacity: 0.86;
}

.wiki-picture-grid {
  fill: none;
  opacity: 0.22;
  stroke: rgba(218, 234, 240, 0.42);
  stroke-width: 1;
}

.wiki-picture-orbit {
  fill: rgba(125, 211, 252, 0.07);
  stroke: rgba(218, 234, 240, 0.24);
  stroke-width: 2;
}

.wiki-picture-node circle {
  fill: rgba(3, 16, 20, 0.9);
  stroke: var(--wiki-picture-accent, var(--accent));
  stroke-width: 2;
}

.wiki-picture-node text,
.wiki-picture-badge text,
.wiki-picture-caption {
  fill: rgba(236, 248, 250, 0.94);
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 14px;
  font-weight: 900;
}

.wiki-picture-badge rect {
  fill: rgba(255, 255, 255, 0.08);
  stroke: rgba(236, 248, 250, 0.2);
}

.wiki-picture-caption {
  fill: rgba(218, 234, 240, 0.68);
  font-size: 18px;
  font-weight: 700;
}

.wiki-flow-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(126px, 1fr));
  gap: 8px;
}

.wiki-flow-step {
  position: relative;
  display: grid;
  gap: 4px;
  min-height: 74px;
  padding: 10px;
  border: 1px solid rgba(125, 211, 252, 0.18);
  border-radius: 8px;
  background: rgba(125, 211, 252, 0.055);
}

.wiki-flow-step b {
  color: rgba(236, 248, 250, 0.94);
  font-size: 0.78rem;
}

.wiki-flow-step span {
  color: var(--muted);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.66rem;
}

.wiki-table-wrap {
  min-width: 0;
  overflow-x: auto;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
}

.wiki-table-title {
  padding: 9px 10px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.1);
  color: rgba(236, 248, 250, 0.92);
  background: rgba(255, 255, 255, 0.025);
  font-size: 0.75rem;
  font-weight: 900;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.wiki-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
}

.wiki-table th,
.wiki-table td {
  padding: 9px 10px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.1);
  color: rgba(218, 234, 240, 0.86);
  font-size: 0.76rem;
  line-height: 1.44;
  text-align: left;
  vertical-align: top;
}

.wiki-table th {
  color: rgba(236, 248, 250, 0.95);
  background: rgba(125, 211, 252, 0.07);
  font-weight: 900;
}

.wiki-code-block {
  overflow: hidden;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: #040b0e;
}

.wiki-code-block figcaption {
  padding: 9px 11px 0;
}

.wiki-code-block pre {
  max-width: 100%;
  margin: 0;
  padding: 11px;
  overflow: auto;
  color: rgba(236, 248, 250, 0.94);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.73rem;
  line-height: 1.5;
  white-space: pre;
}

.wiki-callout {
  padding: 11px;
  border: 1px solid rgba(246, 177, 94, 0.24);
  border-radius: 8px;
  background: rgba(246, 177, 94, 0.07);
}

.wiki-callout strong {
  display: block;
  margin-bottom: 5px;
  color: #f9d594;
}

.wiki-bar-chart,
.wiki-line-chart {
  padding: 11px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}

.wiki-bar-stack {
  display: grid;
  gap: 9px;
}

.wiki-bar-row {
  display: grid;
  grid-template-columns: minmax(120px, 0.42fr) minmax(140px, 1fr) auto;
  gap: 8px;
  align-items: center;
}

.wiki-bar-row > span {
  color: rgba(236, 248, 250, 0.9);
  font-size: 0.75rem;
  font-weight: 800;
}

.wiki-bar-row > b {
  color: var(--accent);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.76rem;
}

.wiki-bar-row small {
  grid-column: 2 / -1;
}

.wiki-bar-track {
  height: 9px;
  overflow: hidden;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 999px;
  background: rgba(3, 10, 13, 0.78);
}

.wiki-bar-track i {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--accent), #7dd3fc);
}

.wiki-line-chart svg {
  width: 100%;
  height: auto;
  min-height: 180px;
}

.wiki-chart-gridline {
  fill: none;
  stroke: rgba(163, 185, 188, 0.14);
  stroke-width: 1;
}

.wiki-line-path {
  fill: none;
  stroke: #7dd3fc;
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.wiki-line-dot {
  fill: var(--accent);
  stroke: #041312;
  stroke-width: 2;
}

.wiki-line-chart text {
  fill: var(--muted);
  font-family: "IBM Plex Sans", sans-serif;
  font-size: 18px;
}

.blog-card-grid,
.bounty-list {
  align-content: start;
}

.blog-featured,
.bounty-detail-panel {
  display: grid;
  gap: 12px;
  align-content: start;
}

.bounty-meta-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.bounty-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

@media (max-width: 1100px) {
  .forum-shell,
  .knowledge-layout,
  .blog-layout,
  .marketplace-layout,
  .community-toolbar {
    grid-template-columns: minmax(0, 1fr);
  }

  body[data-page="wiki"] .knowledge-layout,
  .wiki-metric-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  body[data-page="wiki"] .knowledge-list {
    position: static;
    max-height: none;
  }

  .wiki-bar-row {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .wiki-bar-track,
  .wiki-bar-row small {
    grid-column: 1 / -1;
  }

  .wiki-picture figcaption {
    display: grid;
    gap: 5px;
  }

  .wiki-picture figcaption small {
    max-width: none;
    text-align: left;
  }
}

.summary-strip {
  /* Was 4 fixed columns x 82h tall — each stat box dedicated ~21,000sq
     pixels to display one number plus a redundant subtitle. Switch to
     auto-fill compact rows so labels read across naturally, like a
     readout strip rather than a dashboard of giant tiles. */
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
  gap: 6px;
}

.summary-strip.vertical {
  /* For narrow dock panels: 2 columns instead of 1 so 4-6 stats don't
     stack 500px tall. Falls back to 1 column on really narrow widths. */
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 6px;
}
/* Tighter stat layout when in a vertical/narrow dock panel: smaller
   strong font + thinner padding so 5 stats fit in ~50px each instead
   of ~82px. Mesh rail's mesh-summary uses this. */
.summary-strip.vertical .stat,
.summary-strip.vertical .kpi {
  padding: 6px 9px;
  gap: 0px;
}
.summary-strip.vertical .stat span,
.summary-strip.vertical .kpi span {
  font-size: 0.66rem;
  letter-spacing: 0.06em;
}
.summary-strip.vertical .stat strong,
.summary-strip.vertical .kpi strong {
  font-size: 1.05rem;
  line-height: 1.1;
}
.summary-strip.vertical .stat small,
.summary-strip.vertical .kpi small {
  font-size: 0.66rem;
  line-height: 1.15;
}

.source-card,
.layer-card,
.metric-card {
  min-width: 0;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.04);
}
.stat,
.kpi {
  min-width: 0;
  /* Smaller radius + lighter chrome than full source-cards so the stat
     row reads as a readout strip, not a row of dashboard tiles. */
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}

.stat,
.kpi {
  /* Was a 82h dashboard tile dedicated to ONE number. Now an inline
     "LABEL value subtitle" readout — each stat takes ~32-44h with the
     same information but stops shouting. */
  display: grid;
  grid-template-columns: auto;
  align-items: baseline;
  gap: 0;
  padding: 6px 10px;
}

.stat span,
.kpi span {
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1.1;
}

.stat strong,
.kpi strong {
  /* Was clamp(1.25rem, 2vw, 2rem) — 32px font dwarfed the rest of the
     panel for a single integer. Cap to 1.1rem; the data is still the
     most prominent element in the box but doesn't shout. */
  font-size: 1.1rem;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
  /* Clamp very long string values to at most 2 lines so one rogue
     "Selected: T-Beam Supreme LoRa RX + onboard telemetry" can't
     blow the summary strip from 32h to 130h. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* Redundant "Project rooms" / "Open discussions" subtitles under
   every stat are filler that don't add meaning beyond the label
   above the number. Hide them unless the stat is in a sparse layout
   (e.g. a stand-alone hero card) explicitly opts in with
   .stat.has-detail. */
.stat small,
.kpi small {
  display: none;
}
.stat.has-detail small,
.kpi.has-detail small {
  display: block;
  font-size: 0.66rem;
  color: var(--muted);
  margin-top: 1px;
}

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.kpi-grid.compact .kpi strong {
  font-size: var(--fs-lg);
}

/* Inside the map station-context drawer, .kpi-grid duplicates the
   metric-list directly below it (Water temperature 21 deg C is in
   BOTH places — kpi card AND Sea State group). The metric-list has
   richer info (timestamps, grouped by Sea State / Air & Pressure /
   Other Sensor Readings), so the 2x2 kpi-grid is redundant chrome.
   Hide it to give the drawer back ~100h for the chart preview. */
#context-drawer .panel-section > .kpi-grid.compact { display: none; }

.metric-list,
.table-shell,
.source-grid,
.layer-list {
  display: grid;
  gap: 8px;
}

.metric-item,
.table-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 10px 0;
  border-bottom: 1px solid rgba(163, 185, 188, 0.1);
}

.metric-item:last-child,
.table-row:last-child {
  border-bottom: 0;
}

.metric-item strong,
.table-row strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.metric-item span,
.table-row span {
  color: var(--muted);
  font-size: var(--fs-base);
}

.telemetry-group {
  display: grid;
  gap: 4px;
  padding: 6px 0 8px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.1);
}

.telemetry-group:last-child {
  border-bottom: 0;
}

.telemetry-group h4 {
  margin: 0;
  color: var(--accent-2);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.telemetry-readings {
  display: grid;
  gap: 4px;
}

.telemetry-reading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 6px 10px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.035);
}

.telemetry-reading div {
  display: grid;
  min-width: 0;
  gap: 3px;
}

.telemetry-reading strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.telemetry-reading span {
  color: var(--muted);
  font-size: 0.78rem;
}

.telemetry-reading b {
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: 1rem;
  white-space: nowrap;
}

.mini-chart {
  min-height: 180px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    rgba(3, 10, 13, 0.5);
  background-size: 42px 42px;
  overflow: hidden;
}

.visualization-workbench {
  display: grid;
  grid-template-columns: minmax(196px, 224px) minmax(0, 1fr);
  grid-template-areas:
    "ctxbar  ctxbar"
    "hero    hero"
    "palette controls"
    "palette stage";
  grid-template-rows: auto auto auto minmax(0, 1fr);
  /* Hard-cap the workbench so the page doesn't grow with the recipe
     rail. The internal scroll handles overflow without pushing the
     parent .page-panel.is-active past its viewport. */
  height: min(74vh, 720px);
  max-height: min(74vh, 720px);
  overflow-y: auto;
  gap: 14px;
  padding: 18px;
  border: 1px solid rgba(50, 208, 189, 0.22);
  border-radius: 24px;
  background:
    linear-gradient(135deg, rgba(50, 208, 189, 0.1), transparent 42%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.025)),
    rgba(2, 9, 12, 0.82);
}

.viz-hero {
  grid-area: hero;
}

.viz-hero {
  /* Single-row layout: title block on the left, action buttons on the
     right. Title block has a generous min-width so the H3 doesn't get
     squeezed to 140px and wrap to 4 lines when viz-actions has 5
     buttons. */
  display: grid;
  gap: 12px;
  grid-template-columns: minmax(280px, 1fr) auto;
  align-items: start;
}

.viz-stage {
  display: grid;
  gap: 14px;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
}

.viz-hero h3 {
  margin: 0;
  /* Was clamp(1.4rem, 2vw, 2.15rem) — 28-34px font when forced narrow
     pushed the title to 4-line wrap. Cap smaller so it stays single-row. */
  font-size: clamp(1rem, 1.4vw, 1.4rem);
  line-height: 1.2;
}

.viz-hero p {
  margin: 2px 0 0;
  /* Hide the descriptive blurb on the chart builder — user is already
     here, doesn't need to be told "pick a visual, choose a metric". */
  display: none;
}

.viz-hero .eyebrow { margin: 0; }

/* Numbered workflow guidance — sits where the descriptive paragraph
   used to. Operator sees: 1. Try a recipe, 2. Or build manually, 3.
   Render → Pin → Export. The numbers make the sequence unmistakable.
   Used on Chart Builder + Inspect + any other builder/lab panel that
   wants to teach the workflow. */
.viz-workflow,
.workflow-steps {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  padding: 0;
  margin: 4px 0 0;
  list-style: none;
  counter-reset: viz-step;
  font-size: 12px;
}
.viz-workflow li,
.workflow-steps li {
  counter-increment: viz-step;
  position: relative;
  padding-left: 22px;
  line-height: 1.35;
}
.viz-workflow li::before,
.workflow-steps li::before {
  content: counter(viz-step);
  position: absolute;
  left: 0;
  top: 0;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.40), rgba(50, 208, 189, 0.35));
  color: #fff;
  font-weight: 700;
  font-size: 11px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 0 0 1px rgba(196, 181, 253, 0.30);
}
.viz-workflow strong,
.workflow-steps strong { color: var(--ink); font-weight: 600; }

.viz-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
  max-width: 100%;
}

/* Graphs:builder Stats panel folds behind a summary by default so the
   chart builder gets full vertical space. User can click to expand
   when they want summary/outliers. */
.stats-panel-fold > summary {
  cursor: pointer;
  padding: 6px 8px;
  list-style: none;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
}
.stats-panel-fold > summary::-webkit-details-marker { display: none; }
.stats-panel-fold[open] > summary { color: var(--accent); margin-bottom: 6px; }
.stats-panel-fold[open] > summary {
  background: rgba(50, 208, 189, 0.06);
}
/* .report-panel uses { display: grid }, which silently overrides the
   UA stylesheet rule that hides non-summary children of a closed
   <details>. Force the stats-panel section to honor the closed state
   so the 338h Stats card actually folds away when the user collapses it. */
.stats-panel-fold:not([open]) > section.report-panel { display: none; }
.stats-panel-fold:not([open]) > .panel-context-bar,
.stats-panel-fold:not([open]) > .floating-collapse-btn,
.stats-panel-fold:not([open]) > .floating-drag-handle { display: none; }

/* Same UA-override bug strikes other folds whose children use
   display:grid (.gateway-runtime-list, .halow-step-list, etc). When a
   <details> is closed, hide every non-summary child regardless of
   what display they ask for. */
details:not([open]) > *:not(summary):not(style):not(script) {
  display: none !important;
}

/* Items without explicit grid-area inside .visualization-workbench
   need to span the full grid width — the workbench is a 2-column grid
   (palette | controls/stage), and an unstyled child would land in
   column 1 only (or worse, collide with palette/stage). Span all of
   them to the full width so the recipe rail and folds read as
   page-wide bands, not 1-col strips. */
.visualization-workbench > .recipe-rail,
.visualization-workbench > .viz-toggles,
.visualization-workbench > .viz-examples-fold,
.visualization-workbench > .stats-panel-fold {
  grid-column: 1 / -1;
}

/* Example-workflows fold styling — friendly card with numbered
   examples that show real operator use-cases. Hidden behind a summary
   so it doesn't crowd the chart, but discoverable for new users. Used
   on both .viz-examples-fold (Analyze) and .usage-examples-fold (Data
   page Inspect) — same look, different placement. */
.viz-examples-fold > summary,
.usage-examples-fold > summary {
  cursor: pointer;
  padding: 6px 10px;
  list-style: none;
  border-radius: 8px;
  background: rgba(245, 158, 11, 0.06);
  border: 1px dashed rgba(245, 158, 11, 0.25);
}
.viz-examples-fold > summary::-webkit-details-marker,
.usage-examples-fold > summary::-webkit-details-marker { display: none; }
.viz-examples-fold[open] > summary,
.usage-examples-fold[open] > summary { background: rgba(245, 158, 11, 0.12); color: #fbbf24; }
.viz-examples-list,
.usage-examples-list {
  margin: 8px 0 0;
  padding: 12px 14px 12px 32px;
  border-left: 3px solid rgba(245, 158, 11, 0.35);
  background: rgba(255, 255, 255, 0.02);
  border-radius: 0 8px 8px 0;
  font-size: 13px;
  line-height: 1.55;
}
.viz-examples-list li,
.usage-examples-list li { margin-bottom: 8px; }
.viz-examples-list li:last-child,
.usage-examples-list li:last-child { margin-bottom: 0; }
.viz-examples-list strong,
.usage-examples-list strong { color: var(--accent); font-weight: 600; }
.viz-examples-list em,
.usage-examples-list em { color: #fbbf24; font-style: normal; font-weight: 600; }

.viz-tool-grid {
  grid-area: palette;
  display: grid;
  /* Was single 1fr column — 12 viz tools at ~50h each = 600h vertical,
     overflowed the ~298h palette slot. Now 2 columns of 1fr (cards
     ~100px wide each); 12 tools fit in 6 rows × ~50h = ~310h, almost
     exactly the palette slot. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: max-content;
  align-content: start;
  gap: 6px;
  min-height: 0;
  overflow-y: auto;
}

.viz-tool-group-label {
  grid-column: 1 / -1;
  margin-top: 4px;
  padding-bottom: 2px;
  border-bottom: 1px solid var(--line);
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.viz-tool-group-label:first-child {
  margin-top: 0;
}

.viz-tool {
  display: grid;
  gap: 2px;
  min-height: 0;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.04);
  cursor: pointer;
  text-align: left;
  transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}
.viz-tool strong {
  font-size: 12.5px;
  line-height: 1.15;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.viz-tool:hover,
.viz-tool:focus,
.viz-tool.is-active {
  transform: translateY(-1px);
  border-color: rgba(50, 208, 189, 0.54);
  background: rgba(50, 208, 189, 0.1);
}

.viz-tool span {
  color: var(--muted);
  font-size: 10.5px;
  line-height: 1.15;
  /* Clamp to 1 line; 2-col palette wraps "Station Bars / Compare a
     metric across devices" to 3 lines otherwise. */
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.viz-controls {
  grid-area: controls;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
}

.viz-stage {
  grid-area: stage;
  grid-template-columns: minmax(0, 1fr) minmax(260px, 0.28fr);
  align-items: stretch;
}

.visualization-canvas {
  min-height: 240px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background:
    linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
    rgba(1, 7, 10, 0.72);
  background-size: 44px 44px;
  overflow: auto;
}

.viz-inspector {
  display: grid;
  gap: 8px;
  align-content: start;
  /* min-height: 220px forced this aside to overflow its 152h parent
     grid row by 68px. Drop the floor so the inspector matches the
     stage row; any extra context scrolls internally. */
  min-height: 0;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.035);
  overflow: auto;
}
.viz-inspector h4 { font-size: 12.5px; }
.viz-inspector p { font-size: 11.5px; line-height: 1.3; }

.viz-inspector h4,
.viz-inspector p {
  margin: 0;
}

.viz-inspector-body {
  display: grid;
  gap: 10px;
}

.viz-table {
  display: grid;
  gap: 6px;
  min-width: 720px;
}

.viz-table-row {
  display: grid;
  grid-template-columns: 1.4fr 1fr 0.8fr 0.7fr 1fr;
  gap: 10px;
  align-items: center;
  min-height: 42px;
  padding: 9px 10px;
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
}

.viz-table-row.is-heading {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.viz-table-row span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* === Data + Analyze: floating panels over the persistent map ===
   The map-plane is kept visible behind these two pages so the page-panel
   can render as floating glass cards anchored top-left. Other content
   pages (settings, hardware, forum, wiki, blog, marketplace) keep the
   classic full-screen content surface with the map hidden. */
/* Map-backed everywhere: the Leaflet/Cesium map stays visible behind every
   page. Each page-panel becomes a floating workspace that sits on top of
   the map (left-anchored, with the map showing through on the right).
   The map is the unifying canvas — operators never lose spatial context. */
/* (Removed: `display: block` was collapsing .map-stage to 0 height — the
   map-plane needs its base `display: grid` + auto/1fr/auto/auto rows so the
   map-stage gets the 1fr slot. Keeping it grid lets the world raster
   actually render behind the floating panel.) */

body[data-page="settings"] .page-panel.is-active,
body[data-page="hardware"] .page-panel.is-active,
body[data-page="forum"] .page-panel.is-active,
body[data-page="wiki"] .page-panel.is-active,
body[data-page="blog"] .page-panel.is-active,
body[data-page="marketplace"] .page-panel.is-active {
  /* Floating panel anchored left, leaving the right ~30% open for the map.
     Background opacity tuned so the world raster + station markers stay
     visible behind the panel — the panel feels like a card floating over
     the operational mission view rather than a separate page. We use a
     subtle gradient (denser at the top, fading slightly down) so the
     panel's left edge feels grounded while still letting the map breathe
     through the body. */
  position: absolute;
  top: 70px;
  left: 16px;
  right: 16px;
  bottom: 16px;
  width: auto;
  max-height: calc(100vh - 86px);
  overflow-y: auto;
  background: linear-gradient(180deg, rgba(3, 10, 13, 0.78), rgba(3, 10, 13, 0.58));
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 16px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(6px) saturate(1.05);
  -webkit-backdrop-filter: blur(6px) saturate(1.05);
}

/* The map plane is BEHIND the panel — make sure it sizes to the full viewport
   on every page so it isn't constrained by the previous full-screen-panel
   layout assumption. */
body[data-page="settings"] .map-plane,
body[data-page="hardware"] .map-plane,
body[data-page="forum"] .map-plane,
body[data-page="wiki"] .map-plane,
body[data-page="blog"] .map-plane,
body[data-page="marketplace"] .map-plane {
  position: absolute;
  inset: 0;
  z-index: 1;
}

@media (max-width: 1100px) {
  .visualization-workbench {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "ctxbar"
      "hero"
      "palette"
      "controls"
      "stage";
    height: auto;
  }
}

/* === Control ("/control"): bridge console over a full-screen chart ===
   The map (or, for camera devices, a video view) is the chart; the cockpit
   panels frame it like a ship's bridge console. */
body[data-page="control"] .page-panel.is-active {
  position: absolute;
  inset: 0;
  width: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  overflow: visible;
  pointer-events: none;
}

body[data-page="control"] .page-head {
  display: none;
}

/* Map furniture (rail, time bar, fish toggle, status, overlay panel) belongs
   only on the Observe map page. data-route is a constant shell hook, so
   data-page is the real per-page gate. */
body:not([data-page="map"]) #ocean-layer-dock,
body:not([data-page="map"]) #observe-time-bar,
body:not([data-page="map"]) #immersive-toggle,
body:not([data-page="map"]) #map-status,
body:not([data-page="map"]) #map-overlay-controls,
body:not([data-page="map"]) #context-panel,
body:not([data-page="map"]) #context-drawer,
body:not([data-page="map"]) #globe-legend {
  display: none !important;
}

/* Remaining map furniture is hidden so the cockpit owns the surface. */
body[data-page="control"] .map-utility-strip,
body[data-page="control"] .map-status,
.cockpit {
  display: contents;
}

.cockpit-view {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: none;
  place-items: center;
  padding: 24px;
  pointer-events: auto;
  background: rgba(2, 6, 9, 0.93);
}

.cockpit[data-primary-view="video"] .cockpit-view {
  display: grid;
}

.cockpit-view-inner {
  display: grid;
  gap: 6px;
  max-width: 440px;
  text-align: center;
}

.cockpit-view-inner h3 {
  margin: 0;
}

/* Console panels Ã¢â‚¬â€ built-in dashboard feel with an accent-lit top edge. */
.cockpit-roster,
.cockpit-deck,
.cockpit-console {
  position: absolute;
  z-index: 60;
  pointer-events: auto;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 14px;
  background: rgba(4, 12, 16, 0.72);
  box-shadow: 0 22px 56px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(16px);
}

.cockpit-roster,
.cockpit-deck {
  top: 76px;
  max-height: calc(100% - 216px);
  min-height: 0;
  overflow: hidden;
}

.cockpit-roster {
  left: 16px;
  width: 300px;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  padding: 0;
}

.cockpit-deck {
  right: 16px;
  width: min(440px, 38vw);
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  padding: 0;
}

/* Bottom console Ã¢â‚¬â€ the primary instrument dashboard. */
.cockpit-console {
  left: 16px;
  right: 16px;
  bottom: 16px;
  height: 110px;
  display: flex;
  align-items: stretch;
  overflow-x: auto;
}

.console-cell {
  display: grid;
  align-content: center;
  gap: 4px;
  padding: 12px 20px;
  border-right: 1px solid rgba(120, 160, 170, 0.14);
  min-width: 152px;
}

.console-cell:last-child {
  border-right: 0;
}

.console-cell-id {
  min-width: 264px;
}

.console-cell-view {
  margin-left: auto;
}

.console-label {
  color: rgba(94, 219, 203, 0.9);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.console-readout {
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.98rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.console-readout-mono {
  font-size: 0.8rem;
}

.console-sub {
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.console-link-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.cockpit-lamp-array {
  display: flex;
  gap: 5px;
}

.cockpit-lamp {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(150, 168, 172, 0.35);
}

.cockpit-lamp.is-active {
  background: #55d38a;
  box-shadow: 0 0 8px rgba(85, 211, 138, 0.95);
}

.cockpit-lamp.is-warn {
  background: #f6b15e;
  box-shadow: 0 0 8px rgba(246, 177, 94, 0.9);
}

.gauge-ring {
  position: relative;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: conic-gradient(var(--accent) calc(var(--gauge-val, 0) * 1%), rgba(120, 160, 170, 0.22) 0);
}

.gauge-ring::before {
  content: "";
  position: absolute;
  inset: 6px;
  border-radius: 50%;
  background: rgba(8, 18, 23, 0.98);
}

.gauge-ring strong {
  position: relative;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.8rem;
  font-weight: 700;
}

.console-gauge-row {
  display: flex;
  align-items: center;
  gap: 12px;
}

.console-gauge-meta {
  display: grid;
  gap: 5px;
}

.cockpit-device-list {
  display: grid;
  gap: 5px;
  align-content: start;
  min-height: 0;
  overflow: auto;
  padding: 8px 10px 10px;
}

.cockpit-device {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  text-align: left;
  border: 1px solid rgba(120, 160, 170, 0.2);
  border-radius: 10px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.035);
  cursor: pointer;
}

.cockpit-device-text {
  display: grid;
  gap: 3px;
  min-width: 0;
}

.cockpit-device.is-active {
  border-color: rgba(50, 208, 189, 0.6);
  border-left: 3px solid rgba(50, 208, 189, 0.9);
  background: rgba(50, 208, 189, 0.12);
}

.cockpit-device strong {
  font-size: 0.9rem;
}

.cockpit-device span {
  color: var(--muted);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.cockpit-view-switch {
  display: flex;
  gap: 6px;
}

.cockpit-view-switch .button {
  min-height: 30px;
  padding: 0 12px;
}

/* Deck tab bar Ã¢â‚¬â€ multi-function display page buttons. */
.cockpit-deck-tabs {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
  margin: 12px 14px 0;
  padding: 4px;
  border: 1px solid rgba(120, 160, 170, 0.2);
  border-radius: 11px;
  background: rgba(4, 12, 16, 0.66);
}

.cockpit-deck-tab {
  appearance: none;
  padding: 7px 6px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease;
}

.cockpit-deck-tab:hover {
  color: var(--ink);
}

.cockpit-deck-tab.is-active {
  background: linear-gradient(180deg, rgba(50, 208, 189, 0.22), rgba(50, 208, 189, 0.07));
  color: var(--ink);
  box-shadow: inset 0 0 0 1px rgba(50, 208, 189, 0.42);
}

.cockpit-deck-panel {
  display: grid;
  /* Stack instrument-groups in a single column — .cockpit-deck is a fixed
     440px sidebar, so multi-column won't fit. Tightened gap + padding to
     reclaim vertical space. */
  grid-template-columns: minmax(0, 1fr);
  gap: 8px;
  align-content: start;
  min-height: 0;
  overflow: auto;
  padding: 8px 10px 10px;
}

.cockpit-deck-panel[hidden] {
  display: none;
}

.instrument-group {
  padding: 8px 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.025);
  min-width: 0;
}

/* Hide instrument-groups that render empty (no live data yet). The DOM
   ships them all but firmware-side they're unused on some platforms;
   :has(p.eyebrow:only-child) means "eyebrow but nothing else useful". */
.instrument-group:empty { display: none; }

/* Inline the eyebrow + h3 into a single header row so the cockpit can
   stack 3-4 instrument groups inside a 588h sidebar instead of 2-3.
   ~35h header → ~22h header per group. */
.instrument-group .eyebrow {
  display: inline-block;
  margin: 0 8px 0 0;
  vertical-align: baseline;
}
.instrument-group h3 {
  display: inline-block;
  margin: 0 0 6px;
  font-size: 0.9rem;
  vertical-align: baseline;
}

.cockpit-action-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.cockpit-link-list {
  display: grid;
  gap: 6px;
}

.cockpit-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
}

.cockpit-link > div {
  display: grid;
  gap: 1px;
  min-width: 0;
}

.cockpit-link strong {
  font-size: var(--fs-base);
}

.cockpit-link span {
  color: var(--muted);
  font-size: 0.72rem;
}

.cockpit-roster-group {
  margin: 8px 0 0;
  color: var(--accent);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.compass {
  display: grid;
  gap: 8px;
  justify-items: center;
}

.compass-rose {
  position: relative;
  /* Compass was 124px in a 440px sidebar — chunky and pushed the 3
     other instrument groups to scroll. 96px still reads as a compass
     dial but lets the cockpit show ~4 instrument groups instead of
     2.5. */
  width: 96px;
  height: 96px;
  border-radius: 50%;
  border: 2px solid rgba(120, 160, 170, 0.32);
  background: radial-gradient(circle at 50% 50%, rgba(50, 208, 189, 0.08), rgba(4, 11, 15, 0.92) 70%);
}

.compass-tick {
  position: absolute;
  font-size: 0.66rem;
  font-weight: 700;
  color: var(--muted);
}

.compass-n {
  top: 5px;
  left: 50%;
  transform: translateX(-50%);
  color: var(--accent);
}

.compass-s {
  bottom: 5px;
  left: 50%;
  transform: translateX(-50%);
}

.compass-e {
  right: 7px;
  top: 50%;
  transform: translateY(-50%);
}

.compass-w {
  left: 7px;
  top: 50%;
  transform: translateY(-50%);
}

.compass-needle {
  position: absolute;
  left: 50%;
  top: 16px;
  width: 3px;
  height: calc(50% - 16px);
  margin-left: -1.5px;
  border-radius: 2px;
  background: linear-gradient(var(--accent), rgba(50, 208, 189, 0.15));
  transform-origin: bottom center;
  box-shadow: 0 0 8px rgba(50, 208, 189, 0.6);
}

.telemetry-list,
.sensor-list {
  display: grid;
  gap: 3px;
}

.telemetry-row,
.sensor-reading {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 3px 8px;
  border: 1px solid var(--line);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.025);
  min-width: 0;
}

.telemetry-row span,
.sensor-reading span {
  color: var(--muted);
  font-size: var(--fs-sm);
  min-width: 0;
  overflow-wrap: anywhere;
}

.telemetry-row strong,
.sensor-reading strong {
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.84rem;
  /* Allow long values (e.g. alert headlines) to wrap so they don't push
     the .cockpit-deck sidebar to overflow horizontally. */
  overflow-wrap: anywhere;
  text-align: right;
  min-width: 0;
}

/* ── Live cockpit: status pill + primary instrument tiles ─────────── */
.cockpit-live-bar { display: flex; justify-content: flex-end; margin: 2px 0 6px; }
.cockpit-live-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: rgba(255, 255, 255, 0.03);
  font-size: var(--fs-sm); color: var(--muted); letter-spacing: 0.04em;
}
.cockpit-live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }
.cockpit-live-pill[data-live="on"] { color: var(--accent, #32d0bd); border-color: var(--line-strong, rgba(50, 208, 189, 0.5)); }
.cockpit-live-pill[data-live="on"] .cockpit-live-dot {
  background: var(--accent, #32d0bd);
  animation: cockpit-live-pulse 1.8s ease-in-out infinite;
}
@keyframes cockpit-live-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .cockpit-live-pill[data-live="on"] .cockpit-live-dot { animation: none; } }

.cockpit-primary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 6px;
}
.cockpit-primary-tile {
  display: flex; flex-direction: column; gap: 2px;
  padding: 7px 9px; min-width: 0;
  border: 1px solid var(--line); border-radius: 9px;
  background: rgba(255, 255, 255, 0.025);
}
.cockpit-primary-tile .cpt-label {
  color: var(--muted); font-size: 0.64rem; letter-spacing: 0.06em; text-transform: uppercase;
}
.cockpit-primary-tile .cpt-value {
  font-family: "IBM Plex Mono", monospace; font-size: 1.02rem; color: var(--text);
  line-height: 1.15; overflow-wrap: anywhere;
}
.cockpit-primary-tile .cpt-value .cpt-unit { font-size: 0.66rem; color: var(--muted); margin-left: 2px; }
.cockpit-primary-tile.is-alert { border-color: var(--err, #ff7a7a); background: rgba(255, 122, 122, 0.10); }
.cockpit-primary-tile.is-alert .cpt-value { color: var(--err, #ff7a7a); }
.cockpit-primary-tile.is-ok .cpt-value { color: var(--ok, #8df5b1); }

.sensor-reading strong em {
  color: var(--muted);
  font-style: normal;
  font-size: 0.7rem;
  margin-left: 3px;
}

/* Cockpit panels are narrow Ã¢â‚¬â€ force command forms to a single column. */
body[data-page="control"] .instrument-group .tool-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
}

@media (max-width: 1100px) {
  .cockpit-roster,
  .cockpit-deck {
    left: 10px;
    right: 10px;
    width: auto;
  }

  .cockpit-roster {
    top: 70px;
    bottom: auto;
    height: 30vh;
  }

  .cockpit-deck {
    top: auto;
    bottom: 150px;
    height: 44vh;
  }

  .cockpit-console {
    left: 10px;
    right: 10px;
    bottom: 10px;
  }
}

/* === Mesh ("/mesh"): network console over a full-screen map ===
   The map is the live network view; two glass rails frame it Ã¢â‚¬â€ network
   status on the left, messaging on the right. */
body[data-page="comms"] .page-panel.is-active {
  position: absolute;
  inset: 0;
  width: auto;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  overflow: visible;
  pointer-events: none;
}

body[data-page="comms"] .page-head {
  display: none;
}

body[data-page="comms"] .map-utility-strip,
body[data-page="comms"] .map-status,
.mesh-console {
  display: contents;
}

.mesh-rail {
  position: absolute;
  top: 76px;
  max-height: calc(100% - 92px);
  z-index: 60;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  padding: 0;
  overflow: hidden;
  pointer-events: auto;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 14px;
  background: rgba(4, 12, 16, 0.72);
  box-shadow: 0 22px 56px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(16px);
}

.mesh-rail--network {
  left: 16px;
  width: 340px;
}

.mesh-rail--messaging {
  right: 16px;
  width: min(420px, 34vw);
}

.mesh-rail-body {
  display: grid;
  gap: 14px;
  align-content: start;
  min-height: 0;
  overflow: auto;
  padding: 14px;
}

.mesh-block {
  display: grid;
  gap: 6px;
}

/* Gateway-coverage tables (federation sightings). */
.mesh-coverage-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.72rem;
  margin: 4px 0 10px;
}
.mesh-coverage-table th {
  text-align: left;
  font-weight: 600;
  color: rgba(218, 234, 240, 0.55);
  padding: 3px 8px 3px 0;
  border-bottom: 1px solid rgba(163, 185, 188, 0.18);
}
.mesh-coverage-table td {
  padding: 3px 8px 3px 0;
  border-bottom: 1px solid rgba(163, 185, 188, 0.08);
  word-break: break-word;
}

.mesh-block h3 {
  margin: 0 0 4px;
}

/* Mesh topology graph (Comms page) */
.mesh-topology-meta {
  margin-bottom: 6px;
  font-size: var(--fs-sm);
}
.mesh-topology {
  background: linear-gradient(180deg, #f7fbfd 0%, #e6f1f7 100%);
  border: 1px solid rgba(43, 110, 158, 0.22);
  border-radius: 10px;
  padding: 6px;
  margin-bottom: 8px;
}
.mesh-topology-svg {
  width: 100%;
  height: auto;
  max-height: 260px;
  display: block;
}
.mesh-topology-routes {
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  font-size: var(--fs-sm);
  padding: 8px 10px;
}
.mesh-topology-routes.empty {
  font-style: italic;
  color: rgba(207, 232, 216, 0.6);
}
.mesh-topology-routes-title {
  margin: 0 0 6px;
  font-family: "Inter", "Segoe UI", sans-serif;
  font-size: 0.8rem;
  font-weight: 700;
  color: #cfe8d8;
}
.mesh-topology-route {
  display: grid;
  grid-template-columns: 28px 1fr auto auto;
  gap: 8px;
  padding: 3px 0;
  align-items: baseline;
}
.mesh-topology-route + .mesh-topology-route {
  border-top: 1px dotted rgba(123, 224, 166, 0.18);
}
.mesh-topology-route-hops {
  color: #ffd66a;
  font-weight: 700;
}
.mesh-topology-route-dst {
  color: #eafff0;
  font-weight: 600;
}
.mesh-topology-route-cost {
  text-align: right;
  color: rgba(207, 232, 216, 0.7);
}

@media (max-width: 1100px) {
  .mesh-rail {
    left: 10px;
    right: 10px;
    width: auto;
  }

  .mesh-rail--network {
    top: 70px;
    bottom: auto;
    height: 38vh;
  }

  .mesh-rail--messaging {
    top: auto;
    bottom: 10px;
    height: 44vh;
  }
}

/* === Floating panel chrome (Control + Mesh map-backed pages) ===
   Each panel drags by its title bar, collapses down to that bar, and
   closes to the panel dock. Panels size to the data they contain. */
.dock-panel.is-panel-hidden {
  display: none !important;
}

/* Full-width title bar Ã¢â‚¬â€ the whole strip is the drag handle. */
.panel-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 44px;
  padding: 0 10px 0 14px;
  border-bottom: 1px solid rgba(120, 160, 170, 0.24);
  border-radius: 13px 13px 0 0;
  background: linear-gradient(180deg, rgba(50, 208, 189, 0.14), rgba(255, 255, 255, 0.02));
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.panel-bar:hover {
  background: linear-gradient(180deg, rgba(50, 208, 189, 0.2), rgba(255, 255, 255, 0.03));
}

body.is-dragging-panel,
body.is-dragging-panel .panel-bar {
  cursor: grabbing;
}

.panel-bar::before {
  content: "";
  flex: none;
  width: 9px;
  height: 17px;
  background-image: radial-gradient(rgba(94, 219, 203, 0.85) 1.1px, transparent 1.5px);
  background-size: 4px 4.2px;
}

.panel-bar-title {
  flex: 1;
  min-width: 0;
  font-size: 0.67rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.panel-bar-tools {
  display: flex;
  gap: 4px;
}

.panel-tool {
  width: 24px;
  height: 24px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid rgba(120, 160, 170, 0.22);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.05);
  color: var(--muted);
  cursor: pointer;
}

.panel-tool:hover {
  color: var(--ink);
  border-color: rgba(50, 208, 189, 0.55);
  background: rgba(50, 208, 189, 0.14);
}

.panel-tool-icon {
  display: block;
  font-size: var(--fs-sm);
  line-height: 1;
  transition: transform 140ms ease;
}

.dock-panel.is-collapsed .panel-tool[data-panel-action="collapse"] .panel-tool-icon {
  transform: rotate(180deg);
}

.dock-panel.is-collapsed {
  grid-template-rows: auto;
}

.dock-panel.is-collapsed > :not(.panel-bar) {
  display: none;
}

.dock-panel.is-collapsed .panel-bar {
  border-bottom: 0;
  border-radius: 13px;
}

/* Panel dock Ã¢â‚¬â€ chips that restore closed panels. */
.panel-dock {
  position: fixed;
  top: 86px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 200;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px;
  padding: 6px;
  border: 1px solid rgba(120, 160, 170, 0.22);
  border-radius: 12px;
  background: rgba(5, 12, 16, 0.93);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(14px);
}

.panel-dock:empty {
  display: none;
}

.panel-dock-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border: 1px solid rgba(50, 208, 189, 0.42);
  border-radius: 8px;
  background: rgba(50, 208, 189, 0.12);
  color: var(--ink);
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

.panel-dock-chip::before {
  content: "\002B";
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--accent);
}

.panel-dock-chip:hover {
  border-color: rgba(50, 208, 189, 0.75);
  background: rgba(50, 208, 189, 0.22);
}

/* Bathymetry depth legend Ã¢â‚¬â€ shown on Observe and Plan while the layer is on. */
.bathymetry-legend {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 150;
  display: none;
  gap: 8px;
  width: 192px;
  padding: 12px 14px;
  border: 1px solid rgba(120, 160, 170, 0.24);
  border-top: 2px solid rgba(50, 208, 189, 0.5);
  border-radius: 12px;
  background: rgba(5, 12, 16, 0.93);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(14px);
}

body.bathymetry-on[data-page="map"] .bathymetry-legend,
body.bathymetry-on[data-page="command"] .bathymetry-legend {
  display: grid;
}

.bathymetry-legend .eyebrow,
.bathymetry-legend .muted {
  margin: 0;
}

.bathymetry-legend .muted {
  font-size: 0.72rem;
}

.bathymetry-legend-scale {
  display: grid;
  gap: 3px;
}

.bathymetry-legend-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.72rem;
  color: var(--muted);
}

.bathymetry-legend-swatch {
  width: 24px;
  height: 12px;
  flex: none;
  border-radius: 3px;
}

.chart-suite {
  display: grid;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 22px;
  background:
    radial-gradient(circle at 16% 0%, rgba(50, 208, 189, 0.1), transparent 34%),
    rgba(4, 13, 17, 0.62);
}

.chart-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 10px;
}

.chart-card {
  display: grid;
  gap: 8px;
  align-content: start;
  height: 280px;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.035);
  overflow: auto;
}

.chart-card-wide {
  grid-column: span 2;
}

.chart-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
}

.chart-card h4,
.chart-card h5 {
  margin: 0;
}

.chart-card h5 {
  color: var(--muted);
  font-size: 0.76rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.chart-card-head p {
  margin: 4px 0 0;
}

.mini-bars {
  display: grid;
  gap: 9px;
}

.mini-bar-row {
  display: grid;
  grid-template-columns: minmax(140px, 0.8fr) minmax(120px, 1fr) auto;
  gap: 10px;
  align-items: center;
  min-width: 0;
}

.mini-bar-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.mini-bar-copy strong,
.matrix-station {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.mini-bar-copy span {
  color: var(--muted);
  font-size: var(--fs-sm);
}

.mini-bar-meter {
  height: 11px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.075);
  overflow: hidden;
}

.mini-bar-meter span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.mini-bar-row b {
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-base);
  white-space: nowrap;
}

.qc-fail .mini-bar-meter span,
.freshness-stale .mini-bar-meter span,
.source-key .mini-bar-meter span {
  background: linear-gradient(90deg, #fb7185, #f6b15e);
}

.qc-suspect .mini-bar-meter span {
  background: linear-gradient(90deg, #f6b15e, #ffe08a);
}

.qc-pass .mini-bar-meter span,
.freshness-fresh .mini-bar-meter span,
.source-live .mini-bar-meter span {
  background: linear-gradient(90deg, #55d38a, var(--accent));
}

.metric-matrix {
  display: grid;
  grid-template-columns: minmax(170px, 1.2fr) repeat(var(--metric-columns), minmax(108px, 1fr));
  gap: 6px;
  min-width: max-content;
}

.matrix-corner,
.matrix-heading,
.matrix-station,
.matrix-cell {
  min-height: 42px;
  padding: 9px 10px;
  border: 1px solid rgba(255, 255, 255, 0.075);
  border-radius: 12px;
}

.matrix-corner,
.matrix-heading {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.matrix-station {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.04);
  font-weight: 700;
}

.matrix-cell {
  color: var(--ink);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-base);
  text-align: right;
}

.matrix-missing {
  color: var(--muted);
  background: rgba(255, 255, 255, 0.025);
  text-align: center;
}

.empty {
  display: grid;
  place-items: center;
  /* Was min-height: 120px — single-line "X will appear here" hints
     do not need a 120-tall dashed-border placeholder. Now 44px so
     several empty hints can coexist without dominating the viewport. */
  min-height: 44px;
  padding: 8px 12px;
  color: var(--muted);
  text-align: center;
  border: 1px dashed rgba(163, 185, 188, 0.18);
  border-radius: 10px;
  font-size: 12px;
}

.split-panel,
.command-layout,
.comms-layout {
  display: grid;
  gap: 14px;
}

.split-panel {
  grid-template-columns: minmax(0, 1fr) minmax(300px, 0.38fr);
}

.chart-picker-panel {
  display: grid;
  grid-template-columns: minmax(280px, 1fr) auto;
  gap: 12px;
  align-items: end;
  padding: 16px;
  border: 1px solid rgba(50, 208, 189, 0.22);
  border-radius: 18px;
  background: rgba(7, 21, 25, 0.76);
}

.chart-picker-panel > p {
  grid-column: 1 / -1;
  margin: 0;
}

.environmental-animation-panel {
  display: grid;
  gap: 14px;
}

.environmental-animation-grid {
  display: grid;
  grid-template-columns: minmax(240px, 1.4fr) repeat(5, minmax(108px, 0.48fr)) repeat(5, auto);
  gap: 10px;
  align-items: end;
}

.timeline-strip {
  display: flex;
  flex-wrap: nowrap;
  gap: 8px;
  min-height: 36px;
  max-height: 86px;
  overflow: auto;
  padding-bottom: 4px;
  scroll-snap-type: x proximity;
}

.timeline-frame {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.045);
  color: var(--text);
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 800;
  flex: 0 0 auto;
  scroll-snap-align: start;
}

.timeline-frame:hover,
.timeline-frame:focus-visible {
  border-color: rgba(50, 208, 189, 0.72);
  outline: none;
}

.timeline-frame.is-active {
  color: #051416;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  border-color: transparent;
}

.chart-picker-actions,
.data-browser-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.chart-stack-layout {
  align-items: start;
}

body[data-page="charts"] .chart-picker-panel,
body[data-page="charts"] .chart-stack-layout {
  grid-template-columns: 1fr;
}

body[data-page="charts"] .environmental-animation-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

body[data-page="charts"] .environmental-animation-grid .button {
  min-width: 0;
}

.command-layout {
  grid-template-columns: minmax(320px, 0.35fr) minmax(0, 1fr);
}

.comms-layout {
  grid-template-columns: minmax(260px, 0.25fr) minmax(320px, 0.32fr) minmax(0, 1fr);
}

.comms-layout.compact {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.layer-card,
.source-card,
.metric-card {
  display: grid;
  gap: 4px;
  padding: 10px 12px;
  align-content: start;
}

/* Recipes button in header — accent-tinted so it reads as a
   first-class entry point, not just another secondary button. */
#recipes-book-button {
  border-color: rgba(50, 208, 189, 0.45);
  background: rgba(50, 208, 189, 0.12);
  color: var(--accent);
  font-weight: 600;
}
#recipes-book-button:hover {
  background: rgba(50, 208, 189, 0.22);
  border-color: rgba(50, 208, 189, 0.7);
}

/* Global recipes modal — opens from header Recipes button. Lists
   every recipe in the portal grouped by page so the operator can
   find and run any recipe regardless of where they are. */
#recipes-modal[hidden] { display: none; }
#recipes-modal {
  position: fixed;
  inset: 0;
  z-index: 950;
  display: grid;
  place-items: center;
}
#recipes-modal .modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(2, 7, 11, 0.66);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  cursor: pointer;
}
.recipes-modal-panel {
  position: relative;
  width: min(820px, 92vw);
  max-height: 86vh;
  display: grid;
  grid-template-rows: auto 1fr;
  padding: 16px 20px 18px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 14px;
  background: rgba(7, 18, 24, 0.95);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6);
}
.recipes-modal-panel .modal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.16);
  margin-bottom: 10px;
}
.recipes-modal-panel .modal-head h2 { margin: 0; font-size: 16px; }
.recipes-modal-panel .modal-body {
  display: grid;
  grid-template-rows: auto 1fr;
  gap: 10px;
  min-height: 0;
}
.recipes-modal-search {
  width: 100%;
  padding: 8px 12px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--ink);
  font-size: 13px;
}
.recipes-modal-hint {
  margin: 4px 0 0;
  font-size: 11px;
  line-height: 1.5;
}
.recipes-modal-hint kbd {
  display: inline-block;
  padding: 1px 5px;
  margin: 0 1px;
  border: 1px solid rgba(163, 185, 188, 0.32);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.05);
  font-family: ui-monospace, monospace;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--ink);
}
.recipes-modal-item:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.recipes-modal-list {
  overflow-y: auto;
  display: grid;
  gap: 14px;
  padding-right: 4px;
}
.recipes-modal-group {
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 10px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.025);
}
.recipes-modal-group-title {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 0 0 8px;
  font-size: 12px;
  color: var(--accent-2);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.recipes-modal-group-title .recipes-group-count {
  color: var(--muted);
  font-size: 10.5px;
}
/* Recently used section gets a gold tint so it visually pops as
   "user's most common starting point" in the recipes modal. */
.recipes-modal-recent {
  background: rgba(245, 158, 11, 0.04);
  border: 1px solid rgba(245, 158, 11, 0.22);
  border-radius: 8px;
}
.recipes-modal-recent .recipes-modal-group-title { color: #fbbf24; }
.recipes-modal-recent-item {
  border-color: rgba(245, 158, 11, 0.30);
  background: rgba(245, 158, 11, 0.06);
}
.recipes-modal-recent-item:hover {
  border-color: rgba(245, 158, 11, 0.65);
  background: rgba(245, 158, 11, 0.14);
}
.recipes-modal-group-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 6px;
}
.recipes-modal-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
  color: var(--ink);
  font-size: 12.5px;
  text-align: left;
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease;
  min-width: 0;
}
.recipes-modal-item:hover {
  border-color: rgba(50, 208, 189, 0.45);
  background: rgba(50, 208, 189, 0.08);
}
.recipes-modal-item-label {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
}
.recipes-modal-item-desc {
  font-size: 10.5px;
  color: var(--muted);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  width: 100%;
}
.recipes-modal-item-tip {
  font-size: 10.5px;
  color: var(--muted);
  flex-shrink: 0;
}
.recipes-modal-empty {
  padding: 24px;
  text-align: center;
  color: var(--muted);
  font-size: 12px;
}

/* Admin form sections — was each 229-285h with a 40-60h preamble
   paragraph explaining what the form does. The form labels carry
   that context already. Tighten padding + drop preamble text. */
.system-check-panel.admin-card {
  padding: 10px 14px;
  gap: 6px;
}
.system-check-panel.admin-card .inline-tool {
  gap: 8px;
}
.system-check-panel.admin-card > p.muted {
  font-size: 11.5px;
  margin: 0;
}
.system-check-panel.admin-card .admin-hint[hidden] { display: none; }

/* Admin/Settings API key list — compact single-row readout. Was a
   158h dashboard tile per key. Now ~32h row with status dot, label,
   env var, status pill. The full scope sentence is on the title
   attribute for tooltip access. 2-col grid at wide widths so 10
   keys fit in 5 rows instead of 10. */
#api-key-list.source-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 4px;
}
.api-key-row {
  display: grid;
  grid-template-columns: 12px minmax(140px, 1.2fr) minmax(0, 2fr) auto;
  align-items: center;
  gap: 12px;
  padding: 6px 12px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
  font-size: 12.5px;
}
.api-key-row.is-live {
  border-color: rgba(50, 208, 189, 0.32);
  background: rgba(50, 208, 189, 0.06);
}
.api-key-row.is-missing {
  border-color: rgba(217, 158, 70, 0.32);
  background: rgba(217, 158, 70, 0.05);
}
.api-key-status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
  display: inline-block;
}
.api-key-row.is-live .api-key-status-dot { background: var(--accent); }
.api-key-row.is-missing .api-key-status-dot { background: rgb(217, 158, 70); }
.api-key-label {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.api-key-env {
  font-family: "IBM Plex Mono", monospace;
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.bar-track {
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
  overflow: hidden;
}

.bar-track span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
}

.source-card p,
.layer-card p {
  margin: 0;
}

.layer-card {
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
}

.layer-card.is-active,
.source-card.is-live {
  border-color: rgba(50, 208, 189, 0.35);
  background: rgba(50, 208, 189, 0.08);
}

.source-grid {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.compact-source-grid {
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  margin-top: 10px;
}

.mission-cube-panel {
  display: grid;
  gap: 14px;
}

.earthdata-finder-panel {
  display: grid;
  gap: 14px;
}

.earthdata-finder-grid,
.earthdata-results-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}

.earthdata-map-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.earthdata-result-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10px;
  align-items: center;
  padding: 12px;
  border-bottom: 1px solid var(--line);
}

.earthdata-result-card:last-child {
  border-bottom: 0;
}

.earthdata-result-card p {
  margin: 4px 0 0;
}

.earthdata-link-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

.earthdata-link-row a {
  color: var(--accent);
  font-size: var(--fs-base);
  font-weight: 800;
  text-decoration: none;
}

.earthdata-active-footprint {
  filter: drop-shadow(0 0 14px rgba(50, 208, 189, 0.75));
}

.mission-cube-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(280px, 0.75fr);
  gap: 12px;
  align-items: start;
}

.compact-form {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

.compact-form .button,
.compact-form p {
  grid-column: 1 / -1;
}

.mission-cube-output {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
  margin-top: 12px;
}

.mission-cube-output > div {
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(238, 246, 245, 0.04);
}

.mission-cube-output p {
  margin: 6px 0 0;
}

.data-toolbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 0.25fr);
  gap: 10px;
}

.provider-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: flex-end;
}

.data-access-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}

.data-access-card {
  display: grid;
  gap: 6px;
  min-height: 92px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(238, 246, 245, 0.045);
  color: var(--text);
  text-decoration: none;
}

.data-access-card:hover {
  border-color: rgba(50, 208, 189, 0.45);
  background: rgba(50, 208, 189, 0.08);
}

.data-access-card span {
  color: var(--muted);
  font-size: 0.9rem;
}

.data-browser-panel {
  display: grid;
  gap: 14px;
}

.data-browser-toolbar {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  margin: 8px 0 6px;
}
.data-browser-toolbar > input[type="search"] {
  flex: 1 1 180px; padding: 7px 10px; font-size: 0.84rem;
}
.data-browser-toolbar > select {
  flex: 1 1 200px; padding: 7px 10px; font-size: 0.84rem;
}
.data-browser-toolbar > input[type="number"] {
  flex: 0 0 70px; padding: 7px 10px; font-size: 0.84rem;
  font-family: ui-monospace, "SF Mono", monospace; text-align: right;
}
.data-browser-filter-input {
  width: 100%; padding: 7px 10px; font-size: 0.84rem;
  margin: 4px 0 8px;
}

.data-browser-intent-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
}

.data-browser-intent-strip .small {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.chip {
  font: inherit;
  font-size: 0.78rem;
  line-height: 1;
  padding: 6px 10px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.12s ease, border-color 0.12s ease, opacity 0.12s ease;
}

.chip:hover {
  background: rgba(255, 255, 255, 0.08);
}

.chip.is-active {
  background: rgba(64, 173, 224, 0.22);
  border-color: rgba(64, 173, 224, 0.6);
}

.chip.is-disabled,
.chip[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.chip-count {
  font-variant-numeric: tabular-nums;
  font-size: 0.7rem;
  padding: 1px 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.08);
}

.chip.is-active .chip-count {
  background: rgba(64, 173, 224, 0.32);
}

.data-browser-chart-toolbar {
  display: grid;
  grid-template-columns: minmax(140px, 0.36fr) minmax(180px, 0.5fr) minmax(180px, 0.5fr) auto;
  gap: 10px;
  align-items: end;
}

.compact-control input {
  text-align: right;
}

.endpoint-line {
  grid-column: 1 / -1;
  padding: 8px 10px;
  overflow: hidden;
  color: var(--muted);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
}

.endpoint-line span {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compact-table .table-row {
  grid-template-columns: 1.4fr 1fr 0.8fr 0.8fr 1fr;
}

.compact-table .table-head span {
  color: var(--text);
  font-weight: 700;
}

.data-browser-table .table-row {
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}

.data-browser-table .table-head span {
  color: var(--text);
  font-weight: 700;
}

.data-browser-stats {
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.025);
}

.data-browser-stats.empty {
  color: var(--muted);
  font-size: 0.86rem;
}

.data-browser-stats .eyebrow {
  margin: 0;
}

/* Inspect panel — Quick Actions + stepped layout (2026-05-25 rebuild) */
.data-browser-panel > .panel-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}

/* Workspace tabs overflow — pushes rarely-used tabs into a "More" menu */
.workspace-tabs-more {
  position: relative;
  display: inline-block;
}
.workspace-tabs-more > summary {
  list-style: none;
  cursor: pointer;
}
.workspace-tabs-more > summary::-webkit-details-marker {
  display: none;
}
.workspace-tab-more {
  /* inherit .workspace-tab styling */
}
.workspace-tabs-more-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 25;
  min-width: 200px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(16, 22, 30, 0.96);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  display: grid;
  gap: 2px;
}
.workspace-tabs-more-menu > .workspace-tab {
  text-align: left;
  width: 100%;
  border: 0;
  background: transparent;
}
.workspace-tabs-more-menu > .workspace-tab:hover {
  background: rgba(255, 255, 255, 0.06);
}

/* One-panel pages: hide the tab strip — picker dropdown in the page header replaces it */
.workspace-tabs.data-page-tabs-strip,
.workspace-tabs.graphs-page-tabs-strip,
.workspace-tabs.command-page-tabs-strip,
.workspace-tabs.hardware-page-tabs-strip,
.workspace-tabs.settings-page-tabs-strip {
  display: none !important;
}

/* Unified panel chrome: hide the page-head entirely on one-panel pages
   so the active panel IS the page experience. The picker + global actions
   get relocated into the panel's own header via JS. */
body[data-page="library"] #library-page > .page-head,
body[data-page="inspect"] #inspect-page > .page-head,
body[data-page="graphs"] #graphs-page > .page-head,
body[data-page="command"] #command-page > .page-head,
body[data-page="hardware"] #hardware-page > .page-head,
body[data-page="settings"] #settings-page > .page-head {
  display: none !important;
}

/* One-panel pages with a single body panel: stretch the lone content
   panel to fill the page-panel's remaining height so inner content can
   flex-grow + scroll instead of pushing the page off-viewport. Hardware
   is the only one-panel case currently (settings/command stack multiple
   workspace sections). */
body[data-page="hardware"] #hardware-page.is-active {
  grid-template-rows: minmax(0, 1fr);
  align-content: stretch;
}

/* hardware:firmware: the firmware-target-detail source-grid is 500-600px
   of device cards. Let it flex-grow + scroll inside the section so the
   chrome (picker + artifact summary + flasher form) stays pinned.
   Same pattern applies to hardware:halow with #halow-pair-plan. */
body[data-page="hardware"] [data-workspace-section="hardware:firmware"],
body[data-page="hardware"] [data-workspace-section="hardware:halow"] {
  display: flex;
  flex-direction: column;
  min-height: 0;
  max-height: 100%;
}
body[data-page="hardware"] [data-workspace-section="hardware:firmware"] #firmware-target-detail,
body[data-page="hardware"] [data-workspace-section="hardware:halow"] #halow-pair-plan {
  flex: 1 1 0;
  min-height: 120px;
  overflow-y: auto;
  padding-right: 4px;
}

/* Admin / Settings: long check-lists (remote-access-status,
   preflight-check-list, system-check-list) and the gateway-readiness
   summary push the page past viewport on settings:sharing and
   settings:diagnostics. The page-panel has overflow:auto so it
   already scrolls — but the chrome (picker + section title + outcome
   chips) scrolls off the top, defeating the unified-panel pattern.
   Scroll the inner check-lists instead so the picker stays pinned. */
body[data-page="settings"] [data-workspace-section="settings:sharing"]:first-of-type,
body[data-page="settings"] [data-workspace-section="settings:diagnostics"]:first-of-type {
  display: flex;
  flex-direction: column;
  min-height: 0;
}
body[data-page="settings"] [data-workspace-section="settings:sharing"] #remote-access-status,
body[data-page="settings"] [data-workspace-section="settings:diagnostics"] #preflight-check-list,
body[data-page="settings"] [data-workspace-section="settings:diagnostics"] #system-check-list {
  max-height: 360px;
  overflow-y: auto;
  padding-right: 4px;
}

/* System Check is a secondary diagnostic — fold behind a <details> so
   only Gateway Readiness shows by default. Saves ~313px when closed. */
.system-check-fold {
  /* Override system-check-panel grid display since <details> needs block. */
  display: block;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel-soft);
}
.system-check-fold > summary {
  cursor: pointer;
  padding: 12px 16px;
  list-style: none;
}
.system-check-fold > summary::-webkit-details-marker { display: none; }
.system-check-fold[open] > summary { border-bottom: 1px solid rgba(255,255,255,0.06); }
.system-check-fold > :not(summary) { padding: 0 16px; }
.system-check-fold > :first-child:not(summary) { padding-top: 12px; }
.system-check-fold > :last-child { padding-bottom: 12px; }

/* `<details class="has-summary-action">` with a `.summary-action` button
   inside the body. Position the button absolutely so it visually sits
   in the summary row (top-right) — the actual DOM keeps the button
   OUTSIDE the <summary>, which avoids the "interactive element inside
   <summary>" accessibility warning. Works whether the details is open
   or collapsed. */
.has-summary-action {
  position: relative;
}
.has-summary-action > .summary-action {
  position: absolute;
  top: 8px;
  right: 12px;
  z-index: 2;
}

/* Panel-embedded picker bar: replaces the panel's static title row */
.panel-context-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding-bottom: 6px;
  margin-bottom: 6px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  flex-wrap: nowrap;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
  /* Always span the entire top row when the parent uses CSS grid. */
  grid-column: 1 / -1;
  grid-row: 1;
  /* Ensure the bar takes its own row in flex/grid containers and doesn't
     get pushed below other children with explicit positioning. */
  order: -1;
}
/* visualization-workbench uses grid-template-areas — give the bar the
   named area instead of plain grid-row so it lands above 'hero'. */
.visualization-workbench > .panel-context-bar {
  grid-area: ctxbar;
}
.panel-context-bar-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
  flex: 1 1 auto;
}
.panel-context-bar-right {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}
.panel-context-purpose {
  font-size: 12px;
  color: var(--muted);
  opacity: 0.7;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
  flex: 1 1 0;
}

/* Pages with picker: hide each panel's own static title since the picker
   in the context bar now serves as the title. Keep panel-subtitle visible
   if it has unique info beyond what the picker says. */
body[data-page="library"] #library-page .panel-context-bar ~ .panel-head .panel-title,
body[data-page="inspect"] #inspect-page .panel-context-bar ~ .panel-head .panel-title,
body[data-page="library"] #library-page .panel-context-bar ~ .panel-head .inspect-panel-title-row > div:first-child > h3,
body[data-page="inspect"] #inspect-page .panel-context-bar ~ .panel-head .inspect-panel-title-row > div:first-child > h3,
body[data-page="graphs"] #graphs-page .panel-context-bar ~ .panel-head .panel-title,
body[data-page="command"] #command-page .panel-context-bar ~ .panel-head .panel-title,
body[data-page="hardware"] #hardware-page .panel-context-bar ~ .panel-head .panel-title,
body[data-page="settings"] #settings-page .panel-context-bar ~ .panel-head .panel-title {
  display: none;
}
.panel-context-action {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.panel-context-action:hover {
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink);
}
.panel-context-overflow {
  position: relative;
}
.panel-context-overflow-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 30;
  min-width: 200px;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(16, 22, 30, 0.96);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  display: grid;
  gap: 2px;
}
.panel-context-overflow-item {
  text-align: left;
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--ink);
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
}
.panel-context-overflow-item:hover {
  background: rgba(255, 255, 255, 0.06);
}
.panel-context-overflow[data-open="false"] .panel-context-overflow-menu {
  display: none;
}

/* Repurpose the picker bar to act like a panel title — bigger picker label */
.panel-context-bar .data-view-picker-trigger {
  font-size: 15px;
  font-weight: 700;
  padding: 4px 8px;
}
.panel-context-bar .data-view-picker-label {
  font-size: 15px;
}

/* Data page view picker — single-panel-with-dropdown pattern */
.data-view-picker {
  position: relative;
  display: inline-block;
  z-index: 9999;
}
.data-view-picker-trigger {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-weight: 600;
}
.data-view-picker-caret {
  font-size: 11px;
  opacity: 0.75;
  transition: transform 0.15s ease;
}
.data-view-picker[data-picker-open="true"] .data-view-picker-caret {
  transform: rotate(180deg);
}
.data-view-picker-menu {
  position: fixed;
  z-index: 9999;
  min-width: 260px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(16, 22, 30, 0.97);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
  display: grid;
  gap: 1px;
}
.data-view-picker-menu hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 4px 0;
  opacity: 0.6;
}
.data-view-picker-item {
  text-align: left;
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--ink);
  padding: 8px 10px;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.data-view-picker-item:hover,
.data-view-picker-item:focus-visible {
  background: rgba(255, 255, 255, 0.07);
  outline: none;
}
.data-view-picker-item:focus-visible {
  /* Keyboard focus is visually distinct from mouse hover so Tab nav is obvious. */
  box-shadow: inset 0 0 0 1px rgba(50, 208, 189, 0.45);
}
.data-view-picker-item.is-active {
  background: rgba(102, 178, 255, 0.15);
  color: var(--accent, #6cb7ff);
  font-weight: 600;
}
.data-view-picker-item.is-active::after {
  content: "✓";
  font-weight: 700;
  color: var(--accent, #6cb7ff);
  opacity: 0.7;
  margin-left: 8px;
}
.data-view-picker-item .muted {
  font-weight: 400;
  font-size: 11px;
  opacity: 0.65;
}

/* Data page Inspect tab: parent column should not scroll — the Inspect
   panel manages its own height and the tile grid scrolls internally if
   needed. This wins on specificity over the body[data-page] global
   rule that opted into whole-column scrolling. */
body[data-page="library"] .page-panel[data-page-panel="library"].is-active,
body[data-page="inspect"] .page-panel[data-page-panel="inspect"].is-active,
body.inspect-active .page-panel.is-active {
  overflow-y: hidden;
  overflow-x: hidden;
}

/* Inspect panel — viewport-fit, no internal scroll */
.inspect-viewport:not([hidden]),
.report-panel.data-browser-panel.inspect-viewport:not([hidden]) {
  display: flex !important;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  max-height: calc(100vh - 240px);
  overflow: hidden;
}
.inspect-viewport[hidden] {
  display: none !important;
}
.inspect-viewport > .inspect-panel-head {
  flex: 0 0 auto;
}
.inspect-panel-title-row {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  min-height: 0;
}
/* When the inspect-panel-tools have been moved out (by JS at init)
   into the panel-outcomes row, the panel-head is empty — hide it. */
body[data-page="library"] .data-browser-panel > .panel-head.is-empty,
body[data-page="inspect"] .data-browser-panel > .panel-head.is-empty {
  display: none;
}
/* The tools row, once hoisted into .panel-outcomes, lays out to the
   right via margin-left:auto so the chips keep their flow on the left. */
.panel-outcomes .inspect-panel-tools.hoisted-from-head {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  min-height: 0;
}
.panel-outcomes .inspect-panel-tools.hoisted-from-head .inspect-tool-btn {
  padding: 3px 9px;
  font-size: 11.5px;
  min-height: 0;
  height: 26px;
  border-radius: 8px;
}
.panel-outcomes .inspect-panel-tools.hoisted-from-head .inspect-live-status {
  font-size: 11px;
  white-space: nowrap;
}
.panel-outcomes .inspect-panel-tools.hoisted-from-head .pill {
  height: 24px;
  padding: 2px 8px;
  font-size: 11px;
}
.inspect-panel-tools {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.inspect-tool-btn {
  font-size: 0.84rem;
  padding: 6px 12px;
  white-space: nowrap;
}
.inspect-live-status {
  display: flex;
  align-items: center;
  gap: 6px;
}
.inspect-live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.18);
  flex: none;
  transition: background 0.2s ease, box-shadow 0.2s ease;
}
.inspect-live-dot.is-live {
  background: #4ade80;
  box-shadow: 0 0 8px rgba(74, 222, 128, 0.6);
}
.inspect-live-dot.is-stale {
  background: #f59e0b;
  box-shadow: 0 0 8px rgba(245, 158, 11, 0.5);
}
.inspect-live-dot.is-error {
  background: #ef4444;
  box-shadow: 0 0 8px rgba(239, 68, 68, 0.6);
}

.inspect-live-tiles {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  /* `1fr` was stretching tiles to fill the panel when only a few matched a
     filter — a single 4-tile row would balloon to 390px each. Use `auto`
     so tiles stay compact. Was minmax(96, auto) — that forced 96h on
     every row even with the icon removed. Drop to 60 so each tile fits
     its actual content (value + label + sparkline). */
  grid-auto-rows: minmax(60px, auto);
  gap: 8px;
  overflow-y: auto;
  align-content: start;
  padding-right: 4px;
}
.inspect-live-tiles::-webkit-scrollbar { width: 8px; }
.inspect-live-tiles::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.08); border-radius: 4px; }

/* Modal overlay for Custom Query / Chart — keeps the main panel scroll-free */
.inspect-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(2px);
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.inspect-modal-overlay[hidden] { display: none; }
.inspect-modal-card {
  background: rgba(16, 22, 30, 0.98);
  border: 1px solid var(--line);
  border-radius: 14px;
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
  width: 100%;
  max-width: 680px;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.inspect-modal-card--wide {
  max-width: 900px;
}
.inspect-modal-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  flex: 0 0 auto;
}
.inspect-modal-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
}
.inspect-modal-close {
  background: transparent;
  border: 1px solid var(--line);
  color: inherit;
  border-radius: 8px;
  width: 32px;
  height: 32px;
  cursor: pointer;
  font-size: 0.9rem;
}
.inspect-modal-close:hover {
  background: rgba(255, 255, 255, 0.06);
}
.inspect-modal-body {
  padding: 16px 20px 20px;
  overflow-y: auto;
  display: grid;
  gap: 14px;
  min-height: 0;
}

.live-tile {
  /* Icon column dropped (was a single emoji glyph, now hidden globally).
     Tile is now value + label as one flex column, meta as a second row.
     Sparkline + trend are absolute-positioned overlays. */
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 12px 22px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.018);
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
  min-height: 0;
  position: relative;
}
.live-tile:hover {
  border-color: rgba(50, 208, 189, 0.45);
  background: rgba(50, 208, 189, 0.045);
  transform: translateY(-1px);
  cursor: pointer;
}
.live-tile-icon {
  grid-row: 1 / 3;
  grid-column: 1;
  display: inline-flex;
  align-items: flex-start;
  justify-content: center;
  width: 36px;
  height: 36px;
  font-size: 1.35rem;
  border-radius: 10px;
  background: rgba(50, 208, 189, 0.16);
  margin-top: 2px;
}
.live-tile-body {
  /* Flex column inside the flex-column tile parent — value above label. */
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  min-width: 0;
}
.live-tile-value {
  /* Was 1.85rem (~30px) — that's a poster-sized number for one
     reading. Drop to 1.3rem (~21px) — still the most prominent
     element on the tile, but doesn't shout. */
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 1.15;
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", monospace;
  letter-spacing: -0.01em;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
}
.live-tile-value.is-stringy {
  font-size: var(--fs-lg);
  font-family: inherit;
  letter-spacing: normal;
  /* Long alert headlines and similar string values were overflowing the tile.
     Clamp to 3 lines with a trailing ellipsis. Hover still shows the full
     value via the title attribute the tile renderer sets. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  white-space: normal;
  line-height: 1.25;
  word-break: break-word;
}
.live-tile-unit {
  font-size: 0.85rem;
  font-weight: 500;
  margin-left: 4px;
  color: rgba(255, 255, 255, 0.55);
}
.live-tile-label {
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin-top: 2px;
}
.live-tile-meta {
  /* Inline in the flex-column tile (no grid). */
  font-size: 0.72rem;
  color: rgba(255, 255, 255, 0.45);
  font-variant-numeric: tabular-nums;
  display: flex;
  justify-content: space-between;
  gap: 8px;
}
.live-tile.is-stale .live-tile-meta {
  color: #f59e0b;
}
.live-tile.is-stale {
  border-color: rgba(245, 158, 11, 0.35);
}

.inspect-live-empty {
  padding: 16px;
  text-align: center;
  border: 1px dashed var(--line);
  border-radius: 12px;
}

/* Metric category chips — single-click filter to one metric family */
.inspect-live-categories {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 4px 0 6px;
}
.category-chip {
  font-size: 11px;
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  opacity: 0.85;
  transition: background 0.12s, border-color 0.12s, opacity 0.12s;
}
.category-chip:hover {
  background: rgba(108, 183, 255, 0.12);
  border-color: var(--accent, #6cb7ff);
  opacity: 1;
}
.category-chip.is-active {
  background: rgba(50, 208, 189, 0.2);
  border-color: rgba(50, 208, 189, 0.5);
  opacity: 1;
}

/* Outcome chip strip — recipe-style one-click actions */
.panel-outcomes {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 0;
  margin-bottom: 4px;
}
/* On narrow panel widths (< ~700px), scroll horizontally instead of
   wrapping into 3+ rows that crowd the page above the actual content. */
@media (max-width: 760px) {
  .panel-outcomes {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 10px;
  }
  .outcome-chip {
    flex-shrink: 0;
  }
}
/* Pages with narrow side-panel layouts (Plan 460px, Control cockpit 440px,
   Mesh rails ~340-420px). Force horizontal scroll on outcome chips +
   recipe rail there so they don't eat 2-3 rows of vertical real estate. */
#command-page .panel-outcomes,
#command-page .recipe-rail,
.cockpit-deck-panel .panel-outcomes,
.cockpit-deck-panel .recipe-rail,
.mesh-rail .panel-outcomes,
.mesh-rail .recipe-rail {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: thin;
  /* Parent grid auto-rows can squash this row to ~12px when overflow
     is enabled (browser thinks inner scroll handles overflow), leaving
     the chip text behind a useless vertical scrollbar. Pin a min-height
     so the chips are always legible. */
  min-height: 34px;
  overflow-y: hidden;
}
#command-page .outcome-chip,
#command-page .recipe-chip,
.cockpit-deck-panel .outcome-chip,
.cockpit-deck-panel .recipe-chip,
.mesh-rail .outcome-chip,
.mesh-rail .recipe-chip {
  flex-shrink: 0;
}
.outcome-chip {
  font-size: 12px;
  padding: 5px 12px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
}
.outcome-chip:hover {
  background: rgba(108, 183, 255, 0.14);
  border-color: var(--accent, #6cb7ff);
}
.outcome-chip:active {
  transform: scale(0.97);
  background: rgba(108, 183, 255, 0.22);
}
.outcome-chip.is-active {
  background: rgba(50, 208, 189, 0.18);
  border-color: rgba(50, 208, 189, 0.45);
}

/* Activity feed — clock button anchored top-right + a popover panel */
.activity-feed-button {
  /* Observe-page cleanup: the floating 🕒 recent-activity button was
     visual noise — the same history is reachable via Cmd+K's command
     palette and indirectly via Honu (which sees recent_recipes in the
     portal_state). Hidden in CSS so the JS that injects + tracks
     activity keeps running for those other consumers. */
  display: none;
  position: fixed;
  top: 24px;
  right: 96px;
  z-index: 75;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(7, 18, 24, 0.7);
  border: 1px solid rgba(163, 185, 188, 0.22);
  color: var(--ink);
  font-size: 14px;
  cursor: pointer;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  align-items: center;
  justify-content: center;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.activity-feed-button:hover { background: rgba(50, 208, 189, 0.18); border-color: rgba(50, 208, 189, 0.55); }
.activity-feed-button:active { transform: scale(0.95); }
.activity-feed-dot {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(50, 208, 189, 0.95);
  box-shadow: 0 0 0 1.5px rgba(7, 18, 24, 0.95);
  pointer-events: none;
}
.activity-feed-popover {
  position: fixed;
  z-index: 9600;
  background: rgba(7, 18, 24, 0.96);
  border: 1px solid rgba(163, 185, 188, 0.3);
  border-radius: 12px;
  padding: 12px 14px;
  width: 340px;
  max-height: 60vh;
  overflow-y: auto;
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5);
  color: var(--ink);
  backdrop-filter: blur(10px);
}
.activity-feed-popover header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  font-size: 13px;
}
.activity-feed-close {
  background: none; border: 0; color: rgba(255, 255, 255, 0.5);
  font-size: 18px; cursor: pointer; line-height: 1;
}
.activity-feed-close:hover { color: var(--ink); }
.activity-feed-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.activity-feed-item {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.05);
  font-size: 12px;
  transition: background 140ms ease, border-color 140ms ease, transform 80ms ease;
}
.activity-feed-item:hover {
  background: rgba(50, 208, 189, 0.08);
  border-color: rgba(50, 208, 189, 0.32);
}
.activity-feed-item:active { transform: translateY(1px); }
/* Kind-coded LEFT BORDER stripe instead of an emoji icon. Reads as a
   color band along the start edge of each row — recognizable without
   relying on emoji glyphs. */
.activity-feed-item { border-left-width: 3px; }
.activity-feed-item[data-activity-kind="recipe"] { border-left-color: #ffd574; }
.activity-feed-item[data-activity-kind="watch"]  { border-left-color: #ff8e8a; }
.activity-feed-item[data-activity-kind="ingest"] { border-left-color: var(--accent, #6cb7ff); }
.activity-feed-item[data-activity-kind="page"]   { border-left-color: rgba(180, 200, 210, 0.5); }
.activity-feed-icon {
  font-size: 11px;
  line-height: 1.4;
  font-family: "IBM Plex Mono", monospace;
  font-weight: 700;
  color: rgba(180, 200, 210, 0.8);
}
.activity-feed-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.activity-feed-text {
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.activity-feed-popover footer { margin-top: 10px; display: flex; justify-content: flex-end; }
.button-small { font-size: 11px; padding: 4px 10px; }

/* Map recipe rail — floats over the world raster. Was at top-left
   (top:76 left:80) which collided with the layer-toggle column and
   the Today card. Move it to a bottom-left strip above the time bar
   so it never fights the right-side Today card or context-drawer. */
.floating-map-recipe-rail {
  position: fixed;
  bottom: 100px;
  left: 16px;
  z-index: 70;
  display: none;
  flex-wrap: nowrap;
  gap: 4px;
  padding: 4px 8px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 10px;
  background: rgba(7, 18, 24, 0.78);
  backdrop-filter: blur(10px) saturate(1.1);
  -webkit-backdrop-filter: blur(10px) saturate(1.1);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.4);
  pointer-events: auto;
  max-width: calc(100vw - 32px);
  overflow-x: auto;
}
/* Observe-page cleanup: keep the floating recipe rail HIDDEN. Recipes
   are accessible via the header 🍳 button and the [r] hotkey — the
   floating widget was duplicative clutter on top of the map. The JS
   that injects + binds it still runs (so chips elsewhere keep working)
   — the rail just doesn't render. */
body[data-page="map"] .floating-map-recipe-rail { display: none; }
/* Also hide while the context-drawer is open so the operator can read
   station details without the rail in their peripheral vision. */
body[data-page="map"]:has(#context-drawer:not([hidden])) .floating-map-recipe-rail {
  display: none;
}
.floating-map-recipe-rail .recipe-rail-label { display: none; }
.floating-map-recipe-rail .recipe-chip { padding: 3px 8px; font-size: 11px; }

/* Map "Today" snapshot card — floats top-right of the map. Hidden on
   every page except the actual Map view. Shows live counts of stations,
   measurements today, watches, NHC storms, and the most-recent reading
   headline. Click any stat to jump to its drill-down. */
.map-today-card {
  position: fixed;
  top: 76px;
  right: 16px;
  z-index: 70;
  display: none;
  flex-direction: column;
  gap: 8px;
  width: 280px;
  padding: 10px 12px 12px;
  border: 1px solid rgba(163, 185, 188, 0.24);
  border-radius: 14px;
  background: rgba(7, 18, 24, 0.82);
  backdrop-filter: blur(12px) saturate(1.1);
  -webkit-backdrop-filter: blur(12px) saturate(1.1);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.42);
  pointer-events: auto;
  font-size: 12.5px;
  transition: border-color 200ms ease;
}
/* Observe-page cleanup: keep the Today snapshot card HIDDEN. The same
   information (alerting watch count, active station count) is already
   surfaced via the lighthouse alerts badge in the header + the nav-
   button status badges. The floating card was visual duplication. JS
   that ticks the refresh stays — the card just doesn't render. */
body[data-page="map"] .map-today-card { display: none; }
/* Hide the Today snapshot card when the right-side context-drawer is
   open — they both sit top-right of the map and would otherwise stack
   on top of each other. The drawer carries the active station's
   details, so the Today summary becomes redundant while it's open. */
body[data-page="map"]:has(#context-drawer:not([hidden])) .map-today-card {
  display: none;
}
.map-today-card.has-alert {
  border-color: rgba(255, 142, 138, 0.6);
  box-shadow: 0 0 0 1px rgba(255, 142, 138, 0.18), 0 14px 36px rgba(0, 0, 0, 0.42);
}
.map-today-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.map-today-head strong {
  font-size: 13.5px;
  flex: 1 1 auto;
}
.map-today-eyebrow {
  letter-spacing: 0.14em;
  font-weight: 700;
}
.map-today-refresh {
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  border-radius: 999px;
  width: 22px;
  height: 22px;
  padding: 0;
  font-size: 12px;
  cursor: pointer;
  transition: transform 160ms ease, color 160ms ease;
}
.map-today-refresh:hover { color: var(--accent); transform: rotate(60deg); }
.map-today-stats {
  /* Was 2x2 grid of boxed cards (55h each, total 220h+ for 4 stats).
     Switch to a vertical readout list — each stat is a single row
     with label left, value right. 4 stats in ~110h. */
  display: flex;
  flex-direction: column;
  gap: 1px;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.map-today-stat {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 10px;
  border: 0;
  border-radius: 0;
  background: rgba(255, 255, 255, 0.02);
  color: var(--ink);
  text-align: left;
  cursor: pointer;
  transition: background 140ms ease, transform 80ms ease;
  width: 100%;
}
.map-today-stat + .map-today-stat {
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.map-today-stat:hover {
  background: rgba(50, 208, 189, 0.08);
}
.map-today-stat:active { transform: translateY(1px); }
.map-today-stat span {
  flex: 1 1 auto;
  font-size: 11px;
  color: rgba(180, 200, 210, 0.62);
}
.map-today-stat strong {
  flex: 0 0 auto;
  font-size: 14px;
  font-family: "IBM Plex Mono", monospace;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* When the card is in alert state, paint the watches + storms strongs red
   so the operator's eye lands on the urgent counts. */
.map-today-card.has-alert .map-today-stat[data-today-action="watches"] strong,
.map-today-card.has-alert .map-today-stat[data-today-action="storms"] strong {
  color: #ff8e8a;
}
/* Subtle pulse on the active-alert stat to draw attention. */
.map-today-card.has-alert .map-today-stat[data-today-action="watches"] {
  border-color: rgba(255, 142, 138, 0.4);
  background: rgba(255, 142, 138, 0.06);
  animation: today-alert-pulse 2.2s ease-in-out infinite;
}
@keyframes today-alert-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 142, 138, 0.0); }
  50% { box-shadow: 0 0 0 3px rgba(255, 142, 138, 0.12); }
}
.map-today-headline {
  margin: 0;
  padding: 4px 2px 0;
  font-size: 11px;
  line-height: 1.4;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

/* Blog source-health summary-strip — debug-ish stats hidden behind a
   summary so the briefing list isn't pushed 122px down on every load. */
.blog-source-health {
  margin: 6px 0 4px;
}
.blog-source-health > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
}
.blog-source-health > summary::-webkit-details-marker { display: none; }
.blog-source-health > summary::before {
  content: "▸ ";
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
}
.blog-source-health[open] > summary::before { content: "▾ "; }
.blog-source-health > #blog-source-summary { display: none; margin-top: 8px; }
.blog-source-health[open] > #blog-source-summary { display: grid; }

/* Compact inventory card — header + 1-line summary + details fold.
   27 cards × 415px = 4000px was unacceptable scroll. Now ~120px each.
   (Kept .source-grid 3-col default — bumping to 4 wraps the name and
    eats the savings.) */
.inventory-card-compact { padding: 10px 12px; }
.inventory-card-compact .small { font-size: 11.5px; }
.inventory-card-details > summary {
  cursor: pointer;
  list-style: none;
  padding: 2px 0;
}
.inventory-card-details > summary::-webkit-details-marker { display: none; }
.inventory-card-details[open] > summary { color: var(--accent); }
.inventory-card-details-body { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.inventory-card-details-body p { margin: 0; }

/* Provider-collapsible — wraps the 3 provider workbenches (GFW,
   EarthData, Copernicus) on library:providers behind <details>. Collapsed
   summary stays compact; opening shows the full provider tool. */
.provider-collapsible > details > summary {
  cursor: pointer;
  list-style: none;
  padding: 4px 0;
}
.provider-collapsible > details > summary::-webkit-details-marker { display: none; }
.provider-collapsible > details > summary h3::after {
  content: " ▸";
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.5);
  display: inline-block;
}
.provider-collapsible > details[open] > summary h3::after { content: " ▾"; }

/* Collapsible details inside settings panels — used for big "debug-only"
   sub-panels that would otherwise consume hundreds of px by default. */
.settings-collapsible > summary {
  cursor: pointer;
  list-style: none;
  padding: 4px 0;
}
.settings-collapsible > summary::-webkit-details-marker { display: none; }
.settings-collapsible > summary .section-row { gap: 12px; }
.settings-collapsible > summary h2::after {
  content: " ▸";
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.5);
  transition: transform 0.15s;
  display: inline-block;
}
.settings-collapsible[open] > summary h2::after { content: " ▾"; }

/* Diagnostics: by default hide cards that PASS so the operator focuses
   on Warn/Fail issues. Toggle via the "👁 Show all" chip in the
   diagnostics outcomes row to reveal passing cards too. */
body[data-diag-passing="hide"] .system-check-panel #preflight-check-list .check-card.is-pass,
body[data-diag-passing="hide"] .system-check-panel #system-check-list .check-card.is-pass,
body[data-diag-passing="hide"] .system-check-panel #preflight-actions .check-card.is-pass {
  display: none;
}

/* HaLow check list: hide PASS check-row-cards by default too — when
   all 5/5 are passing the operator only needs the summary-strip. */
.halow-check-list { display: flex; flex-direction: column; gap: 6px; }
.halow-check-list .check-row-card {
  display: grid; grid-template-columns: auto 1fr; gap: 8px;
  padding: 6px 10px; border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
body[data-diag-passing="hide"] .halow-check-list .check-row-card:has(.status-pass) {
  display: none;
}

/* Tool Directory was a 5,000px inline list duplicating Cmd+K. Collapsed
   to a Cmd+K launcher + a "Show legacy view" details fallback. */
.tool-directory-collapsed .tool-directory-actions {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 12px;
  flex-wrap: wrap;
}
.tool-directory-full-details {
  margin-top: 12px;
  padding: 10px 14px;
  border: 1px dashed rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.02);
}
.tool-directory-full-details > summary {
  cursor: pointer;
  list-style: none;
  margin-bottom: 8px;
}
.tool-directory-full-details > summary::-webkit-details-marker { display: none; }
.tool-directory-full-details > summary::before {
  content: "▸ ";
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
}
.tool-directory-full-details[open] > summary::before { content: "▾ "; }

/* Inlined Survey Upload — merged into Survey Plan as a collapsible.
   Same collapsible pattern as .data-lab-details. */
.survey-upload-inline { margin-top: 8px; }
.survey-upload-details {
  border: 1px dashed rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.02);
}
.survey-upload-details > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.survey-upload-details > summary::-webkit-details-marker { display: none; }
.survey-upload-details > summary::before {
  content: "▸";
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
  transition: transform 0.15s;
}
.survey-upload-details[open] > summary::before { transform: rotate(90deg); }
.survey-upload-body { margin-top: 10px; display: flex; flex-direction: column; gap: 10px; }

/* Inlined Data Lab — was its own sub-view, now lives at the bottom of
   Find Sources as an optional <details> so it doesn't waste a picker slot
   while staying reachable when an operator needs to inspect a local
   CSV/GeoJSON/KML file. */
.data-lab-form-inline { margin-top: 8px; }
.data-lab-details {
  border: 1px dashed rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.02);
}
.data-lab-details > summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: 8px;
}
.data-lab-details > summary::-webkit-details-marker { display: none; }
.data-lab-details > summary::before {
  content: "▸";
  font-size: 11px;
  color: rgba(255, 255, 255, 0.5);
  transition: transform 0.15s;
}
.data-lab-details[open] > summary::before { transform: rotate(90deg); }
.data-lab-body { margin-top: 10px; display: flex; flex-direction: column; gap: 10px; }

/* Keyboard cheat-sheet overlay (shown with `?`) */
.hotkey-cheat-sheet {
  position: fixed;
  inset: 0;
  z-index: 9700;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(3px);
}
.hotkey-cheat-card {
  background: rgba(7, 18, 24, 0.96);
  border: 1px solid rgba(50, 208, 189, 0.4);
  border-radius: 14px;
  padding: 18px 22px;
  width: min(640px, 92vw);
  color: var(--ink);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55);
}
.hotkey-cheat-card header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  font-size: 15px;
}
.hotkey-cheat-close {
  background: none; border: 0; color: rgba(255,255,255,0.5); font-size: 22px; cursor: pointer; line-height: 1;
}
.hotkey-cheat-close:hover { color: var(--ink); }
.hotkey-cheat-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.hotkey-cheat-section h4 {
  margin: 0 0 6px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.5);
}
.hotkey-cheat-section ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}
.hotkey-cheat-section kbd {
  display: inline-block;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 11px;
  font-family: ui-monospace, monospace;
  margin-right: 2px;
}

/* Toast notifications — bottom-right stack of dismissable cards used
   by recipes and other multi-step workflows to confirm completion.
   Each toast can carry an action button (e.g. "View" / "Undo"). */
.toast-host {
  position: fixed;
  bottom: 22px;
  right: 22px;
  /* Toasts are transient, non-blocking feedback and must stay visible over
     every overlay that can be open when one fires — popovers (9600), the
     hotkey cheat-sheet (9700), context menus / pickers and the full-screen
     research help overlay (9999). Kept as the topmost layer. */
  z-index: 10050;
  display: flex;
  flex-direction: column-reverse;
  gap: 10px;
  max-width: min(360px, 90vw);
  pointer-events: none;
}
.toast {
  background: linear-gradient(135deg, rgba(50, 208, 189, 0.18), rgba(7, 18, 24, 0.96));
  border: 1px solid rgba(50, 208, 189, 0.45);
  border-radius: 12px;
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  color: var(--ink);
  font-size: 13px;
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.5);
  pointer-events: auto;
  animation: toast-in 0.22s ease-out;
  transition: opacity 0.2s, transform 0.2s;
}
.toast.is-alert {
  background: linear-gradient(135deg, rgba(251, 113, 133, 0.22), rgba(7, 18, 24, 0.96));
  border-color: rgba(251, 113, 133, 0.55);
}
.toast.is-warn {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.22), rgba(7, 18, 24, 0.96));
  border-color: rgba(245, 158, 11, 0.55);
}
.toast-head { display: flex; gap: 8px; align-items: flex-start; }
.toast-text { flex: 1; line-height: 1.35; }
.toast-close {
  background: none;
  border: 0;
  color: rgba(255, 255, 255, 0.5);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0 2px;
}
.toast-close:hover { color: var(--ink); }
.toast-actions { display: flex; gap: 6px; }
.toast-action {
  font-size: 12px;
  padding: 4px 10px;
  border: 1px solid rgba(50, 208, 189, 0.5);
  border-radius: 12px;
  background: rgba(50, 208, 189, 0.15);
  color: var(--ink);
  cursor: pointer;
}
.toast-action:hover { background: rgba(50, 208, 189, 0.3); }
.toast.is-leaving { opacity: 0; transform: translateX(20px); }
@keyframes toast-in {
  from { opacity: 0; transform: translateX(20px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Recipe rail — sits below the outcome-chip row and offers multi-step
   automated workflows (synthesize data → execute UI pivot). Visually
   distinct from outcome-chips (which are single-action shortcuts) so the
   operator's eye learns the difference: chips = navigate / preset,
   recipes = "go do this thing for me". */
.recipe-rail {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  padding: 4px 0 8px;
  margin: 0 0 6px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.08);
}
.recipe-rail-label {
  font-weight: 600;
  margin-right: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 10px;
}
.recipe-rail-sublabel {
  margin-right: 8px;
  font-style: italic;
}
/* "Prominent" variant — used on the Analyze + Data builder panels where
   recipes are the recommended starting point. Tinted background +
   accent-colored label make them visually unmistakable as "do this
   first" presets (vs. the duller default-recipe-rail which is fine for
   secondary contexts like the mesh page rail). */
.recipe-rail-prominent {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.06), rgba(50, 208, 189, 0.04));
  border: 1px solid rgba(196, 181, 253, 0.18);
  border-radius: 10px;
  padding: 8px 12px;
  margin: 6px 0 10px;
  border-bottom: 1px solid rgba(196, 181, 253, 0.18);
}
.recipe-rail-prominent .recipe-rail-label {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--accent);
}
.recipe-chip {
  font-size: 12px;
  padding: 5px 12px;
  border: 1px solid rgba(196, 181, 253, 0.22);
  border-radius: 14px;
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.10), rgba(50, 208, 189, 0.08));
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, transform 0.06s, box-shadow 0.12s;
}
.recipe-chip:hover {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.20), rgba(50, 208, 189, 0.16));
  border-color: rgba(196, 181, 253, 0.55);
  box-shadow: 0 4px 14px rgba(124, 58, 237, 0.15);
}
.recipe-chip:active { transform: scale(0.97); }
/* Metric not in the current data: dim + not-allowed, but still clickable so the
   handler can explain why (it doesn't render a blank chart). */
.recipe-chip.is-unavailable {
  opacity: 0.4;
  filter: grayscale(0.65);
  cursor: not-allowed;
}
.recipe-chip.is-unavailable:hover {
  background: linear-gradient(135deg, rgba(124, 58, 237, 0.10), rgba(50, 208, 189, 0.08));
  border-color: rgba(196, 181, 253, 0.22);
  box-shadow: none;
}
.recipe-chip.is-running {
  background: linear-gradient(135deg, rgba(245, 158, 11, 0.25), rgba(245, 158, 11, 0.12));
  border-color: rgba(245, 158, 11, 0.6);
  cursor: wait;
  animation: recipe-pulse 1s ease-in-out infinite;
}
@keyframes recipe-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0.35); }
  50% { box-shadow: 0 0 0 6px rgba(245, 158, 11, 0); }
}
@media (max-width: 760px) {
  .recipe-rail {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
  }
  .recipe-chip { flex-shrink: 0; }
}

/* Live tile filter row — search + 2 selects + fresh-only toggle, all on
   one row. Without explicit width:auto + flex bases, the global
   `select, input { width: 100% }` rule was making every control take a
   full row, blowing the filter row to 198h. */
.inspect-live-filter-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px 8px;
  flex-wrap: wrap;
}
.inspect-live-filter-row > .inspect-live-search,
.inspect-live-filter-row > .inspect-live-sort {
  width: auto;
  min-height: 32px;
}
.inspect-live-search {
  flex: 1 1 220px;
  min-width: 180px;
  padding: 6px 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(16, 22, 30, 0.7);
  color: var(--ink);
  font-size: 13px;
}
.inspect-live-search:focus {
  outline: none;
  border-color: var(--accent, #6cb7ff);
}
.inspect-live-sort {
  flex: 0 0 auto;
  max-width: 220px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(16, 22, 30, 0.7);
  color: var(--ink);
  font-size: 12px;
  cursor: pointer;
}
.inspect-live-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink);
  opacity: 0.85;
  cursor: pointer;
  white-space: nowrap;
}
.inspect-live-toggle input[type="checkbox"] {
  margin: 0;
  cursor: pointer;
}

/* Sparkline strip inside each tile */
.live-tile-sparkline {
  position: absolute;
  bottom: 28px;
  left: 8px;
  right: 8px;
  height: 22px;
  opacity: 0.85;
  pointer-events: none;
}
.live-tile-sparkline svg {
  width: 100%;
  height: 100%;
  display: block;
}
.live-tile-sparkline path.stroke {
  fill: none;
  stroke: rgba(108, 183, 255, 0.85);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.live-tile-sparkline path.fill {
  fill: rgba(108, 183, 255, 0.12);
  stroke: none;
}
.live-tile.is-stale .live-tile-sparkline path.stroke {
  stroke: rgba(245, 158, 11, 0.7);
}
.live-tile.is-stale .live-tile-sparkline path.fill {
  fill: rgba(245, 158, 11, 0.1);
}

/* Tile becomes a position parent for sparkline + trend arrow */
.live-tile {
  position: relative;
  border-left: 3px solid transparent;
}
/* Category accent stripe — quick visual sort across the dashboard */
.live-tile.is-cat-temp    { border-left-color: rgba(249, 115, 22, 0.7); }   /* orange */
.live-tile.is-cat-wave    { border-left-color: rgba(108, 183, 255, 0.7); }  /* blue   */
.live-tile.is-cat-current { border-left-color: rgba(50, 208, 189, 0.7); }   /* teal   */
.live-tile.is-cat-wind    { border-left-color: rgba(125, 211, 252, 0.7); }  /* sky    */
.live-tile.is-cat-gps     { border-left-color: rgba(167, 139, 250, 0.7); }  /* purple */
.live-tile.is-cat-hw      { border-left-color: rgba(148, 163, 184, 0.7); }  /* gray   */
.live-tile.is-cat-weather { border-left-color: rgba(251, 191, 36, 0.7); }   /* amber  */
.live-tile-trend {
  position: absolute;
  top: 8px;
  right: 8px;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
}
.live-tile-trend.is-up { color: #f97373; background: rgba(249, 115, 115, 0.12); }
.live-tile-trend.is-down { color: #6cb7ff; background: rgba(108, 183, 255, 0.12); }
.live-tile-trend.is-flat { color: rgba(255, 255, 255, 0.5); }

/* Quick chart popover */
.inspect-quick-chart {
  position: absolute;
  inset: 60px 16px auto 16px;
  background: rgba(16, 22, 30, 0.97);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px;
  z-index: 50;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.5);
}
.inspect-quick-chart-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 10px;
}
.inspect-quick-chart-titletext {
  margin: 0 0 2px;
  font-size: 16px;
  font-weight: 600;
}
.inspect-quick-chart-tools {
  display: flex;
  align-items: center;
  gap: 6px;
}
.inspect-quick-chart-canvas {
  background: rgba(0, 0, 0, 0.25);
  border-radius: 8px;
  padding: 8px;
}
.inspect-quick-chart-canvas svg {
  width: 100%;
  height: 180px;
  display: block;
}
.inspect-quick-chart-canvas path.stroke {
  fill: none;
  stroke: var(--accent, #6cb7ff);
  stroke-width: 1.5;
  stroke-linecap: round;
}
.inspect-quick-chart-canvas path.fill {
  fill: rgba(108, 183, 255, 0.15);
  stroke: none;
}
.inspect-quick-chart-canvas circle.point {
  fill: var(--accent, #6cb7ff);
}
.inspect-quick-chart-canvas line.axis,
.inspect-quick-chart-canvas line.grid {
  stroke: rgba(255, 255, 255, 0.08);
  stroke-width: 1;
}
.inspect-quick-chart-stats {
  margin-top: 10px;
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
}
.inspect-quick-chart-stats strong {
  color: var(--ink);
  font-weight: 600;
}
.inspect-quick-chart-related {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed rgba(255, 255, 255, 0.08);
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.inspect-quick-chart-related-label {
  margin-right: 4px;
  white-space: nowrap;
}
.inspect-quick-chart-related-chip {
  font-size: 11px;
  padding: 3px 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
.inspect-quick-chart-related-chip:hover {
  background: rgba(108, 183, 255, 0.15);
  border-color: var(--accent, #6cb7ff);
}
.inspect-quick-chart-related-chip strong {
  color: var(--ink);
  font-weight: 600;
}
.inspect-quick-chart-related-chip .muted {
  color: var(--muted);
  font-size: 10px;
}

.inspect-quick-actions {
  margin: 14px 0 4px;
}
.inspect-quick-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}
.inspect-quick-title {
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--text);
}
.inspect-quick-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.inspect-quick-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px 10px;
  border: 1px solid rgba(50, 208, 189, 0.22);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.22);
  color: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
  font: inherit;
}
.inspect-quick-card:hover {
  border-color: var(--accent, #32d0bd);
  background: rgba(50, 208, 189, 0.08);
  transform: translateY(-1px);
}
.inspect-quick-card:focus-visible {
  outline: 2px solid var(--accent, #32d0bd);
  outline-offset: 2px;
}
.inspect-quick-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.inspect-quick-card-head strong {
  font-size: 0.9rem;
}
.inspect-quick-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  font-size: 1.05rem;
  border-radius: 8px;
  background: rgba(50, 208, 189, 0.14);
  flex: none;
}
.inspect-quick-blurb {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.7);
  flex: 1;
}
.inspect-quick-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px;
  padding-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: var(--fs-xs);
}
.inspect-quick-tag {
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
  padding: 1px 6px;
  color: rgba(255, 255, 255, 0.62);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
}
.inspect-quick-run {
  margin-left: auto;
  font-weight: 700;
  color: var(--accent, #32d0bd);
}
.inspect-quick-card:hover .inspect-quick-run {
  color: #67e8f9;
}

.inspect-advanced {
  margin-top: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.018);
  padding: 4px 12px;
}
.inspect-advanced[open] {
  padding-bottom: 12px;
}
.inspect-advanced-summary {
  cursor: pointer;
  padding: 10px 4px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  list-style: none;
}
.inspect-advanced-summary::-webkit-details-marker {
  display: none;
}
.inspect-advanced-summary::before {
  content: "▸ ";
  display: inline-block;
  width: 14px;
  transition: transform 0.12s ease;
}
.inspect-advanced[open] .inspect-advanced-summary::before {
  transform: rotate(90deg);
}

.data-browser-step {
  margin: 14px 0 6px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.018);
  display: grid;
  gap: 8px;
}

.data-browser-step-label {
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

.data-browser-source-row {
  display: grid;
  grid-template-columns: minmax(160px, 0.4fr) minmax(220px, 1fr);
  gap: 8px;
}
.data-browser-source-row > input[type="search"],
.data-browser-source-row > select {
  padding: 7px 10px;
  font-size: 0.84rem;
}

.data-browser-refine-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: end;
}
.data-browser-refine-row > input[type="search"] {
  padding: 7px 10px;
  font-size: 0.84rem;
}
.data-browser-rows-label {
  display: flex;
  flex-direction: column;
  font-size: 0.72rem;
  color: var(--muted);
  gap: 2px;
}
.data-browser-rows-label > input {
  width: 72px;
  padding: 7px 10px;
  font-size: 0.84rem;
  font-family: ui-monospace, "SF Mono", monospace;
  text-align: right;
}

.data-browser-intent-chips {
  margin: 0;
}

.data-browser-results {
  margin-top: 14px;
  display: grid;
  gap: 8px;
}

.data-browser-results-toolbar {
  display: flex;
  gap: 8px;
  align-items: center;
}
.data-browser-results-toolbar > .data-browser-filter-input {
  flex: 1 1 auto;
  margin: 0;
}

.data-browser-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-shrink: 0;
}

.data-browser-overflow {
  position: relative;
}
.data-browser-overflow > summary {
  list-style: none;
  cursor: pointer;
  padding: 6px 10px;
  font-size: var(--fs-md);
}
.data-browser-overflow > summary::-webkit-details-marker {
  display: none;
}
.data-browser-overflow-menu {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  z-index: 30;
  min-width: 220px;
  padding: 6px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(16, 22, 30, 0.96);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  display: grid;
  gap: 2px;
}
.data-browser-overflow-menu > hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 4px 0;
}
.data-browser-overflow-item {
  text-align: left;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-size: 0.84rem;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  text-decoration: none;
  display: block;
}
.data-browser-overflow-item:hover {
  background: rgba(255, 255, 255, 0.06);
}

.data-browser-chart-section {
  margin-top: 14px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.018);
  padding: 4px 12px;
}
.data-browser-chart-section[open] {
  padding-bottom: 12px;
}
.data-browser-chart-summary {
  cursor: pointer;
  padding: 10px 4px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text);
  list-style: none;
}
.data-browser-chart-summary::-webkit-details-marker {
  display: none;
}
.data-browser-chart-summary::before {
  content: "▸ ";
  display: inline-block;
  width: 14px;
  transition: transform 0.12s ease;
}
.data-browser-chart-section[open] .data-browser-chart-summary::before {
  transform: rotate(90deg);
}
.data-browser-chart-section .data-browser-chart-toolbar label {
  display: flex;
  flex-direction: column;
  font-size: 0.72rem;
  color: var(--muted);
  gap: 2px;
}
.data-browser-chart-section .data-browser-chart-toolbar select {
  padding: 7px 10px;
  font-size: 0.84rem;
}

.stat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(86px, 1fr));
  gap: 8px;
}

.stat-cell {
  display: grid;
  gap: 3px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(238, 246, 245, 0.045);
}

.stat-cell span {
  color: var(--muted);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.stat-cell strong {
  color: var(--text);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-md);
  font-weight: 600;
}

.viz-outlier-list {
  list-style: none;
  margin: 4px 0 0;
  padding: 0;
  display: grid;
  gap: 4px;
}

.viz-outlier-list li {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: rgba(238, 246, 245, 0.04);
  font-size: var(--fs-base);
}

.viz-outlier-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.viz-outlier-figure {
  flex-shrink: 0;
  color: var(--accent);
  font-family: "IBM Plex Mono", monospace;
}

.viz-outlier-clear {
  color: var(--muted);
  font-size: var(--fs-base);
}

.table-preview-note {
  grid-column: 1 / -1;
  color: var(--muted);
  font-size: 0.78rem;
}

.data-browser-table .table-head span.sortable-col {
  cursor: pointer;
  user-select: none;
  transition: color 0.15s ease;
}

.data-browser-table .table-head span.sortable-col:hover,
.data-browser-table .table-head span.sortable-col.is-sorted {
  color: var(--accent);
}

.tool-form {
  display: grid;
  gap: 10px;
  align-content: start;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel-soft);
}

.tool-form h3 {
  margin-bottom: 0;
}

.inline-tool {
  grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
  align-items: end;
}

.inline-tool h3,
.inline-tool .tool-result,
.inline-tool > p {
  grid-column: 1 / -1;
}

.tool-result {
  min-height: 44px;
}

.tool-directory-section {
  display: grid;
  gap: 14px;
}

.system-check-panel,
.tool-directory-group {
  display: grid;
  /* Pin the content column to the panel width so wide children (button
     rows, fixed-min grids) can't balloon the panel off-screen. */
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  padding: 12px 16px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel-soft);
}

/* Compact the section-row title block inside system-check-panel. The
   default h2 (24px font) wraps long titles like "Command Authorization"
   to 2 lines + adds vertical padding. Use 17px font to keep titles on
   one line and tighten the eyebrow/h2 stack. Saves ~40px per panel. */
.system-check-panel .section-row > div > .eyebrow {
  margin: 0 0 1px;
  font-size: 10px;
  letter-spacing: 0.12em;
}
.system-check-panel .section-row > div > h2 {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.25;
  font-weight: 700;
}
.system-check-panel .section-row {
  align-items: center;
  gap: 10px;
}

/* Settings panels: the descriptive p.muted text under each section title
   is one-time onboarding. Move it under the title as a small subtitle,
   and the SECOND p.muted (auxiliary status / hint) shrinks too. */
#settings-page .system-check-panel > p.muted {
  font-size: 0.75rem;
  margin: -2px 0 2px;
  line-height: 1.35;
  color: rgba(180, 200, 210, 0.62);
}

.tool-directory {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}

.tool-directory-details summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  cursor: pointer;
  color: var(--muted);
  font-weight: 800;
}

.tool-directory-details[open] summary {
  color: var(--ink);
}

.tool-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.04);
}

.tool-card p {
  margin: 4px 0 0;
}

.tool-card.is-planned,
.tool-result-button.is-disabled {
  opacity: 0.78;
}

.tool-card-actions {
  display: grid;
  gap: 8px;
  justify-items: end;
}

.tool-note {
  color: var(--muted);
  font-size: var(--fs-base);
  font-weight: 700;
}

.check-list {
  display: grid;
  gap: 8px;
}

.check-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.04);
}

.check-card.is-pass {
  border-color: rgba(85, 211, 138, 0.22);
}

.check-card.is-fail {
  border-color: rgba(251, 113, 133, 0.32);
}

.check-card.is-warn {
  border-color: rgba(250, 204, 21, 0.3);
  background: rgba(250, 204, 21, 0.055);
}

.compact-check-list {
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-bottom: 10px;
}

.check-card p {
  margin: 4px 0 0;
}

.check-row {
  display: flex;
  align-items: center;
  gap: 9px;
  color: var(--muted);
  font-weight: 700;
}

.check-row input {
  width: auto;
  min-height: auto;
}

.route-result {
  min-height: 320px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--panel-soft);
}
/* Empty route-result is just "no route generated yet" — 320h
   placeholder is too aggressive. */
.route-result.empty { min-height: 44px; padding: 8px 14px; }

/* Plan-page forms are subtle cards inside the glass planning drawer. */
body[data-page="command"] .tool-form,
body[data-page="command"] .route-result {
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
  box-shadow: none;
  backdrop-filter: none;
}

/* Route form Ã¢â‚¬â€ task-grouped sections. */
.route-section {
  display: grid;
  gap: 8px;
}

.form-group-label {
  margin: 0;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.55);
}

.route-pick-actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}

.route-manual > summary {
  cursor: pointer;
  padding: 3px 0;
  font-size: 0.72rem;
  color: rgba(125, 211, 252, 0.85);
}

.route-manual-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  margin-top: 6px;
}

.route-actions {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 8px;
}

/* Depth-clearance callout in the route plan result. */
.route-clearance {
  display: grid;
  gap: 8px;
  margin-bottom: 12px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-left: 3px solid rgba(150, 168, 172, 0.6);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.03);
}

.route-clearance.is-ok {
  border-left-color: #55d38a;
}

.route-clearance.is-caution {
  border-left-color: #f6b15e;
}

.route-clearance.is-unsafe {
  border-left-color: #fb7185;
}

.route-clearance-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.route-clearance-head .eyebrow {
  margin: 0;
}

.route-clearance-badge {
  padding: 3px 10px;
  border-radius: 999px;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  background: rgba(150, 168, 172, 0.18);
  color: var(--muted);
}

.route-clearance.is-ok .route-clearance-badge {
  background: rgba(85, 211, 138, 0.18);
  color: #7ae0a4;
}

.route-clearance.is-caution .route-clearance-badge {
  background: rgba(246, 177, 94, 0.2);
  color: #f6b15e;
}

.route-clearance.is-unsafe .route-clearance-badge {
  background: rgba(251, 113, 133, 0.2);
  color: #fb9aa8;
}

.route-clearance p {
  margin: 0;
}

.route-clearance-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.route-clearance-metrics span {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.7rem;
  color: var(--muted);
}

.route-clearance-metrics strong {
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-md);
  color: var(--ink);
}

/* Survey & waypoint plan authoring (Plan page). */
.survey-plan-modes,
.survey-plan-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.survey-plan-modes .button {
  flex: 1;
  min-width: 120px;
}

.survey-plan-readout {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.86rem;
  color: var(--ink);
}

.survey-plan-points {
  display: grid;
  gap: 6px;
  max-height: 220px;
  overflow: auto;
}

.survey-plan-points.empty {
  color: var(--muted);
  font-size: 0.8rem;
}

.survey-plan-point {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.025);
}

.survey-plan-point-index {
  flex: none;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(50, 208, 189, 0.18);
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 700;
}

.survey-plan-point-coord {
  flex: 1;
  min-width: 0;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.78rem;
  color: var(--ink);
}

.survey-plan-point-remove {
  flex: none;
  width: 24px;
  height: 24px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}

.survey-plan-point-remove:hover {
  color: #fb9aa8;
  border-color: rgba(251, 113, 133, 0.5);
}

.leaflet-tooltip.survey-plan-marker-label {
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
  color: #04121a;
  font-weight: 700;
  font-size: 0.7rem;
}

/* Operational alerts Ã¢â‚¬â€ header badge + alerts panel. */
.alerts-badge {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 12px;
  border: 1px solid rgba(120, 160, 170, 0.28);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}

.alerts-badge:hover {
  border-color: rgba(50, 208, 189, 0.5);
  background: rgba(50, 208, 189, 0.06);
}

/* Icon-only mode: round button matching nav-button visual weight.
   Severity is communicated by icon color + beam rotation speed + lamp
   pulse. */
.alerts-badge.is-icon-only {
  padding: 4px;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  justify-content: center;
}
.alerts-badge.is-icon-only .alerts-badge-dot,
.alerts-badge.is-icon-only #alerts-badge-count { display: none; }
.alerts-badge.is-icon-only .alerts-badge-icon {
  width: 28px;
  height: 28px;
}

.alerts-badge-icon {
  width: 20px;
  height: 20px;
  color: var(--accent, #32d0bd);
  flex: none;
  transition: color 0.3s ease;
}
.alerts-badge[data-severity="warning"] .alerts-badge-icon { color: #f6b15e; }
.alerts-badge[data-severity="critical"] .alerts-badge-icon { color: #fb7185; }

.alerts-badge-lamp {
  transform-box: fill-box;
  transform-origin: center;
  animation: lighthouse-lamp-pulse 2.4s ease-in-out infinite;
  filter: drop-shadow(0 0 2px currentColor);
}
.alerts-badge[data-severity="warning"] .alerts-badge-lamp {
  animation-duration: 1.4s;
  filter: drop-shadow(0 0 4px currentColor);
}
.alerts-badge[data-severity="critical"] .alerts-badge-lamp {
  animation-duration: 0.8s;
  filter: drop-shadow(0 0 6px currentColor);
}
@keyframes lighthouse-lamp-pulse {
  0%, 100% { opacity: 0.55; transform: scale(0.9); }
  50%      { opacity: 1; transform: scale(1.15); }
}

.lighthouse-beam-group {
  transform-origin: 20px 14px;
  animation: lighthouse-beam-rotate 8s linear infinite;
}
.alerts-badge[data-severity="warning"] .lighthouse-beam-group { animation-duration: 5s; }
.alerts-badge[data-severity="critical"] .lighthouse-beam-group { animation-duration: 2.5s; }
@keyframes lighthouse-beam-rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.alerts-badge-dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: #55d38a;
}

.alerts-badge[data-severity="warning"] {
  border-color: rgba(246, 177, 94, 0.55);
  background: rgba(246, 177, 94, 0.14);
}

.alerts-badge[data-severity="warning"] .alerts-badge-dot {
  background: #f6b15e;
  box-shadow: 0 0 8px rgba(246, 177, 94, 0.8);
}

.alerts-badge[data-severity="critical"] {
  border-color: rgba(251, 113, 133, 0.6);
  background: rgba(251, 113, 133, 0.16);
}

.alerts-badge[data-severity="critical"] .alerts-badge-dot {
  background: #fb7185;
  box-shadow: 0 0 8px rgba(251, 113, 133, 0.85);
}

.alerts-panel {
  position: fixed;
  top: 86px;
  right: 16px;
  z-index: 220;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  gap: 10px;
  width: 320px;
  max-height: calc(100vh - 110px);
  padding: 14px;
  border: 1px solid rgba(120, 160, 170, 0.24);
  border-top: 2px solid rgba(50, 208, 189, 0.5);
  border-radius: 14px;
  background: rgba(5, 12, 16, 0.96);
  box-shadow: 0 26px 64px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(16px);
}

.alerts-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.alerts-panel-head .eyebrow {
  margin: 0;
}

.alerts-refresh {
  padding: 4px 10px;
  border: 1px solid rgba(120, 160, 170, 0.24);
  border-radius: 7px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}

.alerts-refresh:hover {
  color: var(--ink);
  border-color: rgba(50, 208, 189, 0.5);
}

.alerts-list {
  display: grid;
  gap: 6px;
  min-height: 0;
  overflow: auto;
  align-content: start;
}

.alerts-list.empty {
  color: var(--muted);
  font-size: 0.8rem;
  line-height: 1.5;
}

.alert-row {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-left: 3px solid rgba(150, 168, 172, 0.6);
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.025);
}

.alert-row.alert-warning {
  border-left-color: #f6b15e;
}

.alert-row.alert-critical {
  border-left-color: #fb7185;
}

.alert-dot {
  width: 8px;
  height: 8px;
  flex: none;
  margin-top: 4px;
  border-radius: 50%;
  background: var(--muted);
}

.alert-warning .alert-dot {
  background: #f6b15e;
}

.alert-critical .alert-dot {
  background: #fb7185;
}

.alert-text {
  display: grid;
  gap: 2px;
  min-width: 0;
}

.alert-text strong {
  font-size: 0.8rem;
  color: var(--ink);
}

.alert-text span {
  font-size: 0.72rem;
  color: var(--muted);
}

.report-panel {
  display: grid;
  gap: 14px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 20px;
  background:
    radial-gradient(circle at 0% 0%, rgba(50, 208, 189, 0.1), transparent 36%),
    var(--panel-soft);
}

/* Data + Analyze sub-views with long card/chart grids. Each section had
   ~700-4000px of content and made the entire page-panel scroll.
   Override the page-level flex-shrink:0 so these sections flex-grow
   into available height, and let the inner grid scroll itself.
   Result: the panel-context-bar + picker + summary stay pinned to the
   top while only the card list scrolls. */
body[data-page="library"] .page-panel.is-active > [data-workspace-section="library:inventory"],
body[data-page="library"] .page-panel.is-active > [data-workspace-section="library:sources"],
body[data-page="library"] .page-panel.is-active > [data-workspace-section="library:providers"],
body[data-page="graphs"] .page-panel.is-active > [data-workspace-section="graphs:gallery"],
body[data-page="graphs"] .page-panel.is-active > [data-workspace-section="graphs:quality"] {
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  flex-shrink: 1;
  min-height: 0;
  max-height: 100%;
}
body[data-page="library"] [data-workspace-section="library:inventory"] #data-inventory-list,
body[data-page="library"] [data-workspace-section="library:sources"] #data-sources-grid,
body[data-page="library"] [data-workspace-section="library:providers"] .source-grid,
body[data-page="graphs"] [data-workspace-section="graphs:gallery"] .chart-grid,
body[data-page="graphs"] [data-workspace-section="graphs:quality"] #qc-review-list {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  padding-right: 4px;
}

.report-body {
  display: grid;
  gap: 8px;
  line-height: 1.55;
}

.report-body p {
  margin: 0;
}

.firmware-flasher-panel {
  border-color: rgba(78, 221, 201, 0.34);
  background:
    linear-gradient(135deg, rgba(50, 208, 189, 0.12), transparent 42%),
    rgba(8, 18, 25, 0.86);
}

.firmware-flasher-grid {
  display: grid;
  grid-template-columns: minmax(240px, 1.25fr) minmax(220px, 1fr) minmax(260px, 1.1fr);
  gap: 12px;
  margin: 14px 0;
}

.firmware-artifact-summary {
  display: grid;
  gap: 10px;
  margin: 14px 0;
  padding: 14px;
  border: 1px solid rgba(78, 221, 201, 0.2);
  border-radius: 18px;
  background: rgba(3, 17, 23, 0.72);
}

.firmware-chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.status-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  padding: 6px 10px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  color: var(--muted);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.status-active,
.status-completed,
.status-ok,
.status-pass,
.status-ready {
  border-color: rgba(78, 221, 201, 0.38);
  color: #c9f8ee;
  background: rgba(78, 221, 201, 0.12);
}

.status-paused,
.status-queued,
.status-running,
.status-dry-run,
.status-no-response,
.status-warn,
.status-bringup,
.status-not-configured {
  border-color: rgba(255, 195, 95, 0.34);
  color: #ffe0a2;
  background: rgba(255, 195, 95, 0.1);
}

.status-failed,
.status-fail,
.status-blocked,
.status-invalid {
  border-color: rgba(255, 106, 122, 0.34);
  color: #ffd0d8;
  background: rgba(255, 106, 122, 0.12);
}

.firmware-chip {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 6px 10px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--muted);
  font-size: 0.78rem;
}

.firmware-chip.ready {
  border-color: rgba(78, 221, 201, 0.38);
  color: #c9f8ee;
  background: rgba(78, 221, 201, 0.12);
}

.firmware-chip.missing {
  border-color: rgba(255, 195, 95, 0.34);
  color: #ffe0a2;
  background: rgba(255, 195, 95, 0.1);
}

.firmware-command-card {
  grid-column: 1 / -1;
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(1, 9, 13, 0.5);
}

.firmware-command-card code {
  display: block;
  overflow-x: auto;
  padding: 9px 10px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.32);
  color: #bff2e8;
  white-space: nowrap;
}

.firmware-warning {
  margin: 8px 0 0;
  padding: 10px;
  border: 1px solid rgba(255, 195, 95, 0.24);
  border-radius: 12px;
  background: rgba(255, 195, 95, 0.08);
  color: #ffe0a2;
}

.firmware-target-notes {
  grid-column: 1 / -1;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.045);
}

.firmware-target-notes ul {
  margin: 8px 0 0;
  padding-left: 18px;
}

.firmware-probe-status,
.firmware-job-status {
  margin-top: 12px;
  padding: 14px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 18px;
  background: rgba(2, 8, 12, 0.74);
}

.firmware-log {
  max-height: 260px;
  overflow: auto;
  margin: 12px 0 0;
  padding: 12px;
  border-radius: 14px;
  background: rgba(0, 0, 0, 0.38);
  color: #c9f8ee;
  font-size: 0.78rem;
  line-height: 1.45;
  white-space: pre-wrap;
}

.gateway-runtime-panel {
  border-color: rgba(125, 211, 252, 0.32);
  background:
    radial-gradient(circle at top left, rgba(125, 211, 252, 0.13), transparent 35%),
    rgba(8, 18, 25, 0.88);
  /* Lay out as a flex column so #gateway-runtime-status (which holds the
     selected-bridge form, role inventory, etc) can flex-grow to fill the
     viewport and scroll internally instead of pushing the page-panel
     past the viewport. Stretch to fill the page-panel's height. */
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}

.gateway-runtime-status {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  margin-top: 10px;
  /* Take remaining viewport height; scroll the contents (selected card +
     role inventory + notes) instead of growing the page. */
  flex: 1 1 0;
  min-height: 0;
  overflow: auto;
  padding-right: 4px;
}

.runtime-notes-fold > summary {
  cursor: pointer;
  padding: 6px 2px;
  list-style: none;
  color: var(--muted);
}
.runtime-notes-fold > summary::-webkit-details-marker { display: none; }
.runtime-notes-fold[open] > summary { color: var(--accent); }

.runtime-readiness {
  /* Was 5 fixed columns x 117h tall — each card padding 12, big rounded
     border, with a 3-line p.muted description that was rarely-read
     filler. Switched to a horizontal readout strip: each row is a
     LABEL : value + small muted detail, packed tight. 117h → ~28h per
     row, 5 rows in ~150h total instead of 117h × number-of-rows. */
  display: flex;
  flex-direction: column;
  gap: 0;
  margin: 10px 0;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(2, 8, 12, 0.48);
}

.runtime-readiness-card {
  display: grid;
  grid-template-columns: 110px 1fr;
  align-items: baseline;
  column-gap: 12px;
  row-gap: 0;
  padding: 6px 12px;
  border-radius: 0;
  border: 0;
  background: transparent;
}
.runtime-readiness-card + .runtime-readiness-card {
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}

.runtime-readiness-card span {
  color: var(--muted);
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.runtime-readiness-card strong {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.88rem;
  font-variant-numeric: tabular-nums;
}

.runtime-readiness-card p {
  /* p.muted descriptions ("Start is locked; previews stay safe.",
     "Required for Start/Stop commands.") add nothing operational — the
     state in <strong> already carries the meaning. Hide them. */
  display: none;
}

.gateway-runtime-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.runtime-role-card,
.runtime-action-panel,
.runtime-selected-command,
.runtime-selected-card {
  display: grid;
  grid-auto-rows: min-content;
  align-content: start;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  background: rgba(3, 12, 18, 0.72);
}
.mini-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 6px;
}
.runtime-selected-card .mini-stat-row { gap: 6px; }
.runtime-selected-card > p.muted,
.runtime-selected-command > p.muted {
  font-size: 11px;
  line-height: 1.25;
  margin: 0;
}
.runtime-selected-command strong { font-size: 12px; line-height: 1.1; }
.runtime-selected-command code { font-size: 11.5px; padding: 4px 6px; }
/* The "Offline planning is active, so this command is only for review until
   you switch to Live hardware control" advisory under the launch command
   is the same info already encoded in the Mode pill above and in the
   summary-strip Safety stat. Hide it to reclaim ~70h. */
.runtime-selected-command > p.muted { display: none; }
/* Long role labels ("T-Beam Supreme LoRa RX + onboard telemetry") wrap
   to 2 lines at default h3 size and inflate the card header to 81h.
   Shrink + truncate so the header stays on one row. */
.runtime-selected-card h3 {
  font-size: 14px;
  line-height: 1.2;
  margin: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.runtime-selected-card .eyebrow { font-size: 10px; margin: 0 0 2px; }

.runtime-selected-grid {
  display: grid;
  grid-template-columns: minmax(280px, 0.8fr) minmax(360px, 1.2fr);
  gap: 8px;
}

.runtime-role-card.is-selected {
  border-color: rgba(125, 211, 252, 0.42);
  box-shadow: 0 0 0 1px rgba(125, 211, 252, 0.08);
}

.runtime-role-card.is-running {
  border-color: rgba(78, 221, 201, 0.42);
}

.runtime-selected-command code {
  display: block;
  overflow-x: auto;
  color: #bff2e8;
  white-space: nowrap;
}

.runtime-log {
  max-height: 150px;
  min-height: 42px;
}

.runtime-role-inventory {
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 18px;
  background: rgba(255, 255, 255, 0.035);
  overflow: hidden;
}

.runtime-role-inventory summary {
  cursor: pointer;
  padding: 12px 14px;
  color: #d7f7ff;
  font-weight: 800;
}

.runtime-role-inventory .gateway-runtime-list {
  padding: 0 12px 12px;
}

.runtime-notes {
  margin-top: 0;
}

.halow-pair-panel {
  border-color: rgba(98, 181, 255, 0.28);
  background:
    radial-gradient(circle at top right, rgba(98, 181, 255, 0.14), transparent 34%),
    rgba(8, 18, 25, 0.86);
}

.halow-pair-plan {
  display: grid;
  gap: 14px;
  margin-top: 14px;
}

.halow-link-diagram {
  display: grid;
  grid-template-columns: 1fr auto auto auto 1fr;
  align-items: center;
  gap: 10px;
  padding: 12px;
  border: 1px solid rgba(98, 181, 255, 0.22);
  border-radius: 18px;
  background: linear-gradient(90deg, rgba(98, 181, 255, 0.08), rgba(78, 221, 201, 0.1));
  text-align: center;
}

.halow-link-diagram b,
.halow-link-diagram span,
.halow-link-diagram i {
  padding: 8px 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.24);
}

.halow-link-diagram i {
  color: #a9f3ff;
  font-style: normal;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.halow-role-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}

.halow-role-card,
.check-row-card {
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.045);
}

.halow-role-card code {
  overflow-x: auto;
  color: #bff2e8;
  white-space: nowrap;
}

.halow-check-list {
  display: grid;
  gap: 8px;
}

.check-row-card {
  grid-template-columns: auto 1fr;
  align-items: start;
}

.halow-step-list {
  margin: 0;
  padding: 12px 12px 12px 32px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  background: rgba(2, 8, 12, 0.54);
}

.halow-step-list li + li {
  margin-top: 8px;
}

.tool-finder {
  position: fixed;
  inset: 0;
  z-index: 5000;
  display: grid;
  place-items: start center;
  padding: min(10vh, 84px) 18px 18px;
  background: rgba(2, 8, 11, 0.72);
  backdrop-filter: blur(14px);
}

.tool-finder[hidden] {
  display: none;
}

.tool-finder-panel {
  display: grid;
  gap: 14px;
  width: min(860px, 100%);
  max-height: min(760px, 86vh);
  padding: 18px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 24px;
  background: rgba(8, 18, 24, 0.97);
  box-shadow: var(--shadow);
  overflow: auto;
}

.tool-results {
  display: grid;
  gap: 8px;
}

.tool-result-button {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 14px;
  align-items: center;
  width: 100%;
  min-height: 70px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: 16px;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.045);
  cursor: pointer;
  text-align: left;
}

.tool-result-button:hover,
.tool-result-button:focus,
.tool-result-button.is-active {
  border-color: rgba(50, 208, 189, 0.48);
  background: rgba(50, 208, 189, 0.08);
}
/* Keyboard-driven highlight gets a stronger inset ring to distinguish
   it from mouse hover (so users can see where Enter will land). */
.tool-result-button.is-active {
  box-shadow: inset 0 0 0 1px rgba(50, 208, 189, 0.5);
}

/* Tool finder footer: keyboard hint strip at the bottom of the Cmd+K
   modal showing the available shortcuts. <kbd> elements styled as
   keycaps. */
.tool-finder-footer {
  display: flex;
  gap: 14px;
  padding: 8px 4px 0;
  margin-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  font-size: 11px;
  color: rgba(180, 200, 210, 0.6);
}
.tool-finder-footer kbd {
  display: inline-block;
  padding: 1px 5px;
  margin: 0 2px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.05);
  font-family: "IBM Plex Mono", monospace;
  font-size: 10px;
  line-height: 1.3;
  color: rgba(220, 230, 235, 0.85);
}

.tool-result-button:disabled {
  cursor: not-allowed;
}

.tool-result-button:disabled:hover,
.tool-result-button:disabled:focus {
  border-color: var(--line);
  background: rgba(255, 255, 255, 0.045);
}

.tool-result-button p {
  margin: 4px 0 0;
}

.route-card {
  display: grid;
  gap: 12px;
}

.route-card h3 {
  margin-bottom: 0;
}

.route-list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.route-list li {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 10px;
  border: 1px solid var(--line);
  border-radius: 13px;
}

.leaflet-container {
  z-index: 0;
  background: #071014;
  font-family: "IBM Plex Sans", sans-serif;
  cursor: default;
}

.map-stage .leaflet-control-container {
  position: relative;
  z-index: 20;
}

.leaflet-container a,
.leaflet-interactive,
.leaflet-marker-icon,
.station-marker,
.hardware-pin-marker {
  cursor: default !important;
}

body[data-map-click-mode="point"] .leaflet-container,
body[data-map-click-mode="route-origin"] .leaflet-container,
body[data-map-click-mode="route-destination"] .leaflet-container,
body.ocean-viewer-inspect-active .leaflet-container,
body.ocean-viewer-transect-active .leaflet-container,
body[data-map-click-mode="point"] .leaflet-interactive,
body[data-map-click-mode="route-origin"] .leaflet-interactive,
body[data-map-click-mode="route-destination"] .leaflet-interactive,
body.ocean-viewer-inspect-active .leaflet-interactive,
body.ocean-viewer-transect-active .leaflet-interactive,
body[data-map-click-mode="point"] .leaflet-marker-icon,
body[data-map-click-mode="route-origin"] .leaflet-marker-icon,
body[data-map-click-mode="route-destination"] .leaflet-marker-icon,
body.ocean-viewer-inspect-active .leaflet-marker-icon,
body.ocean-viewer-transect-active .leaflet-marker-icon {
  cursor: crosshair !important;
}

.station-marker {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 2px solid #dffffa;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 8px rgba(50, 208, 189, 0.16), 0 0 26px rgba(50, 208, 189, 0.6);
}

.station-marker.stale {
  background: var(--warn);
  box-shadow: 0 0 0 8px rgba(246, 177, 94, 0.16), 0 0 26px rgba(246, 177, 94, 0.5);
}

/* Kind-specific station markers Ã¢â‚¬â€ buoy / float / gauge / station glyphs drawn
   to a canvas data URL by markerIcon(). The owning network sets the colour. */
.station-glyph-icon img {
  display: block;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(2, 8, 12, 0.55));
  transition: transform 0.12s ease;
  transform-origin: 50% 60%;
}
.station-glyph-icon:hover img {
  transform: scale(1.14);
}
.station-glyph-icon.stale {
  opacity: 0.62;
}
.station-glyph-icon.stale img {
  filter: drop-shadow(0 2px 4px rgba(2, 8, 12, 0.55)) saturate(0.5) brightness(0.95);
}

body.stations-hidden[data-route="observe"] .station-marker,
body.stations-hidden[data-route="observe"] .station-glyph-icon,
body.stations-hidden[data-route="observe"] .hardware-pin-marker {
  display: none;
}

.hardware-pin-marker {
  position: relative;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 2px dashed #ffe5bd;
  border-radius: 999px;
  background: rgba(246, 177, 94, 0.22);
  box-shadow: 0 0 0 9px rgba(246, 177, 94, 0.12), 0 0 28px rgba(246, 177, 94, 0.48);
}

.hardware-pin-marker::after {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 999px;
  background: #ffe5bd;
}

.hardware-pin-popup .station-popup-meta {
  max-height: 220px;
  overflow: auto;
}

.omega-station-popup .leaflet-popup-content-wrapper {
  border: 1px solid rgba(163, 185, 188, 0.24);
  border-radius: 18px;
  color: var(--ink);
  background: rgba(7, 16, 20, 0.96);
  box-shadow: 0 22px 48px rgba(0, 0, 0, 0.42);
}

.omega-station-popup .leaflet-popup-content {
  width: min(300px, 74vw);
  margin: 14px;
}

.omega-station-popup .leaflet-popup-tip {
  background: rgba(7, 16, 20, 0.96);
}

.omega-station-popup .leaflet-popup-close-button {
  color: var(--muted);
}

.station-popup {
  display: grid;
  gap: 12px;
}

.station-popup-head,
.station-popup-value,
.station-popup-actions {
  display: grid;
  gap: 8px;
}

.station-popup-head strong {
  font-size: 1rem;
  line-height: 1.2;
}

.station-popup-value {
  padding: 12px;
  border: 1px solid rgba(50, 208, 189, 0.2);
  border-radius: 14px;
  background: rgba(50, 208, 189, 0.08);
}

.station-popup-value span {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.station-popup-value strong {
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-xl);
}

.station-popup-meta {
  display: grid;
  gap: 8px;
  margin: 0;
}

.station-popup-meta div {
  display: grid;
  grid-template-columns: 92px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}

.station-popup-meta dt {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.station-popup-meta dd {
  margin: 0;
  color: var(--ink);
}

.station-popup-actions {
  grid-template-columns: 1fr 1fr;
}

/* Drill-down "Latest reading" block injected into a catalog marker popup. */
.station-popup-probe {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(163, 185, 188, 0.2);
  display: grid;
  gap: 8px;
}

.station-popup-probe-label {
  margin: 0;
  color: var(--muted);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.station-popup-probe-status {
  color: var(--muted);
  font-size: 0.78rem;
}

@media (min-width: 1101px) and (max-width: 1450px) {
  body[data-page="map"] .console-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) minmax(190px, 248px);
    grid-template-areas:
      "map"
      "side";
  }

  body[data-page="map"] .map-plane {
    min-height: 0;
  }

  body[data-page="map"] .side-panel {
    display: grid;
    grid-template-columns:
      minmax(240px, 0.8fr)
      minmax(320px, 1.08fr)
      minmax(300px, 1fr)
      minmax(340px, 1.12fr)
      minmax(300px, 1fr);
    grid-auto-flow: column;
    gap: 10px;
    align-content: stretch;
    align-items: stretch;
    max-height: 248px;
    overflow-x: auto;
    overflow-y: hidden;
    padding: 10px;
  }

  body[data-page="map"] .side-panel > .panel-section,
  body[data-page="map"] .side-panel > .map-overlay-controls,
  body[data-page="map"] .side-panel > .map-viz-dock {
    min-width: 0;
    min-height: 0;
    max-height: 226px;
    overflow: auto;
    padding: 12px;
  }

  body[data-page="map"] .side-panel > .panel-section:nth-child(2) {
    min-width: 320px;
  }

  body[data-page="map"] .side-panel > .panel-section:nth-child(3),
  body[data-page="map"] .side-panel > .map-overlay-controls,
  body[data-page="map"] .side-panel > .map-viz-dock {
    min-width: 300px;
  }

  body[data-page="map"] .side-panel > .map-overlay-controls {
    min-width: 340px;
  }

  body[data-page="map"] .map-topline {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    padding-top: 12px;
  }

  body[data-page="map"] .map-actions {
    align-items: center;
  }

  body[data-page="map"] .map-stage {
    margin: 10px 12px;
  }

  body[data-page="map"] .map-utility-strip {
    padding-bottom: 7px;
  }

  body[data-page="map"] .map-overlay-controls {
    width: auto;
    max-height: 226px;
  }

  body[data-page="map"] .map-coordinate-tools {
    width: min(320px, calc(100% - 28px));
  }
}

@media (max-width: 1100px) {
  .app-shell {
    height: auto;
    min-height: 100vh;
    overflow: visible;
  }

  .app-header {
    grid-template-columns: 1fr;
  }

  .header-controls {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  .console-grid,
  .split-panel,
  .command-layout,
  .comms-layout {
    grid-template-columns: 1fr;
  }

  .console-grid {
    height: auto;
    overflow: visible;
    grid-template-areas:
      "map"
      "side";
  }

  .side-panel {
    max-height: none;
  }

  .map-plane {
    min-height: 620px;
  }

  body[data-route="observe"] .app-shell {
    height: 100vh;
    height: 100dvh;
    min-height: 100vh;
    overflow: hidden;
  }

  body[data-route="observe"] .app-header {
    left: 10px;
    right: 10px;
    top: 10px;
    grid-template-columns: 1fr;
    max-height: 38vh;
    overflow: auto;
  }

  body[data-route="observe"] .console-grid,
  body[data-route="observe"] .map-plane {
    height: 100%;
    min-height: 0;
  }

  body[data-route="observe"] .map-topline {
    left: 10px;
    right: 10px;
    top: min(42vh, 300px);
    display: grid;
    align-items: stretch;
  }

  body[data-route="observe"] .map-utility-strip {
    left: 10px;
    right: 10px;
    grid-template-columns: 1fr;
  }

  body[data-route="observe"] .map-overlay-controls {
    top: min(54vh, 390px);
    max-height: 34vh;
  }

  body[data-route="observe"] .ocean-viewer-panel {
    left: 10px;
    right: 10px;
    top: min(54vh, 390px);
    width: auto;
    max-height: 34vh;
  }

  body[data-route="observe"] .dto-temporal-control {
    left: 10px;
    right: 10px;
    bottom: 92px;
    width: auto;
    min-width: 0;
    transform: none;
  }

  body[data-route="observe"] .context-drawer {
    left: 10px;
    right: 10px;
    top: min(54vh, 390px);
    bottom: 212px;
    width: auto;
    max-height: none;
  }

  .temporal-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .chart-grid,
  .viz-tool-grid,
  .viz-controls,
  .viz-stage,
  .workspace-tabs,
  .data-browser-toolbar,
  .data-browser-chart-toolbar,
  .earthdata-finder-grid,
  .earthdata-results-grid,
  .environmental-animation-grid,
  .mission-cube-grid,
  .mission-cube-output,
  .firmware-flasher-grid,
  .runtime-readiness,
  .runtime-selected-grid,
  .gateway-runtime-list,
  .chart-picker-panel {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .viz-hero {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 760px) {
  .app-shell {
    padding: 10px;
  }

  /* 13 icon nav buttons on a phone — using 2 cols would make 7 rows
     of 46h each ≈ 320px-tall nav, which eats the whole screen.
     auto-fill with a small min keeps the buttons icon-sized and packs
     6-8 per row depending on viewport, giving a 2-row nav rail. */
  .primary-nav {
    grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  }

  body:not([data-route="observe"]) .primary-nav {
    grid-template-columns: repeat(auto-fill, minmax(44px, 1fr));
  }

  .header-controls,
    .summary-strip,
    .data-toolbar,
    .chart-picker-panel,
    .workspace-tabs,
    .data-browser-toolbar,
    .data-browser-chart-toolbar,
    .earthdata-finder-grid,
    .earthdata-results-grid,
    .environmental-animation-grid,
    .mission-cube-grid,
    .mission-cube-output,
    .firmware-flasher-grid,
    .runtime-readiness,
    .runtime-selected-grid,
    .gateway-runtime-list,
    .compact-form,
    .chart-grid,
    .viz-tool-grid,
    .viz-controls,
    .viz-stage,
    .data-access-grid,
    .source-grid,
    .inline-tool,
    .tool-directory,
    .tool-card {
    grid-template-columns: 1fr;
  }

  .viz-actions {
    justify-content: stretch;
  }

  .chart-card-wide {
    grid-column: auto;
  }

  .chart-card-head,
  .mini-bar-row {
    grid-template-columns: 1fr;
  }

  .chart-card-head {
    display: grid;
  }

  .tool-card-actions {
    justify-items: stretch;
  }

  .map-plane {
    grid-template-rows: auto minmax(420px, 58vh) auto auto;
  }

  body[data-route="observe"] .map-plane {
    grid-template-rows: minmax(0, 1fr);
  }

  .map-viz-dock {
    left: 10px;
    right: 10px;
    bottom: 10px;
    width: auto;
    max-height: min(38vh, 360px);
  }

  .map-overlay-controls {
    left: 10px;
    right: 10px;
    top: 10px;
    width: auto;
    max-height: min(48vh, 420px);
  }

  .ocean-viewer-panel {
    left: 10px;
    right: 10px;
    top: 10px;
    width: auto;
    max-height: min(48vh, 420px);
  }

  .context-drawer,
  body[data-route="observe"] .context-drawer {
    left: 10px;
    right: 10px;
    top: 118px;
    bottom: 188px;
    width: auto;
  }

  .page-panel.is-active {
    left: 10px;
    right: 10px;
    top: 70px;
    bottom: 72px;
    width: auto;
  }

  .context-drawer-head,
  .context-drawer-actions {
    grid-template-columns: 1fr;
  }

  .map-coordinate-tools {
    left: 10px;
    right: 10px;
    bottom: 10px;
    width: auto;
    max-height: min(36vh, 340px);
    overflow: auto;
  }

  .map-overlay-controls.dock-top-left,
  .map-overlay-controls.dock-top-right {
    inset: 10px 10px auto 10px;
  }

  .map-overlay-controls.dock-bottom-left,
  .map-overlay-controls.dock-bottom-right {
    inset: auto 10px 10px 10px;
  }

  .map-overlay-controls.is-free {
    width: min(360px, calc(100% - 20px));
  }

  .map-viz-head,
  .map-overlay-head,
  .ocean-viewer-head,
  .coordinate-head,
  .temporal-head,
  .map-overlay-buttons,
  .map-overlay-primary,
  .ocean-viewer-grid,
  .ocean-product-grid,
  .ocean-time-depth-row,
  .map-utility-strip,
  .overlay-layer-row,
  .overlay-action-row,
  .ocean-viewer-action-row,
  .ocean-profile-head,
  .ocean-profile-stats,
  .coordinate-action-row,
  .coordinate-input-grid,
  .temporal-grid,
  .overlay-product-insight,
  .overlay-preset-grid,
  .map-overlay-head-actions,
  .map-viz-head-actions,
  .map-viz-modes {
    display: grid;
    grid-template-columns: 1fr;
    justify-content: stretch;
  }

  .map-topline,
  .section-row,
  .page-head {
    align-items: stretch;
    flex-direction: column;
  }

  .map-quick-actions,
  .section-actions {
    justify-content: stretch;
  }

  .map-quick-actions .button,
  .section-actions .button {
    flex: 1 1 120px;
  }
}

body[data-route="observe"] .console-grid {
  grid-template-columns: minmax(0, 1fr) !important;
  grid-template-rows: minmax(0, 1fr) !important;
  grid-template-areas: "map" !important;
  height: 100% !important;
  overflow: hidden !important;
}

body[data-route="observe"] .map-plane {
  grid-template-rows: minmax(0, 1fr) !important;
  min-height: 0 !important;
  height: 100% !important;
}

body[data-route="observe"] .side-panel,
body[data-route="observe"] #map-page {
  display: none !important;
}

body[data-route="observe"] .map-overlay-controls.dock-bottom-left {
  inset: auto auto 92px 16px;
}

body[data-route="observe"] .map-overlay-controls.dock-bottom-right {
  inset: auto 16px 92px auto;
}

@media (min-width: 761px) {
  body[data-route="observe"] .map-coordinate-tools:not(.is-free-floating) {
    top: 206px;
    bottom: auto !important;
    z-index: 52;
    max-height: calc(100% - 330px);
    overflow: auto;
  }
}

body[data-route="plan"] .app-shell {
  width: 100%;
  max-width: none;
  padding: 0;
  grid-template-rows: minmax(0, 1fr);
}

body[data-route="plan"] .app-header {
  position: fixed;
  left: 16px;
  right: 16px;
  top: 16px;
  z-index: 80;
  grid-template-columns: minmax(180px, 0.7fr) minmax(280px, 0.72fr) minmax(320px, 0.82fr);
  min-height: 0;
  background: rgba(7, 16, 20, 0.66);
}

body[data-route="plan"] .brand-block p:last-child,
body[data-route="plan"] .side-panel,
body[data-route="plan"] #map-page,
body[data-route="plan"] .ocean-viewer-panel,
body[data-route="plan"] .ocean-layer-dock,
body[data-route="plan"] .context-panel {
  display: none !important;
}

body[data-route="plan"] .console-grid {
  grid-template-columns: minmax(0, 1fr) !important;
  grid-template-rows: minmax(0, 1fr) !important;
  grid-template-areas: "map" !important;
  height: 100% !important;
  margin: 0;
  overflow: hidden !important;
}

body[data-route="plan"] .map-plane {
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  grid-template-rows: minmax(0, 1fr) !important;
  min-height: 0 !important;
  height: 100% !important;
}

body[data-route="plan"] .map-stage {
  margin: 0;
  grid-area: 1 / 1;
}

body[data-route="plan"] #map,
body[data-route="plan"] .globe-canvas {
  border-radius: 0;
}

body[data-route="plan"] .map-topline {
  position: absolute;
  left: 16px;
  right: 16px;
  top: 118px;
  z-index: 45;
  padding: 12px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 18px;
  background: rgba(7, 16, 20, 0.58);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(16px);
}

body[data-route="plan"] .map-utility-strip {
  position: absolute;
  left: 16px;
  right: 16px;
  bottom: 14px;
  z-index: 44;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 18px;
  background: rgba(7, 16, 20, 0.58);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28);
  backdrop-filter: blur(16px);
}

body[data-route="plan"] .map-status {
  position: absolute;
  left: 18px;
  bottom: 82px;
  z-index: 44;
  max-width: min(720px, calc(100% - 36px));
  padding: 8px 12px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 999px;
  background: rgba(7, 16, 20, 0.58);
  backdrop-filter: blur(14px);
}

body[data-route="plan"] .dto-temporal-control {
  display: none;
}

body[data-route="plan"] .map-coordinate-tools:not(.is-free-floating) {
  left: 16px;
  top: 206px;
  bottom: auto !important;
  z-index: 52;
  max-height: calc(100% - 330px);
  overflow: auto;
}

/* Plan content renders as a glass drawer over the map, like the observe page.
   (data-route is a constant shell hook Ã¢â‚¬â€ data-page is the real per-page gate.) */
body[data-page="command"] #command-page.page-panel.is-active {
  position: absolute;
  top: 76px;
  right: 16px;
  bottom: 120px;
  z-index: 62;
  display: grid;
  align-content: start;
  gap: 12px;
  width: min(460px, calc(100vw - 360px));
  max-height: none;
  overflow: auto;
  padding: 14px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 14px;
  background: rgba(4, 12, 16, 0.72);
  box-shadow: 0 22px 56px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(16px);
}

body[data-page="command"] #command-page .page-head {
  align-items: flex-start;
  user-select: none;
}

body[data-page="command"] #command-page .page-head p.muted {
  display: none;
}

body[data-page="command"] #command-page .command-layout {
  grid-template-columns: 1fr;
}

body[data-page="command"] #command-page .route-result {
  min-height: 180px;
  max-height: 38vh;
  overflow: auto;
}

body[data-page="command"] .workspace-tabs {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(163, 185, 188, 0.16);
}

@media (max-width: 760px) {
  body[data-route="observe"] .app-header {
    left: 8px;
    right: 8px;
    top: 8px;
    gap: 6px;
    max-height: none;
    overflow: visible;
    padding: 8px;
    border-radius: 18px;
  }

  body[data-route="observe"] .brand-block {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }

  body[data-route="observe"] .brand-block h1 {
    margin: 0;
    font-size: 1.08rem;
    line-height: 1;
  }

  body[data-route="observe"] .brand-block .eyebrow {
    margin: 0;
    font-size: 0.58rem;
  }

  body[data-route="observe"] .primary-nav {
    grid-template-columns: repeat(4, minmax(64px, 1fr));
    gap: 4px;
    padding: 4px;
  }

  body[data-route="observe"] .nav-button {
    min-height: 32px;
    padding: 0 6px;
    font-size: 0.76rem;
  }

  body[data-route="observe"] .header-controls {
    display: grid;
    grid-template-columns: minmax(150px, 1fr) minmax(140px, 1fr) minmax(96px, auto) minmax(96px, auto);
    gap: 6px;
    align-items: end;
    overflow-x: auto;
    padding-bottom: 2px;
    scrollbar-width: thin;
  }

  body[data-route="observe"] .header-controls .control {
    min-width: 140px;
  }

  body[data-route="observe"] .header-controls .button {
    min-width: 94px;
    min-height: 36px;
    padding-inline: 10px;
  }

  body[data-route="observe"] .map-topline {
    left: 8px;
    right: 8px;
    top: 142px;
    z-index: 43;
    max-height: 112px;
    overflow: auto;
    padding: 8px;
  }

  body[data-route="observe"] .map-topline .eyebrow {
    display: none;
  }

  body[data-route="observe"] .map-topline h2 {
    margin: 0;
    font-size: var(--fs-md);
  }

  body[data-route="observe"] .map-actions {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 2px;
  }

  body[data-route="observe"] .map-actions > * {
    flex: 0 0 auto;
  }

  body[data-route="observe"] .map-coordinate-tools:not(.is-free-floating) {
    left: 8px;
    top: 260px;
    bottom: auto !important;
    z-index: 52;
    width: min(340px, calc(100% - 16px));
    max-height: min(35vh, 320px);
    overflow: auto;
  }

  body[data-route="observe"] .map-coordinate-tools.is-collapsed:not(.is-free-floating) {
    top: 260px;
    width: auto;
  }

  body[data-route="observe"] .ocean-viewer-panel:not(.is-free-floating) {
    left: 8px;
    right: 8px;
    top: auto;
    bottom: 86px;
    width: auto;
    max-height: min(44vh, 360px);
    z-index: 56;
  }

  body[data-route="observe"] .ocean-viewer-panel.is-collapsed:not(.is-free-floating) {
    left: auto;
    right: 8px;
    bottom: 86px;
    width: auto;
  }

  body[data-route="observe"] .map-overlay-controls:not(.is-free) {
    left: 8px;
    right: auto;
    top: auto;
    bottom: 86px;
    width: min(250px, calc(100% - 16px));
    max-height: 42vh;
    z-index: 48;
  }

  body[data-route="observe"] .map-overlay-controls.is-collapsed:not(.is-free) {
    width: auto;
  }

  body[data-route="observe"] .dto-temporal-control:not(.is-free-floating) {
    left: 8px;
    right: 8px;
    bottom: 8px;
    width: auto;
    min-width: 0;
    padding: 8px;
  }

  body[data-route="observe"] .dto-temporal-control .temporal-grid,
  body[data-route="observe"] .dto-temporal-control p {
    display: none;
  }

  body[data-route="observe"] .map-utility-strip {
    display: none;
  }

  body[data-route="observe"] .map-status {
    left: 8px;
    right: 8px;
    bottom: 60px;
    max-width: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

.layer-catalog-panel {
  display: grid;
  gap: 8px;
}

.layer-catalog-body {
  display: grid;
  gap: 8px;
}

.layer-catalog-toolbar {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 6px;
  align-items: end;
}

.layer-catalog-active,
.layer-catalog-list {
  display: grid;
  gap: 6px;
  max-height: 280px;
  overflow: auto;
  padding: 4px;
  border: 1px solid rgba(163, 185, 188, 0.16);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.18);
}

.layer-catalog-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px;
  padding: 8px 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
}

.layer-catalog-row:hover {
  background: rgba(74, 167, 199, 0.16);
}

.layer-catalog-row.is-active {
  outline: 1px solid rgba(125, 211, 252, 0.55);
  background: rgba(125, 211, 252, 0.1);
}

.layer-catalog-row strong {
  font-size: 0.92rem;
}

.layer-catalog-row .meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  font-size: 0.7rem;
  color: rgba(218, 234, 240, 0.72);
}

.layer-catalog-row .meta .pill {
  padding: 1px 6px;
  font-size: 0.62rem;
}

.layer-catalog-row .row-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: stretch;
}

.layer-catalog-row .row-actions button,
.layer-catalog-row .row-actions a {
  font-size: 0.66rem;
  padding: 3px 8px;
}

.layer-catalog-row .credential-hint {
  font-size: var(--fs-xs);
  color: rgba(255, 196, 124, 0.95);
}

.layer-catalog-row .credential-hint a {
  color: inherit;
  text-decoration: underline;
}

.data-sources-panel {
  display: grid;
  gap: 10px;
}

.data-sources-toolbar {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr auto;
  gap: 8px;
  align-items: end;
}

.data-sources-grid {
  display: grid;
  /* Tighter minmax (220 was 280) lets 4 cards fit at ~900px panel width
     instead of 3 — meaningfully shorter total scroll. */
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
}

.data-source-card {
  display: grid;
  gap: 4px;
  padding: 8px 10px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 12px;
  background: rgba(7, 18, 24, 0.6);
}

.data-source-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
}

.data-source-card strong {
  font-size: var(--fs-md);
}

.data-source-card .meta {
  font-size: 0.72rem;
  color: rgba(218, 234, 240, 0.72);
}

/* Expandable device detail in the Data Inventory (all tags + live metrics).
   Native <details> so it's accessible + zero-JS. */
.inv-detail { margin-top: 2px; }
.inv-detail > summary {
  cursor: pointer;
  font-size: 0.72rem;
  color: rgba(125, 211, 252, 0.9);
  list-style: none;
  user-select: none;
}
.inv-detail > summary::-webkit-details-marker { display: none; }
.inv-detail > summary::before { content: "▸ "; }
.inv-detail[open] > summary::before { content: "▾ "; }
.inv-detail-grid {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1px 10px;
  margin: 6px 0 0;
  font-size: 0.7rem;
}
.inv-detail-grid dt { color: rgba(218, 234, 240, 0.55); }
.inv-detail-grid dd { margin: 0; color: rgba(234, 244, 248, 0.92); word-break: break-word; }
.inv-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}
.inv-metrics .pill { font-size: 0.66rem; }

.data-source-card .data-types {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.data-source-card .data-types .pill {
  padding: 1px 6px;
  font-size: 0.62rem;
}

.data-source-card .actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.data-source-card.status-live {
  border-color: rgba(125, 211, 252, 0.4);
}

.data-source-card.status-key-ready {
  border-color: rgba(255, 196, 124, 0.45);
}

.data-source-card.status-planned {
  opacity: 0.85;
}

.status-pill {
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(125, 211, 252, 0.18);
  color: rgba(125, 211, 252, 0.95);
}

.status-pill.status-key-ready {
  background: rgba(255, 196, 124, 0.16);
  color: rgba(255, 196, 124, 0.95);
}

.status-pill.status-missing-key {
  background: rgba(244, 114, 114, 0.18);
  color: rgba(244, 114, 114, 0.95);
}

.status-pill.status-planned {
  background: rgba(218, 234, 240, 0.12);
  color: rgba(218, 234, 240, 0.85);
}

.layer-catalog-floating {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 720;
  width: min(380px, calc(100% - 32px));
  max-height: calc(100% - 280px);
  overflow: auto;
  display: grid;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid rgba(163, 185, 188, 0.28);
  border-radius: 18px;
  background: rgba(7, 18, 24, 0.92);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(18px);
}

.layer-catalog-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.layer-catalog-head h3 {
  margin-bottom: 0;
  font-size: 1rem;
}

.layer-catalog-head-actions {
  display: flex;
  align-items: center;
  gap: 6px;
}

/* Move Map Tools (coord readout) to bottom-left so it doesn't collide with the Layer Catalog. */
body[data-route="observe"] .map-coordinate-tools {
  top: auto;
  bottom: 168px;
}

.row-action-buttons {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
}

.layer-context-panel {
  display: grid;
  gap: 8px;
  margin-top: 8px;
  padding: 10px;
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid rgba(125, 211, 252, 0.18);
}

.layer-context-control {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
  font-size: 0.72rem;
}

.layer-context-control > span {
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.72);
}

.layer-context-control input,
.layer-context-control select {
  width: 100%;
  font-size: 0.78rem;
  padding: 4px 6px;
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(163, 185, 188, 0.28);
  color: inherit;
}

.layer-context-control .hint {
  font-size: 0.65rem;
  font-style: normal;
  color: rgba(218, 234, 240, 0.55);
}

.layer-catalog-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 4px;
}

.layer-catalog-row.is-active {
  border: 1px solid rgba(125, 211, 252, 0.25);
}

.busy-pill {
  background: rgba(255, 196, 124, 0.18);
  color: rgba(255, 196, 124, 0.95);
  animation: pulse-busy 1.4s ease-in-out infinite;
}

.error-pill {
  background: rgba(244, 114, 114, 0.18);
  color: rgba(244, 114, 114, 0.95);
  cursor: help;
}

@keyframes pulse-busy {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

.layer-catalog-row.is-busy {
  outline: 1px solid rgba(255, 196, 124, 0.45);
}

.anim-pill {
  background: rgba(125, 211, 252, 0.18);
  color: rgba(125, 211, 252, 0.95);
  font-variant-numeric: tabular-nums;
}

.is-drag-handle {
  cursor: grab;
  user-select: none;
}
.is-drag-handle:active {
  cursor: grabbing;
}
body.is-dragging-panel {
  user-select: none;
  cursor: grabbing;
}

/* === Header overhaul: single tight row of dropdowns === */

body[data-route="observe"] .app-header {
  display: flex !important;
  flex-direction: row !important;
  align-items: center;
  flex-wrap: nowrap;
  gap: 12px;
  padding: 6px 16px;
  min-height: 48px;
  max-height: 56px;
  overflow: visible;
}

body[data-route="observe"] .brand-block {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex: 0 0 auto;
}

body[data-route="observe"] .brand-block h1 {
  font-size: 1rem;
  margin: 0;
  white-space: nowrap;
}

body[data-route="observe"] .brand-block .eyebrow {
  margin: 0;
  font-size: 0.65rem;
}

body[data-route="observe"] .primary-nav {
  display: flex !important;
  flex-direction: row !important;
  gap: 4px;
  flex: 0 0 auto;
}

body[data-route="observe"] .primary-nav .nav-button {
  padding: 4px 10px;
  font-size: 0.78rem;
}

body[data-route="observe"] .header-controls {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap;
  gap: 6px;
  align-items: center;
  flex: 1 1 auto;
  justify-content: flex-end;
  min-width: 0;
}

body[data-route="observe"] #basemap-select {
  max-width: 160px;
}

.header-dropdown {
  position: relative;
}

.header-dropdown-button {
  white-space: nowrap;
  font-size: 0.78rem;
  padding: 6px 12px;
}

.header-dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 800;
  min-width: 280px;
  max-width: 360px;
  max-height: min(70vh, 520px);
  overflow: auto;
  padding: 6px;
  border: 1px solid rgba(163, 185, 188, 0.28);
  border-radius: 12px;
  background: rgba(7, 18, 24, 0.96);
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(18px);
  display: grid;
  gap: 2px;
}

.header-dropdown-menu .menu-section {
  padding: 4px 6px 2px;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.55);
  border-top: 1px solid rgba(163, 185, 188, 0.12);
  margin-top: 4px;
}

.header-dropdown-menu .menu-section:first-child {
  border-top: none;
  margin-top: 0;
}

.header-dropdown-menu .menu-search {
  display: block;
  width: 100%;
  padding: 6px 8px;
  margin-bottom: 4px;
  font-size: 0.78rem;
  border-radius: 8px;
  border: 1px solid rgba(163, 185, 188, 0.28);
  background: rgba(0, 0, 0, 0.4);
  color: inherit;
}

.header-dropdown-menu .menu-item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  border-radius: 8px;
  cursor: pointer;
  font-size: var(--fs-base);
  border: none;
  background: transparent;
  color: inherit;
  text-align: left;
}

.header-dropdown-menu .menu-item:hover,
.header-dropdown-menu .menu-item:focus {
  background: rgba(74, 167, 199, 0.18);
  outline: none;
}

.header-dropdown-menu .menu-item.is-active {
  background: rgba(125, 211, 252, 0.14);
}

.header-dropdown-menu .menu-item .meta {
  font-size: 0.66rem;
  color: rgba(218, 234, 240, 0.6);
}

.header-dropdown-menu .menu-item .pill {
  font-size: 0.6rem;
  padding: 1px 6px;
}

.header-dropdown-menu .menu-empty {
  padding: 12px 8px;
  text-align: center;
  font-size: 0.78rem;
  color: rgba(218, 234, 240, 0.55);
}

/* === Scientific overlay panel: legend colorbar, freshness, inspect === */
.ctx-legend .ovl-colorbar {
  height: 12px;
  border-radius: 6px;
  margin: 2px 0 3px;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.ovl-colorbar-ticks {
  display: flex;
  justify-content: space-between;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.62rem;
  color: rgba(218, 234, 240, 0.72);
}
.ovl-colorbar-ticks span:nth-child(2) {
  opacity: 0.6;
}
.ovl-freshness {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 0.66rem;
  color: rgba(218, 234, 240, 0.8);
  margin: 3px 0;
}
.ovl-fresh-time {
  font-family: "IBM Plex Mono", monospace;
  color: #7dd3fc;
}
.ovl-fresh-age {
  color: rgba(218, 234, 240, 0.6);
}
.ovl-fresh-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex: 0 0 7px;
  background: rgba(125, 211, 252, 0.6);
}
.ovl-fresh-dot.live {
  background: #34d399;
  box-shadow: 0 0 0 3px rgba(52, 211, 153, 0.18);
}
.ovl-fresh-dot.static {
  background: rgba(148, 163, 184, 0.7);
}
.ovl-inspect-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.ovl-inspect-readout {
  font-size: 0.7rem;
  min-width: 0;
}

/* === Right slide-in context panel === */

.context-panel {
  position: absolute;
  top: 16px;
  right: 16px;
  /* Height follows the content (capped to the viewport) instead of always
     filling it, so a short overlay panel is a short box. */
  max-height: calc(100% - 96px);
  z-index: 740;
  width: min(420px, calc(100% - 32px));
  display: grid;
  grid-template-rows: auto minmax(0, auto);
  border: 1px solid rgba(163, 185, 188, 0.28);
  border-radius: 16px;
  background: rgba(7, 18, 24, 0.94);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(18px);
  overflow: hidden;
  animation: context-panel-slide-in 160ms ease-out;
}

/* Ocean Probe + Area Analysis are heavy data tools — give them a much
   wider workspace than the narrow 420px overlay-options panel. The
   probe has 12 metric cards + multiple forecast charts + station/Argo
   cards; cramming that into 420px caused horizontal overflow + made
   the tool unusable. Widen to ~1400px (or full screen minus margins
   on smaller viewports) and pin to the left so the rail icons stay
   reachable on the right.

   IMPORTANT: this rule uses the #context-panel ID selector + `!important`
   for the critical width/position properties because:
   (a) `body[data-route="observe"] .context-panel` later in the file resets
       width to 366px, AND
   (b) browsers persistently cache portal.css — a class-only selector here
       previously got overridden whenever the cached stylesheet shipped
       before this rule existed.
   The `#id.class` form has specificity (1,1,0) so nothing without an `!important`
   of its own can beat it. `!important` is reserved for the must-win
   width/position; visual properties (display, flex-direction, max-height)
   stay normal so theme-level overrides still work. */
/* Wide-mode applies to Ocean Probe + Region Report (results dashboards
   the user reads after running the tool). It does NOT apply to the
   Coordinates Workshop — that tool is a workbench used WHILE clicking
   the map, so the panel needs to stay narrow on the right so the map
   stays selectable. */
#context-panel.is-tool-probe,
#context-panel.is-tool-area {
  /* Span the full horizontal area, but leave room on the left for the
     observe rail (.ocean-layer-dock: left:16, width:62 → right edge at
     78px) and an 8px breathing gap. Otherwise the panel slides UNDER the
     rail icons (rail z-index:780 > panel z-index:750), making the View /
     Overlays / Sensors buttons invisible while a probe is open. Capped
     max-width so it doesn't go silly-wide on a 4K monitor. */
  left: 92px !important;
  right: 16px !important;
  width: auto !important;
  max-width: min(1400px, calc(100vw - 108px)) !important;
  /* Use a taller workspace too — bottom: 80px leaves room for the
     map-utility-strip without overlapping. */
  top: 76px !important;
  bottom: 80px !important;
  max-height: none !important;
  display: flex;
  flex-direction: column;
}
#context-panel.is-tool-probe .context-panel-body,
#context-panel.is-tool-area .context-panel-body {
  /* No horizontal scroll — every child resizes to fit. Vertical
     scroll handles overflow. */
  overflow-x: hidden;
  overflow-y: auto;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}

.context-panel-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 2px;
  padding: 8px 8px 0 8px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.18);
  /* Keep horizontal scroll capability for when many overlay tabs stack,
     but hide the visible scrollbar — it was showing up as a permanent
     line under a small set of tabs and reading as broken UI. Vertical
     overflow is explicitly hidden so the auto-computed `overflow-y: auto`
     side-effect of setting `overflow-x` doesn't reserve a horizontal
     gutter on Windows Chrome. */
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge */
}
.context-panel-tabs::-webkit-scrollbar {
  display: none; /* Chrome / Safari */
}

.context-panel-tab {
  flex: 0 0 auto;
  padding: 6px 10px;
  border-radius: 8px 8px 0 0;
  background: transparent;
  border: 1px solid transparent;
  border-bottom: none;
  color: rgba(218, 234, 240, 0.7);
  font-size: 0.72rem;
  cursor: pointer;
}

.context-panel-tab.is-active {
  background: rgba(125, 211, 252, 0.12);
  border-color: rgba(125, 211, 252, 0.4);
  color: rgba(218, 234, 240, 0.95);
}

.context-panel-body {
  padding: 12px;
  overflow: auto;
  display: grid;
  gap: 8px;
}

.layer-context-identity {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.layer-context-identity strong {
  font-size: 0.92rem;
  color: rgba(236, 245, 248, 0.97);
}

.layer-context-notes {
  margin: 2px 0;
  font-size: 0.72rem;
  line-height: 1.45;
  color: rgba(190, 208, 214, 0.82);
}

/* Grouped, labeled sections inside the overlay options panel. */
.ctx-group {
  display: grid;
  gap: 8px;
  padding: 9px 10px 10px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.022);
}

.ctx-group-label {
  margin: 0;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.55);
}

.layer-context-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 4px;
}

.layer-context-actions .button {
  flex: 1 1 88px;
  text-align: center;
}

.coord-jump-row {
  display: flex;
  gap: 6px;
}

.coord-jump-row input {
  flex: 1 1 0;
  min-width: 0;
  min-height: 32px;
  padding: 0 8px;
  border: 1px solid rgba(163, 185, 188, 0.26);
  border-radius: 8px;
  color: rgba(218, 234, 240, 0.95);
  background: rgba(1, 7, 10, 0.7);
  font: inherit;
  font-size: 0.78rem;
  color-scheme: dark;
}

.coord-jump-row .button {
  flex: 0 0 auto;
}

.context-panel-close {
  position: absolute;
  top: 8px;
  right: 10px;
  z-index: 1;
  background: transparent;
  border: none;
  color: rgba(218, 234, 240, 0.7);
  font-size: 1.2rem;
  cursor: pointer;
  line-height: 1;
  padding: 4px 6px;
}

.context-panel-close:hover {
  color: rgba(218, 234, 240, 0.95);
}

@keyframes context-panel-slide-in {
  from {
    opacity: 0;
    transform: translateX(16px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.tool-context-card {
  display: grid;
  gap: 10px;
  padding: 10px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.035);
}

.tool-context-card .source-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
}

.tool-context-card .source-body {
  display: grid;
  gap: 5px;
  font-size: 0.78rem;
}

.tool-context-card .source-body .row {
  display: flex;
  justify-content: space-between;
  gap: 10px;
}

.context-button-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

@media (max-width: 720px) {
  body[data-route="observe"] .app-header {
    left: 8px;
    right: 8px;
    top: 8px;
    gap: 8px;
  }

  body[data-route="observe"] .header-controls {
    justify-content: flex-start;
    padding-right: 8px;
  }

  body[data-route="observe"] .header-dropdown {
    position: static;
  }

  body[data-route="observe"] .header-dropdown-menu {
    position: fixed;
    left: 8px;
    right: 8px;
    top: 66px;
    min-width: 0;
    max-width: none;
    max-height: min(62vh, 520px);
  }

  body[data-route="observe"] #basemap-select {
    max-width: 144px;
  }

  .context-panel {
    top: 74px;
    right: 8px;
    bottom: 76px;
    width: calc(100% - 16px);
  }

  .context-button-grid {
    grid-template-columns: 1fr;
  }
}

/* === Copernicus-style Observe shell === */

body[data-route="observe"] .app-header {
  left: 14px;
  right: auto;
  top: 12px;
  z-index: 760;
  width: auto;
  max-width: calc(100% - 28px);
  min-height: 46px;
  max-height: 52px;
  padding: 6px 10px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 14px;
  background: rgba(3, 10, 13, 0.78);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.38);
  backdrop-filter: blur(18px);
}

body[data-route="observe"] .brand-block .eyebrow {
  color: rgba(218, 234, 240, 0.64);
}

body[data-route="observe"] .header-controls {
  display: none !important;
}

body[data-route="observe"] .primary-nav .nav-button {
  min-height: 32px;
  border-radius: 10px;
  min-width: 72px;
  padding: 0 9px;
  font-size: 0.76rem;
}

body[data-route="observe"] .ocean-layer-dock {
  position: absolute;
  left: 16px;
  top: 76px;
  z-index: 780;
  display: block;
  width: auto;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  backdrop-filter: none;
}

/* Icon rail Ã¢â‚¬â€ compact translucent tool strip that keeps the map visible. */
.observe-rail-icons {
  display: flex;
  flex-direction: column;
  /* Size to the icons, NOT the dock. The dock (.ocean-layer-dock) is width:auto
     (shrink-to-fit), so it grows to the widest child -- the coordinate readout.
     Without this, the block-level icon strip would stretch to fill that width and
     visibly resize/jump as the cursor coordinate text changes. */
  width: fit-content;
  gap: 4px;
  padding: 6px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 16px;
  background: rgba(3, 10, 13, 0.6);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(16px);
}


.rail-icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 12px;
  color: rgba(218, 234, 240, 0.74);
  background: transparent;
  cursor: pointer;
  transition: color 0.16s ease, background 0.16s ease, transform 0.16s ease,
    border-color 0.16s ease;
}

.rail-icon:hover {
  color: #eafcff;
  background: rgba(255, 255, 255, 0.06);
  transform: translateY(-1px);
}

.rail-icon.is-active {
  color: #031413;
  background: linear-gradient(135deg, #32d0bd, #e8ff7a);
  border-color: rgba(232, 255, 122, 0.5);
}

.rail-icon-clear:hover {
  color: #ffd9c2;
  background: rgba(255, 138, 92, 0.14);
}

.rail-glyph {
  width: 27px;
  height: 27px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.rail-divider {
  display: block;
  height: 1px;
  margin: 3px 6px;
  background: rgba(163, 185, 188, 0.2);
}

.rail-icon-badge {
  position: absolute;
  top: -3px;
  right: -3px;
  min-width: 16px;
  height: 16px;
  display: grid;
  place-items: center;
  padding: 0 4px;
  border-radius: 999px;
  background: #e8ff7a;
  color: #04130f;
  font-size: 0.6rem;
  font-weight: 900;
}

.rail-icon-badge[hidden] {
  display: none;
}

/* Each rail glyph carries a small continuous loop. */
.rail-meridian {
  transform-box: fill-box;
  transform-origin: center;
  animation: railMeridian 5s ease-in-out infinite;
}

@keyframes railMeridian {
  0%,
  100% {
    transform: scaleX(1);
  }
  50% {
    transform: scaleX(0.08);
  }
}

.rail-stack-top {
  transform-box: fill-box;
  transform-origin: center;
  animation: railStackFloat 3.2s ease-in-out infinite;
}

@keyframes railStackFloat {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-1.7px);
  }
}

.rail-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: railPulse 2.6s ease-out infinite;
}

.rail-pulse-2 {
  animation-delay: -1.3s;
}

@keyframes railPulse {
  0% {
    transform: scale(0.32);
    opacity: 0.85;
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

.rail-ripple {
  transform-box: fill-box;
  transform-origin: center;
  animation: railRipple 2.8s ease-out infinite;
}

@keyframes railRipple {
  0% {
    transform: scale(0.35);
    opacity: 0;
  }
  35% {
    opacity: 0.75;
  }
  100% {
    transform: scale(1.25);
    opacity: 0;
  }
}

.rail-target {
  transform-box: fill-box;
  transform-origin: center;
  animation: railTarget 2.6s ease-out infinite;
}

@keyframes railTarget {
  0% {
    transform: scale(0.5);
    opacity: 0.7;
  }
  70%,
  100% {
    transform: scale(1.05);
    opacity: 0;
  }
}

.rail-wipe {
  animation: railWipe 2.4s linear infinite;
}

@keyframes railWipe {
  to {
    stroke-dashoffset: -21;
  }
}

/* Sample droplet pulses faster while sampling is armed. */
.rail-icon[data-ocean-tool="sample"].is-active .rail-glyph {
  animation: railSamplePulse 1.4s ease-in-out infinite;
}

@keyframes railSamplePulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.12);
  }
}

/* The Key glyph rocks like a key turning a lock, pivoting on its bow. */
.rail-key {
  transform-box: view-box;
  transform-origin: 12px 6.6px;
  animation: railKeyTurn 4s ease-in-out infinite;
}

@keyframes railKeyTurn {
  0%,
  56%,
  100% {
    transform: rotate(0deg);
  }
  70%,
  84% {
    transform: rotate(-22deg);
  }
}

/* Flyout control popups, anchored to the right of the rail. */
.rail-popup {
  position: absolute;
  left: calc(100% + 10px);
  top: 0;
  width: 252px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 12px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 14px;
  background: rgba(4, 12, 15, 0.78);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(18px);
  animation: railPopupIn 0.14s ease;
}

.rail-popup[hidden] {
  display: none;
}

@keyframes railPopupIn {
  from {
    opacity: 0;
    transform: translateX(-6px);
  }
}

.rail-popup-overlays {
  width: 272px;
  max-height: 72vh;
}

.rail-popup-title {
  margin: 0;
  font-size: 0.66rem;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.56);
}

.rail-popup-subtitle {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 1px solid rgba(163, 185, 188, 0.12);
}

.rail-popup-toggle {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 11px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 10px;
  color: rgba(218, 234, 240, 0.9);
  background: rgba(255, 255, 255, 0.03);
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 700;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.16s ease, background 0.16s ease;
}

.rail-popup-toggle:hover {
  border-color: rgba(163, 185, 188, 0.38);
}

.rail-popup-toggle.is-active {
  border-color: rgba(50, 208, 189, 0.5);
  background: rgba(50, 208, 189, 0.12);
  color: #eafcff;
}

.rail-toggle-dot {
  width: 12px;
  height: 12px;
  flex-shrink: 0;
  border-radius: 50%;
  border: 2px solid rgba(163, 185, 188, 0.5);
  transition: background 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}

.rail-popup-toggle.is-active .rail-toggle-dot {
  border-color: #32d0bd;
  background: #32d0bd;
  box-shadow: 0 0 0 3px rgba(50, 208, 189, 0.22);
}

.rail-popup-action {
  padding: 9px 11px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 10px;
  color: rgba(218, 234, 240, 0.9);
  background: rgba(255, 255, 255, 0.03);
  font: inherit;
  font-size: 0.8rem;
  font-weight: 700;
  cursor: pointer;
  transition: border-color 0.16s ease, background 0.16s ease;
}

.rail-popup-action:hover {
  border-color: rgba(163, 185, 188, 0.4);
  background: rgba(255, 255, 255, 0.07);
}

.rail-popup-overlays .ocean-layer-dock-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  /* Constrain children so a long Copernicus / NASA layer name can't push
     the dock-list wider than the 272px popup and trigger a horizontal
     scrollbar inside the popup. */
  overflow-x: hidden;
}
.rail-popup-overlays .ocean-layer-dock-list * {
  min-width: 0;
  overflow-wrap: anywhere;
}

/* All rail popups off the observe rail (View / Overlays / Sensors / Map Key)
   share the same chrome — when content is taller than 72vh the popup
   itself OR its inner list scrolls. Default browser scrollbars show up
   as a permanent ~16px gutter on Windows Chrome which the user reads as
   broken UI. Hide the visible scrollbars everywhere inside .rail-popup;
   wheel / touch / keyboard scroll still works so long lists stay
   reachable. */
.rail-popup,
.rail-popup *,
.rail-popup-overlays .ocean-layer-dock-list {
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* legacy Edge */
}
.rail-popup::-webkit-scrollbar,
.rail-popup *::-webkit-scrollbar,
.rail-popup-overlays .ocean-layer-dock-list::-webkit-scrollbar {
  width: 0;
  height: 0;
  display: none; /* Chrome / Safari */
}

.ocean-data-taxonomy {
  display: grid;
  gap: 6px;
  padding: 8px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.035);
}

.ocean-data-type {
  display: grid;
  grid-template-columns: 11px minmax(0, 1fr) auto;
  gap: 7px;
  align-items: center;
}

.ocean-data-type.is-muted {
  opacity: 0.58;
}

.ocean-data-type-swatch,
.map-data-kind-swatch {
  width: 10px;
  height: 10px;
  border-radius: 999px;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.05);
}

.ocean-data-type-copy {
  min-width: 0;
}

.ocean-data-type-label {
  display: block;
  overflow: hidden;
  color: rgba(238, 251, 255, 0.94);
  font-size: 0.72rem;
  font-weight: 800;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ocean-data-type-detail {
  display: block;
  overflow: hidden;
  color: rgba(190, 211, 218, 0.72);
  font-size: 0.62rem;
  line-height: 1.25;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ocean-data-type-count {
  min-width: 28px;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(7, 16, 20, 0.72);
  color: rgba(232, 248, 252, 0.86);
  font-size: 0.62rem;
  font-weight: 900;
  text-align: center;
}

.kind-platform {
  background: #32d0bd;
}

.kind-network {
  background: #7dd3fc;
}

.kind-vessel {
  background: #f59e0b;
}

.kind-sample {
  background: #a78bfa;
}

.kind-field {
  background: #22c55e;
}

.kind-chart {
  background: #facc15;
}

/* Fish-in-kelp toggle Ã¢â‚¬â€ hides all chrome for a fullscreen map. */
.immersive-toggle {
  display: none;
}

body[data-page="map"] .immersive-toggle {
  position: fixed;
  bottom: 18px;
  left: 18px;
  z-index: 780;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  padding: 0;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 50%;
  background: rgba(3, 10, 13, 0.42);
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(10px);
  opacity: 0.5;
  cursor: pointer;
  transition: opacity 0.22s ease, background 0.22s ease, transform 0.22s ease,
    top 0.3s ease, border-color 0.22s ease;
}

body[data-page="map"] .immersive-toggle:hover {
  opacity: 1;
  background: rgba(3, 10, 13, 0.72);
  transform: scale(1.07);
}

body.map-immersive .immersive-toggle {
  opacity: 0.62;
  border-color: rgba(50, 208, 189, 0.42);
}

body.map-immersive .immersive-toggle:hover {
  opacity: 1;
}

.immersive-glyph {
  width: 30px;
  height: 30px;
  overflow: visible;
}

.immersive-fish-body,
.immersive-fish-tail {
  fill: #9fe8dd;
}

.immersive-fish-eye {
  fill: #04130f;
}

.immersive-fish-swim {
  transform-box: fill-box;
  transform-origin: center;
  transition: transform 0.55s cubic-bezier(0.5, 0, 0.25, 1), opacity 0.4s ease;
}

body.map-immersive .immersive-fish-swim {
  transform: translateX(-13px);
  opacity: 0.05;
}

.immersive-fish-bob {
  transform-box: fill-box;
  transform-origin: center;
  animation: fishBob 3.4s ease-in-out infinite;
}

@keyframes fishBob {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-1.5px);
  }
}

.kelp-strand {
  fill: none;
  stroke: #57c08c;
  stroke-width: 2.4;
  stroke-linecap: round;
  transform-box: fill-box;
  transform-origin: bottom center;
  animation: kelpSway 4.6s ease-in-out infinite;
}

.kelp-strand:nth-child(2) {
  stroke: #6bd29c;
  animation-delay: -1.5s;
}

.kelp-strand:nth-child(3) {
  animation-delay: -3s;
}

@keyframes kelpSway {
  0%,
  100% {
    transform: rotate(-3.5deg);
  }
  50% {
    transform: rotate(3.5deg);
  }
}

/* Immersive mode Ã¢â‚¬â€ hide all observe chrome so only the map (and fish) remain. */
body.map-immersive .app-header,
body.map-immersive #ocean-layer-dock,
body.map-immersive #observe-time-bar,
body.map-immersive #map-status,
body.map-immersive #context-panel,
body.map-immersive .context-drawer,
body.map-immersive #copilot-launcher,
body.map-immersive #copilot-panel {
  display: none !important;
}

body.map-immersive .map-plane .map-stage {
  margin: 0;
}

/* === Icon navigation Ã¢â‚¬â€ animated SVG menu with hover tooltips === */
body[data-route="observe"] .primary-nav.icon-nav {
  gap: 5px;
  padding: 4px;
}

body[data-route="observe"] .primary-nav.icon-nav .nav-button {
  position: relative;
  display: grid;
  place-items: center;
  width: 42px;
  min-width: 0;
  height: 42px;
  padding: 0;
  border-radius: 12px;
  color: rgba(218, 234, 240, 0.66);
  overflow: visible;
}

body[data-route="observe"] .primary-nav.icon-nav .nav-button:hover {
  color: #eafcff;
  background: rgba(255, 255, 255, 0.07);
  transform: translateY(-1px);
}

body[data-route="observe"] .primary-nav.icon-nav .nav-button.is-active {
  color: #041312;
  background: linear-gradient(135deg, var(--accent), #8cf3e4);
  box-shadow: 0 0 0 1px rgba(140, 243, 228, 0.4), 0 6px 18px rgba(50, 208, 189, 0.32);
}

.nav-glyph {
  width: 23px;
  height: 23px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.18s ease;
}

.nav-button:hover .nav-glyph {
  transform: scale(1.14);
}

.nav-tip {
  position: absolute;
  top: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%) translateY(-3px);
  padding: 3px 9px;
  border-radius: 7px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  background: rgba(3, 10, 13, 0.94);
  color: #dff8ff;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.03em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.16s ease, transform 0.16s ease;
  z-index: 5;
}

.nav-button:hover .nav-tip {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Each glyph below is a small animation that loops continuously. */

/* Observe Ã¢â‚¬â€ sonar sweep with a return blip */
.nav-sonar-sweep {
  transform-box: view-box;
  transform-origin: 12px 12px;
  animation: navSonarSweep 3.4s linear infinite;
}

@keyframes navSonarSweep {
  to {
    transform: rotate(360deg);
  }
}

.nav-sonar-blip {
  animation: navSonarBlip 3.4s ease-in-out infinite;
}

@keyframes navSonarBlip {
  0%,
  64%,
  100% {
    opacity: 0.2;
  }
  78% {
    opacity: 1;
  }
}

/* Plan Ã¢â‚¬â€ route dots flow toward a pinging destination */
.nav-route-line {
  animation: navRouteFlow 1.1s linear infinite;
}

@keyframes navRouteFlow {
  to {
    stroke-dashoffset: -7.4;
  }
}

.nav-route-ping {
  transform-box: view-box;
  transform-origin: 18.6px 18.6px;
  animation: navRoutePing 2.6s ease-out infinite;
}

@keyframes navRoutePing {
  0% {
    transform: scale(0.3);
    opacity: 0.75;
  }
  70%,
  100% {
    transform: scale(1.05);
    opacity: 0;
  }
}

/* Control Ã¢â‚¬â€ helm wheel turns slowly */
.nav-helm {
  transform-box: view-box;
  transform-origin: 12px 12px;
  animation: navHelmTurn 9s linear infinite;
}

@keyframes navHelmTurn {
  to {
    transform: rotate(360deg);
  }
}

/* Analyze Ã¢â‚¬â€ bars rise and fall like a live readout */
.nav-cbar {
  transform-box: fill-box;
  transform-origin: 50% 100%;
}

.nav-cbar:nth-of-type(1) {
  animation: navCbar 2.6s ease-in-out infinite;
}

.nav-cbar:nth-of-type(2) {
  animation: navCbar 2.6s ease-in-out infinite -0.85s;
}

.nav-cbar:nth-of-type(3) {
  animation: navCbar 2.6s ease-in-out infinite -1.7s;
}

@keyframes navCbar {
  0%,
  100% {
    transform: scaleY(0.5);
  }
  50% {
    transform: scaleY(1);
  }
}

/* Data Ã¢â‚¬â€ a scan band sweeps down the cylinder */
.nav-db-scan {
  animation: navDbScan 2.9s ease-in-out infinite;
}

@keyframes navDbScan {
  0% {
    transform: translateY(-4.3px);
    opacity: 0;
  }
  22%,
  78% {
    opacity: 0.95;
  }
  100% {
    transform: translateY(6px);
    opacity: 0;
  }
}

/* Mesh Ã¢â‚¬â€ data pips travel the links out from the hub */
.nav-mesh-pip {
  animation: navMeshPipA 2.5s ease-in-out infinite;
}

.nav-mesh-pip-b {
  animation-name: navMeshPipB;
  animation-delay: -0.83s;
}

.nav-mesh-pip-c {
  animation-name: navMeshPipC;
  animation-delay: -1.66s;
}

@keyframes navMeshPipA {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  18%,
  82% {
    opacity: 1;
  }
  100% {
    transform: translate(0, -8px);
    opacity: 0;
  }
}

@keyframes navMeshPipB {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  18%,
  82% {
    opacity: 1;
  }
  100% {
    transform: translate(-7px, 6.8px);
    opacity: 0;
  }
}

@keyframes navMeshPipC {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  18%,
  82% {
    opacity: 1;
  }
  100% {
    transform: translate(7px, 6.8px);
    opacity: 0;
  }
}

/* Hardware Ã¢â‚¬â€ current cycles through the pins while the core pulses */
.nav-chip-core {
  transform-box: fill-box;
  transform-origin: center;
  animation: navChipCore 2s ease-in-out infinite;
}

@keyframes navChipCore {
  0%,
  100% {
    opacity: 0.5;
    transform: scale(0.84);
  }
  50% {
    opacity: 1;
    transform: scale(1);
  }
}

.nav-chip-pin {
  animation: navChipPin 2.4s ease-in-out infinite;
}

.nav-chip-pin:nth-of-type(1) {
  animation-delay: 0s;
}
.nav-chip-pin:nth-of-type(2) {
  animation-delay: 0.3s;
}
.nav-chip-pin:nth-of-type(3) {
  animation-delay: 0.6s;
}
.nav-chip-pin:nth-of-type(4) {
  animation-delay: 0.9s;
}
.nav-chip-pin:nth-of-type(5) {
  animation-delay: 1.2s;
}
.nav-chip-pin:nth-of-type(6) {
  animation-delay: 1.5s;
}
.nav-chip-pin:nth-of-type(7) {
  animation-delay: 1.8s;
}
.nav-chip-pin:nth-of-type(8) {
  animation-delay: 2.1s;
}

@keyframes navChipPin {
  0%,
  68%,
  100% {
    opacity: 0.32;
  }
  34% {
    opacity: 1;
  }
}

/* Admin Ã¢â‚¬â€ two gears mesh in opposite directions */
.nav-cog {
  transform-box: view-box;
}

.nav-cog-main {
  transform-origin: 9px 9px;
  animation: navCogCw 6s linear infinite;
}

.nav-cog-sub {
  transform-origin: 16.6px 16.6px;
  animation: navCogCcw 4.2s linear infinite;
}

@keyframes navCogCw {
  to {
    transform: rotate(360deg);
  }
}

@keyframes navCogCcw {
  to {
    transform: rotate(-360deg);
  }
}

.nav-forum-lines {
  transform-box: view-box;
  animation: navForumLines 2.6s ease-in-out infinite alternate;
}
@keyframes navForumLines {
  from { opacity: 0.3; transform: translateX(-1px); }
  to { opacity: 1; transform: translateX(1px); }
}

.nav-wiki-lines {
  transform-box: view-box;
  transform-origin: left center;
  animation: navWikiLines 2.2s ease infinite alternate;
}
@keyframes navWikiLines {
  from { transform: scaleX(0.85); opacity: 0.6; }
  to { transform: scaleX(1); opacity: 1; }
}

.nav-blog-pen {
  transform-box: view-box;
  transform-origin: center;
  animation: navBlogPen 2s cubic-bezier(0.4, 0, 0.2, 1) infinite alternate;
}
@keyframes navBlogPen {
  from { transform: translateY(-1px) translateX(1px); }
  to { transform: translateY(1px) translateX(-1px); }
}

.nav-market-string {
  transform-box: view-box;
  transform-origin: center;
  animation: navMarketString 2.4s ease-in-out infinite alternate;
}
@keyframes navMarketString {
  from { transform: translateY(1px); opacity: 0.6; }
  to { transform: translateY(-1px); opacity: 1; }
}

/* â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
   Ocean Probe â€” rich spot-sample dashboard
   â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â• */

/* Ocean Probe report — the heavy data tool that shows up inside
   .context-panel.is-tool-probe. Designed to scale from a narrow drawer
   (when the wide layout isn't applied) all the way to ~1200px wide. */
.probe-report {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* No horizontal scroll on the report container — children must
     resize, not overflow. */
  min-width: 0;
  max-width: 100%;
}

.probe-hero {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; border-radius: 10px;
  background: linear-gradient(135deg, rgba(50,208,189,0.12), rgba(125,211,252,0.08));
  border: 1px solid rgba(50,208,189,0.22);
  flex-wrap: wrap;
  gap: 8px;
}
.probe-hero-coords { font-family: "IBM Plex Mono", monospace; font-size: var(--fs-md); font-weight: 700; color: #e8ff7a; }
.probe-hero-time { font-size: 0.7rem; color: rgba(218,234,240,0.6); margin-top: 2px; }

.probe-conditions {
  display: grid;
  /* Auto-fill with a generous min so wide panels show 6-8 metric cards
     per row instead of being stuck at 3. The narrow drawer still gets
     2-3 columns. */
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 8px;
  min-width: 0;
}

.probe-metric-card {
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid rgba(163,185,188,0.14);
  background: rgba(255,255,255,0.03);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.probe-metric-card:hover {
  border-color: rgba(50,208,189,0.35);
  background: rgba(50,208,189,0.06);
}
.probe-metric-label {
  font-size: 0.62rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: rgba(218,234,240,0.5);
}
.probe-metric-value {
  font-size: var(--fs-lg); font-weight: 800; color: #dff8ff;
  font-variant-numeric: tabular-nums;
}
.probe-metric-unit { font-size: var(--fs-xs); font-weight: 400; color: rgba(218,234,240,0.5); margin-left: 2px; }

.probe-sparkline { margin-top: 4px; }
.probe-sparkline svg { width: 100%; height: 28px; display: block; }

/* Region Report metric cards — under the mean value, show a thin track
   with a colored mark at the relative position of the mean within the
   [min, max] window, plus a "min–max · Δrange" caption. Same vertical
   footprint as the Ocean Probe sparkline so the wide-mode probe-
   conditions grid stays balanced when both tools are visible. */
.area-spread { margin-top: 4px; display: flex; flex-direction: column; gap: 3px; }
.area-spread-track {
  position: relative;
  width: 100%;
  height: 4px;
  border-radius: 2px;
  background: rgba(163, 185, 188, 0.18);
  overflow: visible;
}
.area-spread-mark {
  position: absolute;
  top: 50%;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  transform: translateY(-50%);
  background: #32d0bd;
  box-shadow: 0 0 0 2px rgba(7, 18, 24, 0.95);
}
.area-spread-meta {
  font-size: 0.6rem;
  color: rgba(218, 234, 240, 0.45);
  font-variant-numeric: tabular-nums;
}

/* ── Coordinates Workshop ────────────────────────────────────────────
   New body for the .context-panel.is-tool-coords tool. Reuses the
   .probe-hero / .probe-actions-bar / .probe-conditions / .probe-stations-
   row chrome plus a few coord-specific bits. */
.coords-workshop {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  max-width: 100%;
}
.coords-mono {
  font-family: "IBM Plex Mono", monospace;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}
.coords-format-toggle {
  display: inline-flex;
  align-self: flex-start;
  gap: 0;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 8px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.03);
}
.coords-format-toggle button {
  font: inherit;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 5px 12px;
  border: 0;
  background: transparent;
  color: rgba(218, 234, 240, 0.7);
  cursor: pointer;
  transition: background 0.16s ease, color 0.16s ease;
}
.coords-format-toggle button + button {
  border-left: 1px solid rgba(163, 185, 188, 0.22);
}
.coords-format-toggle button:hover {
  background: rgba(255, 255, 255, 0.06);
  color: #dff8ff;
}
.coords-format-toggle button.is-active {
  background: rgba(50, 208, 189, 0.18);
  color: #eafcff;
}
.coords-input-row {
  display: flex;
  gap: 6px;
  align-items: stretch;
  margin-bottom: 6px;
}
.coords-input-row-split > input[type="number"] {
  flex: 1 1 0;
  min-width: 0;
}
.coords-input-row > .coords-input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 7px 10px;
  border-radius: 6px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  background: rgba(255, 255, 255, 0.04);
  color: #dff8ff;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.8rem;
}
.coords-input-row > input[type="number"] {
  padding: 7px 10px;
  border-radius: 6px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  background: rgba(255, 255, 255, 0.04);
  color: #dff8ff;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.8rem;
}
.coords-input-hint {
  font-size: 0.66rem;
  margin-top: 4px;
}
.coords-input-hint kbd {
  background: rgba(255,255,255,0.08);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 0.62rem;
}
/* Pin list rows — index, coord, distance/bearing meta, action buttons */
.coords-pin-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 8px;
}
.coords-pin-row {
  display: grid;
  grid-template-columns: 32px 1fr auto auto;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(163, 185, 188, 0.1);
  transition: background 0.16s ease, border-color 0.16s ease;
}
.coords-pin-row:hover {
  background: rgba(50, 208, 189, 0.06);
  border-color: rgba(50, 208, 189, 0.3);
}
.coords-pin-num {
  font-weight: 800;
  color: rgba(218, 234, 240, 0.5);
  font-size: 0.7rem;
}
.coords-pin-coord {
  font-size: 0.78rem;
  color: #dff8ff;
}
.coords-pin-meta {
  font-size: 0.66rem;
  color: rgba(218, 234, 240, 0.5);
  text-align: right;
  white-space: nowrap;
}
.coords-pin-actions {
  display: inline-flex;
  gap: 2px;
}
.coords-pin-action {
  font: inherit;
  font-size: 0.78rem;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: rgba(218, 234, 240, 0.6);
  padding: 3px 6px;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, color 0.14s ease;
}
.coords-pin-action:hover {
  background: rgba(50, 208, 189, 0.12);
  border-color: rgba(50, 208, 189, 0.35);
  color: #eafcff;
}
.coords-pin-action.coords-pin-remove:hover {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(239, 68, 68, 0.4);
  color: #fda4af;
}
/* Bookmarks */
.coords-bookmark-list {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 8px;
}
.coords-bookmark-row {
  display: grid;
  grid-template-columns: minmax(80px, 1fr) auto auto;
  align-items: center;
  gap: 8px;
  padding: 5px 8px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(163, 185, 188, 0.08);
  font-size: var(--fs-sm);
}
.coords-bookmark-name {
  color: #dff8ff;
  font-weight: 600;
}
.coords-bookmark-coord {
  color: rgba(218, 234, 240, 0.5);
  font-size: var(--fs-xs);
  text-align: right;
}
.coords-bookmark-actions {
  display: inline-flex;
  gap: 2px;
}
.coords-bookmark-add {
  margin-top: 6px;
  border-top: 1px dashed rgba(163, 185, 188, 0.16);
  padding-top: 8px;
}

/* SST heatmap card — the SVG should fill its parent (the .probe-source-
   section's body) and not blow out the column width when the panel is
   narrow. */
.area-heatmap-card .area-heatmap-body {
  padding: 10px 12px;
  display: flex;
  justify-content: center;
  align-items: center;
}
.area-heatmap-card .area-heatmap-body svg {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Action bar — sticky at the top of the probe report so re-probe /
   copy / inspect-station / AI / close are always one click away even
   after scrolling through forecast charts. */
.probe-actions-bar {
  position: sticky;
  top: -8px; /* pull up to hide the scroll-gap gradient */
  z-index: 3;
  margin: -8px -2px 0;
  padding: 8px 4px;
  /* Solid bottom so the gradient doesn't overlap chart hover tooltips
     with a translucent blur layer. The user reported hover text
     looking "really lite" — the backdrop-filter was washing out the
     hover label whenever it rendered near the top of a chart. */
  background: rgb(7, 18, 24);
}
.probe-actions-bar .probe-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.probe-actions-bar .button {
  font-size: var(--fs-sm);
  padding: 6px 12px;
  min-height: 30px;
}

/* Stations row — NDBC + Argo side-by-side in the wide probe layout. */
.probe-stations-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 10px;
  min-width: 0;
}
.context-panel.is-tool-probe .probe-stations-row,
.context-panel.is-tool-area .probe-stations-row {
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

.probe-source-section {
  border: 1px solid rgba(163,185,188,0.14);
  border-radius: 8px; overflow: hidden;
  min-width: 0;
}
.probe-source-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 7px 10px;
  background: rgba(255,255,255,0.03);
  border-bottom: 1px solid rgba(163,185,188,0.1);
}
.probe-source-head strong { font-size: var(--fs-sm); color: #dff8ff; }
.probe-source-body { padding: 6px 10px; display: grid; gap: 3px; }
.probe-source-body .row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 0.72rem; padding: 2px 0;
  border-bottom: 1px solid rgba(163,185,188,0.06);
}
.probe-source-body .row:last-child { border-bottom: 0; }
.probe-source-body .row span { color: rgba(218,234,240,0.55); }
.probe-source-body .row strong { color: #dff8ff; font-variant-numeric: tabular-nums; }

.probe-ai-section {
  padding: 10px 12px; border-radius: 8px;
  background: linear-gradient(135deg, rgba(232,255,122,0.06), rgba(50,208,189,0.06));
  border: 1px solid rgba(232,255,122,0.18);
}
.probe-ai-section .probe-ai-label {
  font-size: 0.64rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: #e8ff7a; margin-bottom: 6px;
}
.probe-ai-section .probe-ai-text {
  font-size: 0.76rem; line-height: 1.55; color: rgba(218,234,240,0.88);
}
.probe-ai-btn {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 8px 16px; border: 1px solid rgba(232,255,122,0.5);
  border-radius: 6px; background: rgba(232,255,122,0.12);
  color: #e8ff7a; font-size: 0.75rem; font-weight: 800;
  cursor: pointer; transition: background 0.15s, border-color 0.15s;
}
.probe-ai-btn:hover { background: rgba(232,255,122,0.22); border-color: rgba(232,255,122,0.7); }

/* Forecast charts — Plotly.js powered. */
.probe-forecast-grid {
  padding: 10px;
  display: flex; flex-direction: column; gap: 14px;
  min-width: 0;
}
.probe-chart-group {
  display: flex; flex-direction: column; gap: 8px;
  min-width: 0;
}
.probe-chart-group-label {
  font-size: 0.7rem; font-weight: 800; text-transform: uppercase;
  letter-spacing: 0.06em; color: rgba(218,234,240,0.55);
  padding: 4px 0; border-bottom: 1px solid rgba(163,185,188,0.12);
}

/* In the wide Ocean Probe layout, charts within a group lay out
   side-by-side so the operator can compare related series at a glance
   instead of scrolling vertically through 9 stacked charts. */
.context-panel.is-tool-probe .probe-chart-group {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 10px;
}
.context-panel.is-tool-probe .probe-chart-group-label {
  grid-column: 1 / -1;
}

.probe-forecast-chart {
  border: 1px solid rgba(163,185,188,0.12);
  border-radius: 8px;
  background: rgba(0,0,0,0.2);
  overflow: hidden;
  min-width: 0;
}

/* Force the Plotly hover tooltip to be fully readable inside the probe
   charts. Plotly's default styling sometimes ends up rendering the
   hover text against a near-transparent or color-shifted background
   when our dark theme + nested stacking contexts collide. These rules
   override the SVG fill/stroke on the hover overlay directly so we
   get solid dark bg + opaque white text regardless of what Plotly's
   JS-level hoverlabel config does. */

/* Chart canvas wrapper bg. Stays on the DIV wrappers only — DO NOT
   touch SVG .bg rects, because Plotly uses class="bg" for the drag-
   layer rect that overlays the plot area, and Plotly relies on it
   being transparent so traces show through. Forcing fill on .bg was
   covering the data lines and producing an all-black chart. */
.probe-forecast-chart .js-plotly-plot,
.probe-forecast-chart .plot-container {
  background: rgb(4, 10, 14);
}
/* paper_bgcolor + plot_bgcolor in the Plotly layout config handle the
   actual SVG <rect class="bg"> fills — let Plotly manage those. */

/* Hover tooltip — DROP the .probe-forecast-chart scope. The previous
   scoped selectors weren't matching because Plotly sometimes renders
   the .hoverlayer at a different DOM level than the chart container.
   These rules now apply to ANY Plotly chart on the page, which is
   fine — we want the same dark theme everywhere.

   Use g.hovertext (Plotly v2 modern DOM) AND .hovertext (older) AND
   .hoverlayer * as a triple-redundant pattern so SOMETHING wins. */
g.hovertext,
.hovertext,
.hoverlayer,
.hoverlayer * {
  opacity: 1 !important;
  fill-opacity: 1 !important;
}
g.hovertext > path,
.hovertext > path,
.hoverlayer path,
.hoverlayer rect {
  fill: rgb(10, 20, 28) !important;
  stroke: rgba(50, 208, 189, 0.95) !important;
  stroke-width: 1.5px !important;
}
g.hovertext text,
g.hovertext tspan,
.hovertext text,
.hovertext tspan,
.hoverlayer text,
.hoverlayer tspan {
  fill: #ffffff !important;
  stroke: none !important;
  font-family: 'IBM Plex Mono', 'Roboto Mono', monospace !important;
  font-size: 12px !important;
  font-weight: 700 !important;
  paint-order: stroke fill !important;
}
.hoverlayer { pointer-events: none; }
.hoverlayer .hovertext { pointer-events: auto; }

/* Axis labels + tick text — readable against the dark plot bg. */
.probe-forecast-chart .xtick text,
.probe-forecast-chart .ytick text,
.probe-forecast-chart .ytitle,
.probe-forecast-chart .xtitle {
  fill: rgba(218, 234, 240, 0.85) !important;
}
.probe-forecast-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: 5px 10px;
  border-bottom: 1px solid rgba(163,185,188,0.08);
}
.probe-forecast-title { font-size: var(--fs-xs); font-weight: 700; color: #dff8ff; }
.probe-forecast-range { font-size: 0.6rem; color: rgba(218,234,240,0.4); font-family: "IBM Plex Mono", monospace; }

.probe-chart-unit { font-weight: 400; font-size: 0.6rem; color: rgba(218,234,240,0.4); }

.probe-chart-row {
  display: flex; gap: 0;
}
.probe-chart-canvas-wrap {
  flex: 1 1 0; min-width: 0;
  min-height: 220px;
}
/* Make Plotly modebar float top-right inside the chart */
.probe-chart-canvas-wrap .modebar { position: absolute !important; top: 2px; right: 2px; }

.probe-chart-stats {
  flex-shrink: 0; width: 62px;
  display: flex; flex-direction: column; justify-content: center;
  padding: 6px 7px;
  border-left: 1px solid rgba(163,185,188,0.1);
  font-family: "IBM Plex Mono", monospace;
  background: rgba(0,0,0,0.08);
}
.pcs-row {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 0.58rem; line-height: 1.6;
}
.pcs-label { color: rgba(218,234,240,0.4); font-weight: 600; }
.pcs-val { color: #dff8ff; font-weight: 700; font-variant-numeric: tabular-nums; }



/* Area Analysis (Region Report) */
.area-report { display: flex; flex-direction: column; gap: 10px; }

.area-hero {
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; border-radius: 10px;
  background: linear-gradient(135deg, rgba(125,211,252,0.12), rgba(50,208,189,0.08));
  border: 1px solid rgba(125,211,252,0.22);
}
.area-hero-title { font-size: var(--fs-base); font-weight: 800; color: #dff8ff; }
.area-hero-meta { font-size: var(--fs-xs); color: rgba(218,234,240,0.55); font-family: "IBM Plex Mono", monospace; }

.area-stats-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px;
}
.area-stat-card {
  padding: 7px 9px; border-radius: 7px;
  border: 1px solid rgba(163,185,188,0.12);
  background: rgba(255,255,255,0.025);
}
.area-stat-card .area-stat-label {
  font-size: 0.6rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: rgba(218,234,240,0.45);
}
.area-stat-card .area-stat-value {
  font-size: 1rem; font-weight: 800; color: #dff8ff; font-variant-numeric: tabular-nums;
}
.area-stat-card .area-stat-range {
  font-size: 0.62rem; color: rgba(218,234,240,0.4);
}

.area-grid-heatmap { margin-top: 4px; }
.area-grid-heatmap svg { width: 100%; height: auto; display: block; }

.area-station-list { display: grid; gap: 4px; }
.area-station-item {
  display: flex; align-items: center; justify-content: space-between;
  padding: 5px 8px; border-radius: 6px; font-size: 0.7rem;
  border: 1px solid rgba(163,185,188,0.1);
  background: rgba(255,255,255,0.02);
}
.area-station-item .site { color: #dff8ff; font-weight: 600; }
.area-station-item .coords { color: rgba(218,234,240,0.4); font-family: "IBM Plex Mono", monospace; font-size: 0.64rem; }

/* Box select crosshair */
body.is-area-selecting { cursor: crosshair; }


/* === Status readout Ã¢â‚¬â€ translucent pill centered below the header === */
body[data-route="observe"] #map-status {
  position: absolute;
  top: 72px;
  left: 50%;
  right: auto;
  bottom: auto;
  transform: translateX(-50%);
  z-index: 700;
  display: flex;
  align-items: flex-start;
  gap: 9px;
  width: auto;
  max-width: min(560px, calc(100vw - 220px));
  margin: 0;
  padding: 7px 16px;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 999px;
  background: rgba(3, 10, 13, 0.64);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.42);
  backdrop-filter: blur(14px);
  color: rgba(218, 234, 240, 0.84);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.71rem;
  line-height: 1.4;
}

body[data-route="observe"] #map-status::before {
  content: "";
  flex-shrink: 0;
  width: 7px;
  height: 7px;
  margin-top: 3px;
  border-radius: 50%;
  background: var(--accent);
  animation: statusDotPulse 2.4s ease-in-out infinite;
}

@keyframes statusDotPulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(50, 208, 189, 0.5);
  }
  50% {
    box-shadow: 0 0 0 5px rgba(50, 208, 189, 0);
  }
}

/* Thin translucent time + depth scrubber pinned to the bottom of the Observe map. */
.observe-time-bar {
  display: none;
}

body[data-page="map"] .observe-time-bar {
  position: absolute;
  left: 282px;
  right: 16px;
  bottom: 14px;
  margin-inline: auto;
  /* Compact: the bar now holds only the clock + scrubber + depth (coords moved
     to the rail), so it doesn't need to sprawl across the map. */
  max-width: 680px;
  z-index: 720;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  padding: 5px 12px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 999px;
  background: rgba(3, 10, 13, 0.6);
  box-shadow: 0 16px 44px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(16px);
}

body[data-route="observe"] .map-stage.is-globe .observe-time-bar {
  left: 316px;
  right: 316px;
  max-width: 760px;
  border-radius: 18px;
}

.time-bar-modes {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
}

.time-bar-mode {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 24px;
  padding: 0 11px;
  border: 0;
  border-radius: 999px;
  color: rgba(218, 234, 240, 0.66);
  background: transparent;
  font: inherit;
  font-size: var(--fs-xs);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  cursor: pointer;
  transition: color 0.15s ease, background 0.15s ease;
}

.time-bar-mode:hover {
  color: #dff8ff;
}

.time-bar-mode.is-active {
  color: #031413;
  background: linear-gradient(135deg, #32d0bd, #e8ff7a);
}

.time-bar-glyph {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.time-bar-live-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(218, 234, 240, 0.5);
}

.time-bar-mode.is-active .time-bar-live-dot {
  background: #031413;
  animation: timeBarPulse 1.9s ease-in-out infinite;
}

@keyframes timeBarPulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(3, 20, 19, 0.65);
  }
  55% {
    box-shadow: 0 0 0 5px rgba(3, 20, 19, 0);
  }
}

.time-bar-clock {
  flex-shrink: 0;
  min-width: 70px;
  color: #e8ff7a;
  font-size: 0.72rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.time-bar-track {
  display: flex;
  flex: 1 1 200px;
  min-width: 180px;
  margin: 0;
}

/* The master-clock controls are grouped so animation mode can swap them out:
   while an overlay time-lapse runs, the time bar shows #timelapse-controls
   in their place. */
.time-bar-master {
  display: flex;
  /* Take a full row of the (wrapping) time bar so the scrubber stretches. */
  flex: 1 1 100%;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  min-width: 0;
}

body.timeline-animating .time-bar-master {
  display: none;
}

/* While an animation runs the bar carries a multi-row control block; switch the
   999px pill to a panel radius so the stacked rows read as a tidy panel instead
   of a stretched capsule, and let it size to its content. */
body.timeline-animating .observe-time-bar {
  border-radius: 16px;
  flex-direction: column;
  align-items: stretch;
}

#observe-time-bar #timelapse-controls {
  order: -1;
  flex: 1 1 100%;
  min-width: 0;
  margin-top: 0;
}

/* The second row holds the animation range + step + speed controls so the
   user can adjust playback while the time-lapse runs. Keep it visible and
   let it wrap inside the time bar if the pill is narrow. */
#observe-time-bar #timelapse-controls .tl-row:nth-child(2) {
  font-size: var(--fs-xs);
  flex-wrap: wrap;
  gap: 6px 10px;
}

#observe-time-bar #timelapse-controls .tl-row:nth-child(2) input[type="date"],
#observe-time-bar #timelapse-controls .tl-row:nth-child(2) select {
  font-size: inherit;
  padding: 2px 4px;
}

.observe-time-bar input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 16px;
  min-height: 0;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

.observe-time-bar input[type="range"]::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
}

.observe-time-bar input[type="range"]::-moz-range-track {
  height: 4px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.16);
}

.observe-time-bar input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  margin-top: -4.5px;
  width: 13px;
  height: 13px;
  border: 2px solid #02110f;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}

.observe-time-bar input[type="range"]::-moz-range-thumb {
  width: 13px;
  height: 13px;
  border: 2px solid #02110f;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
}

.time-bar-datetime {
  flex-shrink: 0;
  width: 188px;
  min-height: 28px;
  padding: 0 8px;
  border: 1px solid rgba(163, 185, 188, 0.24);
  border-radius: 8px;
  color: rgba(218, 234, 240, 0.94);
  background: rgba(1, 7, 10, 0.7);
  font: inherit;
  font-size: 0.72rem;
  color-scheme: dark;
}

.time-bar-depth {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
  padding-left: 12px;
  border-left: 1px solid rgba(163, 185, 188, 0.16);
  color: rgba(125, 211, 252, 0.92);
}

/* Hide depth + cursor readouts by default. The static placeholders
   ("Surface 0 m" / "Move cursor over map") were eating ~30px of the
   time-bar on every Map view load when the operator hasn't interacted
   with depth slicing or cursor tracking yet. Show them when they
   actually have data via body[data-depth-active] / body[data-cursor-active]
   data attributes (set by the corresponding JS handlers). */
body:not([data-depth-active="true"]) .time-bar-depth { display: none; }

.time-bar-depth input[type="range"] {
  width: 96px;
}

.time-bar-depth-label {
  min-width: 78px;
  color: rgba(218, 234, 240, 0.86);
  font-size: 0.7rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}


.observe-panel-sections {
  display: flex;
  flex-direction: column;
  gap: 8px;
  min-height: 0;
  overflow-y: auto;
  padding-right: 2px;
}

.observe-panel-section {
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.025);
}

.observe-panel-section > summary {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  cursor: pointer;
  list-style: none;
  font-size: var(--fs-sm);
  font-weight: 800;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #dff8ff;
}

.observe-panel-section > summary::-webkit-details-marker {
  display: none;
}

.observe-panel-section > summary::after {
  content: "+";
  margin-left: auto;
  font-size: var(--fs-md);
  color: rgba(218, 234, 240, 0.6);
}

.observe-panel-section[open] > summary::after {
  content: "\2212";
}

.observe-section-flag {
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(50, 208, 189, 0.18);
  color: #8cf3e4;
  font-size: 0.62rem;
  text-transform: none;
}

.observe-section-body {
  display: grid;
  gap: 8px;
  padding: 0 9px 9px;
}

.observe-panel-section .ocean-layer-dock-list {
  max-height: 42vh;
  overflow-y: auto;
}

.observe-panel-section .temporal-grid {
  grid-template-columns: 1fr;
  gap: 7px;
}

.observe-panel-section input[type="range"] {
  accent-color: var(--accent);
}

.ocean-dock-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.ocean-dock-head h3 {
  margin: 0;
  font-size: 1rem;
}

.ocean-view-switch {
  display: inline-grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2px;
  padding: 3px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
}

.ocean-view-switch button {
  min-width: 38px;
  min-height: 28px;
  border: 0;
  border-radius: 7px;
  color: rgba(218, 234, 240, 0.76);
  background: transparent;
  font: inherit;
  font-size: 0.72rem;
  font-weight: 900;
  cursor: pointer;
}

.ocean-view-switch button.is-active {
  color: #031413;
  background: linear-gradient(135deg, #32d0bd, #e8ff7a);
}

.ocean-dock-select {
  display: grid;
  gap: 4px;
}

.ocean-dock-select span,
.ocean-dock-section summary {
  font-size: 0.65rem;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(218, 234, 240, 0.68);
}

.ocean-dock-select select {
  width: 100%;
  min-height: 34px;
  border: 1px solid rgba(163, 185, 188, 0.24);
  border-radius: 8px;
  color: rgba(218, 234, 240, 0.94);
  background: rgba(1, 7, 10, 0.68);
  font: inherit;
  font-size: var(--fs-base);
}

.ocean-layer-active-summary {
  display: block;
  padding: 8px 9px;
  border: 1px solid rgba(125, 211, 252, 0.22);
  border-radius: 10px;
  color: rgba(218, 234, 240, 0.78);
  background: rgba(125, 211, 252, 0.07);
  font-size: 0.72rem;
  line-height: 1.35;
}

.ocean-layer-active-summary strong {
  color: #e8ff7a;
}

.ocean-layer-dock-list {
  display: grid;
  gap: 8px;
  min-height: 0;
  overflow: auto;
  padding-right: 3px;
  scrollbar-width: thin;
}

.ocean-dock-section {
  display: block;
  padding: 7px;
  border: 1px solid rgba(163, 185, 188, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.026);
}

.ocean-dock-section summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  cursor: pointer;
  list-style: none;
}

.ocean-dock-section summary::-webkit-details-marker {
  display: none;
}

.ocean-dock-section summary::after {
  content: "+";
  flex: 0 0 auto;
  color: rgba(125, 211, 252, 0.78);
}

.ocean-dock-section[open] summary::after {
  content: "-";
}

.ocean-dock-section:not([open]) > .ocean-dock-source-meta,
.ocean-dock-section:not([open]) > .ocean-dock-section-body {
  display: none;
}

.ocean-dock-source-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ocean-dock-source-pill {
  flex: 0 0 auto;
  padding: 2px 6px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 999px;
  color: rgba(218, 234, 240, 0.72);
  background: rgba(255, 255, 255, 0.04);
  font-size: 0.58rem;
  letter-spacing: 0;
  text-transform: none;
}

.ocean-dock-source-pill.is-live {
  color: #ccffe1;
  border-color: rgba(85, 211, 138, 0.24);
  background: rgba(85, 211, 138, 0.14);
}

.ocean-dock-source-pill.is-key-ready {
  color: #ffe0b4;
  border-color: rgba(246, 177, 94, 0.26);
  background: rgba(246, 177, 94, 0.13);
}

.ocean-dock-source-pill.is-missing-key {
  color: #ffd0d8;
  border-color: rgba(244, 114, 114, 0.26);
  background: rgba(244, 114, 114, 0.14);
}

.ocean-dock-source-meta {
  margin: -2px 0 4px;
  color: rgba(218, 234, 240, 0.52);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.62rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ocean-dock-section-body {
  display: grid;
  gap: 5px;
  margin-top: 2px;
}

.ocean-dock-layer {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 30px;
  padding: 5px 10px;
  border: 1px solid rgba(163, 185, 188, 0.14);
  border-radius: 7px;
  color: rgba(218, 234, 240, 0.74);
  background: rgba(255, 255, 255, 0.03);
  text-align: left;
  cursor: pointer;
  font-size: 0.78rem;
}

/* Network-colour swatch beside a sensor layer's name in the dock/sensors
   panel Ã¢â‚¬â€ matches the marker tint that network draws on the map. */
.ocean-dock-layer-swatch {
  flex-shrink: 0;
  width: 9px;
  height: 9px;
  margin-right: 7px;
  border-radius: 50%;
  border: 1px solid rgba(5, 13, 19, 0.55);
}

.ocean-dock-layer:hover,
.ocean-dock-layer:focus-visible {
  border-color: rgba(125, 211, 252, 0.42);
  background: rgba(125, 211, 252, 0.1);
  color: #dff8ff;
  outline: none;
}

.ocean-dock-layer.is-active {
  border-color: rgba(50, 208, 189, 0.55);
  background: rgba(50, 208, 189, 0.16);
  color: #eafff9;
  font-weight: 700;
}

.ocean-dock-layer.is-disabled {
  cursor: not-allowed;
  opacity: 0.48;
}

/* A click triggers an async layer-data fetch; the button shows a shimmer so
   the user can see the click registered while the data loads. */
.ocean-dock-layer.is-loading {
  position: relative;
  overflow: hidden;
  border-color: rgba(125, 211, 252, 0.55);
  color: #eafcff;
}

.ocean-dock-layer.is-loading::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 0%, rgba(125, 211, 252, 0.22) 50%, transparent 100%);
  background-size: 200% 100%;
  animation: oceanDockLoading 1.1s linear infinite;
}

@keyframes oceanDockLoading {
  from { background-position: 200% 0; }
  to { background-position: -200% 0; }
}

/* Reusable inline spinner for status lines on slow operations (external
   dataset fetches, public-feed ingest) -- a disabled button + static text
   alone can read as "hung" on a 30-45s query. */
.inline-spinner {
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: 7px;
  vertical-align: -1px;
  border: 2px solid rgba(125, 211, 252, 0.28);
  border-top-color: rgba(125, 211, 252, 0.95);
  border-radius: 50%;
  animation: inlineSpin 0.8s linear infinite;
}
@keyframes inlineSpin { to { transform: rotate(360deg); } }

.ocean-dock-layer-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ocean-dock-actions {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 6px;
}

.ocean-dock-actions .button {
  min-height: 32px;
  padding: 0 7px;
  font-size: 0.72rem;
}

.ocean-dock-actions .button.is-active {
  color: #031413;
  border-color: transparent;
  background: linear-gradient(135deg, #32d0bd, #e8ff7a);
}

body[data-route="observe"] .dto-temporal-control:not(.is-free-floating) {
  left: 280px;
  right: auto;
  bottom: 18px;
  z-index: 720;
  width: min(600px, calc(100vw - 690px));
  min-width: 0;
  transform: none;
  padding: 10px 12px;
  border-radius: 12px;
  background: rgba(3, 10, 13, 0.82);
}

/* Collapsed Master Clock: only the head strip shows, shrunk to its content. */
body[data-route="observe"] .dto-temporal-control.is-collapsed:not(.is-free-floating) {
  width: auto;
}

.dto-temporal-control.is-collapsed .temporal-grid,
.dto-temporal-control.is-collapsed #temporal-status {
  display: none;
}

body[data-route="observe"] .dto-temporal-control .temporal-grid {
  grid-template-columns: minmax(160px, 1.35fr) minmax(180px, 1fr) minmax(140px, 0.85fr) auto;
  gap: 8px;
}

body[data-route="observe"] .context-panel {
  top: 76px;
  right: 16px;
  left: auto;
  z-index: 750;
  width: min(366px, calc(100vw - 64px));
  max-height: calc(100% - 200px);
  display: flex;
  flex-direction: column;
  border: 1px solid rgba(163, 185, 188, 0.2);
  border-radius: 14px;
  background: rgba(3, 10, 13, 0.74);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(18px);
  overflow: hidden;
}

body[data-route="observe"] .context-panel-tabs {
  flex: 0 0 auto;
}

body[data-route="observe"] .context-panel-body {
  flex: 1 1 auto;
  min-height: 0;
}

/* Buffered time-lapse controls fold into the bottom of the overlay panel. */
#context-panel #timelapse-controls {
  flex: 0 0 auto;
  margin: 0;
  padding: 9px 12px 11px;
  border-top: 1px solid rgba(163, 185, 188, 0.18);
  background: rgba(125, 211, 252, 0.05);
}

body[data-route="observe"] .globe-legend {
  left: auto;
  right: 16px;
  top: 76px;
  z-index: 735;
  width: 282px;
  max-height: calc(100% - 210px);
  overflow: auto;
  border-radius: 12px;
  background: rgba(3, 10, 13, 0.8);
}

body[data-route="observe"] .map-stage.is-globe::after {
  display: none;
  content: none;
}

body[data-route="observe"] .map-utility-strip {
  display: none !important;
}

body[data-route="observe"] .map-status {
  left: 540px;
  right: 316px;
  top: 18px;
  bottom: auto;
  z-index: 710;
  max-width: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

body[data-route="observe"] .map-coordinate-tools:not(.is-free-floating) {
  left: 316px;
  top: 76px;
  bottom: auto !important;
  z-index: 740;
  max-height: calc(100% - 210px);
}

body[data-route="observe"] .map-stage .leaflet-top.leaflet-left {
  top: 76px;
  left: 314px;
}

body[data-route="observe"] .map-stage .leaflet-bottom.leaflet-left {
  left: 316px;
  bottom: 114px;
}

body[data-route="observe"] .map-stage.is-globe .leaflet-control-container {
  display: none;
}

@media (max-width: 760px) {
  /* Observe header on phones/tablets: wrap into two tidy rows instead of a
     50px horizontal-scroll strip that hides half the nav behind a sideways
     swipe. Row 1: brand + alerts + Copilot. Row 2: the destination nav as
     a 4-column grid. The
     secondary data controls (metric / scope / layers / basemap) are hidden
     here Ã¢â‚¬â€ the ocean layer dock below already drives layer selection Ã¢â‚¬â€ to
     keep the header compact. The ocean dock is offset to clear the header. */
  body[data-route="observe"] .app-header {
    left: 8px;
    right: 8px;
    top: 8px;
    width: auto;
    max-width: none;
    flex-wrap: wrap !important;
    max-height: none;
    height: auto;
    min-height: 0;
    overflow: visible;
    gap: 8px 6px;
    padding: 8px 10px;
  }

  body[data-route="observe"] .brand-block {
    order: 1;
    flex: 1 1 auto;
    min-width: 0;
  }

  body[data-route="observe"] #alerts-badge,
  body[data-route="observe"] #copilot-launcher {
    order: 1;
    flex: 0 0 auto;
  }

  body[data-route="observe"] .primary-nav {
    order: 2;
    flex: 1 1 100%;
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 4px;
  }

  /* Secondary controls are hidden on the mobile Observe header Ã¢â‚¬â€ the ocean
     layer dock provides layer control, and a compact header matters more. */
  body[data-route="observe"] .header-metrics,
  body[data-route="observe"] .header-controls {
    display: none !important;
  }

  body[data-route="observe"] .brand-block h1 {
    font-size: var(--fs-md);
  }

  body[data-route="observe"] .primary-nav .nav-button {
    min-height: 34px;
    padding: 0 7px;
    font-size: 0.72rem;
  }

  /* Ocean layer dock on mobile: the icon rail is a compact horizontal
     toolbar across the top of the map instead of a tall full-width panel,
     and the layer popups open as bottom sheets so they can never appear
     off-screen the way an "open to the right of the rail" popup does once
     the rail spans the full viewport width. */
  body[data-route="observe"] .ocean-layer-dock {
    left: 8px;
    right: 8px;
    top: 220px;
    bottom: auto;
    width: auto;
    max-height: none;
    padding: 0;
  }

  body[data-route="observe"] .observe-rail-icons {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: 4px;
    padding: 6px;
  }

  body[data-route="observe"] .observe-rail-icons .rail-icon {
    width: 40px;
    height: 40px;
  }

  /* !important overrides the inline top/left the rail's JS sets to anchor
     the popup to a clicked icon Ã¢â‚¬â€ on mobile we always want a bottom sheet. */
  body[data-route="observe"] .rail-popup {
    position: fixed !important;
    left: 8px !important;
    right: 8px !important;
    bottom: 8px !important;
    top: auto !important;
    width: auto !important;
    max-width: none !important;
    max-height: 62vh;
    overflow-y: auto;
    z-index: 760;
  }

  body[data-route="observe"] .ocean-layer-dock-list {
    max-height: none;
  }

  .ocean-dock-actions {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .ocean-dock-layer {
    min-height: 28px;
  }

  /* Long unbreakable strings Ã¢â‚¬â€ file paths, URLs, tokens Ã¢â‚¬â€ must wrap on a
     phone. Left un-wrapped (e.g. white-space: nowrap on a <code> path)
     their intrinsic width balloons the page-panel grid off-screen. */
  .page-panel code,
  .page-panel .mono,
  .page-panel .console-readout-mono,
  .page-panel .runtime-readiness-card strong {
    overflow-wrap: anywhere;
    white-space: normal;
  }

  .page-panel pre {
    overflow-wrap: anywhere;
    white-space: pre-wrap;
  }

  /* Action button rows wrap on a phone instead of squashing every button
     until its label is clipped ("Preview Command" Ã¢â€ â€™ "Ã¢â‚¬Â¦mand"). !important
     overrides the always-on body[data-route="observe"] .map-actions rule
     that otherwise forces a nowrap horizontal-scroll strip. */
  .page-panel .map-actions,
  .page-panel .route-actions,
  .page-panel .survey-plan-actions,
  .page-panel .cockpit-action-grid {
    flex-wrap: wrap !important;
    overflow-x: visible !important;
  }

  .page-panel .map-actions > button,
  .page-panel .map-actions > a,
  .page-panel .route-actions > button,
  .page-panel .route-actions > a {
    flex: 1 1 auto !important;
  }

  /* Control-page cockpit status console: wrap the cells into rows on a
     phone instead of a horizontal-scroll strip ~1000 px wide. */
  .cockpit-console {
    height: auto;
    max-height: 44vh;
    flex-wrap: wrap;
    overflow-x: visible;
    overflow-y: auto;
  }

  .cockpit-console .console-cell {
    min-width: 0;
    flex: 1 1 44%;
    border-right: 0;
    border-bottom: 1px solid rgba(120, 160, 170, 0.14);
    padding: 8px 12px;
  }

  .cockpit-console .console-cell-id,
  .cockpit-console .console-cell-view {
    flex: 1 1 100%;
    margin-left: 0;
  }

  .console-readout {
    overflow-wrap: anywhere;
  }

  /* Timeline (#observe-time-bar) spans the phone width instead of staying
     pinned at the desktop left:282px, which left it ~77 px wide. */
  body[data-page="map"] .observe-time-bar {
    left: 8px;
    right: 8px;
    bottom: 8px;
    max-width: none;
    padding: 6px 10px;
  }

  /* Every non-map page-panel is positioned at top:70-76px (or 0 for the
     Control/Mesh dock layouts). On mobile, the wrapped header can reach
     roughly 210 px, which hid the panels' own close/collapse controls.
     Push them below the header so their full content (and the dock-panel
     bars with the Ã¢Å“â€¢ buttons) is reachable. Also span the viewport width:
     the Plan panel uses `width: min(460px, calc(100vw - 360px))`, which
     collapses to ~15 px on a phone (the desktop formula reserves 360 px
     for the map), squishing the whole route planner. */
  body:not([data-page="map"]) .page-panel.is-active {
    top: 220px !important;
    left: 8px !important;
    right: 8px !important;
    width: auto !important;
    max-width: none !important;
  }

  body[data-route="observe"] .dto-temporal-control:not(.is-free-floating) {
    left: 8px;
    right: 8px;
    bottom: 8px;
    width: auto;
    padding: 8px;
  }

  body[data-route="observe"] .context-panel {
    left: 8px;
    right: 8px;
    top: 220px;
    bottom: 72px;
    width: auto;
  }

  /* Ocean Probe / Region Report panel on phones — push below the wrapped
     mobile header (otherwise the !important wide-mode `top: 76px` slides
     the panel over the nav). Matches the narrow-mode mobile rule above
     but with #id-based specificity to win against the desktop !important
     wide-mode rule. Also relax the desktop max-width (which assumes 32px
     gutters) so the panel uses the full 16px-margin phone width. */
  #context-panel.is-tool-probe,
  #context-panel.is-tool-area {
    left: 8px !important;
    right: 8px !important;
    top: 220px !important;
    bottom: 72px !important;
    max-width: none !important;
  }

  body[data-route="observe"] .globe-legend {
    display: none;
  }

  body[data-route="observe"] .map-status {
    left: 8px;
    right: 8px;
    bottom: 60px;
    max-width: none;
  }

  body[data-route="observe"] .map-status {
    display: none;
  }

  body[data-route="observe"] .map-coordinate-tools:not(.is-free-floating) {
    left: 8px;
    right: 8px;
    top: auto;
    bottom: 72px !important;
    width: auto;
    max-height: 40vh;
  }

  body[data-route="observe"] .map-stage .leaflet-top.leaflet-left {
    left: auto;
    right: 8px;
    top: 220px;
  }

  body[data-route="observe"] .map-stage .leaflet-bottom.leaflet-left {
    left: 8px;
    bottom: 64px;
  }
}

/* === Spot Sample report === */

.spot-sample-report {
  display: grid;
  gap: 8px;
}

.spot-sample-source {
  padding: 8px 10px;
  border: 1px solid rgba(163, 185, 188, 0.18);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
}

.spot-sample-source .source-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 4px;
}

.spot-sample-source .source-head strong {
  font-size: 0.85rem;
}

.spot-sample-source .source-head .pill {
  font-size: 0.6rem;
}

.spot-sample-source .source-body {
  font-size: 0.75rem;
  color: rgba(218, 234, 240, 0.85);
  display: grid;
  gap: 4px;
}

.spot-sample-source .source-body .row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.spot-sample-source.error {
  border-color: rgba(244, 114, 114, 0.3);
}

/* --- Auto-ingest indicator (header chip, left of the bell) --------- */
/* Backed by /v1/gateway/auto-ingest/status, polls every 15s. Three
   states via the .auto-ingest-dot color: green = ok, amber = partial
   / never-run, red = error. Click triggers /run-now so the operator
   can force a pull without finding the buried Settings button. */
.auto-ingest-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: var(--ink);
  font-size: 11px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
  margin-right: 6px;
  font-family: inherit;
  white-space: nowrap;
}
.auto-ingest-indicator:hover {
  background: rgba(108, 183, 255, 0.10);
  border-color: var(--accent, #6cb7ff);
}
.auto-ingest-indicator.is-busy {
  opacity: 0.7;
  cursor: wait;
}
.auto-ingest-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: rgba(255, 196, 87, 0.85);
  box-shadow: 0 0 6px rgba(255, 196, 87, 0.45);
  flex-shrink: 0;
}
.auto-ingest-indicator.is-ok .auto-ingest-dot {
  background: #6ee7a8;
  box-shadow: 0 0 6px rgba(110, 231, 168, 0.45);
}
.auto-ingest-indicator.is-error .auto-ingest-dot {
  background: #ff9b9b;
  box-shadow: 0 0 6px rgba(255, 155, 155, 0.45);
}
.auto-ingest-indicator.is-disabled .auto-ingest-dot {
  background: rgba(255, 255, 255, 0.25);
  box-shadow: none;
}
/* Space-weather chip: amber for G1/G2, red for G3+ (is-ok reuses the green dot). */
.space-weather-indicator.is-warn .auto-ingest-dot {
  background: #ffc457;
  box-shadow: 0 0 6px rgba(255, 196, 87, 0.5);
}
.space-weather-indicator.is-alert .auto-ingest-dot {
  background: #ff7a7a;
  box-shadow: 0 0 8px rgba(255, 122, 122, 0.6);
  animation: cockpit-live-pulse 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .space-weather-indicator.is-alert .auto-ingest-dot { animation: none; }
}
.auto-ingest-indicator.is-disabled {
  opacity: 0.55;
}
.auto-ingest-label {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 11px;
}

/* --- Notifications bell + dropdown panel ---------------------------- */
/* Lives in the header next to alerts-badge / copilot-launcher.
   Backed by /v1/notifications; polls unread-count every 30s. */
.notifications-bell {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: transparent;
  border: 1px solid transparent;
  color: var(--accent, #32d0bd);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.notifications-bell:hover {
  background: rgba(50, 208, 189, 0.08);
  border-color: rgba(50, 208, 189, 0.32);
}
.notifications-bell-icon {
  width: 22px;
  height: 22px;
  display: block;
}
.notifications-bell-count {
  position: absolute;
  top: 4px;
  right: 4px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: #d65555;
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  box-shadow: 0 0 0 2px var(--bg, #0b1928);
}

.notifications-panel {
  position: fixed;
  top: 64px;
  right: 12px;
  width: 380px;
  max-width: calc(100vw - 24px);
  max-height: min(560px, calc(100vh - 96px));
  display: flex;
  flex-direction: column;
  background: rgba(11, 25, 40, 0.98);
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 10px;
  box-shadow: 0 12px 36px rgba(0, 0, 0, 0.55);
  z-index: 9999;
  overflow: hidden;
}
.notifications-panel[hidden] { display: none; }
.notifications-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid rgba(123, 224, 166, 0.18);
  background: rgba(13, 35, 55, 0.6);
}
.notifications-panel-head strong { font-size: 0.92rem; color: #eafff0; }
.notifications-panel-actions { display: flex; gap: 4px; align-items: center; }
.notifications-panel-link {
  background: transparent;
  border: 1px solid transparent;
  color: rgba(207, 232, 216, 0.75);
  padding: 3px 8px;
  border-radius: 6px;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease;
}
.notifications-panel-link:hover { background: rgba(123, 224, 166, 0.1); color: #eafff0; }
.notifications-list { flex: 1; overflow-y: auto; padding: 4px; }
.notifications-empty {
  margin: 0;
  padding: 24px 16px;
  text-align: center;
  font-size: var(--fs-base);
  color: rgba(207, 232, 216, 0.65);
  font-style: italic;
}
.notifications-item {
  display: grid;
  grid-template-columns: 32px 1fr auto;
  gap: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  border: 1px solid transparent;
  border-left: 3px solid rgba(123, 224, 166, 0.32);
  margin-bottom: 4px;
  transition: background 0.14s ease, border-color 0.14s ease;
}
.notifications-item:hover { background: rgba(123, 224, 166, 0.05); }
.notifications-item.is-unread {
  background: rgba(123, 224, 166, 0.06);
  border-left-color: #7be0a6;
}
.notifications-item.is-warning { border-left-color: #ffc94a; }
.notifications-item.is-warning.is-unread { background: rgba(255, 201, 74, 0.08); }
.notifications-item.is-critical { border-left-color: #ff7575; }
.notifications-item.is-critical.is-unread { background: rgba(255, 117, 117, 0.08); }
.notifications-item-icon { font-size: 1.2rem; line-height: 1.2; }
.notifications-item-body { min-width: 0; }
.notifications-item-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px;
}
.notifications-item-title { font-size: var(--fs-base); color: #eafff0; font-weight: 600; }
.notifications-item-time { font-size: var(--fs-xs); white-space: nowrap; flex-shrink: 0; }
.notifications-item-text {
  margin: 2px 0 0;
  font-size: 0.76rem;
  line-height: 1.45;
  color: rgba(207, 232, 216, 0.85);
}
.notifications-item-meta {
  font-size: 0.7rem;
  margin: 4px 0 0;
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  color: rgba(207, 232, 216, 0.55);
}
.notifications-item-actions {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-self: flex-start;
}
.notifications-item-action {
  background: transparent;
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: rgba(207, 232, 216, 0.75);
  padding: 2px 8px;
  border-radius: 6px;
  font-size: 0.7rem;
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease;
}
.notifications-item-action:hover { background: rgba(123, 224, 166, 0.14); color: #eafff0; }

/* Primary per-kind actions (Retry / Open watch) read more prominently
   than the universal read/dismiss icons so the operator's eye lands
   on the recovery path first. */
.notifications-item-action-primary {
  border-color: rgba(50, 208, 189, 0.55);
  color: #aef5e8;
  background: rgba(50, 208, 189, 0.10);
  font-weight: 600;
  padding: 2px 10px;
}
.notifications-item-action-primary:hover {
  background: rgba(50, 208, 189, 0.25);
  color: #ffffff;
  border-color: rgba(50, 208, 189, 0.85);
}

/* Header current-user chip + dropdown. Sits between the
   notifications bell and the Honu launcher. Hidden in
   owner_auth_disabled / demo mode where there's no user to show. */
.user-display {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  background: rgba(7, 16, 20, 0.92);
  border: 1px solid var(--line, rgba(123, 224, 166, 0.22));
  border-radius: 999px;
  color: var(--text, #eafff0);
  font-size: 0.85rem;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease;
}
.user-display:hover {
  background: rgba(50, 208, 189, 0.12);
  border-color: rgba(50, 208, 189, 0.5);
}
.user-display-avatar {
  font-size: 1rem;
  line-height: 1;
}
.user-display-name {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.user-display-panel {
  position: fixed;
  top: 64px;
  right: 12px;
  width: 280px;
  background: rgba(7, 16, 20, 0.96);
  border: 1px solid rgba(50, 208, 189, 0.45);
  border-radius: 12px;
  padding: 14px;
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.55);
  z-index: 1000;
}
.user-display-head {
  margin-bottom: 12px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--line, rgba(123, 224, 166, 0.22));
}
.user-display-head strong {
  display: block;
  color: var(--accent-strong, #6ff5e3);
  font-size: var(--fs-md);
  margin-bottom: 4px;
}
.user-display-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}
.user-display-actions .button {
  padding: 6px 14px;
  font-size: 0.85rem;
}

/* Inline change-password form inside the user dropdown. Hidden until
   the user clicks "Change password…"; revealed in-place so the
   dropdown grows downward without re-anchoring. */
.user-display-change-password-form {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line, rgba(123, 224, 166, 0.22));
  display: grid;
  gap: 10px;
}
.user-display-change-password-form .control {
  display: grid;
  gap: 4px;
  font-size: 0.78rem;
  color: var(--muted, rgba(207, 232, 216, 0.7));
}
.user-display-change-password-form .control span {
  color: var(--text, #eafff0);
  font-weight: 500;
}
.user-display-change-password-form input[type="password"] {
  width: 100%;
  padding: 7px 10px;
  background: rgba(7, 16, 20, 0.7);
  border: 1px solid var(--line, rgba(123, 224, 166, 0.22));
  border-radius: 6px;
  color: var(--text, #eafff0);
  font-size: 0.88rem;
  font-family: inherit;
}
.user-display-change-password-form input[type="password"]:focus {
  outline: none;
  border-color: var(--accent, #32d0bd);
  background: rgba(7, 16, 20, 0.9);
}
.user-display-change-password-actions {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  align-items: center;
}
.user-display-change-password-actions .button {
  padding: 6px 14px;
  font-size: 0.85rem;
}
#user-cp-status {
  margin: 0;
  min-height: 1.2em;
}
#user-cp-status.is-error {
  color: var(--err, #ff7a7a);
}
#user-cp-status.is-ok {
  color: var(--ok, #8df5b1);
}

/* Admin Users panel rows (Settings → Users). */
#users-list:not(.empty) {
  display: grid;
  gap: 8px;
  padding: 0;
  background: transparent;
}
.user-row {
  display: grid;
  gap: 6px;
  padding: 12px 14px;
  background: rgba(7, 16, 20, 0.55);
  border: 1px solid var(--line, rgba(123, 224, 166, 0.22));
  border-radius: 8px;
}
.user-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.user-row-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.user-row-actions .button {
  padding: 4px 10px;
  font-size: 0.8rem;
}
.user-row-role {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-left: 6px;
}
.user-row-role.role-admin {
  background: rgba(255, 196, 87, 0.18);
  color: #ffc457;
  border: 1px solid rgba(255, 196, 87, 0.5);
}
.user-row-role.role-operator {
  background: rgba(50, 208, 189, 0.15);
  color: #6ff5e3;
  border: 1px solid rgba(50, 208, 189, 0.5);
}
.user-row-role.role-viewer {
  background: rgba(123, 224, 166, 0.10);
  color: rgba(207, 232, 216, 0.85);
  border: 1px solid rgba(123, 224, 166, 0.32);
}
.user-row-disabled {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  background: rgba(255, 122, 122, 0.15);
  color: #ff7a7a;
  border: 1px solid rgba(255, 122, 122, 0.45);
  margin-left: 4px;
}

/* Login Security panel rate-limit rows. */
#login-security-list:not(.empty) {
  display: grid;
  gap: 8px;
  padding: 0;
  background: transparent;
}
.rl-row {
  display: grid;
  gap: 4px;
  padding: 10px 14px;
  background: rgba(255, 122, 122, 0.08);
  border: 1px solid rgba(255, 122, 122, 0.35);
  border-radius: 8px;
}
.rl-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.rl-row-ip {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  color: #ff7a7a;
  font-size: var(--fs-md);
}
.rl-row-actions .button {
  padding: 4px 12px;
  font-size: 0.8rem;
}

/* 23/N: Audit Trail rows + family-filter controls. Lives under
   Settings → Login Security. Same row pattern as .rl-row + .user-row
   but with a family badge instead of a per-row action button.
   Color-coded badges:
     - user-mgmt → amber (consistent with the admin role badge from 12/N)
     - rate-limit → soft red (consistent with .rl-row hue from 18/N)
     - other → muted (future-proof for new audit families). */
.audit-trail-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin: 10px 0 14px;
}
.audit-trail-family-chips {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.audit-trail-window {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.audit-trail-window select {
  background: rgba(255, 255, 255, 0.05);
  color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.85rem;
}
.audit-row {
  display: grid;
  gap: 6px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  margin-bottom: 8px;
}
.audit-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  flex-wrap: wrap;
}
.audit-row-action {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.audit-row-family-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.audit-row-family-user-mgmt {
  background: rgba(255, 196, 87, 0.15);
  color: #ffc457;
  border: 1px solid rgba(255, 196, 87, 0.35);
}
.audit-row-family-rate-limit {
  background: rgba(255, 122, 122, 0.12);
  color: #ff9b9b;
  border: 1px solid rgba(255, 122, 122, 0.35);
}
.audit-row-family-other {
  background: rgba(255, 255, 255, 0.06);
  color: rgba(255, 255, 255, 0.7);
  border: 1px solid rgba(255, 255, 255, 0.15);
}
.audit-row-when {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  white-space: nowrap;
}
.audit-row-detail {
  font-size: 0.9rem;
  color: rgba(255, 255, 255, 0.85);
}
.audit-row-meta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: center;
}
/* 24/N: per-row pivot button — small inline link with a subtle
   chip background so it's discoverable but doesn't compete with
   the row content. */
.audit-row-pivot {
  background: rgba(50, 208, 189, 0.10);
  color: #6ee7d4;
  border: 1px solid rgba(50, 208, 189, 0.30);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 0.75rem;
  cursor: pointer;
  font-family: inherit;
}
.audit-row-pivot:hover {
  background: rgba(50, 208, 189, 0.18);
  color: #a3f0e5;
}
/* Brief highlight pulse when an audit-row pivot lands on a target. */
.audit-pivot-highlight {
  outline: 2px solid rgba(50, 208, 189, 0.85);
  outline-offset: 2px;
  background-color: rgba(50, 208, 189, 0.10);
  transition: outline-color 0.4s ease, background-color 0.4s ease;
}
/* 25/N: sticky-header date dividers between rows from different UTC
   days. Only emitted when the window is 7d or longer. */
.audit-date-divider {
  position: sticky;
  top: 0;
  z-index: 2;
  background: rgba(7, 16, 20, 0.92);
  backdrop-filter: blur(4px);
  color: rgba(255, 255, 255, 0.65);
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 4px 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin: 6px 0;
}

/* Brief highlight pulse for a watch row deep-linked from a
   watch.fired notification. Helps the operator spot the row their
   click was about, especially when the Watches list is long. */
.watch-item-highlight {
  outline: 2px solid rgba(255, 196, 87, 0.85);
  outline-offset: 2px;
  background-color: rgba(255, 196, 87, 0.10);
  transition: outline-color 0.4s ease, background-color 0.4s ease;
}

/* Remote params: Active Device Configurations panel
   (under Control → Command). Cards list per-(node, device, profile)
   applied state; clicking Edit opens a schema-driven typed form. */
.device-configs-list {
  display: grid;
  gap: 10px;
  margin-top: 8px;
}
.device-configs-list.empty {
  padding: 14px;
  text-align: left;
  color: rgba(207, 232, 216, 0.65);
  font-size: 0.85rem;
}

/* Remote params (9/N): Recent Applies panel — chronological feed of
   every device-config apply with a one-click revert button. Visually
   distinct from the active-configs cards above (muted accent + tighter
   row) so operators can scan back through history at a glance. */
.device-config-history-list {
  display: grid;
  gap: 8px;
  margin-top: 8px;
}
.device-config-history-list.empty {
  padding: 14px;
  text-align: left;
  color: rgba(207, 232, 216, 0.65);
  font-size: 0.85rem;
}
.device-config-history-filter {
  display: flex;
  gap: 10px;
  align-items: flex-end;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.device-config-history-row {
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.03);
  display: grid;
  gap: 6px;
}
.device-config-history-row-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
}
.device-config-history-meta code {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  background: rgba(255, 255, 255, 0.06);
  padding: 1px 6px;
  border-radius: 4px;
}
.device-config-history-params summary {
  cursor: pointer;
  display: inline-block;
  padding: 2px 0;
}
.device-config-history-params-pre {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.8rem;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 6px;
  padding: 8px 10px;
  margin: 6px 0 0;
  overflow-x: auto;
  white-space: pre;
}
/* 12/N: inline delta badges on history rows. Color matches the
   notification severity convention — green for additions, amber for
   changes, red for removals, muted for no-changes/first-apply. */
.history-delta-badge,
.history-delta-none,
.history-delta-first {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 1px 6px;
  border-radius: 4px;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  font-weight: 600;
  border: 1px solid transparent;
}
.history-delta-badge {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.10);
}
.history-delta-add { color: #6ee7a8; }
.history-delta-change { color: #ffc457; }
.history-delta-remove { color: #ff9b9b; }
.history-delta-none {
  color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.03);
}
.history-delta-first {
  color: #6ee7a8;
  background: rgba(110, 231, 168, 0.08);
  border-color: rgba(110, 231, 168, 0.25);
}

/* Firmware Builder (2/N) panel — two-column wizard with sensor
   checkbox cards on the right + the board/runtime config on the
   left. */
.firmware-builder-grid {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) minmax(320px, 2fr);
  gap: 16px;
  margin: 12px 0;
}
@media (max-width: 720px) {
  .firmware-builder-grid { grid-template-columns: 1fr; }
}
.firmware-builder-col {
  display: grid;
  gap: 10px;
}
.firmware-builder-col .control { display: grid; gap: 4px; }
.firmware-builder-col select,
.firmware-builder-col input {
  background: rgba(255, 255, 255, 0.05);
  color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.85rem;
}
.firmware-builder-sensors {
  display: grid;
  gap: 8px;
  max-height: 460px;
  overflow-y: auto;
  padding: 4px;
}
.firmware-builder-sensors.empty {
  text-align: left;
  color: rgba(207, 232, 216, 0.65);
  font-size: 0.85rem;
  padding: 12px;
}
.fw-sensor-card {
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.03);
}
.fw-sensor-card.fw-sensor-checked {
  border-color: rgba(50, 208, 189, 0.45);
  background: rgba(50, 208, 189, 0.06);
}
.fw-sensor-head {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}
.fw-sensor-name {
  font-weight: 600;
}
.fw-sensor-desc { margin: 4px 0; }
.fw-sensor-metrics {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
}
.fw-sensor-params {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px dashed rgba(255, 255, 255, 0.10);
}
.fw-param input, .fw-param select {
  width: 100%;
}
.firmware-builder-result {
  margin-top: 10px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.25);
}
.firmware-builder-result.empty {
  color: rgba(207, 232, 216, 0.65);
  font-size: 0.85rem;
}
.fw-preview pre,
.fw-build-result pre {
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  background: rgba(0, 0, 0, 0.35);
  padding: 8px 10px;
  border-radius: 6px;
  overflow-x: auto;
  white-space: pre;
  max-height: 360px;
  overflow-y: auto;
}
.fw-build-ok { color: #6ee7a8; }
.fw-build-failed { color: #ff9b9b; }
.firmware-builder-overrides {
  margin-top: 4px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 6px;
  padding: 6px 10px;
}
.firmware-builder-overrides textarea {
  width: 100%;
  background: rgba(0, 0, 0, 0.35);
  color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  padding: 6px 10px;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.8rem;
}
.fw-board-defaults {
  margin-top: 4px;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.75rem;
  word-break: break-word;
}
.firmware-builder-templates-row {
  display: flex;
  align-items: end;
  gap: 8px;
  flex-wrap: wrap;
  margin: 8px 0 12px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 8px;
}
.firmware-builder-templates-row .control { flex: 1 1 240px; }
.firmware-builder-templates-row select {
  background: rgba(255, 255, 255, 0.05);
  color: inherit;
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.85rem;
  width: 100%;
}
.device-config-card {
  border: 1px solid rgba(50, 208, 189, 0.25);
  border-radius: 10px;
  padding: 12px 14px;
  background: rgba(7, 16, 20, 0.55);
}
.device-config-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 8px;
}
.device-config-card-head strong {
  font-size: var(--fs-md);
  color: #eafff0;
}
.device-config-params {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 4px 16px;
  font-size: 0.85rem;
}
.device-config-param {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  border-bottom: 1px dashed rgba(123, 224, 166, 0.08);
  padding: 2px 0;
}
.device-config-param-key {
  color: rgba(207, 232, 216, 0.75);
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.8rem;
}
.device-config-param-value {
  color: #eafff0;
  font-family: var(--mono, ui-monospace, SFMono-Regular, monospace);
  font-size: 0.8rem;
  text-align: right;
}
.device-config-editor {
  margin-top: 12px;
  padding: 14px;
  border: 1px solid rgba(50, 208, 189, 0.45);
  border-radius: 10px;
  background: rgba(7, 16, 20, 0.75);
}
.device-config-editor-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}
.device-config-editor-head h4 {
  margin: 0;
  font-size: var(--fs-md);
  color: #aef5e8;
}

/* --- OMEGA Copilot ---------------------------------------------- */
/* The Copilot launcher lives inline in the header controls Ã¢â‚¬â€ no longer a
   floating button cluttering the Observe map. */
/* Honu daily-briefing badge: a small dot on the launcher when a fresh
   briefing hasn't been opened yet (replaces the removed Briefings page). */
.copilot-briefing-badge {
  position: absolute;
  top: 4px;
  right: 6px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #f59e0b;
  box-shadow: 0 0 0 2px rgba(7, 16, 20, 0.92), 0 0 8px rgba(245, 158, 11, 0.7);
  pointer-events: none;
}
/* Today's-briefing card that leads the Honu thread on open. */
.copilot-briefing-card { border-left: 2px solid rgba(245, 158, 11, 0.55); }
.copilot-briefing-eyebrow { margin: 0 0 2px; font-size: 11px; color: rgba(245, 158, 11, 0.95); font-weight: 600; }
.copilot-briefing-title { margin: 0 0 4px; font-size: var(--fs-md); }
.copilot-briefing-body { font-size: 0.78rem; line-height: 1.45; }
.copilot-briefing-body ul { margin: 4px 0; padding-left: 16px; }
.copilot-briefing-body li { margin-bottom: 6px; }
.copilot-briefing-body a { color: rgba(125, 211, 252, 0.95); }

.copilot-launcher {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  /* Slightly larger than the other header buttons so Honu reads as the
     primary AI affordance. */
  padding: 8px 16px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(7, 16, 20, 0.92);
  color: var(--ink);
  font-weight: 700;
  font-size: 0.88rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  cursor: pointer;
}

.copilot-launcher:hover {
  border-color: var(--accent);
  background: rgba(50, 208, 189, 0.08);
}

/* Icon-only mode: round button slightly larger than nav buttons so
   Honu still reads as the primary AI affordance, but not by enough
   to look oversized next to the alerts badge + nav rail. */
.copilot-launcher.is-icon-only {
  padding: 4px;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  justify-content: center;
  background: rgba(7, 16, 20, 0.85);
  box-shadow: 0 0 0 0 rgba(50, 208, 189, 0.55);
  transition: box-shadow 0.3s ease, border-color 0.3s ease, background 0.3s ease;
}
.copilot-launcher.is-icon-only:hover {
  box-shadow: 0 0 0 4px rgba(50, 208, 189, 0.2);
  border-color: rgba(50, 208, 189, 0.7);
  background: rgba(50, 208, 189, 0.1);
}
.copilot-launcher.is-icon-only .copilot-dot,
.copilot-launcher.is-icon-only .copilot-launcher-label {
  display: none;
}
.copilot-launcher.is-icon-only .copilot-launcher-icon {
  width: 32px;
  height: 32px;
}

.copilot-launcher-icon {
  width: 26px;
  height: 26px;
  color: var(--accent, #32d0bd);
  flex: none;
  transition: color 0.4s ease;
}
.copilot-launcher:hover .copilot-launcher-icon { color: #67e8f9; }
.copilot-launcher:has(#copilot-launcher-dot.is-down) .copilot-launcher-icon { color: #fb7185; }
.copilot-launcher:has(#copilot-launcher-dot.is-ready) .copilot-launcher-icon { color: #67e8f9; }

/* Body bobs gently up + down — no rotation, since rotating the whole
   body shifts the rotation pivot of nested elements and makes the
   globe-shell drift away from the turtle. */
.honu-body {
  transform-box: fill-box;
  transform-origin: center;
  animation: honu-bob 4s ease-in-out infinite;
}
@keyframes honu-bob {
  0%, 100% { transform: translateY(-0.6px); }
  50%      { transform: translateY(0.6px); }
}

/* Each animated sub-element rotates around its OWN bounding-box
   center via fill-box + center. Keeps the globe locked to the shell. */
.honu-shell {
  transform-box: fill-box;
  transform-origin: center;
  animation: honu-shell-spin 16s linear infinite;
}
@keyframes honu-shell-spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.honu-flippers-front {
  transform-box: fill-box;
  transform-origin: center;
  animation: honu-paddle-front 2.2s ease-in-out infinite;
}
.honu-flippers-back {
  transform-box: fill-box;
  transform-origin: center;
  animation: honu-paddle-back 2.2s ease-in-out infinite;
}
@keyframes honu-paddle-front {
  0%, 100% { transform: rotate(-5deg); }
  50%      { transform: rotate(5deg); }
}
@keyframes honu-paddle-back {
  0%, 100% { transform: rotate(5deg); }
  50%      { transform: rotate(-5deg); }
}

.honu-head {
  transform-box: fill-box;
  transform-origin: center;
  animation: honu-head-look 5s ease-in-out infinite;
}
@keyframes honu-head-look {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}

.copilot-launcher:hover .honu-flippers-front,
.copilot-launcher:hover .honu-flippers-back { animation-duration: 0.9s; }
.copilot-launcher:hover .honu-shell { animation-duration: 6s; }
.copilot-launcher:hover .honu-body { animation-duration: 2.4s; }

.copilot-launcher-label {
  letter-spacing: 0.05em;
}

.copilot-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted);
}

.copilot-dot.is-ready {
  background: var(--ok);
  box-shadow: 0 0 10px rgba(85, 211, 138, 0.7);
}

.copilot-dot.is-down {
  background: var(--bad);
}

.copilot-panel {
  position: fixed;
  right: 16px;
  top: 16px;
  bottom: 16px;
  z-index: 1101;
  width: min(430px, calc(100vw - 32px));
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  box-shadow: var(--shadow);
  backdrop-filter: blur(22px);
}

.copilot-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* The eyebrow + h2 stack was 86h. Compact eyebrow → 11px above a
     1rem h2 = ~50h header. Action icons align center now. */
  margin-bottom: 4px;
}
.copilot-head .eyebrow {
  margin: 0;
  font-size: 10px;
}

.copilot-head h2 {
  margin: 1px 0 0;
  font-size: 1rem;
  line-height: 1.2;
}

.copilot-starters {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 0 8px;
  margin-bottom: 6px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.07);
}
.copilot-starters-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.copilot-starters-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: rgba(207, 232, 216, 0.55);
}
.copilot-starters-toggle {
  font-size: 11px;
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.10);
  color: rgba(207, 232, 216, 0.7);
  border-radius: 10px;
  padding: 1px 8px;
  cursor: pointer;
  white-space: nowrap;
}
.copilot-starters-toggle:hover {
  background: rgba(255, 255, 255, 0.05);
  color: var(--ink);
}
/* Category rows so chips don't all blur together. Each category
   has a tiny inline label + horizontally-wrapping chip cluster. */
.copilot-starters-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.copilot-starters-category {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 6px;
}
.copilot-starters-category-label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(207, 232, 216, 0.45);
  margin-right: 2px;
  min-width: 56px;
}
.copilot-starter-chip {
  font-size: 12px;
  padding: 3px 9px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s, transform 0.06s;
}
.copilot-starter-chip:hover {
  background: rgba(108, 183, 255, 0.13);
  border-color: var(--accent, #6cb7ff);
}
.copilot-starter-chip:active {
  background: rgba(108, 183, 255, 0.2);
  transform: scale(0.97);
}
.copilot-starter-chip[data-cat="discover"] { border-color: rgba(108, 183, 255, 0.30); }
.copilot-starter-chip[data-cat="analyze"]  { border-color: rgba(255, 196, 87, 0.30); }
.copilot-starter-chip[data-cat="plan"]     { border-color: rgba(180, 140, 255, 0.30); }
.copilot-starter-chip[data-cat="act"]      { border-color: rgba(110, 231, 168, 0.30); }
/* Collapsed state: hide the body but keep the head + toggle. */
.copilot-starters.is-collapsed .copilot-starters-body { display: none; }

.copilot-status-action,
.copilot-status-help {
  display: inline-flex;
  align-items: center;
  margin-left: 6px;
  padding: 2px 8px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  font-size: 11px;
}
.copilot-status-action:hover,
.copilot-status-help:hover {
  background: rgba(108, 183, 255, 0.13);
  border-color: var(--accent, #6cb7ff);
}
.copilot-statusline.is-error {
  color: rgb(249, 115, 115);
  background: rgba(249, 115, 115, 0.08);
  padding: 6px 10px;
  border-radius: 8px;
  border-left: 3px solid rgba(249, 115, 115, 0.6);
}

.copilot-statusline {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.3;
  padding: 2px 0;
  color: rgba(180, 200, 210, 0.55);
}
/* Hide the statusline when it just says "Ready" — there's no signal
   for the operator. Error states (with .is-error class) still show
   prominently with the red border + retry buttons. */
.copilot-statusline.is-ready { display: none; }

.copilot-thread {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-right: 4px;
}

.copilot-msg {
  padding: 10px 13px;
  border-radius: 14px;
  border: 1px solid var(--line);
  font-size: 0.9rem;
  line-height: 1.45;
}

.copilot-msg p {
  white-space: pre-wrap;
  word-break: break-word;
}

.copilot-msg-user {
  align-self: flex-end;
  max-width: 86%;
  background: rgba(50, 208, 189, 0.14);
  border-color: rgba(50, 208, 189, 0.4);
}

.copilot-msg-assistant {
  align-self: flex-start;
  max-width: 92%;
  background: var(--panel-soft);
}

.copilot-msg-error {
  align-self: stretch;
  background: rgba(251, 113, 133, 0.12);
  border-color: rgba(251, 113, 133, 0.45);
}

.copilot-trace {
  margin-top: 7px;
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}

.copilot-trace-item {
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-xs);
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--line);
  color: var(--muted);
}

.copilot-trace-item.is-bad {
  color: var(--bad);
  border-color: rgba(251, 113, 133, 0.45);
}

.copilot-meta {
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.66rem;
  color: var(--muted);
  margin: 4px 0 0;
}

.copilot-pending {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 38%;
  overflow-y: auto;
}

.copilot-action {
  padding: 11px 13px;
  border-radius: 14px;
  border: 1px solid rgba(246, 177, 94, 0.5);
  background: rgba(246, 177, 94, 0.1);
}

.copilot-action.is-resolved {
  border-color: var(--line);
  background: var(--panel-soft);
}

.copilot-action h3 {
  margin: 0 0 4px;
  font-size: 0.9rem;
}

.copilot-action p {
  margin: 0 0 6px;
  font-size: 0.83rem;
}

.copilot-action-endpoint {
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-xs);
  color: var(--muted);
}

.copilot-action-buttons {
  display: flex;
  gap: 8px;
  margin-top: 9px;
}

.copilot-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
}

.copilot-input {
  flex: 1;
  resize: none;
  padding: 9px 11px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(7, 16, 20, 0.7);
  color: var(--ink);
  /* Override the global textarea min-height: 120px — chat inputs should
     start short and grow with content. ~52px = 2 lines + padding. */
  min-height: 52px;
  max-height: 240px;
  line-height: 1.4;
}

.copilot-input:focus {
  outline: none;
  border-color: var(--accent);
}

.copilot-panel.is-busy .copilot-input,
.copilot-panel.is-busy #copilot-send {
  opacity: 0.6;
  pointer-events: none;
}

@media (max-width: 560px) {
  .copilot-panel {
    right: 8px;
    left: 8px;
    top: 8px;
    bottom: 8px;
    width: auto;
  }
}

/* Map key Ã¢â‚¬â€ content styles for the rail popup opened by the animated Key
   icon on the Observe rail. The legend can grow (overlay fields + sensor
   networks + distance scale), so the popup scrolls rather than overflowing
   the map. The popup frame itself is handled by .rail-popup. */
.rail-popup-key {
  max-height: 72vh;
  overflow-y: auto;
}

.map-legend-row {
  display: grid;
  grid-template-columns: 26px 1fr;
  gap: 9px;
  align-items: center;
}

.map-legend-icon {
  width: 26px;
  height: 26px;
}

.map-legend-row span {
  font-size: var(--fs-sm);
  line-height: 1.3;
  color: var(--ink);
}

.map-legend-row span strong {
  font-weight: 800;
}

.map-data-kind-list {
  display: grid;
  gap: 7px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.16);
}

.map-data-kind-row {
  display: grid;
  grid-template-columns: 13px 1fr;
  gap: 8px;
  align-items: start;
}

.map-data-kind-row span:last-child {
  color: rgba(218, 234, 240, 0.86);
  font-size: var(--fs-xs);
  line-height: 1.32;
}

.map-data-kind-row strong {
  color: var(--ink);
  font-weight: 900;
}

/* Overlay fields + sensor-network swatches Ã¢â‚¬â€ JS-populated rows, shown in
   the Map Key popup only while an overlay or sensor layer is active. */
.map-legend-overlays {
  display: grid;
  gap: 9px;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.16);
}

.map-legend-overlays[hidden] {
  display: none;
}

.map-legend-section-label {
  margin: 0;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Small explanatory note under the marker-shape rows. */
.map-legend-hint {
  margin: 0;
  padding-bottom: 9px;
  border-bottom: 1px solid rgba(163, 185, 188, 0.16);
  font-size: 0.66rem;
  line-height: 1.35;
  color: var(--muted);
}

.map-legend-overlay {
  display: grid;
  gap: 4px;
}

.map-legend-overlay-name {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0;
}

.map-legend-overlay-title {
  overflow: hidden;
  font-size: var(--fs-sm);
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--ink);
}

.map-legend-overlay-unit {
  flex-shrink: 0;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: var(--muted);
}

/* Sensor-network key rows Ã¢â‚¬â€ a colour swatch matching the marker tint. */
.map-legend-network {
  display: flex;
  align-items: center;
  gap: 8px;
}

.map-legend-network-dot {
  flex-shrink: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  border: 1px solid rgba(5, 13, 19, 0.6);
}

.map-legend-network-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  font-size: 0.72rem;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--ink);
}

.map-legend-network-count {
  flex-shrink: 0;
  font-size: 0.62rem;
  font-weight: 700;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.map-legend-gradient {
  height: 9px;
  border-radius: 5px;
  border: 1px solid rgba(163, 185, 188, 0.26);
  background: linear-gradient(90deg, #1b3a52, #7dd3fc);
}

.map-legend-scale-labels {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--muted);
}

/* Distance scale Ã¢â‚¬â€ Leaflet's scale control, re-homed into the legend panel. */
.map-legend-distance {
  display: grid;
  gap: 4px;
  margin-top: 2px;
  padding-top: 9px;
  border-top: 1px solid rgba(163, 185, 188, 0.16);
}

.map-legend-distance-label {
  margin: 0;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.map-legend-distance-host .leaflet-control-scale {
  margin: 0;
  pointer-events: none;
}

.map-legend-distance-host .leaflet-control-scale-line {
  box-sizing: border-box;
  overflow: hidden;
  min-width: 28px;
  padding: 1px 5px 2px;
  border: 1px solid rgba(163, 185, 188, 0.6);
  border-top: none;
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.25;
  white-space: nowrap;
  color: var(--ink);
  background: transparent;
  box-shadow: none;
  text-shadow: none;
}

.map-legend-distance-host .leaflet-control-scale-line:not(:first-child) {
  margin-top: -1px;
  border-top: 1px solid rgba(163, 185, 188, 0.6);
  border-bottom: none;
}

@media (max-width: 560px) {
  .rail-popup-key {
    max-height: 64vh;
  }
}

/* --- Copilot header actions + AI-narrated tour overlay ---------------- */

.copilot-head-actions {
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* Icon buttons in Honu header */
.copilot-icon-btn {
  font: inherit;
  font-size: 0.85rem;
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.copilot-icon-btn:hover {
  background: rgba(108, 199, 255, 0.12);
  border-color: rgba(108, 199, 255, 0.5);
  color: var(--ink);
}

/* Expanded (full-width) panel mode */
.copilot-panel.is-expanded {
  width: min(800px, calc(100vw - 32px));
}

#copilot-tour {
  font-size: 0.8rem;
  padding: 6px 10px;
}

.tour-overlay {
  position: fixed;
  inset: 0;
  z-index: 5200;
  pointer-events: none;
}

.tour-overlay[hidden] {
  display: none !important;
}

.tour-backdrop {
  position: fixed;
  background: rgba(8, 14, 22, 0.66);
  backdrop-filter: blur(1px);
  pointer-events: auto;
  transition: top 0.35s ease, left 0.35s ease, width 0.35s ease, height 0.35s ease;
}

.tour-spotlight {
  position: fixed;
  border-radius: 12px;
  border: 2px solid #6cc7ff;
  box-shadow:
    0 0 0 1px rgba(0, 0, 0, 0.4),
    0 0 18px 6px rgba(108, 199, 255, 0.55),
    0 0 0 9999px transparent;
  pointer-events: none;
  transition: top 0.35s ease, left 0.35s ease, width 0.35s ease, height 0.35s ease;
}

.tour-spotlight.is-pulsing {
  animation: tour-pulse 1.6s ease-in-out infinite;
}

@keyframes tour-pulse {
  0%, 100% {
    box-shadow:
      0 0 0 1px rgba(0, 0, 0, 0.4),
      0 0 14px 4px rgba(108, 199, 255, 0.42),
      0 0 0 9999px transparent;
  }
  50% {
    box-shadow:
      0 0 0 1px rgba(0, 0, 0, 0.4),
      0 0 26px 9px rgba(108, 199, 255, 0.78),
      0 0 0 9999px transparent;
  }
}

.tour-card {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translateX(-50%);
  width: min(540px, calc(100vw - 32px));
  padding: 18px 20px 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: var(--shadow);
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
  backdrop-filter: blur(18px);
}

.tour-card.is-top {
  bottom: auto;
  top: 28px;
}

.tour-card-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
}

.tour-card-eyebrow {
  margin: 0;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted, #6e7d8a);
  display: flex;
  align-items: center;
  gap: 8px;
}

.tour-card-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(108, 199, 255, 0.18);
  color: #1f6fa6;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tour-card-badge[hidden] {
  display: none !important;
}

.tour-first-visit-actions {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.tour-first-visit-actions .button {
  font-size: 0.85rem;
  padding: 6px 12px;
}

/* Quick-pick tour grid inside the first-visit banner */
.tour-first-visit-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  margin: 10px 0;
}
.tour-first-visit-card {
  display: grid;
  grid-template-columns: 36px 1fr;
  grid-template-rows: auto auto auto;
  column-gap: 10px;
  row-gap: 2px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 8px;
  background: rgba(8, 22, 14, 0.4);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, transform 0.1s ease;
}
.tour-first-visit-card:hover {
  background: rgba(13, 60, 80, 0.5);
  border-color: #7be0a6;
  transform: translateY(-1px);
}
.tour-first-visit-card-emoji {
  grid-row: 1 / span 3;
  font-size: 1.5rem;
  align-self: center;
  text-align: center;
}
.tour-first-visit-card strong {
  font-size: 0.92rem;
  color: #eafff0;
}
.tour-first-visit-card-meta {
  font-size: 0.7rem;
  color: rgba(207, 232, 216, 0.6);
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
}
.tour-first-visit-card-desc {
  font-size: 0.78rem;
  color: rgba(207, 232, 216, 0.82);
  line-height: 1.45;
}

/* Tour menu (opens when the 🎓 button is clicked) */
.tour-menu-intro {
  margin: 0 0 14px;
  font-size: 0.86rem;
  line-height: 1.5;
  color: rgba(207, 232, 216, 0.82);
}
.tour-menu-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 10px;
}
.tour-menu-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px;
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 10px;
  background: rgba(13, 35, 55, 0.4);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, transform 0.1s ease, box-shadow 0.14s ease;
}
.tour-menu-card:hover {
  background: rgba(13, 60, 80, 0.55);
  border-color: #7be0a6;
  transform: translateY(-2px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
}
.tour-menu-card-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.tour-menu-card-emoji {
  font-size: 1.7rem;
  line-height: 1;
  flex-shrink: 0;
}
.tour-menu-card-head strong {
  display: block;
  font-size: 0.96rem;
  color: #eafff0;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.tour-menu-card-duration {
  display: block;
  font-size: 0.7rem;
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  color: rgba(207, 232, 216, 0.6);
  margin-top: 2px;
}
.tour-menu-card-desc {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: rgba(207, 232, 216, 0.78);
}
.tour-menu-card.tour-menu-card-ai {
  border-style: dashed;
  border-color: rgba(255, 214, 106, 0.45);
  background: rgba(40, 30, 10, 0.35);
}
.tour-menu-card.tour-menu-card-ai:hover {
  border-color: #ffd66a;
  background: rgba(60, 45, 15, 0.5);
}

/* --- Copilot starter-prompt chips ------------------------------------- */

.copilot-chips-host {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.copilot-chips-lead {
  margin: 0;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--muted, #6e7d8a);
  text-transform: uppercase;
}

.copilot-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.copilot-chip {
  font: inherit;
  font-size: var(--fs-base);
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(108, 199, 255, 0.08);
  color: var(--ink, #102031);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
  text-align: left;
}

.copilot-chip:hover {
  background: rgba(108, 199, 255, 0.18);
  border-color: rgba(108, 199, 255, 0.6);
}

.copilot-chip:active {
  transform: scale(0.98);
}

.copilot-panel.is-busy .copilot-chip {
  opacity: 0.55;
  pointer-events: none;
}

/* Follow-up chip variant â€” slightly different color to distinguish from starters */
.copilot-chip-followup {
  background: rgba(50, 208, 189, 0.08);
  border-color: rgba(50, 208, 189, 0.3);
}

.copilot-chip-followup:hover {
  background: rgba(50, 208, 189, 0.18);
  border-color: rgba(50, 208, 189, 0.6);
}

.copilot-follow-ups .copilot-chips-lead {
  font-size: 0.72rem;
  color: rgba(50, 208, 189, 0.7);
}

/* Markdown rendering in assistant messages */
.copilot-body {
  word-break: break-word;
}

.copilot-body b {
  font-weight: 700;
  color: var(--ink);
}

.copilot-h1 {
  display: block;
  font-size: 1.05rem;
  font-weight: 700;
  margin: 6px 0 4px;
  color: var(--ink);
}

.copilot-h2 {
  display: block;
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 5px 0 3px;
  color: var(--ink);
}

.copilot-h3 {
  display: block;
  font-size: 0.88rem;
  font-weight: 600;
  margin: 4px 0 2px;
  color: var(--ink);
}

.copilot-code {
  display: block;
  margin: 6px 0;
  padding: 8px 10px;
  border-radius: 8px;
  background: rgba(7, 16, 20, 0.6);
  border: 1px solid var(--line);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.78rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-x: auto;
}

.copilot-inline-code {
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(7, 16, 20, 0.5);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.82em;
}

.copilot-li {
  display: block;
  padding-left: 6px;
  margin: 1px 0;
}

/* Copy response button */
.copilot-copy {
  position: absolute;
  top: 6px;
  right: 6px;
  font: inherit;
  font-size: 0.72rem;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 6px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.15s ease, background 0.15s ease;
}

.copilot-msg:hover .copilot-copy {
  opacity: 0.7;
}

.copilot-copy:hover {
  opacity: 1 !important;
  background: rgba(108, 199, 255, 0.12);
  border-color: var(--line);
}

.copilot-msg-assistant {
  position: relative;
}

/* Timestamps */
.copilot-timestamp {
  display: block;
  font-size: 0.65rem;
  color: var(--muted);
  opacity: 0.5;
  margin-top: 4px;
  text-align: right;
}

.copilot-msg-user .copilot-timestamp {
  text-align: left;
}

/* LaTeX math rendering */
.copilot-math {
  font-family: "Georgia", serif;
  font-style: italic;
  color: var(--ink);
}

/* Chat tables */
.copilot-table {
  width: 100%;
  border-collapse: collapse;
  margin: 8px 0;
  font-size: var(--fs-base);
}

.copilot-table th,
.copilot-table td {
  padding: 4px 8px;
  border: 1px solid var(--line);
  text-align: left;
}

.copilot-table th {
  background: rgba(108, 199, 255, 0.08);
  font-weight: 600;
}

.copilot-table tr:nth-child(even) td {
  background: rgba(255, 255, 255, 0.02);
}

/* Horizontal rules in chat */
.copilot-hr {
  border: none;
  border-top: 1px solid var(--line);
  margin: 8px 0;
  opacity: 0.4;
}

/* --- Honu thinking indicator animation ---------------------------------- */

.copilot-thinking {
  border-color: rgba(108, 199, 255, 0.3);
  background: rgba(108, 199, 255, 0.04);
}

.copilot-thinking-content {
  display: flex;
  align-items: center;
  gap: 2px;
  font-size: 0.85rem;
  color: var(--muted);
}

.copilot-thinking-text {
  font-style: italic;
}

.copilot-dots span {
  display: inline-block;
  animation: copilot-bounce 1.4s infinite ease-in-out both;
  font-weight: 700;
  font-size: 1.1em;
}

.copilot-dots span:nth-child(1) { animation-delay: 0s; }
.copilot-dots span:nth-child(2) { animation-delay: 0.2s; }
.copilot-dots span:nth-child(3) { animation-delay: 0.4s; }

@keyframes copilot-bounce {
  0%, 80%, 100% {
    opacity: 0.3;
    transform: translateY(0);
  }
  40% {
    opacity: 1;
    transform: translateY(-3px);
  }
}

/* --- Honu AI pulse highlight animation ---------------------------------- */

.ai-pulse {
  position: relative;
  z-index: 100;
  animation: honu-pulse 0.65s ease-in-out 3;
}

@keyframes honu-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(108, 199, 255, 0);
  }
  50% {
    box-shadow: 0 0 18px 6px rgba(108, 199, 255, 0.6);
  }
}

.tour-card-counter {
  margin: 0;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--muted, #6e7d8a);
}

.tour-card-head-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.tour-card-playpause {
  font: inherit;
  font-size: 0.78rem;
  line-height: 1;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: rgba(108, 199, 255, 0.10);
  color: var(--ink, #102031);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.tour-card-playpause:hover {
  background: rgba(108, 199, 255, 0.22);
  border-color: rgba(108, 199, 255, 0.6);
}

.tour-card-playpause.is-paused {
  background: rgba(255, 191, 89, 0.18);
  border-color: rgba(255, 191, 89, 0.55);
  color: #8a5b00;
}

.tour-card-playpause[hidden] {
  display: none !important;
}

.tour-card-dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin: 4px 0 -2px;
}

.tour-card-dots[hidden] {
  display: none !important;
}

.tour-card-dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border-radius: 999px;
  border: 1px solid rgba(108, 199, 255, 0.5);
  background: transparent;
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}

.tour-card-dot:hover {
  background: rgba(108, 199, 255, 0.35);
  transform: scale(1.15);
}

.tour-card-dot.is-done {
  background: rgba(108, 199, 255, 0.5);
  border-color: rgba(108, 199, 255, 0.5);
}

.tour-card-dot.is-active {
  background: #1f6fa6;
  border-color: #1f6fa6;
  transform: scale(1.25);
}

.tour-card-title {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink, #102031);
}

.tour-card-narration {
  margin: 0;
  font-size: 0.92rem;
  line-height: 1.5;
  color: var(--ink, #102031);
  white-space: pre-wrap;
}

.tour-card-loading {
  margin: 0;
  font-size: 0.88rem;
  color: var(--muted, #6e7d8a);
  font-style: italic;
}

.tour-card-error {
  margin: 0;
  font-size: 0.88rem;
  color: #b14848;
}

.tour-card-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: 2px;
}

.tour-card-actions-right {
  display: flex;
  gap: 8px;
}

.tour-card-button {
  font: inherit;
  font-size: 0.85rem;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink, #102031);
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.tour-card-button:hover:not([disabled]) {
  background: rgba(108, 199, 255, 0.12);
  border-color: rgba(108, 199, 255, 0.6);
}

.tour-card-button[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.tour-card-button.is-primary {
  background: #1f6fa6;
  color: #f6fbff;
  border-color: #1f6fa6;
}

.tour-card-button.is-primary:hover:not([disabled]) {
  background: #2a82bd;
  border-color: #2a82bd;
}

.tour-card-button.is-quiet {
  border-color: transparent;
  color: var(--muted, #6e7d8a);
}

.tour-card-button.is-quiet:hover:not([disabled]) {
  color: var(--ink, #102031);
  background: rgba(108, 199, 255, 0.08);
  border-color: transparent;
}

@media (max-width: 560px) {
  .tour-card {
    width: calc(100vw - 16px);
    bottom: 12px;
    padding: 14px 16px;
  }
  .tour-card-actions {
    flex-direction: column-reverse;
    align-items: stretch;
  }
  .tour-card-actions-right {
    justify-content: space-between;
  }
}

.viz-dashboard {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  height: 100%;
}

.viz-dash-item {
  min-height: 200px;
}

@media (max-width: 900px) {
  .viz-dashboard {
    grid-template-columns: 1fr;
  }
}

/* Make the persistent map (the #map-page shell that holds #map-stage)
   visible behind the floating panels on Data + Analyze. We don't touch
   the app-shell grid — instead we lift #map-page out of normal flow as
   a fixed full-viewport backdrop with z-index:0 and hide the Observe
   overlays inside it so only the leaflet map renders. */

body[data-page="library"] #map-page,body[data-page="inspect"] #map-page,
body[data-page="graphs"] #map-page {
  display: block !important;
  position: fixed !important;
  inset: 0;
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  overflow: hidden;
  z-index: 0;
}

body[data-page="library"] #map-page > *:not(#map-stage):not(#map-toolbar),body[data-page="inspect"] #map-page > *:not(#map-stage):not(#map-toolbar),
body[data-page="graphs"] #map-page > *:not(#map-stage):not(#map-toolbar) {
  display: none !important;
}

body[data-page="library"] #map-page #map-stage,body[data-page="inspect"] #map-page #map-stage,
body[data-page="graphs"] #map-page #map-stage {
  position: absolute;
  inset: 0;
  margin: 0;
  height: 100vh;
  width: 100vw;
  display: block;
  z-index: 0;
}

body[data-page="library"] #map-page #map,body[data-page="inspect"] #map-page #map,
body[data-page="graphs"] #map-page #map {
  width: 100% !important;
  height: 100% !important;
  position: absolute;
  inset: 0;
  border-radius: 0;
}

/* The active Data / Analyze page-panel sits above the map at z:10. */
body[data-page="library"] #library-page.is-active,
body[data-page="inspect"] #inspect-page.is-active,
body[data-page="graphs"] #graphs-page.is-active {
  z-index: 10;
}

/* ===== Floating-cards-over-the-map layout for Data + Analyze ===========
   The Data and Analyze pages keep the map fully visible behind the UI.
   The page-panel becomes a transparent layout container; each child
   (page head, tab strip, active workspace section) renders as a small
   floating glass card anchored along the top-left of the viewport.
   Other pages keep the original right-docked drawer. */

body[data-page="library"] .page-panel.is-active,body[data-page="inspect"] .page-panel.is-active,
body[data-page="graphs"] .page-panel.is-active {
  position: absolute;
  top: 76px;
  right: 16px;
  bottom: 16px;
  left: 16px;
  width: auto;
  display: flex;
  flex-direction: column;
  /* Stretch children to fill the available width. The translucent
     card backgrounds + backdrop-filter blur keep the map visible
     behind the panels — that's the "see the map without squishing
     the tools" target. */
  align-items: stretch;
  gap: 12px;
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  /* The WHOLE column scrolls when total stack overflows. Each card
     stays at full intrinsic height — no nested scrollbars within cards. */
  overflow-y: auto;
  overflow-x: hidden;
  pointer-events: none; /* Map remains pannable/clickable in the gaps. */
}

body[data-page="library"] .page-panel.is-active > *,body[data-page="inspect"] .page-panel.is-active > *,
body[data-page="graphs"] .page-panel.is-active > * {
  pointer-events: auto;
  flex-shrink: 0; /* Keep intrinsic size — don't squeeze cards short. */
  /* No more 960px width cap — panels stretch to fill the full
     viewport (minus the 16px outer margins) so tables, forms, and
     multi-column layouts get the space they need. The map is still
     visible THROUGH each card via rgba+backdrop-blur. */
}

body[data-page="library"] .page-head,body[data-page="inspect"] .page-head,
body[data-page="graphs"] .page-head {
  padding: 10px 14px;
  border: 1px solid rgba(50, 208, 189, 0.22);
  border-radius: 14px;
  background: rgba(7, 18, 24, 0.92);
  backdrop-filter: blur(16px);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.35);
  max-width: 520px;
}

body[data-page="library"] .page-head h2,body[data-page="inspect"] .page-head h2,
body[data-page="graphs"] .page-head h2 {
  margin: 2px 0 4px;
  font-size: 1.1rem;
}

body[data-page="library"] .page-head p,body[data-page="inspect"] .page-head p,
body[data-page="graphs"] .page-head p {
  font-size: 0.78rem;
  margin: 0;
}

body[data-page="library"] .workspace-tabs,body[data-page="inspect"] .workspace-tabs,
body[data-page="graphs"] .workspace-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  padding: 6px;
  border: 1px solid rgba(50, 208, 189, 0.22);
  border-radius: 999px;
  background: rgba(7, 18, 24, 0.92);
  backdrop-filter: blur(16px);
  box-shadow: 0 14px 36px rgba(0, 0, 0, 0.35);
}

body[data-page="library"] [data-workspace-section]:not([hidden]),body[data-page="inspect"] [data-workspace-section]:not([hidden]),
body[data-page="graphs"] [data-workspace-section]:not([hidden]) {
  position: relative;
  padding: 14px 16px;
  border: 1px solid rgba(50, 208, 189, 0.24);
  border-radius: 16px;
  background: rgba(7, 18, 24, 0.94);
  backdrop-filter: blur(20px);
  box-shadow: 0 22px 60px rgba(0, 0, 0, 0.5);
  /* No inner scrolling — the card grows to fit its content fully, and
     the parent page-panel column scrolls if the total stack exceeds the
     viewport. No width cap — the card stretches edge-to-edge of the
     parent so the data tools have the full viewport to work with. */
}

/* Floating-card drag handle — a small grip at the top-left of every
   workspace section that lets the user drag the card anywhere on the
   map. Position persists per page in localStorage. Double-click to
   reset to the anchored position. */
.floating-drag-handle {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font: inherit;
  font-size: 1.1rem;
  line-height: 1;
  color: rgba(255, 255, 255, 0.6);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  cursor: grab;
  touch-action: none;
  z-index: 3;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.floating-drag-handle:hover {
  background: rgba(64, 173, 224, 0.18);
  border-color: rgba(64, 173, 224, 0.4);
  color: inherit;
}
.is-dragging .floating-drag-handle,
.floating-drag-handle:active {
  cursor: grabbing;
}

/* When a section is being dragged, lift it above siblings and add a
   slight shadow / scale so the drag feels physical. */
body[data-page="library"] [data-workspace-section].is-dragging,body[data-page="inspect"] [data-workspace-section].is-dragging,
body[data-page="graphs"] [data-workspace-section].is-dragging {
  z-index: 100;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
  cursor: grabbing;
}

/* Reserve space inside the card for the drag handle on the left and the
   collapse chevron on the right so they don't overlap content. Applies
   to both the legacy section-row and the new panel-head pattern. */
body[data-page="library"] [data-workspace-section]:not([hidden]) .section-row,body[data-page="inspect"] [data-workspace-section]:not([hidden]) .section-row,
body[data-page="graphs"] [data-workspace-section]:not([hidden]) .section-row,
body[data-page="library"] [data-workspace-section]:not([hidden]) > .panel-head,body[data-page="inspect"] [data-workspace-section]:not([hidden]) > .panel-head,
body[data-page="graphs"] [data-workspace-section]:not([hidden]) > .panel-head {
  padding-left: 28px;
  padding-right: 28px;
}

/* ===== Responsive: phone + small tablet =============================
   On narrower viewports, tighten the page-panel gutters so the data
   tools get more usable width. Also reduce per-card padding so a 375px
   phone doesn't bury the content under chrome. The translucent map
   background stays — phones still benefit from the spatial context. */
@media (max-width: 760px) {
  body[data-page="library"] .page-panel.is-active,
  body[data-page="inspect"] .page-panel.is-active,
  body[data-page="graphs"] .page-panel.is-active,
  body[data-page="settings"] .page-panel.is-active,
  body[data-page="hardware"] .page-panel.is-active,
  body[data-page="forum"] .page-panel.is-active,
  body[data-page="wiki"] .page-panel.is-active,
  body[data-page="blog"] .page-panel.is-active,
  body[data-page="marketplace"] .page-panel.is-active {
    top: 64px;
    left: 8px;
    right: 8px;
    bottom: 8px;
    gap: 8px;
  }

  body[data-page="library"] .page-head,
  body[data-page="inspect"] .page-head,
  body[data-page="graphs"] .page-head {
    max-width: 100%;
    padding: 8px 12px;
  }

  body[data-page="library"] [data-workspace-section]:not([hidden]),
  body[data-page="inspect"] [data-workspace-section]:not([hidden]),
  body[data-page="graphs"] [data-workspace-section]:not([hidden]) {
    padding: 10px 12px;
  }

  /* Workspace-tabs row can grow tall on mobile when it wraps. Switch
     to horizontal scroll so the row stays compact and operators can
     swipe through sub-views. */
  body[data-page="library"] .workspace-tabs,
  body[data-page="inspect"] .workspace-tabs,
  body[data-page="graphs"] .workspace-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
  }
  body[data-page="library"] .workspace-tabs .workspace-tab,
  body[data-page="inspect"] .workspace-tabs .workspace-tab,
  body[data-page="graphs"] .workspace-tabs .workspace-tab {
    flex-shrink: 0;
  }
}

/* ===== Compact panel system (rebuild) ============================== */
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 6px 12px; margin-bottom: 6px;
}
.panel-head.subhead {
  margin-top: 14px; padding-top: 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.panel-title {
  margin: 0; font-size: var(--fs-md); font-weight: 700;
  display: inline-flex; align-items: baseline; gap: 8px;
}
.panel-subtitle {
  font-size: 0.72rem; font-weight: 500; letter-spacing: 0; text-transform: none;
}
/* Panel-subtitle filler text ("Live readings from this gateway. Updates
   every 5s.", "summary + outliers from the current chart") is duplicate
   chrome — the panel-title above already tells the user what they're
   looking at. Hide globally. */
.panel-title .panel-subtitle.muted,
.panel-head .panel-subtitle.muted { display: none; }
.panel-subtitle-h {
  margin: 0; font-size: var(--fs-base); font-weight: 600;
  display: inline-flex; align-items: baseline; gap: 8px;
}
.panel-toolbar {
  display: inline-flex; align-items: center; gap: 4px; flex-wrap: wrap;
}
.panel-toolbar .button {
  /* Override the global .button min-height: 40px so the toolbar
     reads as a tight control strip, not 9 chunky buttons. */
  min-height: 28px; height: 28px;
  padding: 0 10px; font-size: var(--fs-sm); font-weight: 600;
  line-height: 1; border-radius: 8px;
}
.panel-toolbar .button.button-primary { padding: 0 12px; }
.panel-toolbar .toolbar-icon {
  min-width: 32px; padding: 0 6px;
  font-size: 0.85rem; text-align: center;
  display: inline-flex; align-items: center; justify-content: center;
}
.panel-toolbar .toolbar-danger {
  color: rgba(251, 113, 133, 0.85);
  border-color: rgba(251, 113, 133, 0.35);
}
.panel-toolbar .toolbar-danger:hover {
  color: #fb7185;
  background: rgba(251, 113, 133, 0.12);
  border-color: rgba(251, 113, 133, 0.6);
}
.toolbar-divider {
  width: 1px; height: 18px;
  background: rgba(255, 255, 255, 0.12);
  margin: 0 2px;
}
.pinpoint-coords.compact-row {
  display: flex; align-items: center; gap: 6px;
  margin: 8px 0 10px;
}
.pinpoint-coords.compact-row input {
  flex: 1; min-width: 70px; padding: 5px 8px;
  font-size: 0.8rem;
  font-family: ui-monospace, "SF Mono", monospace;
}

/* Floating-card collapse affordance — a chevron button at the top-right.
   When collapsed, only the section-row header stays visible so the card
   shrinks to a thin handle without losing its place. */
.floating-collapse-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font: inherit;
  font-size: 0.9rem;
  line-height: 1;
  color: inherit;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  cursor: pointer;
  z-index: 2;
  transition: background 0.12s, border-color 0.12s;
}

.floating-collapse-btn:hover {
  background: rgba(64, 173, 224, 0.18);
  border-color: rgba(64, 173, 224, 0.4);
}

body[data-page="library"] [data-workspace-section].is-collapsed,body[data-page="inspect"] [data-workspace-section].is-collapsed,
body[data-page="graphs"] [data-workspace-section].is-collapsed {
  max-height: 60px;
  overflow: hidden;
  padding-right: 44px;
}

body[data-page="library"] [data-workspace-section].is-collapsed > *:not(.section-row):not(.floating-collapse-btn):not(.page-head),body[data-page="inspect"] [data-workspace-section].is-collapsed > *:not(.section-row):not(.floating-collapse-btn):not(.page-head),
body[data-page="graphs"] [data-workspace-section].is-collapsed > *:not(.section-row):not(.floating-collapse-btn):not(.page-head) {
  display: none;
}

@media (max-width: 1024px) {
  body[data-page="library"] .page-panel.is-active > *,  body[data-page="inspect"] .page-panel.is-active > *,
  body[data-page="graphs"] .page-panel.is-active > *,
  body[data-page="library"] [data-workspace-section]:not([hidden]),  body[data-page="inspect"] [data-workspace-section]:not([hidden]),
  body[data-page="graphs"] [data-workspace-section]:not([hidden]) {
    max-width: calc(100vw - 32px);
  }
}

/* ===== Research workflow panels (Data Find / Pin Board, Analyze Pin / Stats) ===== */

.finder-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 6px 0 8px;
}

@media (max-width: 700px) {
  .finder-grid { grid-template-columns: 1fr; }
}

.finder-cell { display: flex; flex-direction: column; gap: 4px; }
.finder-cell input[type="search"] {
  padding: 7px 10px;
  font-size: 0.84rem;
}

.finder-presets {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 6px 0 8px;
  border-bottom: 1px dashed rgba(255, 255, 255, 0.08);
  margin-bottom: 6px;
}
.finder-presets-label {
  margin-right: 4px;
}
.finder-preset-chip {
  font-size: 12px;
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s, border-color 0.12s;
}
.finder-preset-chip:hover {
  background: rgba(108, 183, 255, 0.12);
  border-color: var(--accent, #6cb7ff);
}
.finder-preset-chip:active {
  background: rgba(108, 183, 255, 0.2);
}

/* Provider catalog (Find Sources default state) */
.finder-catalog-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 6px 0 10px;
}
.finder-catalog-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 10px;
}
.finder-catalog-card {
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.finder-catalog-card.is-ok {
  border-color: rgba(50, 208, 189, 0.35);
}
.finder-catalog-card.is-warn {
  border-color: rgba(251, 191, 36, 0.35);
}
.finder-catalog-card.is-err {
  border-color: rgba(249, 115, 115, 0.4);
}
.finder-catalog-card-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
}
.finder-catalog-card-head strong {
  font-size: 13px;
}
.finder-catalog-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.finder-catalog-metric-chip {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  padding: 3px 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--ink);
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.finder-catalog-metric-chip:hover {
  background: rgba(108, 183, 255, 0.15);
  border-color: var(--accent, #6cb7ff);
}
.finder-catalog-metric-chip.is-more {
  cursor: default;
  opacity: 0.65;
}
.finder-catalog-actions {
  font-size: 11px;
  opacity: 0.6;
}

.finder-results {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 220px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.18);
  font-size: var(--fs-base);
}

.finder-result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 8px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid transparent;
  border-radius: 8px;
  text-align: left;
  color: inherit;
  cursor: pointer;
  font: inherit;
  transition: background 0.12s, border-color 0.12s;
}

.finder-result:hover { background: rgba(255, 255, 255, 0.06); }

.finder-result.is-selected {
  background: rgba(64, 173, 224, 0.18);
  border-color: rgba(64, 173, 224, 0.55);
}

.finder-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: 8px 0 12px;
}

.finder-matches { padding: 8px 0; }

.finder-match-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.finder-match {
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.22);
}

.finder-match-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.finder-match-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}

/* ----- Pin Board ----- */

.pinboard-list { padding: 4px 0; }
.pinboard-list.empty { padding: 20px; text-align: center; opacity: 0.6; }
.pinboard-items { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.pinboard-item {
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.22);
}

.pinboard-item-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 4px;
}

.pinboard-item-actions { display: flex; gap: 8px; margin-top: 8px; }

/* ----- Pinpoint ----- */

.pinpoint-coords {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: end;
  margin: 8px 0;
}

.pinpoint-results { padding: 4px 0; }
.pinpoint-results.empty { padding: 20px; text-align: center; opacity: 0.6; }

.pinpoint-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin-bottom: 8px;
}

.pinpoint-group { margin: 12px 0; }

.pinpoint-group h4 {
  margin: 0 0 6px;
  font-size: 0.92rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.pinpoint-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }

.pinpoint-list li {
  display: flex;
  align-items: center;
  gap: 8px;
}

/* ----- Stats ----- */

.stats-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
  gap: 8px;
}

.stats-grid li {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.22);
}

.stats-summary { padding: 4px 0; }
.stats-summary.empty { padding: 20px; text-align: center; opacity: 0.6; }

.stats-anomalies { margin-top: 12px; font-size: 0.85rem; }
.stats-anomalies.is-hidden { display: none; }

.anomaly-list { margin: 6px 0 0 20px; padding: 0; }

.stats-snippet {
  margin-top: 12px;
  padding: 10px;
  font-size: 0.78rem;
  background: rgba(0, 0, 0, 0.4);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  overflow-x: auto;
  white-space: pre-wrap;
}

/* ----- Multi-pin list + swatches + compare table ----- */

.pinpoint-pin-list {
  margin: 10px 0;
}

.pinpoint-pin-list.empty {
  padding: 14px;
  border: 1px dashed rgba(255,255,255,0.1);
  border-radius: 8px;
  text-align: center;
  opacity: 0.65;
  font-size: 0.85rem;
}

.research-pin-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.research-pin-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  background: rgba(0,0,0,0.18);
  transition: border-color 0.12s, background 0.12s;
}

.research-pin-item.is-selected {
  border-color: rgba(64,173,224,0.55);
  background: rgba(64,173,224,0.12);
}

.research-pin-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  flex-shrink: 0;
  box-shadow: 0 0 0 2px rgba(0,0,0,0.4);
}

.research-pin-label {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  padding: 4px 6px;
  background: transparent;
  border: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: 6px;
}

.research-pin-label:hover {
  background: rgba(255,255,255,0.04);
}

.research-pin-remove {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: 6px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: 1rem;
}

.research-pin-remove:hover {
  background: rgba(251,113,133,0.2);
  border-color: rgba(251,113,133,0.5);
}

.pinpoint-compare-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 10px;
  font-size: var(--fs-base);
}

.pinpoint-compare-table th,
.pinpoint-compare-table td {
  padding: 6px 10px;
  text-align: left;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}

.pinpoint-compare-table th {
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  opacity: 0.7;
}

.pinpoint-compare-head {
  margin-bottom: 8px;
  font-size: var(--fs-md);
}

/* Leaflet marker tooltip for research pins. */
.research-pin-tooltip {
  background: rgba(7,18,24,0.92) !important;
  border: 1px solid rgba(255,255,255,0.16) !important;
  color: #e6f6f4 !important;
  box-shadow: 0 4px 14px rgba(0,0,0,0.45) !important;
  font-size: var(--fs-sm) !important;
  padding: 2px 6px !important;
}

.research-pin-tooltip::before {
  border-right-color: rgba(7,18,24,0.92) !important;
}

/* ----- Pin sparkline inline preview ----- */
.pinpoint-sparkline {
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 10px;
  background: rgba(0,0,0,0.22);
}

.pinpoint-sparkline-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
}

.pinpoint-sparkline-head strong { flex: 1; min-width: 0; }

.pinpoint-spark-host { min-height: 40px; }

.pinpoint-spark-svg {
  width: 100%;
  height: 64px;
  margin: 6px 0;
}

.pinpoint-spark-svg svg {
  width: 100%;
  height: 100%;
  display: block;
}

.pinpoint-spark-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  font-size: 0.78rem;
}

.pinpoint-spark-stats > span {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

/* ----- Per-station "All Metrics" stacked small-multiples ----- */
.pinpoint-stacked-head {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding-bottom: 6px; margin-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.pinpoint-stacked-head > button { margin-left: auto; }
.pinpoint-stacked-rows { display: flex; flex-direction: column; gap: 6px; }
.pinpoint-stacked-row {
  padding: 6px 8px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-left: 3px solid var(--stacked-color, #22d3ee);
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.18);
}
.pinpoint-stacked-row-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px;
  margin-bottom: 2px; font-size: 0.78rem;
}
.pinpoint-stacked-metric {
  display: inline-flex; align-items: center; gap: 6px;
  background: none; border: 0; padding: 2px 4px;
  color: inherit; cursor: pointer; font: inherit;
}
.pinpoint-stacked-metric:hover strong { color: var(--stacked-color, #22d3ee); }
.pinpoint-stacked-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.pinpoint-stacked-last strong { font-size: var(--fs-md); }
.pinpoint-stacked-row-svg { height: 42px; }
.pinpoint-stacked-row-svg svg { width: 100%; height: 100%; display: block; }

/* ----- Map right-click context menu ----- */
.research-context-menu {
  position: absolute;
  z-index: 9999;
  display: flex;
  flex-direction: column;
  min-width: 220px;
  padding: 6px;
  border: 1px solid rgba(50, 208, 189, 0.32);
  border-radius: 10px;
  background: rgba(7, 18, 24, 0.96);
  backdrop-filter: blur(16px);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.55);
}

.research-context-coord {
  padding: 6px 8px;
  font-size: 0.75rem;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.6);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  margin-bottom: 4px;
}

.research-context-menu button {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  font: inherit;
  font-size: 0.85rem;
  text-align: left;
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}

.research-context-menu button:hover {
  background: rgba(64, 173, 224, 0.18);
  border-color: rgba(64, 173, 224, 0.4);
}

/* ----- Map measure tool tooltip ----- */
.research-measure-tip {
  background: rgba(7, 18, 24, 0.94) !important;
  border: 1px solid rgba(34, 211, 238, 0.45) !important;
  color: #e6f6f4 !important;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5) !important;
  font-size: 0.78rem !important;
  padding: 6px 8px !important;
  line-height: 1.35 !important;
}

.research-measure-tip strong { color: #67e8f9; }
.research-measure-tip.is-final { border-color: rgba(34, 211, 238, 0.7) !important; }
.research-measure-tip::before { display: none !important; }
.research-measure-line { pointer-events: none; }

/* ----- Annotation markers + section list ----- */
.research-annotation-icon { display: flex; align-items: center; justify-content: center; }
.research-annotation-icon span {
  width: 26px; height: 26px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px;
  border: 2px solid rgba(7, 18, 24, 0.9);
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.18), 0 4px 10px rgba(0, 0, 0, 0.5);
}
.research-annotation-tip {
  background: rgba(7, 18, 24, 0.92) !important;
  border: 1px solid rgba(251, 191, 36, 0.4) !important;
  color: #fde68a !important;
  font-size: 0.75rem !important;
  padding: 3px 6px !important;
  max-width: 220px !important;
}
.research-annotation-tip::before { border-top-color: rgba(7, 18, 24, 0.92) !important; }
.annotation-section { margin-top: 18px; padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.08); }
.annotation-list-host.empty {
  padding: 10px 12px; font-size: 0.78rem; color: rgba(255, 255, 255, 0.55);
  border: 1px dashed rgba(255, 255, 255, 0.12); border-radius: 8px;
}
.annotation-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.annotation-item {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px;
  border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 8px;
  background: rgba(0, 0, 0, 0.18);
}
.annotation-swatch {
  width: 12px; height: 12px; border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.4); flex-shrink: 0;
}
.annotation-label {
  flex: 1; min-width: 0; text-align: left;
  background: none; border: 0; color: inherit;
  padding: 4px 6px; cursor: pointer;
  display: flex; flex-direction: column; gap: 1px;
}
.annotation-label strong {
  font-size: 0.85rem; font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.annotation-label:hover strong { color: #fbbf24; }
.annotation-edit, .annotation-color, .annotation-remove {
  background: none; border: 1px solid transparent;
  color: rgba(255, 255, 255, 0.55); cursor: pointer;
  padding: 2px 6px; border-radius: 4px;
  font-size: 0.85rem; flex-shrink: 0;
}
.annotation-edit:hover, .annotation-color:hover { color: #fbbf24; border-color: rgba(251, 191, 36, 0.4); }
.annotation-remove:hover { color: #fb7185; border-color: rgba(251, 113, 133, 0.4); }
.compact-row { gap: 10px; padding-bottom: 4px; }

/* ----- Pin tags + tag filter ----- */
.research-pin-tag-chips { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.research-pin-tag-chip {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 6px; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600;
  color: rgba(255, 255, 255, 0.78);
  background: rgba(34, 211, 238, 0.14);
  border: 1px solid rgba(34, 211, 238, 0.3);
  border-radius: 10px; cursor: pointer; white-space: nowrap;
}
.research-pin-tag-chip:hover { background: rgba(34, 211, 238, 0.28); border-color: rgba(34, 211, 238, 0.6); }
.research-pin-tag-chip.is-active { background: rgba(251, 191, 36, 0.32); border-color: rgba(251, 191, 36, 0.7); color: #fde68a; }
.research-pin-tag-more { font-size: var(--fs-xs); color: rgba(255, 255, 255, 0.55); padding: 1px 4px; }
.pin-tag-filter {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding: 8px 10px; margin-bottom: 8px;
  border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 8px;
  background: rgba(0, 0, 0, 0.18);
}
.pin-tag-filter[hidden] { display: none; }
.research-pin-tag-clear {
  margin-left: auto; padding: 2px 8px; font-size: 0.72rem;
  background: none; border: 1px solid rgba(251, 113, 133, 0.4);
  color: #fda4af; border-radius: 4px; cursor: pointer;
}
.research-pin-tag-clear:hover { background: rgba(251, 113, 133, 0.12); }
.research-pin-item.is-filtered-out { opacity: 0.4; }

/* ----- "? Shortcuts" button + help overlay ----- */
.research-help-button {
  align-self: flex-start; margin-top: 4px;
  padding: 4px 10px; font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: rgba(255, 255, 255, 0.65);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 999px; cursor: pointer;
}
.research-help-button:hover { color: #fbbf24; border-color: rgba(251, 191, 36, 0.5); background: rgba(251, 191, 36, 0.1); }
.research-page-head-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.research-page-head-actions .research-help-button { margin-top: 0; }

/* ----- Live cursor coordinates + scale readout ----- */
.research-cursor-readout {
  position: fixed; right: 18px; bottom: 18px;
  z-index: 600; padding: 6px 12px;
  display: flex; flex-direction: column; gap: 1px;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Consolas", monospace;
  font-size: 0.78rem; color: #67e8f9;
  background: rgba(7, 18, 24, 0.92);
  border: 1px solid rgba(34, 211, 238, 0.34);
  border-radius: 8px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.45);
  pointer-events: none; user-select: none;
  letter-spacing: 0.02em;
}
.research-cursor-readout[hidden] { display: none; }
.research-cursor-readout .cursor-coord { color: #67e8f9; font-weight: 600; }
.research-cursor-readout .cursor-meta { color: rgba(255, 255, 255, 0.72); font-size: 0.72rem; }

/* ----- Recipes (outcome-oriented workflows) ----- */
.recipes-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 12px; margin-top: 12px;
}
.recipe-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 14px 14px 10px;
  border: 1px solid rgba(50, 208, 189, 0.22); border-radius: 12px;
  background: rgba(0, 0, 0, 0.22); color: inherit;
  text-align: left; cursor: pointer;
  transition: border-color 0.15s, background 0.15s, transform 0.1s;
}
.recipe-card:hover { border-color: var(--accent, #32d0bd); background: rgba(50, 208, 189, 0.08); transform: translateY(-1px); }
.recipe-card:focus-visible { outline: 2px solid var(--accent, #32d0bd); outline-offset: 2px; }
.recipe-card-head { display: flex; align-items: center; gap: 10px; }
.recipe-card-head strong { font-size: var(--fs-md); }
.recipe-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; font-size: 1.2rem;
  border-radius: 8px;
  background: rgba(50, 208, 189, 0.14);
  flex: none;
}
.recipe-blurb { margin: 0; line-height: 1.5; flex: 1; }
.recipe-card-foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  padding-top: 6px; border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.recipe-tag {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.04em;
  font-weight: 600; padding: 1px 6px;
  color: rgba(255, 255, 255, 0.62);
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
}
.recipe-run { margin-left: auto; font-size: 0.78rem; font-weight: 700; color: var(--accent, #32d0bd); }
.recipe-card:hover .recipe-run { color: #67e8f9; }
.recipe-banner {
  position: fixed; top: 76px; left: 50%; transform: translateX(-50%);
  z-index: 8000;
  display: flex; align-items: center; gap: 12px;
  max-width: calc(100vw - 32px);
  padding: 10px 16px;
  border: 1px solid rgba(251, 191, 36, 0.55);
  border-radius: 12px;
  background: rgba(50, 38, 8, 0.96);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
  color: #fde68a;
}
.recipe-banner .recipe-icon { background: rgba(251, 191, 36, 0.22); color: #fde68a; }
.recipe-banner-body { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.recipe-banner-body strong { font-size: 0.9rem; }
.recipe-banner-body code {
  font-family: ui-monospace, "SF Mono", monospace; font-size: 0.7rem;
  padding: 1px 5px; background: rgba(251, 191, 36, 0.18); border-radius: 4px;
}
.recipe-banner-clear, .recipe-banner-dismiss {
  padding: 5px 11px; font-size: var(--fs-sm); font-weight: 600;
  background: rgba(251, 191, 36, 0.16);
  border: 1px solid rgba(251, 191, 36, 0.4);
  color: #fde68a; border-radius: 6px; cursor: pointer; white-space: nowrap;
}
.recipe-banner-clear:hover, .recipe-banner-dismiss:hover { background: rgba(251, 191, 36, 0.28); }

/* ----- Demo Mode (sandbox synthetic data) ----- */
.demo-mode-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin: 12px 0; padding: 14px 16px;
  border: 1px dashed rgba(167, 139, 250, 0.5); border-radius: 12px;
  background: linear-gradient(135deg, rgba(167, 139, 250, 0.08), rgba(34, 211, 238, 0.04));
}
.demo-mode-pitch { flex: 1; display: flex; flex-direction: column; gap: 2px; min-width: 240px; }
.demo-mode-pitch strong { font-size: var(--fs-md); }
#demo-mode-toggle.is-active { background: rgba(167, 139, 250, 0.28); border-color: rgba(167, 139, 250, 0.7); color: #e9d5ff; }
.demo-mode-banner {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  z-index: 8500;
  display: flex; align-items: center; gap: 12px;
  max-width: calc(100vw - 32px);
  padding: 10px 16px;
  border: 1px solid rgba(167, 139, 250, 0.55);
  border-radius: 12px;
  background: rgba(36, 22, 52, 0.96);
  box-shadow: 0 18px 50px rgba(0, 0, 0, 0.55);
  color: #e9d5ff;
}
.demo-mode-flask {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; font-size: 1.4rem;
  border-radius: 8px; background: rgba(167, 139, 250, 0.22);
}
.demo-mode-banner-body { display: flex; flex-direction: column; gap: 1px; flex: 1; min-width: 0; }
.demo-mode-banner-body strong { font-size: 0.9rem; }
.demo-mode-banner-body code {
  font-family: ui-monospace, "SF Mono", monospace; font-size: 0.7rem;
  padding: 1px 5px; background: rgba(167, 139, 250, 0.18); border-radius: 4px;
}
#demo-mode-disable-btn {
  padding: 5px 12px; font-size: var(--fs-sm); font-weight: 600;
  background: rgba(167, 139, 250, 0.18);
  border: 1px solid rgba(167, 139, 250, 0.45);
  color: #e9d5ff; border-radius: 6px; cursor: pointer; white-space: nowrap;
}
#demo-mode-disable-btn:hover { background: rgba(167, 139, 250, 0.32); }

/* ----- Smart empty states (skeleton UI + Populate CTA) ----- */
.empty-state { display: flex; flex-direction: column; gap: 14px; padding: 8px 0; }
.empty-state .skeleton-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
  opacity: 0.45; pointer-events: none;
}
.empty-state .skeleton-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 8px; background: rgba(0, 0, 0, 0.16);
}
.skeleton-bar {
  display: inline-block; height: 10px; border-radius: 4px;
  background: rgba(255, 255, 255, 0.08);
  background-image: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.04) 50%, transparent 100%);
  background-size: 200% 100%;
  animation: skeleton-shimmer 1.6s linear infinite;
}
.skeleton-bar.muted-bar { background: rgba(255, 255, 255, 0.04); }
.skeleton-block { display: block; width: 100%; border-radius: 6px; }
@keyframes skeleton-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.empty-state .research-pin-swatch.skeleton-bar { width: 14px; height: 14px; border-radius: 50%; }
.skeleton-detail {
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px;
  border: 1px solid rgba(255, 255, 255, 0.05);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.16);
  opacity: 0.5; pointer-events: none;
}
.skeleton-detail-head { display: flex; align-items: center; gap: 10px; }
.skeleton-detail-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.empty-state-cta { display: flex; flex-direction: column; gap: 8px; }
.empty-state-cta p { margin: 0; }
.empty-state-actions { display: flex; flex-wrap: wrap; gap: 6px; }
.empty-state-actions .button { font-size: 0.78rem; padding: 6px 12px; }

/* ----- Visual data lineage (🔗 button + node-graph modal) ----- */
.chart-lineage-btn {
  margin-left: auto;
  padding: 3px 10px;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em;
  color: #67e8f9;
  background: rgba(34, 211, 238, 0.1);
  border: 1px solid rgba(34, 211, 238, 0.35);
  border-radius: 999px; cursor: pointer; white-space: nowrap;
}
.chart-lineage-btn:hover { background: rgba(34, 211, 238, 0.22); border-color: rgba(34, 211, 238, 0.7); }

.lineage-modal-overlay {
  position: fixed; inset: 0; z-index: 9500;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px);
}
.lineage-modal {
  width: min(620px, calc(100vw - 32px));
  max-height: calc(100vh - 80px);
  padding: 20px 24px;
  border: 1px solid rgba(34, 211, 238, 0.4);
  border-radius: 16px;
  background: rgba(7, 18, 24, 0.98);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6);
  overflow-y: auto;
}
.lineage-modal-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.lineage-modal-head h3 { margin: 0; font-size: 1.0rem; }
.lineage-modal-close {
  margin-left: auto; width: 28px; height: 28px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: inherit; border-radius: 8px;
  font-size: 1.1rem; line-height: 1; cursor: pointer;
}
.lineage-modal-close:hover { background: rgba(251, 113, 133, 0.18); border-color: rgba(251, 113, 133, 0.5); }
.lineage-flow { list-style: none; margin: 12px 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.lineage-node {
  display: grid; grid-template-columns: 36px 1fr; gap: 10px;
  padding: 10px 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 3px solid rgba(34, 211, 238, 0.5);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.22);
}
.lineage-node-source { border-left-color: #fbbf24; }
.lineage-node-filter { border-left-color: #f97316; }
.lineage-node-groupBy { border-left-color: #a78bfa; }
.lineage-node-transform { border-left-color: #84cc16; }
.lineage-node-render { border-left-color: #67e8f9; }
.lineage-node-icon {
  display: flex; align-items: center; justify-content: center;
  font-size: 1.2rem; width: 30px; height: 30px;
  border-radius: 8px; background: rgba(255, 255, 255, 0.06);
}
.lineage-node-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.lineage-node-body strong { font-size: 0.88rem; }
.lineage-node-body code {
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Consolas", monospace;
  font-size: 0.72rem; color: #67e8f9;
  background: rgba(34, 211, 238, 0.1);
  padding: 2px 6px; border-radius: 4px; word-break: break-all;
}
.lineage-arrow {
  grid-column: 1 / -1; text-align: center;
  color: rgba(255, 255, 255, 0.45); font-size: 1.1rem; line-height: 0.6;
  padding: 2px 0;
}
.lineage-modal-foot {
  display: flex; gap: 8px;
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}

/* ----- Anomaly watches (push-not-pull) ----- */
.chart-watch-btn {
  padding: 3px 10px; font-size: 0.7rem; font-weight: 600; letter-spacing: 0.03em;
  color: #fde68a;
  background: rgba(251, 191, 36, 0.12);
  border: 1px solid rgba(251, 191, 36, 0.4);
  border-radius: 999px; cursor: pointer; white-space: nowrap; margin-left: 6px;
}
.chart-watch-btn:hover { background: rgba(251, 191, 36, 0.24); border-color: rgba(251, 191, 36, 0.7); }

.watches-list-ul {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
  /* Cap the alert / watch list width so individual rows don't stretch
     edge-to-edge on the wide Inspect panel — long rows make the
     sparkline + actions feel disconnected from the watch label. */
  max-width: 920px;
}

.watches-quickadd {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  padding: 10px;
  margin: 8px 0;
  border: 1px dashed rgba(255, 255, 255, 0.1);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.02);
  /* Same rationale as .watches-list-ul: cap so the form doesn't sprawl
     across the wide Inspect panel. */
  max-width: 920px;
}
.watches-quickadd-label {
  margin-right: 4px;
}
.watches-quickadd-input {
  flex: 1 1 140px;
  min-width: 120px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(16, 22, 30, 0.7);
  color: var(--ink);
  font-size: 12px;
}
.watches-quickadd-threshold {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--ink);
}
.watches-quickadd-threshold input {
  width: 56px;
  padding: 6px 8px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(16, 22, 30, 0.7);
  color: var(--ink);
  font-size: 12px;
  text-align: right;
}
#watches-quickadd-submit {
  font-size: 12px;
  padding: 6px 12px;
}
.watch-item {
  display: grid;
  /* icon | body | sparkline | chart | recheck | remove */
  grid-template-columns: 30px 1fr 110px auto auto auto;
  gap: 10px;
  align-items: center; padding: 10px 14px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left: 3px solid rgba(85, 211, 138, 0.55);
  border-radius: 10px;
  background: rgba(0, 0, 0, 0.2);
}
@media (max-width: 760px) {
  /* On narrow panels, drop the sparkline column (the watch body already shows
     the last value + deviation %, which is the same signal in text form). */
  .watch-item { grid-template-columns: 30px 1fr auto auto auto; }
  .watch-sparkline { display: none; }
}
.watch-severity-warning { border-left-color: #f6b15e; background: rgba(246, 177, 94, 0.06); }
.watch-severity-critical { border-left-color: #fb7185; background: rgba(251, 113, 133, 0.08); }
.watch-icon { display: flex; align-items: center; justify-content: center; font-size: 1.1rem; }
.watch-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.watch-body strong { font-size: 0.9rem; }
.watch-sparkline {
  /* Anchor the sparkline SVG drawer (it draws into a 200x22 viewbox) into
     the row's grid column. Hover shows the data range visually. */
  width: 100%;
  height: 22px;
  opacity: 0.85;
}
.watch-sparkline:empty::before {
  content: "—";
  color: rgba(255, 255, 255, 0.25);
  font-size: 0.75rem;
}
.watch-chart, .watch-recheck, .watch-remove {
  background: none; border: 1px solid transparent;
  color: rgba(255, 255, 255, 0.55); cursor: pointer;
  padding: 4px 8px; border-radius: 6px; font-size: var(--fs-md);
}
.watch-chart:hover { color: #c4b5fd; border-color: rgba(196, 181, 253, 0.4); }
.watch-recheck:hover { color: #67e8f9; border-color: rgba(34, 211, 238, 0.4); }
.watch-remove:hover { color: #fb7185; border-color: rgba(251, 113, 133, 0.4); }
.research-help-overlay {
  position: fixed; inset: 0; z-index: 9999;
  display: flex; align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.55); backdrop-filter: blur(4px);
  pointer-events: auto;
}
.research-help-card {
  width: min(680px, calc(100vw - 32px));
  max-height: calc(100vh - 80px);
  padding: 22px 26px;
  border: 1px solid rgba(50, 208, 189, 0.4);
  border-radius: 18px;
  background: rgba(7, 18, 24, 0.97);
  box-shadow: 0 40px 100px rgba(0, 0, 0, 0.6);
  overflow-y: auto;
}
.research-help-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.research-help-head h3 { margin: 0; font-size: 1.05rem; }
.research-help-close {
  margin-left: auto; width: 32px; height: 32px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: inherit; border-radius: 8px;
  font-size: 1.2rem; line-height: 1; cursor: pointer;
}
.research-help-close:hover { background: rgba(251, 113, 133, 0.18); border-color: rgba(251, 113, 133, 0.5); }
.research-help-list {
  list-style: none; margin: 14px 0; padding: 0;
  display: grid; grid-template-columns: max-content 1fr;
  gap: 8px 18px; align-items: center;
}
.research-help-list li { display: contents; }
.research-help-keys { display: inline-flex; align-items: center; gap: 4px; justify-self: end; }
.research-help-keys kbd {
  display: inline-block; min-width: 22px; padding: 2px 7px;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Consolas", monospace;
  font-size: 0.78rem; text-align: center;
  color: #67e8f9;
  background: rgba(34, 211, 238, 0.12);
  border: 1px solid rgba(34, 211, 238, 0.42);
  border-radius: 6px;
  box-shadow: 0 2px 0 rgba(34, 211, 238, 0.18);
}
.research-help-label { color: rgba(255, 255, 255, 0.86); font-size: 0.86rem; }
.research-help-tips {
  margin-top: 14px; padding: 10px 12px;
  border: 1px dashed rgba(255, 255, 255, 0.12);
  border-radius: 8px; line-height: 1.5;
}
.research-help-tips kbd {
  display: inline-block; padding: 1px 5px;
  font-family: ui-monospace, "SF Mono", monospace;
  font-size: 0.72rem;
  background: rgba(34, 211, 238, 0.1);
  border: 1px solid rgba(34, 211, 238, 0.32);
  border-radius: 4px; color: #67e8f9;
}

/* ----- Per-pin metric picker + multi-pin compare sparklines ----- */
.pinpoint-metric-picker {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  font-size: 0.8rem;
}

.pinpoint-metric-picker select {
  flex: 1;
  padding: 4px 8px;
  font: inherit;
  font-size: var(--fs-base);
  color: inherit;
  background: rgba(0, 0, 0, 0.32);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 6px;
}

.pinpoint-compare-sparks {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 14px;
}

.pinpoint-compare-spark-card {
  padding: 8px 10px 6px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-left-width: 4px;
  border-left-style: solid;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.22);
}

.pinpoint-compare-spark-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-size: 0.85rem;
}

.pinpoint-compare-spark-svg {
  width: 100%;
  height: 56px;
}

.pinpoint-compare-spark-svg svg {
  width: 100%;
  height: 100%;
  display: block;
}

/* ----- Pairwise distance matrix ----- */
.pinpoint-distance-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
}

.pinpoint-distance-table th,
.pinpoint-distance-table td {
  padding: 5px 8px;
  text-align: center;
  border: 1px solid rgba(255,255,255,0.06);
}

.pinpoint-distance-table th {
  background: rgba(255,255,255,0.04);
  font-weight: 500;
}

.pinpoint-distance-table thead th {
  text-align: left;
}

.pinpoint-distance-table tbody th {
  text-align: left;
  white-space: nowrap;
}

/* ----- Saved Finder searches ----- */
.finder-saved-searches {
  margin: 10px 0;
  padding: 8px 10px;
  border: 1px solid rgba(255,255,255,0.06);
  border-radius: 8px;
  background: rgba(0,0,0,0.18);
}

.finder-saved-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.finder-saved-list li {
  display: flex;
  align-items: center;
  gap: 2px;
}

.finder-saved-chip {
  font-size: 0.78rem;
  max-width: 280px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.finder-saved-remove {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  padding: 0;
}

.finder-saved-remove:hover {
  background: rgba(251,113,133,0.2);
  border-color: rgba(251,113,133,0.5);
}

/* ----- Provider health badges (in Finder match list) ----- */
.finder-health-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  border-radius: 999px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.12);
  color: rgba(255,255,255,0.6);
}
.finder-health-badge.is-ok { background: rgba(34,197,94,0.16); border-color: rgba(34,197,94,0.45); color: #86efac; }
.finder-health-badge.is-needs-key { background: rgba(250,204,21,0.16); border-color: rgba(250,204,21,0.45); color: #fde047; }
.finder-health-badge.is-error { background: rgba(248,113,113,0.16); border-color: rgba(248,113,113,0.5); color: #fca5a5; }
.finder-health-badge.is-checking { opacity: 0.5; }

/* ----- Inline provider preview ----- */
.finder-preview-host {
  margin-top: 8px;
  padding: 8px 10px;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  background: rgba(0,0,0,0.24);
}

.finder-preview-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.finder-preview-head strong { flex: 1; }

.finder-preview-close {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 5px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  color: inherit;
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-md);
  padding: 0;
}
.finder-preview-close:hover {
  background: rgba(251,113,133,0.2);
  border-color: rgba(251,113,133,0.5);
}

.finder-preview-table-wrap {
  overflow-x: auto;
  max-height: 220px;
  overflow-y: auto;
}

.finder-preview-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}

.finder-preview-table th,
.finder-preview-table td {
  padding: 4px 8px;
  text-align: left;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.finder-preview-table th {
  background: rgba(255,255,255,0.04);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.65rem;
  letter-spacing: 0.04em;
  position: sticky;
  top: 0;
}

/* ----- Finder results head bar ----- */
.finder-results-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 4px 0 8px;
}

/* ----- Pin rename + notes ----- */
.research-pin-rename {
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.08);
  color: rgba(255,255,255,0.7);
  cursor: pointer;
  font: inherit;
  font-size: 0.85rem;
  padding: 0;
}
.research-pin-rename:hover {
  background: rgba(64, 173, 224, 0.18);
  border-color: rgba(64, 173, 224, 0.4);
  color: inherit;
}

.pinpoint-note-block {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 8px 0;
}

.pinpoint-note-block textarea {
  width: 100%;
  resize: vertical;
  min-height: 44px;
  padding: 6px 8px;
  font: inherit;
  font-size: var(--fs-base);
  color: inherit;
  background: rgba(0, 0, 0, 0.28);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
}

.pinpoint-note-block textarea:focus {
  outline: none;
  border-color: rgba(64, 173, 224, 0.55);
}

.pinpoint-compare-note {
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── BBS forum (old-school message-board look) ────────────────────────
   The forum page leans into the BBS aesthetic: monospace, ASCII banner,
   fixed-width tables for boards and topics, numbered posts. Keeps the
   same DOM IDs so the event handlers still work. */
.bbs-page {
  color: #cfe8d8;
}
.bbs-banner {
  margin: 0 0 12px;
  padding: 8px 12px;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.66rem;
  line-height: 1.25;
  color: #7be0a6;
  background: rgba(8, 22, 14, 0.6);
  border: 1px solid rgba(123, 224, 166, 0.18);
  border-radius: 6px;
  overflow-x: auto;
  white-space: pre;
  text-shadow: 0 0 6px rgba(123, 224, 166, 0.28);
}
.bbs-page-head h2 {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.bbs-summary-strip { /* match BBS palette via inherited stat-card colors */ }

.bbs-section {
  margin-bottom: 12px;
  padding: 0;
  border-top: 1px dashed rgba(123, 224, 166, 0.18);
  padding-top: 8px;
}
.bbs-section-title {
  margin: 0 0 6px;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.78rem;
  font-weight: 700;
  color: #7be0a6;
  letter-spacing: 0.04em;
  text-shadow: 0 0 6px rgba(123, 224, 166, 0.18);
}

/* Board list — one row per board, monospace columns. */
.bbs-board-list {
  display: flex;
  flex-direction: column;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: var(--fs-sm);
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  overflow: hidden;
}
.bbs-board-row {
  display: grid;
  grid-template-columns: 2fr 1fr 0.6fr 0.6fr 1.4fr 0.5fr;
  align-items: center;
  gap: 8px;
  padding: 7px 12px;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-top: 1px solid rgba(123, 224, 166, 0.08);
  font: inherit;
  transition: background 0.14s ease, color 0.14s ease;
}
.bbs-board-row:first-child { border-top: 0; }
.bbs-board-row-head {
  background: rgba(123, 224, 166, 0.08);
  color: #b3e8c8;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  cursor: default;
  font-size: 0.66rem;
}
.bbs-board-row:not(.bbs-board-row-head):hover {
  background: rgba(123, 224, 166, 0.08);
  color: #eafff0;
}
.bbs-board-row.is-active {
  background: rgba(123, 224, 166, 0.16);
  color: #eafff0;
  box-shadow: inset 3px 0 0 #7be0a6;
}
.bbs-board-row .bbs-col-name {
  display: flex; flex-direction: column; gap: 1px;
}
.bbs-board-row .bbs-col-name strong { color: #eafff0; font-weight: 700; }
.bbs-board-row .bbs-col-name small { color: rgba(207, 232, 216, 0.55); font-size: 0.62rem; }
.bbs-col-sysop, .bbs-col-topics, .bbs-col-posts { color: rgba(207, 232, 216, 0.7); }
.bbs-col-last { color: rgba(207, 232, 216, 0.55); font-size: var(--fs-xs); }
.bbs-col-new { color: #ffd66a; text-align: right; font-weight: 700; }

/* Topic list */
.bbs-topic-list {
  display: flex;
  flex-direction: column;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: var(--fs-sm);
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  overflow: hidden;
}
.bbs-topic-row {
  display: grid;
  grid-template-columns: 0.4fr 3fr 1fr 0.4fr 1.2fr 0.8fr;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border: 0;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-top: 1px solid rgba(123, 224, 166, 0.08);
  font: inherit;
  transition: background 0.14s ease;
}
.bbs-topic-row:first-child { border-top: 0; }
.bbs-topic-row-head {
  background: rgba(123, 224, 166, 0.08);
  color: #b3e8c8;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  font-size: 0.62rem;
  cursor: default;
}
.bbs-topic-row:not(.bbs-topic-row-head):hover {
  background: rgba(123, 224, 166, 0.08);
}
.bbs-topic-row.is-active {
  background: rgba(123, 224, 166, 0.18);
  box-shadow: inset 3px 0 0 #7be0a6;
}
.bbs-topic-row .bbs-col-num { color: rgba(207, 232, 216, 0.55); }
.bbs-topic-row .bbs-col-title { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.bbs-topic-row .bbs-col-title strong {
  color: #eafff0; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bbs-topic-row .bbs-col-title small { color: rgba(207, 232, 216, 0.45); font-size: 0.6rem; }
.bbs-topic-row .bbs-col-status { color: rgba(207, 232, 216, 0.55); text-align: right; font-size: 0.66rem; }
.bbs-topic-row.is-hot .bbs-col-status      { color: #ff9166; }
.bbs-topic-row.is-pinned .bbs-col-status   { color: #ffd66a; }
.bbs-topic-row.is-resolved .bbs-col-status { color: rgba(123, 224, 166, 0.55); }

/* Topic detail — numbered posts */
.bbs-topic-detail {
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.78rem;
}
.bbs-post {
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.34);
  overflow: hidden;
}
.bbs-post-head {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 6px 12px;
  background: rgba(123, 224, 166, 0.08);
  border-bottom: 1px solid rgba(123, 224, 166, 0.18);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
}
.bbs-post-num {
  color: #7be0a6;
  font-weight: 800;
}
.bbs-post-author {
  color: #eafff0;
  font-weight: 700;
  text-transform: uppercase;
}
.bbs-post-role {
  color: rgba(207, 232, 216, 0.6);
}
.bbs-post-time {
  margin-left: auto;
  color: rgba(207, 232, 216, 0.55);
}
.bbs-post-body {
  padding: 10px 14px;
  line-height: 1.55;
  color: #d8efe2;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.bbs-post-footer {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.66rem;
  color: rgba(123, 224, 166, 0.5);
  padding: 4px 0;
}

/* Composer */
.bbs-composer {
  margin-top: 8px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.3);
  font-family: "IBM Plex Mono", "Courier New", monospace;
}
.bbs-composer textarea {
  font-family: inherit;
  font-size: 0.78rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: #d8efe2;
}
.bbs-composer textarea:focus {
  outline: none;
  border-color: rgba(123, 224, 166, 0.6);
}

/* Make topic list + post detail scroll inside their own region so the
   page doesn't grow indefinitely on long boards. */
.bbs-topic-section .bbs-topic-detail {
  max-height: 360px;
  overflow-y: auto;
  padding-right: 4px;
}
.bbs-topic-list {
  max-height: 220px;
  overflow-y: auto;
}
.bbs-board-list {
  max-height: 200px;
  overflow-y: auto;
}

/* Mobile: collapse the column-heavy rows to 2-col stacks so the BBS
   tables don't overflow horizontally on a phone. */
@media (max-width: 760px) {
  .bbs-board-row,
  .bbs-topic-row {
    grid-template-columns: 1fr auto;
    grid-template-rows: auto auto;
  }
  .bbs-board-row > .bbs-col-sysop,
  .bbs-board-row > .bbs-col-topics,
  .bbs-board-row > .bbs-col-posts,
  .bbs-board-row > .bbs-col-last,
  .bbs-topic-row > .bbs-col-author,
  .bbs-topic-row > .bbs-col-replies,
  .bbs-topic-row > .bbs-col-last,
  .bbs-topic-row > .bbs-col-num {
    display: none;
  }
}

/* ── BBS sections menu (top nav) ────────────────────────────────────── */
.bbs-section-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 6px 0 8px;
  padding: 6px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.36);
}
.bbs-nav-btn {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 5px 10px;
  border: 1px solid rgba(123, 224, 166, 0.18);
  border-radius: 4px;
  background: transparent;
  color: rgba(207, 232, 216, 0.7);
  cursor: pointer;
  transition: background 0.14s ease, color 0.14s ease, border-color 0.14s ease;
}
.bbs-nav-btn:hover {
  background: rgba(123, 224, 166, 0.08);
  color: #eafff0;
}
.bbs-nav-btn.is-active {
  background: rgba(123, 224, 166, 0.18);
  color: #eafff0;
  border-color: #7be0a6;
  box-shadow: 0 0 0 1px rgba(123, 224, 166, 0.38) inset;
}

/* ── BBS module containers ──────────────────────────────────────────── */
.bbs-module {
  font-family: "IBM Plex Mono", "Courier New", monospace;
}
.bbs-module[hidden] { display: none; }

/* Files */
.bbs-files-layout {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: 12px;
  align-items: start;
}
.bbs-file-dirs { display: flex; flex-direction: column; gap: 4px; }
.bbs-file-dir {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 7px 10px;
  border: 1px solid rgba(123, 224, 166, 0.18);
  border-radius: 5px;
  background: transparent;
  color: inherit;
  text-align: left;
  cursor: pointer;
  font: inherit;
  font-size: 0.72rem;
  position: relative;
}
.bbs-file-dir:hover { background: rgba(123, 224, 166, 0.08); }
.bbs-file-dir.is-active {
  background: rgba(123, 224, 166, 0.18);
  border-color: #7be0a6;
  color: #eafff0;
}
.bbs-file-dir strong { color: #eafff0; font-weight: 700; }
.bbs-file-dir small { color: rgba(207, 232, 216, 0.55); font-size: 0.62rem; }
.bbs-file-dir .pill { position: absolute; top: 6px; right: 8px; font-size: 0.58rem; padding: 1px 6px; }
.bbs-file-list { display: flex; flex-direction: column; gap: 2px; }
.bbs-file-row {
  display: grid;
  grid-template-columns: minmax(220px, 1.6fr) 80px 80px 60px minmax(180px, 2fr);
  gap: 8px;
  align-items: center;
  padding: 6px 10px;
  border: 0;
  border-top: 1px solid rgba(123, 224, 166, 0.06);
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  font-size: 0.72rem;
  cursor: pointer;
}
.bbs-file-row:hover { background: rgba(123, 224, 166, 0.08); }
.bbs-file-row-head {
  background: rgba(123, 224, 166, 0.08);
  color: #b3e8c8;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.62rem;
  cursor: default;
}
.bbs-fc-name { color: #eafff0; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bbs-fc-size, .bbs-fc-date, .bbs-fc-dls { color: rgba(207, 232, 216, 0.7); }
.bbs-fc-desc { color: rgba(207, 232, 216, 0.55); font-size: var(--fs-xs); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Mail */
.bbs-mail-list { display: flex; flex-direction: column; gap: 0; }
.bbs-mail-row {
  display: grid;
  grid-template-columns: 32px 90px 110px 1fr 130px;
  gap: 8px;
  align-items: center;
  padding: 5px 10px;
  border: 0;
  border-top: 1px solid rgba(123, 224, 166, 0.06);
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  font-size: 0.72rem;
  cursor: pointer;
}
.bbs-mail-row:hover { background: rgba(123, 224, 166, 0.08); }
.bbs-mail-row.is-unread strong, .bbs-mail-row.is-unread .bbs-mc-from, .bbs-mail-row.is-unread .bbs-mc-subj { color: #eafff0; font-weight: 700; }
.bbs-mail-row-head { background: rgba(123, 224, 166, 0.08); font-weight: 700; text-transform: uppercase; font-size: 0.62rem; cursor: default; color: #b3e8c8; }
.bbs-mc-status { color: #7be0a6; }
.bbs-mc-subj { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #cfe8d8; }
.bbs-mc-from { color: #d8efe2; }
.bbs-mc-date, .bbs-mc-num { color: rgba(207, 232, 216, 0.55); }
.bbs-mail-body {
  margin: 4px 0 6px;
  padding: 10px 14px;
  background: rgba(123, 224, 166, 0.06);
  border-left: 3px solid #7be0a6;
  border-radius: 0 4px 4px 0;
  font-size: 0.78rem;
}
.bbs-mail-body pre { margin: 0 0 8px; white-space: pre-wrap; color: #d8efe2; font-family: inherit; }
.bbs-mail-composer {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.3);
}
.bbs-mail-composer .control { display: flex; flex-direction: column; gap: 3px; }
.bbs-mail-composer .control > span { font-size: 0.66rem; color: #7be0a6; }
.bbs-mail-composer input,
.bbs-mail-composer textarea {
  font-family: inherit;
  font-size: 0.78rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: #d8efe2;
  padding: 5px 8px;
  border-radius: 4px;
}
.bbs-mail-composer input:focus, .bbs-mail-composer textarea:focus { outline: none; border-color: rgba(123, 224, 166, 0.6); }

/* Games */
.bbs-games-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}
.bbs-game-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.34);
}
.bbs-game-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.bbs-game-head strong { color: #eafff0; font-size: 0.84rem; }
.bbs-game-desc { margin: 0; font-size: var(--fs-sm); color: rgba(207, 232, 216, 0.75); line-height: 1.5; }
.bbs-game-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 4px; }
.bbs-game-stage {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: stretch;
}
.bbs-game-screen {
  margin: 0;
  padding: 10px 14px;
  font-family: inherit;
  font-size: 0.78rem;
  color: #7be0a6;
  background: rgba(0, 0, 0, 0.42);
  border: 1px solid rgba(123, 224, 166, 0.28);
  border-radius: 6px;
  white-space: pre;
  overflow-x: auto;
  text-shadow: 0 0 6px rgba(123, 224, 166, 0.22);
}
.bbs-game-controls { display: flex; flex-wrap: wrap; gap: 6px; padding: 0 2px; }
.bbs-guess-input {
  padding: 5px 10px;
  border: 1px solid rgba(123, 224, 166, 0.3);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.4);
  color: #d8efe2;
  font-family: inherit;
  font-size: 0.78rem;
  width: 100px;
}

/* Sonar Hunt 6×6 grid */
.sh-grid {
  display: grid;
  grid-template-columns: repeat(6, 44px);
  gap: 4px;
  margin: 4px 0;
}
.sh-cell {
  width: 44px;
  height: 44px;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 1.1rem;
  font-weight: 800;
  background: rgba(8, 22, 38, 0.6);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: rgba(207, 232, 216, 0.8);
  cursor: pointer;
  border-radius: 4px;
  transition: background 0.14s ease, border-color 0.14s ease;
}
.sh-cell:not(:disabled):hover {
  background: rgba(123, 224, 166, 0.18);
  border-color: #7be0a6;
}
.sh-cell.is-hit { background: rgba(239, 68, 68, 0.35); border-color: #ef4444; color: #fff; }
.sh-cell.is-miss { background: rgba(255, 255, 255, 0.04); color: rgba(207, 232, 216, 0.35); }
.sh-cell.is-revealed { background: rgba(123, 224, 166, 0.18); border-color: rgba(123, 224, 166, 0.4); }

/* Art Gallery — real image cards + filter tags + submit form */
.bbs-art-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 4px;
}
.bbs-art-tag {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.7rem;
  padding: 4px 10px;
  border: 1px solid rgba(123, 224, 166, 0.18);
  border-radius: 12px;
  background: transparent;
  color: rgba(207, 232, 216, 0.7);
  cursor: pointer;
}
.bbs-art-tag:hover { background: rgba(123, 224, 166, 0.08); color: #eafff0; }
.bbs-art-tag.is-active { background: rgba(123, 224, 166, 0.2); border-color: #7be0a6; color: #eafff0; }
.bbs-art-tag small { color: rgba(207, 232, 216, 0.5); margin-left: 4px; }
.bbs-art-tag.is-active small { color: rgba(234, 255, 240, 0.7); }

.bbs-art-gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 8px;
}
.bbs-art-tile {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0;
  border: 1px solid rgba(123, 224, 166, 0.18);
  border-radius: 6px;
  overflow: hidden;
  background: rgba(8, 22, 14, 0.34);
  color: inherit;
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: border-color 0.16s ease, transform 0.16s ease;
}
.bbs-art-tile:hover { border-color: #7be0a6; transform: translateY(-1px); }
.bbs-art-tile.is-active { border-color: #7be0a6; box-shadow: 0 0 0 1px rgba(123, 224, 166, 0.35); }
.bbs-art-tile-img {
  width: 100%;
  aspect-ratio: 4 / 3;
  background: linear-gradient(135deg, rgba(13, 35, 55, 0.6), rgba(8, 22, 14, 0.6));
  display: block;
  overflow: hidden;
  position: relative;
}
.bbs-art-tile-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.bbs-art-tile-img img.failed {
  display: none;
}
.bbs-art-tile-img:has(img.failed)::after {
  content: "image unavailable";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: rgba(207, 232, 216, 0.5);
  font-size: 0.72rem;
}
.bbs-art-tile-meta {
  padding: 6px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-top: 1px solid rgba(123, 224, 166, 0.12);
}
.bbs-art-tile-meta strong { color: #eafff0; font-size: 0.76rem; }
.bbs-art-tile-meta small { color: rgba(207, 232, 216, 0.5); font-size: 0.64rem; }

/* Full viewer */
.bbs-art-viewer-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, 1fr);
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 6px;
  background: rgba(0, 0, 0, 0.32);
}
.bbs-art-viewer-img {
  width: 100%;
  max-height: 480px;
  object-fit: contain;
  background: #000;
  border-radius: 4px;
}
.bbs-art-viewer-meta { display: flex; flex-direction: column; gap: 4px; }
.bbs-art-viewer-meta strong { color: #eafff0; font-size: 0.88rem; }
.bbs-art-viewer-meta a { color: rgba(125, 211, 252, 0.85); text-decoration: none; }
.bbs-art-viewer-meta a:hover { text-decoration: underline; }

/* Submit form */
.bbs-art-submit {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.3);
}
.bbs-art-submit .control { display: flex; flex-direction: column; gap: 3px; }
.bbs-art-submit .control > span { font-size: 0.66rem; color: #7be0a6; }
.bbs-art-submit input,
.bbs-art-submit select,
.bbs-art-submit textarea {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.78rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: #d8efe2;
  padding: 5px 8px;
  border-radius: 4px;
}
.bbs-art-submit input:focus,
.bbs-art-submit textarea:focus,
.bbs-art-submit select:focus { outline: none; border-color: rgba(123, 224, 166, 0.6); }

@media (max-width: 760px) {
  .bbs-art-viewer-wrap { grid-template-columns: 1fr; }
}

/* ── BBS Chatroom ─────────────────────────────────────────────────── */
.bbs-chat-channels {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 4px;
}
.bbs-chat-channel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 6px 12px;
  border: 1px solid rgba(123, 224, 166, 0.2);
  border-radius: 6px;
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  cursor: pointer;
}
.bbs-chat-channel:hover { background: rgba(123, 224, 166, 0.08); }
.bbs-chat-channel.is-active { background: rgba(123, 224, 166, 0.18); border-color: #7be0a6; }
.bbs-chat-channel strong { color: #eafff0; font-size: 0.78rem; }
.bbs-chat-channel small { color: rgba(207, 232, 216, 0.5); font-size: 0.62rem; }
.bbs-chat-channel .pill { position: absolute; top: 6px; right: 8px; font-size: 0.58rem; padding: 1px 6px; }

.bbs-chat-section { display: flex; flex-direction: column; gap: 6px; }
.bbs-chat-log {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.78rem;
  line-height: 1.55;
  color: #cfe8d8;
  background: rgba(0, 0, 0, 0.42);
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 6px;
  padding: 10px 14px;
  max-height: 360px;
  min-height: 240px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: rgba(123, 224, 166, 0.32) transparent;
}
.bbs-chat-line { padding: 1px 0; }
.bbs-chat-time { color: rgba(207, 232, 216, 0.4); font-size: 0.7rem; }
.bbs-chat-line strong { color: #eafff0; }
.bbs-chat-line.is-action em { color: #b8f5e8; font-style: italic; }
.bbs-chat-line.is-system .bbs-chat-sys { color: #ffd66a; font-style: italic; }
.bbs-chat-line.is-whisper { color: #c4a5ff; }
.bbs-chat-line.is-whisper em { color: #d8c0ff; }
.bbs-chat-line.is-roll { color: #ffa66a; }

.bbs-chat-composer {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.34);
}
.bbs-chat-prompt {
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.8rem;
  font-weight: 700;
  color: #7be0a6;
  flex: 0 0 auto;
}
#bbs-chat-input {
  flex: 1 1 auto;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.8rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: #d8efe2;
  padding: 6px 10px;
  border-radius: 4px;
}
#bbs-chat-input:focus { outline: none; border-color: rgba(123, 224, 166, 0.6); }

/* ── BBS One-liners ──────────────────────────────────────────────── */
.bbs-oneliner-compose {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border: 1px solid rgba(123, 224, 166, 0.22);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.34);
}
#bbs-ol-text {
  flex: 1 1 auto;
  font-family: "IBM Plex Mono", "Courier New", monospace;
  font-size: 0.8rem;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid rgba(123, 224, 166, 0.22);
  color: #d8efe2;
  padding: 6px 10px;
  border-radius: 4px;
}
#bbs-ol-text:focus { outline: none; border-color: rgba(123, 224, 166, 0.6); }
.bbs-oneliner-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  font-family: "IBM Plex Mono", "Courier New", monospace;
}
.bbs-oneliner-row {
  padding: 8px 12px;
  border-top: 1px solid rgba(123, 224, 166, 0.08);
}
.bbs-oneliner-row:first-child { border-top: 0; }
.bbs-oneliner-head { display: flex; align-items: baseline; gap: 8px; }
.bbs-oneliner-head strong { color: #7be0a6; font-size: 0.78rem; }
.bbs-oneliner-text {
  margin: 2px 0 0;
  color: #d8efe2;
  font-size: 0.84rem;
  line-height: 1.5;
  font-style: italic;
}

/* ── BBS Aquarium ─────────────────────────────────────────────────────
   A small ocean scene, not a brown-trim tank. Top of the box is bright
   surface light; bottom is deep blue. Sandy floor with pebbles. */
.bbs-aq-stage {
  position: relative;
  height: 300px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(125, 211, 252, 0.18);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.05),
    inset 0 10px 30px rgba(255, 255, 255, 0.08),
    inset 0 -24px 50px rgba(0, 0, 0, 0.35),
    0 6px 18px rgba(0, 0, 0, 0.35);
  transition: filter 0.4s ease, background 0.4s ease;
  /* Sky-meets-water at the top, deep blue at the bottom */
  background: linear-gradient(180deg,
    #aae6f4 0%,
    #6ec7e6 8%,
    #3a9fcd 22%,
    #1e6c9a 50%,
    #0e4775 78%,
    #06314f 100%);
}
.bbs-aq-stage.is-dark {
  filter: brightness(0.36) saturate(0.6) hue-rotate(-8deg);
}
.bbs-aq-stage.is-dirty {
  filter: sepia(0.18) saturate(0.7) brightness(0.92);
}
.bbs-aq-stage.is-dirty.is-dark {
  filter: brightness(0.34) sepia(0.18) saturate(0.5);
}
.bbs-aq-water { position: absolute; inset: 0; }

/* Surface ripples — a soft horizontal shimmer at the top */
.bbs-aq-surface {
  position: absolute;
  top: 0; left: -10%; right: -10%;
  height: 18px;
  background:
    linear-gradient(180deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0)),
    repeating-linear-gradient(90deg,
      transparent 0, transparent 16px,
      rgba(255, 255, 255, 0.18) 16px, rgba(255, 255, 255, 0.18) 22px);
  animation: aq-ripple 9s ease-in-out infinite;
  pointer-events: none;
}
@keyframes aq-ripple {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(-22px); }
}

/* Sun rays beaming down from the surface */
.bbs-aq-ray {
  position: absolute;
  top: -10px;
  width: 90px;
  height: 78%;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.22) 0%,
    rgba(255, 255, 255, 0.10) 50%,
    rgba(255, 255, 255, 0) 100%);
  filter: blur(4px);
  transform-origin: top center;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0.85;
}
.bbs-aq-ray-1 { left: 14%; transform: rotate(-8deg);  animation: aq-ray 7s ease-in-out infinite; }
.bbs-aq-ray-2 { left: 45%; transform: rotate(-2deg);  animation: aq-ray 7s ease-in-out infinite 1.6s; }
.bbs-aq-ray-3 { left: 72%; transform: rotate(5deg);   animation: aq-ray 7s ease-in-out infinite 3.2s; }
@keyframes aq-ray {
  0%, 100% { opacity: 0.45; }
  50%      { opacity: 0.95; }
}

/* Background schools of fish drift across slowly */
.bbs-aq-school {
  position: absolute;
  height: 32px;
  pointer-events: none;
  opacity: 0.55;
}
.bbs-aq-school-1 { top: 26%; width: 220px; animation: aq-school 38s linear infinite; }
.bbs-aq-school-2 { top: 58%; width: 180px; animation: aq-school 46s linear -16s infinite reverse; opacity: 0.4; }
@keyframes aq-school {
  0%   { left: -25%; }
  100% { left: 110%; }
}

/* Honu (sea turtle) cameo — drifts left-to-right very slowly */
.bbs-aq-turtle {
  position: absolute;
  top: 38%;
  width: 78px;
  height: 50px;
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.25));
  opacity: 0.9;
  animation: aq-turtle 60s linear infinite;
  pointer-events: none;
}
@keyframes aq-turtle {
  0%   { left: -22%; top: 38%; transform: scaleX(1); }
  48%  { left: 95%;  top: 30%; transform: scaleX(1); }
  50%  { left: 95%;  top: 30%; transform: scaleX(-1); }
  98%  { left: -22%; top: 42%; transform: scaleX(-1); }
  100% { left: -22%; top: 38%; transform: scaleX(1); }
}

/* Jellyfish floats up + down slowly */
.bbs-aq-jelly {
  position: absolute;
  right: 8%;
  top: 18%;
  width: 36px;
  height: 60px;
  filter: drop-shadow(0 0 8px rgba(255, 180, 220, 0.5));
  pointer-events: none;
  animation: aq-jelly 9s ease-in-out infinite;
}
@keyframes aq-jelly {
  0%, 100% { transform: translateY(0)   scale(1, 1); }
  50%      { transform: translateY(-14px) scale(1.05, 0.92); }
}

/* Bubbles — varied sizes */
.bbs-aq-bubble {
  position: absolute;
  bottom: -10px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: radial-gradient(circle at 30% 30%,
    rgba(255, 255, 255, 0.85),
    rgba(255, 255, 255, 0.25) 60%,
    transparent 70%);
  animation: aq-bubble 7.5s linear infinite;
  pointer-events: none;
}
.bbs-aq-bubble-sm { width: 6px; height: 6px; animation-duration: 9s; }
.bbs-aq-bubble-lg { width: 14px; height: 14px; animation-duration: 6s; }
@keyframes aq-bubble {
  0%   { transform: translateY(0)    scale(0.6); opacity: 0; }
  10%  { opacity: 0.85; }
  90%  { opacity: 0.85; }
  100% { transform: translateY(-260px) scale(1.05); opacity: 0; }
}

/* Coral cluster (bottom-left) */
.bbs-aq-coral {
  position: absolute;
  bottom: 24px;
  width: 58px;
  height: 72px;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.25));
}
.bbs-aq-coral-1 { left: 6%; transform-origin: bottom center; animation: aq-coral-sway 5s ease-in-out infinite; }
@keyframes aq-coral-sway {
  0%, 100% { transform: rotate(-1.5deg); }
  50%      { transform: rotate(1.5deg); }
}

/* Anemone (bottom-right area) — waving tentacles */
.bbs-aq-anemone {
  position: absolute;
  right: 26%;
  bottom: 24px;
  width: 70px;
  height: 50px;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.25));
}
.bbs-aq-anemone-tent {
  animation: aq-anemone-wave 2.4s ease-in-out infinite;
  transform-origin: 50% 100%;
}
@keyframes aq-anemone-wave {
  0%, 100% { transform: rotate(-6deg) translateX(0); }
  50%      { transform: rotate(6deg) translateX(2px); }
}

/* Starfish resting on the sand */
.bbs-aq-starfish {
  position: absolute;
  bottom: 24px;
  right: 14%;
  width: 36px;
  height: 36px;
  pointer-events: none;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
  transform: rotate(-12deg);
}

/* Kelp — three colors, three heights, swaying at different rates */
.bbs-aq-kelp {
  position: absolute;
  bottom: 24px;
  width: 32px;
  pointer-events: none;
  transform-origin: bottom center;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.22));
}
.bbs-aq-kelp-1 { left: 32%; height: 110px; animation: aq-kelp-sway 4.4s ease-in-out infinite; }
.bbs-aq-kelp-2 { left: 60%; height: 80px;  animation: aq-kelp-sway 3.6s ease-in-out -1.2s infinite; }
.bbs-aq-kelp-3 { left: 84%; height: 130px; animation: aq-kelp-sway 5.2s ease-in-out -2.4s infinite; }
@keyframes aq-kelp-sway {
  0%, 100% { transform: rotate(-5deg); }
  50%      { transform: rotate(5deg); }
}

/* Sandy floor with pebbles */
.bbs-aq-floor {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 32px;
  background:
    linear-gradient(180deg,
      #f0d99c 0%,
      #d8b87a 40%,
      #b29560 100%);
  border-top: 2px solid #ffe9b8;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
.bbs-aq-pebble {
  position: absolute;
  bottom: 4px;
  border-radius: 50%;
  display: block;
  box-shadow: inset -1px -1px 0 rgba(0, 0, 0, 0.3), 0 1px 1px rgba(0, 0, 0, 0.25);
}
/* The fish — head drawn on the RIGHT side of the SVG so scaleX(1) faces
   right and matches the rightward-motion half of the keyframe.
   - Outer .bbs-aq-fish wrapper handles position (left/top)
   - Inner .bbs-aq-fish-flip handles the horizontal flip at the turnaround
   - .bbs-aq-fish-tail wags continuously (separate keyframe)
   Color: currentColor + a CSS-var-driven hue so 6 variants share one SVG. */
.bbs-aq-fish {
  position: absolute;
  top: 30%;
  left: -15%;
  width: 100px;
  height: 50px;
  color: hsl(var(--aq-hue, 18), 78%, 55%);
  filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.35));
  animation: aq-swim 12s ease-in-out infinite;
}
.bbs-aq-fish-flip {
  width: 100%;
  height: 100%;
  display: block;
  transform-origin: center center;
  animation: aq-flip 12s steps(1, end) infinite;
}
/* Tail wags side to side. transform-origin is on the right of the path
   (where the tail joins the body) so the wag pivots from the body. */
.bbs-aq-fish-tail {
  transform-origin: 30px 30px;
  animation: aq-tail 0.42s ease-in-out infinite;
}
@keyframes aq-swim {
  0%   { left: -18%;  top: 30%; }
  22%  { left: 18%;   top: 22%; }
  48%  { left: 88%;   top: 38%; }
  52%  { left: 88%;   top: 40%; }
  74%  { left: 30%;   top: 50%; }
  98%  { left: -18%;  top: 30%; }
  100% { left: -18%;  top: 30%; }
}
/* Flip is a discrete step that fires AT the turnaround (50%) so the fish
   abruptly faces the other way. Default scaleX(1) = facing right (matches
   the SVG where the head/eye is on the right). */
@keyframes aq-flip {
  0%, 49%   { transform: scaleX(1); }
  50%, 99%  { transform: scaleX(-1); }
  100%      { transform: scaleX(1); }
}
@keyframes aq-tail {
  0%, 100% { transform: rotate(-14deg); }
  50%      { transform: rotate(14deg); }
}

.bbs-aq-stage.is-dead .bbs-aq-fish {
  animation: none;
  top: 25%; left: 45%;
  transform: rotate(180deg);
  opacity: 0.55;
  filter: grayscale(0.7) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.35));
}
.bbs-aq-stage.is-dead .bbs-aq-fish-flip,
.bbs-aq-stage.is-dead .bbs-aq-fish-tail {
  animation: none;
}
.bbs-aq-dead-banner {
  position: absolute;
  inset: auto 0 calc(50% - 10px) 0;
  text-align: center;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.86rem;
  font-weight: 700;
  color: #ff8480;
  letter-spacing: 0.06em;
  text-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
}

.bbs-aq-stats { display: flex; flex-direction: column; gap: 5px; padding: 8px 12px; border: 1px solid rgba(123, 224, 166, 0.16); border-radius: 6px; background: rgba(8, 22, 14, 0.32); font-family: "IBM Plex Mono", monospace; font-size: 0.78rem; }
.bbs-aq-stat { display: grid; grid-template-columns: 120px 1fr 38px; gap: 8px; align-items: center; }
.bbs-aq-stat-label { color: rgba(207, 232, 216, 0.75); }
.bbs-aq-stat-bar { position: relative; height: 10px; background: rgba(123, 224, 166, 0.1); border-radius: 5px; overflow: hidden; }
.bbs-aq-stat-fill { display: block; height: 100%; background: #7be0a6; transition: width 0.4s ease, background 0.3s ease; }
.bbs-aq-stat-fill.is-mid { background: linear-gradient(90deg, #ffd66a, #ffaa5b); }
.bbs-aq-stat-fill.is-low { background: linear-gradient(90deg, #ff7575, #ff9591); }
.bbs-aq-stat-pct { color: rgba(207, 232, 216, 0.6); text-align: right; font-variant-numeric: tabular-nums; }

.bbs-aq-controls { display: flex; flex-wrap: wrap; gap: 6px; padding: 4px 0; }

.bbs-aq-log {
  padding: 8px 12px;
  border: 1px solid rgba(123, 224, 166, 0.14);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.32);
  font-family: "IBM Plex Mono", monospace;
  font-size: var(--fs-sm);
  color: rgba(207, 232, 216, 0.75);
  max-height: 140px;
  overflow-y: auto;
  scrollbar-width: thin;
}
.bbs-aq-log-line { padding: 1px 0; }

/* ── Conservation Sanctuary chrome ─────────────────────────────────── */

/* Adoption picker — grid of species cards */
.bbs-aq-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 10px;
}
.bbs-aq-picker-card {
  display: grid;
  grid-template-rows: 100px auto;
  gap: 8px;
  padding: 10px;
  border: 1px solid rgba(123, 224, 166, 0.2);
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(13, 35, 55, 0.4), rgba(8, 22, 14, 0.35));
  color: inherit;
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: border-color 0.16s ease, transform 0.16s ease, background 0.16s ease;
}
.bbs-aq-picker-card:hover {
  border-color: #7be0a6;
  transform: translateY(-2px);
  background: linear-gradient(180deg, rgba(13, 60, 80, 0.5), rgba(8, 30, 22, 0.45));
}
.bbs-aq-picker-preview {
  display: grid; place-items: center;
  background: linear-gradient(180deg, #aae6f4 0%, #3a9fcd 60%, #1e6c9a 100%);
  border-radius: 8px;
  height: 100px;
  overflow: hidden;
}
.bbs-aq-picker-preview svg { width: 80%; height: 70%; }
.bbs-aq-picker-meta { display: flex; flex-direction: column; gap: 3px; }
.bbs-aq-picker-meta strong { color: #eafff0; font-size: 0.86rem; }
.bbs-aq-picker-meta em { font-style: italic; }
.bbs-aq-picker-desc {
  margin: 4px 0;
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: rgba(207, 232, 216, 0.78);
}
.bbs-aq-picker-tags { display: flex; flex-wrap: wrap; gap: 4px; }

/* IUCN badge */
.bbs-aq-iucn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border: 1px solid;
  border-radius: 10px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.bbs-aq-tag {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 10px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.62rem;
  color: rgba(207, 232, 216, 0.7);
}

/* Pet card above the tank */
.bbs-aq-pet-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.2);
  border-radius: 10px;
  background: rgba(8, 22, 14, 0.34);
  margin-bottom: 8px;
}
.bbs-aq-pet-card-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
}
.bbs-aq-pet-card-name strong { font-size: 1.05rem; color: #eafff0; }
.bbs-aq-pet-card-name span { display: block; }
.bbs-aq-pet-card-meta { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.bbs-aq-streak,
.bbs-aq-mood {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border: 1px solid rgba(163, 185, 188, 0.22);
  border-radius: 10px;
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.64rem;
  color: rgba(207, 232, 216, 0.75);
}
.bbs-aq-pet-desc {
  margin: 2px 0 0;
  font-size: 0.78rem;
  color: rgba(207, 232, 216, 0.78);
  font-style: italic;
}

/* Badges row */
.bbs-aq-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}
.bbs-aq-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border: 1px solid rgba(255, 214, 106, 0.32);
  border-radius: 14px;
  background: rgba(255, 214, 106, 0.1);
  font-family: "IBM Plex Mono", monospace;
  font-size: 0.66rem;
  color: #ffe18a;
}
.bbs-aq-badge span { font-size: 0.84rem; }

/* Fact card */
.bbs-aq-fact {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 10px 14px;
  border-left: 3px solid #7be0a6;
  background: rgba(123, 224, 166, 0.06);
  border-radius: 0 8px 8px 0;
}
.bbs-aq-fact-text {
  font-size: 0.84rem;
  line-height: 1.55;
  color: #d8efe2;
}
.bbs-aq-fact-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
}

/* ── Per-species swim behaviour ────────────────────────────────────── */
/* Clownfish — narrow horizontal range near the anemone */
.bbs-aq-fish.is-swim-clownfish {
  animation: aq-swim-clown 7s ease-in-out infinite;
}
@keyframes aq-swim-clown {
  0%, 100% { left: 38%; top: 50%; }
  25%      { left: 52%; top: 46%; }
  49%      { left: 64%; top: 52%; }
  50%, 99% { left: 64%; top: 52%; }
  74%      { left: 52%; top: 56%; }
}
.bbs-aq-fish.is-swim-clownfish .bbs-aq-fish-flip { animation: aq-flip-fast 7s steps(1, end) infinite; }
@keyframes aq-flip-fast {
  0%, 49% { transform: scaleX(1); }
  50%, 99% { transform: scaleX(-1); }
  100% { transform: scaleX(1); }
}

/* Honu — slow, wide, low swim */
.bbs-aq-fish.is-swim-honu { animation: aq-swim 22s ease-in-out infinite; }
.bbs-aq-fish.is-swim-honu .bbs-aq-fish-flip { animation: aq-flip 22s steps(1, end) infinite; }
.bbs-aq-fish.is-swim-honu .bbs-aq-fish-tail { animation: none; }
.bbs-aq-fish.is-swim-honu { width: 130px; height: 56px; }

/* Seahorse — vertical drift in one spot */
.bbs-aq-fish.is-swim-seahorse {
  width: 70px; height: 110px;
  animation: aq-swim-seahorse 7s ease-in-out infinite;
}
.bbs-aq-fish.is-swim-seahorse .bbs-aq-fish-flip,
.bbs-aq-fish.is-swim-seahorse .bbs-aq-fish-tail { animation: none; }
@keyframes aq-swim-seahorse {
  0%, 100% { left: 45%; top: 42%; transform: rotate(-2deg); }
  50%      { left: 45%; top: 28%; transform: rotate(2deg); }
}

/* Manta — wide glide, large body */
.bbs-aq-fish.is-swim-manta {
  width: 150px; height: 60px;
  animation: aq-swim 18s ease-in-out infinite;
}
.bbs-aq-fish.is-swim-manta .bbs-aq-fish-flip { animation: aq-flip 18s steps(1, end) infinite; }
.bbs-aq-fish.is-swim-manta .bbs-aq-fish-tail { animation: none; }

/* Octopus — mostly hides bottom-left, drifts out occasionally */
.bbs-aq-fish.is-swim-octopus {
  width: 110px; height: 70px;
  animation: aq-swim-octo 16s ease-in-out infinite;
}
.bbs-aq-fish.is-swim-octopus .bbs-aq-fish-flip { animation: aq-flip 16s steps(1, end) infinite; }
@keyframes aq-swim-octo {
  0%, 5%, 95%, 100% { left: 4%; top: 48%; }  /* hides in the coral */
  35%               { left: 30%; top: 38%; }
  55%               { left: 55%; top: 44%; }
  75%               { left: 8%; top: 46%; }
}

/* Pufferfish — slow rounded drift, idle-floats */
.bbs-aq-fish.is-swim-pufferfish {
  width: 100px; height: 60px;
  animation: aq-swim 16s ease-in-out infinite;
}
.bbs-aq-fish.is-swim-pufferfish .bbs-aq-fish-flip { animation: aq-flip 16s steps(1, end) infinite; }
.bbs-aq-fish.is-swim-pufferfish .bbs-aq-fish-tail { animation: aq-tail 0.9s ease-in-out infinite; }

/* Jellyfish — vertical bob with bell pulse */
.bbs-aq-fish.is-swim-jellyfish {
  width: 110px; height: 80px;
  animation: aq-swim-jelly 9s ease-in-out infinite;
}
.bbs-aq-fish.is-swim-jellyfish .bbs-aq-fish-flip { animation: aq-jelly-pulse 2.6s ease-in-out infinite; }
.bbs-aq-fish.is-swim-jellyfish .bbs-aq-fish-tail { animation: aq-tail 1.4s ease-in-out infinite; }
@keyframes aq-swim-jelly {
  0%, 100% { left: 50%; top: 30%; }
  50%      { left: 50%; top: 10%; }
}
@keyframes aq-jelly-pulse {
  0%, 100% { transform: scale(1, 1); }
  50%      { transform: scale(1.08, 0.92); }
}

/* Tropical (default) — keeps the original animations */
.bbs-aq-fish.is-swim-tropical { animation: aq-swim 12s ease-in-out infinite; }

/* ═══════════════════════════════════════════════════════════════════════
   ╔═════════════════════════════════════════════════════════════════════╗
   ║  OCEAN-THEMED BBS — page-wide ocean palette                         ║
   ║  Scoped to .bbs-page.is-ocean-theme so other BBS pages can stay     ║
   ║  green-phosphor if anyone ever wants to revert.                     ║
   ╚═════════════════════════════════════════════════════════════════════╝
   ═══════════════════════════════════════════════════════════════════════ */

.bbs-page.is-ocean-theme {
  /* Ocean palette — used by everything inside the BBS */
  --aq-deep:     #0e3a5f;    /* dark teal — primary text */
  --aq-mid:      #1d6798;    /* mid blue — secondary text */
  --aq-pale:     #4a91bc;    /* mid wave — muted text */
  --aq-foam:     #eaf6fa;    /* foam white — card bg */
  --aq-foam-2:   #d8ebf2;    /* deeper foam — header bands */
  --aq-sand:     #f5ecd4;    /* warm sand — accent */
  --aq-coral:    #ff8a7a;    /* coral pink — primary action */
  --aq-coral-d:  #e36652;    /* deeper coral — hover */
  --aq-kelp:     #3eaa6c;    /* kelp green — success */
  --aq-amber:    #f0b85c;    /* amber — warning */
  --aq-red:      #d65555;    /* alert red */

  color: var(--aq-deep);
}

/* ASCII banner — recolour to teal-on-foam instead of phosphor-on-deep-green */
.bbs-page.is-ocean-theme .bbs-banner {
  color: var(--aq-deep);
  background: linear-gradient(180deg, #f0f8fb 0%, #e2eff5 100%);
  border: 1px solid rgba(43, 110, 158, 0.25);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
  font-size: 0.7rem;
  line-height: 1.35;
  padding: 10px 14px;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.6);
}

/* Section nav — ocean pill buttons instead of phosphor terminal buttons */
.bbs-page.is-ocean-theme .bbs-section-nav {
  background: linear-gradient(180deg, #ffffff 0%, #f4f9fb 100%);
  border: 1px solid rgba(43, 110, 158, 0.22);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset;
  padding: 8px;
  gap: 6px;
  border-radius: 10px;
}
.bbs-page.is-ocean-theme .bbs-nav-btn {
  font-family: "JetBrains Mono", "IBM Plex Mono", "Courier New", monospace;
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 6px 12px;
  border: 1px solid rgba(43, 110, 158, 0.22);
  border-radius: 8px;
  background: #fff;
  color: var(--aq-mid);
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
}
.bbs-page.is-ocean-theme .bbs-nav-btn:hover {
  background: var(--aq-foam);
  color: var(--aq-deep);
  border-color: var(--aq-mid);
  transform: translateY(-1px);
}
.bbs-page.is-ocean-theme .bbs-nav-btn.is-active {
  background: linear-gradient(180deg, #2b6e9e 0%, #1d6798 100%);
  color: #fff;
  border-color: #1d6798;
  box-shadow: 0 2px 8px rgba(14, 58, 95, 0.25);
}

/* Page heads inside each module — softer, ocean-themed h2 */
.bbs-page.is-ocean-theme .bbs-page-head {
  background: linear-gradient(180deg, #ffffff 0%, var(--aq-foam) 100%);
  border: 1px solid rgba(43, 110, 158, 0.18);
  border-radius: 10px;
  padding: 12px 18px;
  margin: 0 0 10px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset;
}
.bbs-page.is-ocean-theme .bbs-page-head h2 {
  font-family: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
  text-transform: none;
  letter-spacing: -0.01em;
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--aq-deep);
  margin: 0;
  text-shadow: none;
}
.bbs-page.is-ocean-theme .bbs-page-head .eyebrow {
  color: var(--aq-mid);
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.bbs-page.is-ocean-theme .bbs-page-head .muted,
.bbs-page.is-ocean-theme .bbs-page-head p {
  color: var(--aq-mid);
  font-size: var(--fs-base);
}

/* Section dividers — dropdown the dashed phosphor line, use foam underline */
.bbs-page.is-ocean-theme .bbs-section {
  border-top: 1px solid rgba(43, 110, 158, 0.12);
  padding-top: 10px;
  margin-bottom: 14px;
}
.bbs-page.is-ocean-theme .bbs-section:first-of-type {
  border-top: none;
  padding-top: 0;
}

/* Section titles — drop the `— [ HEADER ] —` phosphor framing */
.bbs-page.is-ocean-theme .bbs-section-title {
  font-family: "Inter", "Segoe UI", sans-serif;
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--aq-deep);
  text-shadow: none;
  margin: 0 0 8px;
}

/* Module-wide text colour + font — sans for body, mono kept for tables/logs */
.bbs-page.is-ocean-theme .bbs-module {
  font-family: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
  color: var(--aq-deep);
}

/* Keep monospace where it earns the BBS feel: file lists, who-online,
   stats tables, log lines, message-board columns. */
.bbs-page.is-ocean-theme .bbs-board-list,
.bbs-page.is-ocean-theme .bbs-file-list,
.bbs-page.is-ocean-theme .bbs-thread-list,
.bbs-page.is-ocean-theme .bbs-thread-view,
.bbs-page.is-ocean-theme .bbs-mail-list,
.bbs-page.is-ocean-theme .bbs-games-list,
.bbs-page.is-ocean-theme .bbs-whoson-list,
.bbs-page.is-ocean-theme .bbs-stats-grid,
.bbs-page.is-ocean-theme .bbs-bulletin-list,
.bbs-page.is-ocean-theme .bbs-game-stage,
.bbs-page.is-ocean-theme .bbs-chat-thread,
.bbs-page.is-ocean-theme .bbs-oneliner-list,
.bbs-page.is-ocean-theme .bbs-aq-log {
  font-family: "JetBrains Mono", "IBM Plex Mono", "Courier New", monospace;
}

/* Body text colour throughout the BBS — readable on light bg */
.bbs-page.is-ocean-theme .bbs-module .muted,
.bbs-page.is-ocean-theme .bbs-module .muted.small {
  color: var(--aq-mid);
}

/* Buttons inside the BBS that aren't already ocean-styled — soften them */
.bbs-page.is-ocean-theme .bbs-module .button:not(.bbs-aq-btn) {
  border-color: rgba(43, 110, 158, 0.25);
}

/* ── Game cards (ocean theme, icon-led) ──────────────────────────── */
.bbs-page.is-ocean-theme .bbs-game-card {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 12px;
  padding: 12px;
  background: #fff;
  border: 1px solid rgba(43, 110, 158, 0.18);
  border-radius: 12px;
  color: var(--aq-deep);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset, 0 2px 8px rgba(14, 58, 95, 0.06);
  transition: transform 0.14s ease, box-shadow 0.14s ease, border-color 0.14s ease;
}
.bbs-page.is-ocean-theme .bbs-game-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 18px rgba(14, 58, 95, 0.16);
  border-color: var(--aq-mid);
}
.bbs-page.is-ocean-theme .bbs-game-icon {
  width: 56px;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bbs-page.is-ocean-theme .bbs-game-icon svg {
  width: 56px;
  height: 56px;
  display: block;
}
.bbs-page.is-ocean-theme .bbs-game-body {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
}
.bbs-page.is-ocean-theme .bbs-game-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.bbs-page.is-ocean-theme .bbs-game-head strong {
  color: var(--aq-deep);
  font-size: 0.96rem;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.bbs-page.is-ocean-theme .bbs-game-genre {
  font-size: 0.66rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--aq-pale);
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--aq-foam);
  flex-shrink: 0;
}
.bbs-page.is-ocean-theme .bbs-game-desc {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--aq-mid);
}
.bbs-page.is-ocean-theme .bbs-game-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 4px;
}

/* ═══════════════════════════════════════════════════════════════════════
   ╔═════════════════════════════════════════════════════════════════════╗
   ║  BBS LAYOUT REDESIGN — compact header + sidebar nav + lobby hub     ║
   ║  Replaces the ASCII banner + 12-button top nav with a sidebar-and-  ║
   ║  main split, plus a new Lobby module that previews all sections.   ║
   ╚═════════════════════════════════════════════════════════════════════╝
   ═══════════════════════════════════════════════════════════════════════ */

/* Hide the legacy ASCII banner + top nav inside the ocean-themed BBS — the
   redesign uses the new .bbs-header + .bbs-sidebar instead. The HTML is
   left in place so a future toggle could revert; we just don't show them. */
.bbs-page.is-ocean-theme .bbs-banner,
.bbs-page.is-ocean-theme .bbs-section-nav {
  display: none;
}

/* ── Header bar ──────────────────────────────────────────────────── */
.bbs-page.is-ocean-theme .bbs-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 18px;
  margin: 0 0 12px;
  border-radius: 12px;
  background: linear-gradient(180deg, #2b6e9e 0%, #1d6798 100%);
  color: #fff;
  box-shadow: 0 2px 10px rgba(14, 58, 95, 0.22);
  flex-wrap: wrap;
}
.bbs-header-identity {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.bbs-header-mark {
  width: 38px;
  height: 38px;
  flex-shrink: 0;
}
.bbs-header-mark svg { width: 100%; height: 100%; display: block; }
.bbs-header-text {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
.bbs-header-title {
  margin: 0;
  font-family: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: -0.01em;
  text-transform: none;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
}
.bbs-header-tagline {
  margin: 0;
  font-size: 0.78rem;
  color: rgba(225, 240, 252, 0.78);
  font-weight: 500;
}
.bbs-header-stats {
  display: flex;
  gap: 6px;
  flex-shrink: 0;
}
.bbs-header-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 4px 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.18);
  min-width: 60px;
}
.bbs-header-stat-value {
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  font-size: 1rem;
  font-weight: 700;
  color: #fff;
  line-height: 1.1;
}
.bbs-header-stat-label {
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgba(225, 240, 252, 0.72);
  font-weight: 600;
  margin-top: 1px;
}

/* ── Two-column layout (sidebar + main) ──────────────────────────── */
.bbs-page.is-ocean-theme .bbs-layout {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 14px;
  align-items: start;
}
@media (max-width: 880px) {
  .bbs-page.is-ocean-theme .bbs-layout {
    grid-template-columns: 1fr;
  }
}

/* ── Sidebar nav ─────────────────────────────────────────────────── */
.bbs-page.is-ocean-theme .bbs-sidebar {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 8px;
  background: linear-gradient(180deg, #ffffff 0%, #f4f9fb 100%);
  border: 1px solid rgba(43, 110, 158, 0.18);
  border-radius: 12px;
  box-shadow: 0 2px 10px rgba(14, 58, 95, 0.06);
  position: sticky;
  top: 8px;
  align-self: start;
}
@media (max-width: 880px) {
  .bbs-page.is-ocean-theme .bbs-sidebar {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    padding: 8px;
  }
  .bbs-page.is-ocean-theme .bbs-side-group {
    display: contents;     /* let buttons flow into the parent row */
  }
  .bbs-page.is-ocean-theme .bbs-side-group-label { display: none; }
}
.bbs-side-group {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 10px;
  margin-top: 4px;
  border-top: 1px dashed rgba(74, 145, 188, 0.2);
}
.bbs-side-group:first-of-type {
  border-top: none;
  padding-top: 4px;
  margin-top: 0;
}
.bbs-side-group-label {
  display: block;
  padding: 0 8px 4px;
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--aq-pale);
  font-weight: 600;
}
.bbs-side-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--aq-deep);
  font-family: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, transform 0.1s ease;
  text-align: left;
  width: 100%;
  position: relative;
}
.bbs-side-btn:hover {
  background: var(--aq-foam);
  border-color: rgba(74, 145, 188, 0.28);
}
.bbs-side-btn.is-active {
  background: linear-gradient(180deg, #2b6e9e 0%, #1d6798 100%);
  border-color: #1d6798;
  color: #fff;
  box-shadow: 0 2px 6px rgba(14, 58, 95, 0.2);
}
.bbs-side-icon {
  font-size: 1.05rem;
  line-height: 1;
  flex-shrink: 0;
  width: 20px;
  text-align: center;
}
.bbs-side-label {
  flex: 1;
  white-space: nowrap;
}
.bbs-side-badge {
  background: #d65555;
  color: #fff;
  font-size: 0.66rem;
  font-weight: 700;
  padding: 1px 7px;
  border-radius: 999px;
  line-height: 1.4;
}

/* ── Main content area ───────────────────────────────────────────── */
.bbs-page.is-ocean-theme .bbs-main {
  min-width: 0;
}

/* ── Lobby module (hub view) ─────────────────────────────────────── */
.bbs-lobby {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.bbs-lobby-hero {
  padding: 14px 18px;
  background: linear-gradient(180deg, #ffffff 0%, var(--aq-foam) 100%);
  border: 1px solid rgba(43, 110, 158, 0.18);
  border-radius: 12px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset;
}
.bbs-lobby-hero h3 {
  margin: 0 0 4px;
  font-family: "Inter", "Segoe UI", sans-serif;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  color: var(--aq-deep);
}
.bbs-lobby-hero p {
  margin: 0;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--aq-mid);
}
.bbs-lobby-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 10px;
}
.bbs-lobby-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 12px 14px;
  border: 1px solid rgba(43, 110, 158, 0.18);
  border-radius: 10px;
  background: #fff;
  color: var(--aq-deep);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.7) inset, 0 2px 6px rgba(14, 58, 95, 0.04);
}
.bbs-lobby-card:hover {
  transform: translateY(-2px);
  border-color: var(--aq-mid);
  box-shadow: 0 6px 16px rgba(14, 58, 95, 0.14);
}
.bbs-lobby-card-icon {
  font-size: 1.5rem;
  line-height: 1;
  margin-bottom: 4px;
}
.bbs-lobby-card-title {
  font-size: 0.92rem;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.bbs-lobby-card-sub {
  font-size: 0.76rem;
  color: var(--aq-mid);
  line-height: 1.4;
}

/* ═══════════════════════════════════════════════════════════════════════
   ╔═════════════════════════════════════════════════════════════════════╗
   ║  OCEAN-THEMED SANCTUARY MODULE                                      ║
   ║  Overrides the BBS phosphor chrome with a readable ocean palette    ║
   ║  scoped to [data-bbs-module="aquarium"].is-ocean-theme              ║
   ╚═════════════════════════════════════════════════════════════════════╝
   ═══════════════════════════════════════════════════════════════════════ */

[data-bbs-module="aquarium"].is-ocean-theme {
  /* Palette inherits from .bbs-page.is-ocean-theme — defined globally above */
  color: var(--aq-deep);
  font-family: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, sans-serif;
  /* No more big outer padding/border — the page's ocean chrome handles it */
}

/* Drop the dashed dividers + green phosphor titles inside the sanctuary */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-section {
  border-top: none;
  padding-top: 0;
  margin-bottom: 0;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-section-title {
  display: none;     /* legacy titles — the new .bbs-aq-card-head replaces them */
}

/* ── Hero header (compact inline row — keeps the tank above the fold) ─ */
.bbs-aq-hero {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 16px;
  border-radius: 10px;
  background: linear-gradient(180deg, #2b6e9e 0%, #1d6798 100%);
  color: #fff;
  margin: 0 0 10px;
  box-shadow: 0 2px 6px rgba(14, 58, 95, 0.18);
}
.bbs-aq-hero-left {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.bbs-aq-title {
  margin: 0;
  font-family: inherit;
  font-weight: 700;
  font-size: 1.08rem;
  letter-spacing: -0.01em;
  text-transform: none;
  color: #fff;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.18);
}
.bbs-aq-kicker {
  margin: 0;
  font-size: 0.72rem;
  color: rgba(220, 240, 250, 0.82);
  font-weight: 500;
  letter-spacing: 0.005em;
}
/* Collapsible "About" details — keeps the description discoverable but folded by default */
.bbs-aq-hero-more {
  flex-shrink: 0;
  font-size: 0.78rem;
  max-width: 50%;
}
.bbs-aq-hero-more summary {
  cursor: pointer;
  padding: 4px 10px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: rgba(240, 248, 252, 0.95);
  font-weight: 600;
  font-size: var(--fs-sm);
  list-style: none;
  user-select: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.bbs-aq-hero-more summary::-webkit-details-marker { display: none; }
.bbs-aq-hero-more summary:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.5);
}
.bbs-aq-hero-more[open] summary {
  background: rgba(255, 255, 255, 0.22);
  border-color: rgba(255, 255, 255, 0.5);
}
.bbs-aq-hero-more p {
  position: absolute;
  margin-top: 8px;
  max-width: 520px;
  padding: 12px 16px;
  background: #fff;
  color: var(--aq-deep);
  border: 1px solid rgba(43, 110, 158, 0.22);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(14, 58, 95, 0.18);
  font-size: var(--fs-base);
  line-height: 1.5;
  z-index: 5;
  right: 22px;
}

/* ── Card chrome (replaces dashed BBS sections) ────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-card {
  background: #fff;
  border: 1px solid rgba(43, 110, 158, 0.15);
  border-radius: 14px;
  padding: 16px 20px 18px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.8) inset, 0 2px 10px rgba(14, 58, 95, 0.06);
  color: var(--aq-deep);
}
.bbs-aq-card-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 12px;
  padding: 0 0 10px;
  border-bottom: 1px solid rgba(74, 145, 188, 0.18);
}
.bbs-aq-card-title {
  margin: 0;
  font-family: inherit;
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--aq-deep);
  text-shadow: none;
}
.bbs-aq-card-sub {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.4;
  color: var(--aq-mid);
}

/* Grid layout: tank full-width, then care + stats side-by-side,
   then fact + log side-by-side. Stacks on narrow viewports. */
.bbs-aq-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: 14px;
}
.bbs-aq-card-tank { grid-column: 1 / -1; }
.bbs-aq-card-care { grid-column: 1; }
.bbs-aq-card-stats { grid-column: 2; }
.bbs-aq-card-fact { grid-column: 1; }
.bbs-aq-card-log { grid-column: 2; }
@media (max-width: 880px) {
  .bbs-aq-grid { grid-template-columns: 1fr; }
  .bbs-aq-card-tank,
  .bbs-aq-card-care,
  .bbs-aq-card-stats,
  .bbs-aq-card-fact,
  .bbs-aq-card-log { grid-column: 1; }
}

/* ── Bigger observation tank ──────────────────────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stage {
  height: 460px;
  border-radius: 14px;
  border: 1px solid rgba(43, 110, 158, 0.28);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.6) inset,
    inset 0 14px 36px rgba(255, 255, 255, 0.18),
    inset 0 -28px 60px rgba(0, 0, 0, 0.32),
    0 8px 28px rgba(14, 58, 95, 0.18);
}

/* Habitat-specific tank backgrounds — applied via .is-habitat-* class */
.bbs-aq-stage.is-habitat-reef {
  background: linear-gradient(180deg,
    #aae6f4 0%, #6ec7e6 8%, #3a9fcd 22%,
    #1e6c9a 50%, #0e4775 78%, #06314f 100%);
}
.bbs-aq-stage.is-habitat-open {
  background: linear-gradient(180deg,
    #9ad8e8 0%, #5cb2cc 8%, #2c8eb8 22%,
    #1a78a8 45%, #0c5380 70%, #062c4d 100%);
}
.bbs-aq-stage.is-habitat-kelp {
  background: linear-gradient(180deg,
    #cae7d2 0%, #9bccae 8%, #6ba788 22%,
    #487a5e 50%, #1d533a 78%, #08362a 100%);
}

/* Selected pet ring — subtle glow without disrupting the swim animation */
.bbs-aq-fish.is-selected {
  filter: drop-shadow(0 0 6px rgba(255, 233, 130, 0.85)) drop-shadow(0 0 14px rgba(255, 200, 80, 0.5));
}

/* Habitat-specific floor textures */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-floor-reef {
  background: linear-gradient(180deg, rgba(238, 218, 184, 0.6) 0%, rgba(220, 195, 152, 0.85) 100%);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-floor-open {
  background: linear-gradient(180deg, rgba(8, 32, 52, 0.5) 0%, rgba(4, 16, 32, 0.9) 100%);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-floor-kelp {
  background: linear-gradient(180deg, rgba(108, 110, 100, 0.6) 0%, rgba(76, 84, 72, 0.92) 100%);
}
@media (min-width: 1240px) {
  [data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stage {
    height: 520px;
  }
}

/* ── Pet info strip (single row of chips between the tank head + tank) ── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-pet-card {
  background: transparent;
  border: none;
  padding: 0;
  margin: 0 0 8px;
  color: var(--aq-deep);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-pet-card-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-scientific {
  font-family: inherit;
  font-size: var(--fs-sm);
  padding: 3px 10px;
  color: var(--aq-pale);
  font-style: italic;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-scientific em {
  font-style: italic;
}

/* Pills inside the pet card (IUCN, streak, mood) — light style */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-iucn,
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-streak,
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-mood {
  font-family: inherit;
  font-size: 0.72rem;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid rgba(74, 145, 188, 0.32);
  background: #fff;
  color: var(--aq-mid);
  font-weight: 600;
  letter-spacing: 0;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-iucn {
  /* inline color comes from the JS, overrides border + bg */
  font-weight: 700;
}

/* ── Care buttons — chunky, readable, ocean palette ──────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-controls {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px;
}
.bbs-aq-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border: 1px solid rgba(43, 110, 158, 0.25);
  background: #fff;
  border-radius: 10px;
  color: var(--aq-deep);
  font-family: inherit;
  font-size: 0.88rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease, box-shadow 0.15s ease;
  text-align: left;
}
.bbs-aq-btn:hover {
  background: var(--aq-foam);
  border-color: var(--aq-mid);
  box-shadow: 0 3px 8px rgba(43, 110, 158, 0.14);
  transform: translateY(-1px);
}
.bbs-aq-btn:active { transform: translateY(0); }
.bbs-aq-btn-icon { font-size: 1.2rem; line-height: 1; }
.bbs-aq-btn-primary {
  background: linear-gradient(180deg, #2b6e9e 0%, #1d6798 100%);
  border-color: #1d6798;
  color: #fff;
}
.bbs-aq-btn-primary:hover {
  background: linear-gradient(180deg, #3a85b8 0%, #2278a8 100%);
  color: #fff;
}
.bbs-aq-btn-quiet {
  background: var(--aq-foam-2);
  color: var(--aq-mid);
  border-color: rgba(74, 145, 188, 0.32);
}

/* ── Stat bars — readable foam-on-deep ───────────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stats {
  background: transparent;
  border: none;
  padding: 0;
  font-family: inherit;
  font-size: 0.86rem;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat {
  grid-template-columns: 100px 1fr 38px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-label {
  color: var(--aq-deep);
  font-weight: 600;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-bar {
  height: 12px;
  background: rgba(43, 110, 158, 0.12);
  border-radius: 6px;
  border: 1px solid rgba(43, 110, 158, 0.18);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-fill {
  background: linear-gradient(90deg, #3eaa6c, #4ec48a);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-fill.is-mid {
  background: linear-gradient(90deg, var(--aq-amber), #f4ca6c);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-fill.is-low {
  background: linear-gradient(90deg, var(--aq-coral), #ff9a7a);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-stat-pct {
  color: var(--aq-mid);
  font-weight: 600;
}

/* ── Badges row — amber chips on foam ────────────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-badges {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed rgba(74, 145, 188, 0.22);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-badge {
  background: linear-gradient(180deg, #fff5dc, #ffe9b8);
  border: 1px solid rgba(214, 162, 60, 0.4);
  color: #8c5a18;
  font-family: inherit;
  font-weight: 600;
  font-size: var(--fs-sm);
  padding: 4px 10px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-empty-badges {
  font-size: 0.78rem;
  color: var(--aq-pale);
  font-style: italic;
}

/* ── Field guide (rotating fact card) ────────────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-fact {
  background: linear-gradient(180deg, #f5ecd4 0%, #f9f1de 100%);
  border: 1px solid rgba(206, 168, 90, 0.32);
  border-left: 4px solid var(--aq-coral);
  border-radius: 0 10px 10px 0;
  padding: 14px 18px;
  color: #5b3f1a;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-fact-text {
  font-size: 0.94rem;
  line-height: 1.55;
  color: #4a3010;
  font-weight: 500;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-fact-meta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed rgba(206, 168, 90, 0.4);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-fact-source {
  font-size: var(--fs-sm);
  color: #8c6a30;
  font-style: italic;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-fact em { font-style: italic; }

/* ── Sanctuary log ───────────────────────────────────────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-log {
  background: var(--aq-foam);
  border: 1px solid rgba(74, 145, 188, 0.22);
  border-radius: 10px;
  padding: 10px 14px;
  font-family: "JetBrains Mono", "IBM Plex Mono", monospace;
  font-size: 0.78rem;
  color: var(--aq-mid);
  max-height: 200px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-log-line {
  padding: 2px 0;
  border-bottom: 1px dotted rgba(74, 145, 188, 0.14);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-log-line:last-child {
  border-bottom: none;
}

/* ── Adoption picker — light cards with ocean preview ────────────── */
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker {
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 14px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-card {
  background: #fff;
  border: 1px solid rgba(43, 110, 158, 0.2);
  color: var(--aq-deep);
  padding: 12px;
  grid-template-rows: 130px auto;
  font-family: inherit;
  box-shadow: 0 2px 10px rgba(14, 58, 95, 0.06);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-card:hover {
  background: var(--aq-foam);
  border-color: var(--aq-mid);
  transform: translateY(-3px);
  box-shadow: 0 8px 22px rgba(14, 58, 95, 0.18);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-preview {
  height: 130px;
  border-radius: 10px;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-meta strong {
  color: var(--aq-deep);
  font-size: var(--fs-md);
  font-weight: 700;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-meta em {
  color: var(--aq-pale);
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-picker-desc {
  color: var(--aq-mid);
  font-size: 0.78rem;
}
[data-bbs-module="aquarium"].is-ocean-theme .bbs-aq-tag {
  font-family: inherit;
  color: var(--aq-mid);
  background: var(--aq-foam-2);
  border-color: rgba(74, 145, 188, 0.32);
  font-size: 0.7rem;
}

/* ── Habitat picker (3 big habitat cards) ─────────────────────────── */
.bbs-aq-habitat-picker {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 14px;
}
.bbs-aq-habitat-card {
  display: grid;
  grid-template-rows: 160px auto;
  gap: 12px;
  padding: 12px;
  border: 1px solid rgba(43, 110, 158, 0.2);
  border-radius: 12px;
  background: #fff;
  color: inherit;
  text-align: left;
  font: inherit;
  cursor: pointer;
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
  box-shadow: 0 2px 10px rgba(14, 58, 95, 0.06);
}
.bbs-aq-habitat-card:hover {
  transform: translateY(-3px);
  border-color: var(--aq-mid);
  box-shadow: 0 8px 22px rgba(14, 58, 95, 0.18);
}
.bbs-aq-habitat-preview {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  /* Inline gradient is applied via JS (each habitat has its own palette) */
}
.bbs-aq-habitat-preview-fish {
  position: absolute;
  width: 40px;
  height: 18px;
  animation: aq-swim 14s ease-in-out infinite;
}
.bbs-aq-habitat-preview-fish:nth-child(2) { animation-delay: -4s; animation-duration: 16s; }
.bbs-aq-habitat-preview-fish:nth-child(3) { animation-delay: -8s; animation-duration: 18s; }
.bbs-aq-habitat-meta {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.bbs-aq-habitat-meta strong {
  color: var(--aq-deep);
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: -0.005em;
}
.bbs-aq-habitat-meta p {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--aq-mid);
}
.bbs-aq-habitat-species {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 4px;
}
.bbs-aq-habitat-species .bbs-aq-tag {
  border-radius: 999px;
  padding: 2px 8px;
  font-size: 0.66rem;
  background: #fff;
  font-weight: 600;
}

/* ── Picker actions strip (Back to habitat picker) ────────────────── */
.bbs-aq-picker-actions {
  display: flex;
  justify-content: flex-start;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed rgba(74, 145, 188, 0.22);
}

/* ── Empty picker text (all species adopted) ──────────────────────── */
.bbs-aq-empty-picker {
  margin: 0;
  padding: 20px;
  text-align: center;
  font-style: italic;
  color: var(--aq-mid);
}

/* ── Roster strip — chip per adopted pet ──────────────────────────── */
.bbs-aq-roster {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px dashed rgba(74, 145, 188, 0.2);
}
.bbs-aq-roster-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 8px;
  border: 1px solid rgba(43, 110, 158, 0.25);
  border-radius: 999px;
  background: #fff;
  color: var(--aq-deep);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease, transform 0.1s ease;
}
.bbs-aq-roster-chip:hover {
  background: var(--aq-foam);
  border-color: var(--aq-mid);
  transform: translateY(-1px);
}
.bbs-aq-roster-chip.is-selected {
  background: linear-gradient(180deg, #fff5dc 0%, #ffe9b8 100%);
  border-color: rgba(214, 162, 60, 0.55);
  box-shadow: 0 0 0 2px rgba(255, 214, 106, 0.32);
}
.bbs-aq-roster-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 16px;
  flex-shrink: 0;
}
.bbs-aq-roster-name {
  white-space: nowrap;
}
.bbs-aq-roster-iucn {
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding-left: 4px;
  border-left: 1px solid rgba(43, 110, 158, 0.18);
  margin-left: 2px;
}
.bbs-aq-roster-release {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: rgba(214, 85, 85, 0.12);
  color: #b8463a;
  font-size: var(--fs-sm);
  font-weight: 700;
  margin-left: 2px;
  transition: background 0.14s ease, color 0.14s ease;
}
.bbs-aq-roster-release:hover {
  background: #d65555;
  color: #fff;
}
.bbs-aq-roster-add {
  padding: 4px 12px;
  border: 1px dashed rgba(43, 110, 158, 0.35);
  border-radius: 999px;
  background: transparent;
  color: var(--aq-mid);
  font: inherit;
  font-size: 0.76rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.14s ease, border-color 0.14s ease;
}
.bbs-aq-roster-add:hover {
  background: var(--aq-foam);
  border-color: var(--aq-mid);
  border-style: solid;
}
.bbs-aq-roster-full {
  padding: 4px 12px;
  font-size: var(--fs-sm);
  font-style: italic;
  color: var(--aq-pale);
}
.bbs-aq-pet-count,
.bbs-aq-banner-sub {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 10px;
  font-family: inherit;
  font-size: 0.66rem;
  font-weight: 600;
  color: var(--aq-pale);
  border: 1px solid rgba(74, 145, 188, 0.22);
  margin-left: 6px;
}

/* Polls */
.bbs-polls-list { display: flex; flex-direction: column; gap: 12px; }
.bbs-poll-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid rgba(123, 224, 166, 0.16);
  border-radius: 6px;
  background: rgba(8, 22, 14, 0.34);
}
.bbs-poll-head { display: flex; flex-direction: column; gap: 2px; }
.bbs-poll-head strong { font-size: 0.84rem; color: #eafff0; }
.bbs-poll-opts { display: flex; flex-direction: column; gap: 4px; }
.bbs-poll-opt {
  display: grid;
  grid-template-columns: minmax(180px, 1.4fr) minmax(120px, 2fr) 90px;
  gap: 10px;
  align-items: center;
  padding: 5px 10px;
  border: 1px solid rgba(123, 224, 166, 0.1);
  border-radius: 4px;
  background: transparent;
  color: inherit;
  text-align: left;
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
}
.bbs-poll-opt:hover { background: rgba(123, 224, 166, 0.06); border-color: rgba(123, 224, 166, 0.3); }
.bbs-poll-opt.is-mine { background: rgba(123, 224, 166, 0.14); border-color: #7be0a6; }
.bbs-poll-opt-bar {
  position: relative;
  height: 8px;
  border-radius: 4px;
  background: rgba(123, 224, 166, 0.1);
  overflow: hidden;
}
.bbs-poll-opt-fill {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, #7be0a6, rgba(123, 224, 166, 0.4));
  transition: width 0.3s ease;
}
.bbs-poll-opt-count { color: rgba(207, 232, 216, 0.7); text-align: right; font-size: 0.7rem; font-variant-numeric: tabular-nums; }
.bbs-poll-opt-label { color: #d8efe2; }
.bbs-poll-opt.is-mine .bbs-poll-opt-label { color: #eafff0; font-weight: 700; }

/* Who's On */
.bbs-whoson-list { display: flex; flex-direction: column; }
.bbs-whoson-row {
  display: grid;
  grid-template-columns: 130px minmax(140px, 1.3fr) 50px minmax(180px, 2fr) 70px;
  gap: 10px;
  align-items: center;
  padding: 5px 10px;
  border-top: 1px solid rgba(123, 224, 166, 0.06);
  font-size: var(--fs-sm);
  color: rgba(207, 232, 216, 0.8);
}
.bbs-whoson-row-head { background: rgba(123, 224, 166, 0.08); color: #b3e8c8; font-weight: 700; text-transform: uppercase; font-size: 0.62rem; }
.bbs-whoson-row strong { color: #eafff0; }

/* Bulletins */
.bbs-bulletins-list { display: flex; flex-direction: column; gap: 10px; }
.bbs-bulletin {
  padding: 10px 14px;
  border-left: 3px solid rgba(123, 224, 166, 0.4);
  background: rgba(8, 22, 14, 0.34);
  border-radius: 0 6px 6px 0;
}
.bbs-bulletin.is-sysop { border-left-color: #e8ff7a; background: rgba(232, 255, 122, 0.06); }
.bbs-bulletin-head { display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; margin-bottom: 4px; }
.bbs-bulletin-num { color: #7be0a6; font-size: 0.7rem; font-weight: 700; }
.bbs-bulletin.is-sysop .bbs-bulletin-num { color: #e8ff7a; }
.bbs-bulletin-head strong { color: #eafff0; font-size: var(--fs-base); }
.bbs-bulletin-body { margin: 0; line-height: 1.6; color: #d8efe2; font-size: 0.78rem; white-space: pre-wrap; }

/* Stats */
.bbs-stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 8px;
}
.bbs-stats-top { display: flex; flex-direction: column; }
.bbs-stats-top-row {
  display: grid;
  grid-template-columns: 60px 1fr 80px;
  gap: 8px;
  padding: 5px 10px;
  border-top: 1px solid rgba(123, 224, 166, 0.06);
  font-size: 0.78rem;
  color: rgba(207, 232, 216, 0.85);
}
.bbs-stats-top-row-head { background: rgba(123, 224, 166, 0.08); color: #b3e8c8; font-weight: 700; text-transform: uppercase; font-size: 0.62rem; }
.bbs-sc-rank { color: #7be0a6; font-weight: 700; }
.bbs-sc-handle strong { color: #eafff0; }
.bbs-sc-posts { color: rgba(207, 232, 216, 0.7); font-variant-numeric: tabular-nums; }

/* Mobile collapses */
@media (max-width: 760px) {
  .bbs-files-layout { grid-template-columns: 1fr; }
  .bbs-file-row { grid-template-columns: 1fr; grid-template-rows: auto auto; }
  .bbs-file-row > .bbs-fc-size, .bbs-file-row > .bbs-fc-date, .bbs-file-row > .bbs-fc-dls { display: none; }
  .bbs-mail-row { grid-template-columns: 1fr auto; }
  .bbs-mail-row > .bbs-mc-num, .bbs-mail-row > .bbs-mc-date { display: none; }
  .bbs-whoson-row { grid-template-columns: 1fr auto; }
  .bbs-whoson-row > .bbs-wc-from, .bbs-whoson-row > .bbs-wc-node, .bbs-whoson-row > .bbs-wc-action { display: none; }
  .bbs-poll-opt { grid-template-columns: 1fr; grid-template-rows: auto auto auto; }
}



/* ── BBS SysOp moderation (admin-only powers) ───────────────────────
   Mod bar + per-post delete + composer note only render when the
   logged-in user is admin (gated in JS by _bbsIsSysop). Terminal-
   flavored to match the BBS aesthetic. */
.bbs-mod-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; padding: 6px 8px; margin-bottom: 10px; border: 1px dashed rgba(255,196,87,0.45); border-radius: 6px; background: rgba(255,196,87,0.06); }
.bbs-mod-label { font-size: 10px; font-weight: 700; letter-spacing: 0.08em; color: #ffc457; margin-right: 4px; }
.bbs-mod-btn { font-size: 11px; padding: 3px 9px; border: 1px solid rgba(255,255,255,0.14); border-radius: 5px; background: rgba(255,255,255,0.04); color: var(--ink, #e6f2ee); cursor: pointer; font-family: inherit; white-space: nowrap; }
.bbs-mod-btn:hover { background: rgba(255,196,87,0.14); border-color: rgba(255,196,87,0.5); }
.bbs-mod-btn.is-on { background: rgba(255,196,87,0.20); border-color: #ffc457; color: #ffd982; }
.bbs-mod-btn.bbs-mod-danger { border-color: rgba(255,122,122,0.4); color: #ff9b9b; margin-left: auto; }
.bbs-mod-btn.bbs-mod-danger:hover { background: rgba(255,122,122,0.14); border-color: #ff7a7a; }
.bbs-post-del { margin-left: auto; background: none; border: 1px solid rgba(255,122,122,0.3); color: #ff9b9b; border-radius: 4px; font-size: 11px; padding: 1px 7px; cursor: pointer; }
.bbs-post-del:hover { background: rgba(255,122,122,0.14); border-color: #ff7a7a; }
.forum-composer-sysop-note { margin: 6px 0 0; padding: 5px 9px; font-size: 11px; color: #ffd982; background: rgba(255,196,87,0.08); border-left: 3px solid #ffc457; border-radius: 4px; }

/* ═══════ Hardware page v2 — 2-section single-page layout ═══════
 * Replaces the 5-tab top nav with a Gateway / Sensor Nodes group
 * structure. Sub-tabs for flash modes live inside the Sensor Nodes
 * card. See gateway/static/portal.js → _initHardwareV2Layout. */

/* No global display override — the JS clears the `hidden` attribute on
 * every relocated panel at init AND re-clears after any setWorkspace
 * dispatch via the workspace:changed event listener. An earlier
 * version had `display: block !important` here which BLED THROUGH
 * closed <details> wrappers (Gateway content stayed rendered outside
 * the collapsed box, visually covering the Sensor Nodes section
 * below). Bug pinned in tests/test_firmware_builder.py. */
.hardware-page-v2-active [data-flash-panel].hw-flash-mode-hidden {
  display: none !important;
}

/* The role groups (📡 Gateway, 🛰 Sensor Nodes). */
.hw-group {
  margin: 1.25rem 0;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  background: rgba(255,255,255,0.02);
}
.hw-group-gateway { border-left: 3px solid #4a9eff; }
.hw-group-sensors { border-left: 3px solid #4ade80; }

/* <details>-based group header (Gateway uses this) */
.hw-group-summary {
  padding: 0.75rem 1rem;
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-size: 1.05rem;
  user-select: none;
  list-style: none;
}
.hw-group-summary::-webkit-details-marker { display: none; }
.hw-group-summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  color: rgba(255,255,255,0.5);
  transition: transform 0.15s ease;
}
.hw-group[open] .hw-group-summary::before { transform: rotate(90deg); }

/* Plain header (Sensor Nodes uses this — always expanded) */
.hw-group-header {
  padding: 0.75rem 1rem 0.5rem;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-size: 1.05rem;
}

.hw-group-icon { font-size: 1.2em; }
.hw-group-title { font-weight: 600; }
.hw-group-sub { margin-left: 0.4rem; }
.hw-group-body { padding: 0.5rem 1rem 1rem; }

/* Nested collapsible (HaLow sits inside the Gateway group like this) */
.hw-collapsible {
  margin-top: 0.75rem;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 6px;
  background: rgba(0,0,0,0.15);
}
.hw-collapsible-summary {
  padding: 0.5rem 0.75rem;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.hw-collapsible-summary::-webkit-details-marker { display: none; }
.hw-collapsible-summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  color: rgba(255,255,255,0.5);
  margin-right: 0.3em;
  transition: transform 0.15s ease;
}
.hw-collapsible[open] .hw-collapsible-summary::before { transform: rotate(90deg); }
.hw-collapsible > [data-workspace-section] {
  padding: 0.5rem 0.75rem 0.75rem;
}

/* Inline flash-mode sub-tabs — small, contextual, less prominent
 * than the (now-hidden) top-level workspace-tabs. */
.hw-flash-mode-tabs {
  display: flex;
  gap: 0.25rem;
  padding: 0 1rem;
  margin-bottom: 0.75rem;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}
.hw-flash-mode-tab {
  background: none;
  border: none;
  color: rgba(255,255,255,0.7);
  padding: 0.5rem 0.8rem;
  cursor: pointer;
  font-size: 0.9rem;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  border-radius: 4px 4px 0 0;
  transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.hw-flash-mode-tab:hover {
  color: #fff;
  background: rgba(255,255,255,0.04);
}
.hw-flash-mode-tab.is-active {
  color: #4ade80;
  border-bottom-color: #4ade80;
  background: rgba(74,222,128,0.06);
}
.hw-flash-mode-body { padding: 0 1rem 1rem; }
.hw-flash-mode-body > [data-workspace-section] {
  margin: 0;
}

/* Hide the legacy top tab strip + picker on the v2 layout. We keep
 * the DOM nodes for any deep-link JS that calls setWorkspace, but
 * they're invisible. */
body[data-page="hardware"] .hardware-page-v2 .workspace-tabs.hardware-page-tabs-strip,
body[data-page="hardware"] .hardware-page-v2 .page-head .data-view-picker {
  display: none !important;
}

/* Narrow viewports: stack sub-tabs vertically so they don't wrap awkwardly. */
@media (max-width: 600px) {
  .hw-flash-mode-tabs {
    flex-direction: column;
    border-bottom: none;
  }
  .hw-flash-mode-tab {
    text-align: left;
    border-bottom: 1px solid transparent;
    margin-bottom: 0;
    border-radius: 4px;
  }
  .hw-flash-mode-tab.is-active {
    border-left: 3px solid #4ade80;
    border-bottom-color: transparent;
  }
}

/* ═══════ Firmware library family cards ═══════
 * 3 family cards (each with a variant chooser) replace what was 6
 * confusing flat entries. Operator picks PURPOSE first, then variant.
 */
.hw-fw-role-section { margin-bottom: 1.25rem; }
.hw-fw-role-title {
  margin: 0 0 0.5rem 0;
  font-size: var(--fs-md);
  font-weight: 600;
  color: rgba(255,255,255,0.85);
}
.hw-fw-family-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 0.75rem;
}
.hw-fw-family-card {
  padding: 0.85rem 1rem 0.75rem;
  background: rgba(255,255,255,0.03);
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.hw-fw-family-head { display: flex; align-items: baseline; gap: 0.4rem; }
.hw-fw-family-icon { font-size: 1.15em; }
.hw-fw-family-name { font-size: 1rem; }
.hw-fw-family-summary { margin: 0; line-height: 1.35; }
.hw-fw-variant-picker { display: flex; align-items: center; gap: 0.4rem; margin: 0.25rem 0; }
.hw-fw-variant-picker > span { font-size: 0.8rem; color: rgba(255,255,255,0.65); white-space: nowrap; }
.hw-fw-variant-picker select { flex: 1; }
.hw-fw-variant-detail {
  padding: 0.4rem 0.5rem;
  background: rgba(0,0,0,0.2);
  border-radius: 4px;
  border-left: 2px solid rgba(255,255,255,0.1);
}
.hw-fw-variant-differentiator {
  margin: 0 0 0.4rem 0;
  font-style: italic;
}
.hw-fw-variant-meta {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.15rem 0.6rem;
  margin: 0;
  font-size: var(--fs-base);
}
.hw-fw-variant-meta dt {
  color: rgba(255,255,255,0.55);
  font-weight: 500;
}
.hw-fw-variant-meta dd { margin: 0; }
.hw-fw-family-actions {
  margin-top: auto;
  padding-top: 0.25rem;
}

/* ═══════ Observe — animation control panel (collapsible) ═══════
 * The animation panel was previously `hidden` with no unhide path,
 * so operators couldn't reach date range / speed / play controls.
 * Now a <details> below the map that expands on click, plus an
 * 'Animate' chip in the Master Clock bar that opens it directly.
 */
.observe-animation-panel { padding: 0.6rem 0.9rem; }
.observe-animation-panel > summary {
  cursor: pointer;
  padding: 0.4rem 0;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  flex-wrap: wrap;
}
.observe-animation-panel > summary::-webkit-details-marker { display: none; }
.observe-animation-panel > summary::before {
  content: "▸";
  display: inline-block;
  width: 1em;
  color: rgba(255,255,255,0.5);
  transition: transform 0.15s ease;
}
.observe-animation-panel[open] > summary::before { transform: rotate(90deg); }
.observe-animation-summary > .eyebrow { margin: 0; }
.observe-animation-summary > strong { font-size: 1rem; }
#open-observe-animation-button { white-space: nowrap; }

/* ═══════ Observe — always-visible animation strip ═══════
 * Replaces the broken <details> approach. Operator feedback
 * 2026-05-30: "the Animate chip doesn't do anything, no way to
 * select start/end date or range like 24hr/1m/1y, no speed section".
 * Solution: a persistent strip with quick-range preset chips,
 * speed chips, and big Play/Stop — no toggle to miss.
 */
.observe-animation-strip {
  margin-top: 0.5rem;
  padding: 0.75rem 1rem;
  background: rgba(255,255,255,0.04);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.observe-animation-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  flex-wrap: wrap;
}
.observe-animation-head .eyebrow { margin: 0; }
.observe-animation-title { margin: 0; font-size: 1rem; display: flex; align-items: center; gap: .5rem; }
.observe-animation-row {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: flex-start;
}
.observe-animation-block {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
  flex: 1;
}
.observe-animation-label {
  font-size: 0.78rem;
  color: rgba(255,255,255,0.6);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-weight: 600;
}
.observe-animation-input { width: 100%; min-width: 240px; }
.observe-animation-presets {
  display: flex;
  gap: 0.35rem;
  flex-wrap: wrap;
}
.observe-preset-chip {
  background: rgba(255,255,255,0.05);
  border: 1px solid rgba(255,255,255,0.12);
  color: rgba(255,255,255,0.8);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.85rem;
  cursor: pointer;
  transition: all 0.12s ease;
}
.observe-preset-chip:hover {
  background: rgba(255,255,255,0.1);
  border-color: rgba(255,255,255,0.25);
  color: #fff;
}
.observe-preset-chip.is-active {
  background: rgba(74,158,255,0.18);
  border-color: #4a9eff;
  color: #fff;
  font-weight: 600;
}
.observe-animation-dates {
  display: flex;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-top: 0.3rem;
}
.observe-animation-sub {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  font-size: 0.8rem;
}
.observe-animation-sub > span {
  color: rgba(255,255,255,0.55);
  font-size: 0.75rem;
}
.observe-animation-sub > input {
  width: 140px;
  padding: 0.25rem 0.4rem;
  background: rgba(0,0,0,0.25);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 4px;
  color: #fff;
}
.observe-animation-actions { padding-top: 0.4rem; }
.observe-animation-actions .button { white-space: nowrap; }

/* Visually-hidden helper for the kept-for-back-compat speed <select> */
.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* ═══════ Observe — on-screen station-color legend ═══════ */
.observe-station-legend {
  position: absolute;
  bottom: 16px;
  right: 16px;
  z-index: 600;
  background: rgba(15,23,42,0.92);
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 8px;
  padding: 0.4rem 0.7rem;
  font-size: 0.85rem;
  max-width: 280px;
  backdrop-filter: blur(8px);
}
.observe-station-legend > summary {
  cursor: pointer;
  user-select: none;
  list-style: none;
  font-weight: 600;
  padding: 0.15rem 0;
}
.observe-station-legend > summary::-webkit-details-marker { display: none; }
.observe-station-legend > summary::before {
  content: "▾";
  display: inline-block;
  margin-right: 0.3em;
  transition: transform 0.15s ease;
}
.observe-station-legend:not([open]) > summary::before { transform: rotate(-90deg); }
.observe-legend-list {
  list-style: none;
  padding: 0.4rem 0 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}
.observe-legend-list > li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.8rem;
  line-height: 1.25;
}
.observe-legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.4);
  flex-shrink: 0;
}

/* Legend section headers + counts (per-category live numbers) */
.observe-legend-section-title {
  font-size: 0.78rem;
  font-weight: 600;
  color: rgba(255,255,255,0.85);
  margin: 0.5rem 0 0.2rem;
  padding-top: 0.3rem;
  border-top: 1px solid rgba(255,255,255,0.08);
}
.observe-legend-section-title:first-of-type { border-top: none; padding-top: 0; }
.observe-legend-list { margin-bottom: 0.2rem; }
.observe-legend-count {
  margin-left: auto;
  font-size: 0.75rem;
  font-weight: 600;
  color: rgba(255,255,255,0.55);
  font-variant-numeric: tabular-nums;
  padding: 0.05rem 0.4rem;
  border-radius: 999px;
  background: rgba(255,255,255,0.08);
}
.observe-legend-count[data-legend-count-active="true"] {
  color: #fff;
  background: rgba(74,158,255,0.25);
}
.observe-legend-count[data-legend-count-zero="true"] {
  opacity: 0.4;
}

/* Active animation strip — pulsing border when an animation is
 * playing so the operator sees "yes, this is running" at a glance. */
.observe-animation-strip.is-playing {
  border-color: #4a9eff;
  box-shadow: 0 0 0 1px rgba(74,158,255,0.35), 0 0 18px rgba(74,158,255,0.15);
  animation: observe-strip-pulse 1.8s ease-in-out infinite;
}
@keyframes observe-strip-pulse {
  0%, 100% { box-shadow: 0 0 0 1px rgba(74,158,255,0.35), 0 0 18px rgba(74,158,255,0.15); }
  50%      { box-shadow: 0 0 0 1px rgba(74,158,255,0.55), 0 0 30px rgba(74,158,255,0.30); }
}
.observe-animation-strip.is-buffering #environmental-animation-status {
  background: rgba(251,191,36,0.18);
  color: #fbbf24;
  border: 1px solid #fbbf24;
}
.observe-animation-strip.is-playing #environmental-animation-status {
  background: rgba(74,158,255,0.18);
  color: #4a9eff;
  border: 1px solid #4a9eff;
}

/* "Enable overlay" inline button inside the legend — shows up when
 * a category like Argo has 0 visible features but its overlay layer
 * could be turned on. */
.observe-legend-row {
  position: relative;
}
.observe-legend-enable {
  display: inline-block;
  margin-left: 0.4rem;
  padding: 0.1rem 0.5rem;
  font-size: 0.7rem;
  border-radius: 999px;
  cursor: pointer;
}
.observe-legend-enable[hidden] { display: none; }
.observe-legend-count[data-overlay-hinted="1"] {
  color: #fbbf24;
  background: rgba(251,191,36,0.15);
}

/* ── MapLibre GL beta renderer ──────────────────────────────────────────
   A GPU-rendered map overlaying the Leaflet stage (same grid cell), shown
   only when the operator toggles it. Lets us evaluate smooth/sharp/trail-free
   rendering before any migration off Leaflet. */
#map-gl {
  grid-area: 1 / 1;
  position: relative;
  z-index: 1; /* above Leaflet #map (z-index 0) when visible */
  height: 100%;
  min-height: 0;
  border-radius: 18px;
  overflow: hidden;
  background: #08141a;
}
#map-gl[hidden] {
  display: none;
}
/* Self-hosted CesiumJS 3D digital-twin globe — the preferred 3D renderer, so it
   sits above both Leaflet (#map, z0) and the MapLibre globe (#map-gl, z1). */
#cesium-globe {
  grid-area: 1 / 1;
  position: relative;
  z-index: 2;
  height: 100%;
  min-height: 0;
  border-radius: 18px;
  overflow: hidden;
  background: #04080d;
}
#cesium-globe[hidden] {
  display: none;
}
.map-gl-toggle {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 6; /* above both renderers and the legend */
  padding: 6px 13px;
  font: 600 12px/1.2 inherit;
  letter-spacing: 0.02em;
  color: #cfece6;
  background: rgba(8, 20, 26, 0.82);
  border: 1px solid rgba(54, 224, 200, 0.4);
  border-radius: 999px;
  cursor: pointer;
  backdrop-filter: blur(6px);
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.map-gl-toggle:hover {
  background: rgba(12, 28, 36, 0.95);
  border-color: rgba(54, 224, 200, 0.7);
}
.map-gl-toggle.is-active {
  color: #08141a;
  background: #36e0c8;
  border-color: #36e0c8;
}
/* Basemap switch sits just below the renderer toggle; only shown in GL mode. */
.map-gl-style {
  top: 46px;
  right: 12px;
  color: #cfece6;
  background: rgba(8, 20, 26, 0.82);
  border-color: rgba(54, 224, 200, 0.4);
}
.map-gl-style[hidden] {
  display: none;
}
/* Globe/flat projection switch sits below the basemap switch in GL mode. */
.map-gl-projection {
  top: 80px;
  right: 12px;
  color: #cfece6;
  background: rgba(8, 20, 26, 0.82);
  border-color: rgba(54, 224, 200, 0.4);
}
.map-gl-projection[hidden] {
  display: none;
}
.map-stage.is-globe .map-gl-toggle,
.map-stage.is-globe .map-gl-style,
.map-stage.is-globe .map-gl-projection {
  display: none; /* the legacy globe-canvas mode owns the stage */
}

/* Firmware OTA fleet status (Hardware page) */
.firmware-fleet-families { display: flex; flex-wrap: wrap; gap: 6px; margin: 8px 0; }
.firmware-fleet-grid { width: 100%; border-collapse: collapse; font-size: var(--fs-base); margin-top: 8px; }
.firmware-fleet-grid th, .firmware-fleet-grid td { text-align: left; padding: 6px 10px; border-bottom: 1px solid rgba(148, 163, 184, 0.18); }
.firmware-fleet-grid th { color: #94a3b8; font-weight: 600; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }
.firmware-fleet-grid tbody tr:hover { background: rgba(148, 163, 184, 0.06); }
.firmware-fleet-register { margin-top: 12px; }
.firmware-fleet-register > summary { cursor: pointer; color: #7dd3fc; font-size: 0.85rem; }
#fleet-reg-result { margin-top: 6px; }

/* Mesh page: per-node live link-health cards (Network Status rail). */
.mesh-node-health { display: flex; flex-direction: column; gap: 8px; }
.mesh-node-health.empty { display: block; color: var(--muted); font-size: 0.8rem; padding: 6px 2px; }
.mesh-health-card {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px 10px;
  background: var(--panel-soft);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.mesh-health-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.mesh-health-label { font-weight: 600; color: var(--ink); font-size: var(--fs-base); }
.mesh-health-sig { display: flex; align-items: baseline; gap: 10px; }
.mesh-rssi { font-weight: 600; font-variant-numeric: tabular-nums; color: var(--muted); }
.mesh-rssi.good { color: var(--ok); }
.mesh-rssi.ok { color: var(--warn); }
.mesh-rssi.weak { color: var(--bad); }
.mesh-health-counts { font-variant-numeric: tabular-nums; }
.mesh-health-foot { display: flex; align-items: center; gap: 6px; }

/* Sensors panel: stations classified by group -> org -> device type/role. */
.sensor-class-panel { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 2px; }
.sensor-class-group { display: flex; flex-direction: column; gap: 3px; }
.sensor-class-grouphdr {
  display: flex; justify-content: space-between; align-items: baseline; gap: 8px;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--ink); padding: 2px 2px 1px;
}
.sensor-class-row {
  display: flex; align-items: center; gap: 8px; width: 100%;
  background: var(--panel-soft); border: 1px solid var(--line); border-radius: 9px;
  padding: 5px 8px; cursor: pointer; text-align: left; color: var(--muted);
  font-size: 0.78rem; transition: border-color 0.12s, color 0.12s;
}
.sensor-class-row:hover { border-color: var(--line-strong, var(--accent)); }
.sensor-class-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
  background: transparent; border: 1.5px solid var(--muted);
}
.sensor-class-row.is-on { color: var(--ink); }
.sensor-class-row.is-on .sensor-class-dot { background: var(--accent); border-color: var(--accent); }
.sensor-class-label { flex: 1 1 auto; }
.sensor-class-count { font-variant-numeric: tabular-nums; font-weight: 600; opacity: 0.85; }
.sensor-class-orghdr {
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--accent); padding: 4px 2px 1px 4px; opacity: 0.92;
}

/* ============================================================
   UI overhaul Phase 1 (specs/ui-overhaul.md) — shell.
   1a: the nav speaks. Hover-only .nav-tip captions become permanent
   labels (icon-only nav is expert-only UI), the 12 destinations group
   into Observe | Analyze | Operate | Community | Admin via flex order
   (no DOM surgery; click handlers untouched), and the metric/scope
   cluster compacts to pay for the extra width.
   ============================================================ */
.primary-nav.icon-nav .nav-button,
body[data-route] .primary-nav.icon-nav .nav-button {
  display: grid;
  grid-template-rows: auto auto;
  place-items: center;
  width: auto;
  min-width: 50px;
  height: 48px;
  padding: 3px 6px 2px;
  row-gap: 0;
}
.primary-nav.icon-nav .nav-button .nav-tip,
body[data-route] .primary-nav.icon-nav .nav-button .nav-tip {
  position: static;
  transform: none;
  opacity: 0.72;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
  transition: opacity 0.16s ease;
}
.primary-nav.icon-nav .nav-button:hover .nav-tip,
.primary-nav.icon-nav .nav-button.is-active .nav-tip {
  opacity: 1;
  transform: none;
}

/* Group order: Observe (map, inspect) | Analyze (graphs, library) |
   Operate (command, control, hardware, comms) | Community (marketplace,
   forum, wiki) | Admin (settings). */
.primary-nav .nav-button[data-page="map"] { order: 1; }
.primary-nav .nav-button[data-page="inspect"] { order: 2; }
.primary-nav .nav-button[data-page="graphs"] { order: 3; }
.primary-nav .nav-button[data-page="library"] { order: 4; }
.primary-nav .nav-button[data-page="command"] { order: 5; }
.primary-nav .nav-button[data-page="control"] { order: 6; }
.primary-nav .nav-button[data-page="hardware"] { order: 7; }
.primary-nav .nav-button[data-page="comms"] { order: 8; }
.primary-nav .nav-button[data-page="marketplace"] { order: 9; }
.primary-nav .nav-button[data-page="forum"] { order: 10; }
.primary-nav .nav-button[data-page="wiki"] { order: 11; }
.primary-nav .nav-button[data-page="settings"] { order: 12; }

/* A thin divider opens each new group. */
.primary-nav .nav-button[data-page="graphs"],
.primary-nav .nav-button[data-page="command"],
.primary-nav .nav-button[data-page="marketplace"],
.primary-nav .nav-button[data-page="settings"] {
  margin-left: 12px;
  position: relative;
}
.primary-nav .nav-button[data-page="graphs"]::before,
.primary-nav .nav-button[data-page="command"]::before,
.primary-nav .nav-button[data-page="marketplace"]::before,
.primary-nav .nav-button[data-page="settings"]::before {
  content: "";
  position: absolute;
  left: -7px;
  top: 22%;
  height: 56%;
  width: 1px;
  background: rgba(163, 185, 188, 0.28);
}

/* Pay for the label width: drop the redundant "Metric"/"Data scope"
   eyebrows (the selects are self-describing) and cap select width. */
.header-metrics .header-metric > span { display: none; }
.header-metrics select { max-width: 150px; }

/* Compact the right-side status cluster: the ingest indicator and account
   button keep their icon + full info in the title tooltip; the inline text
   was costing ~300px the labeled nav needs. */
.auto-ingest-indicator > :not(.auto-ingest-dot) { display: none; }
.user-display > :not(.user-display-avatar) { display: none; }
.primary-nav.icon-nav .nav-button,
body[data-route] .primary-nav.icon-nav .nav-button {
  min-width: 46px;
  padding: 3px 4px 2px;
}

/* Narrow viewports: drop back to icon-only nav (the hover tooltip styling
   no longer exists, so rely on title-less compact captions hidden). */
@media (max-width: 1279px) {
  .primary-nav.icon-nav .nav-button .nav-tip,
  body[data-route] .primary-nav.icon-nav .nav-button .nav-tip { display: none; }
  .primary-nav.icon-nav .nav-button,
  body[data-route] .primary-nav.icon-nav .nav-button { height: 42px; min-width: 42px; }
}

/* 1b: one affordance per choice. Five pages (inspect, graphs, library,
   command, settings) showed BOTH a view-picker dropdown and a workspace-tab
   strip for the same selection. The tabs win; the dropdown is retired.
   (The picker sync JS no-ops safely on hidden elements.) */
.data-view-picker { display: none !important; }

/* 1c: recipes become a disclosure, not a permanent carousel. Rails are
   collapsed by default (chips + sublabel hidden); the rail label is the
   toggle. State persists per rail in localStorage. */
.recipe-rail .recipe-rail-label { cursor: pointer; user-select: none; }
.recipe-rail .recipe-rail-label::after {
  content: " ▾";
  opacity: 0.7;
  font-size: 0.9em;
}
.recipe-rail.is-collapsed .recipe-rail-label::after { content: " ▸"; }
.recipe-rail.is-collapsed .recipe-chip,
.recipe-rail.is-collapsed .recipe-rail-sublabel { display: none; }

/* ============================================================
   UI overhaul Phase 2 (specs/ui-overhaul.md): outcome-chip rows never
   wrap into multi-line walls. 8-15 chips per row across control /
   hardware / inspect / comms ballooned panel headers to 2-3 lines;
   a single scrollable line keeps every action one swipe away while
   the panel content stays the star. (Recipe rails are already
   collapsed disclosures — Phase 1c.)
   ============================================================ */
.panel-outcomes {
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.panel-outcomes > * { flex: 0 0 auto; }

/* Phase 3a: viz palette groups are disclosures — Explore stays open,
   the science groups expand on demand. */
.viz-tool-group-label { cursor: pointer; user-select: none; }
.viz-tool-group-label::after { content: " ▾"; opacity: 0.7; }
.viz-tool-group-label.is-collapsed::after { content: " ▸"; }

/* Phase 4: community-page echoes. The wiki stat strip repeats counts the
   list already shows; the marketplace chip row duplicates 5 of the filter
   select's 7 options (the select is the complete affordance). */
#wiki-summary { display: none; }
[data-page-panel="marketplace"] .panel-outcomes { display: none; }

/* Phase 5: "Learn this page" (press ?) — a 3-step plain-English
   walkthrough per page for first-time users. */
.learn-page-overlay {
  position: fixed;
  inset: 0;
  z-index: 4000;
  display: grid;
  place-items: center;
  background: rgba(3, 10, 13, 0.72);
}
.learn-page-card {
  width: min(480px, 92vw);
  padding: 22px 26px;
  border: 1px solid rgba(50, 208, 189, 0.35);
  border-radius: 16px;
  background: var(--panel);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.55);
}
.learn-page-card h3 {
  margin: 0 0 4px;
  font-size: var(--fs-lg);
  color: var(--ink);
}
.learn-page-card .learn-page-purpose {
  margin: 0 0 14px;
  color: var(--muted);
  font-size: var(--fs-base);
}
.learn-page-card ol {
  margin: 0 0 16px;
  padding-left: 22px;
  display: grid;
  gap: 9px;
  color: var(--ink);
  font-size: var(--fs-base);
  line-height: 1.45;
}
.learn-page-card .learn-page-foot {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--muted);
  font-size: var(--fs-xs);
}

/* B1: QARTOD quality badges on live tiles. */
.live-tile-qc { font-size: 9px; line-height: 1; }
.live-tile-qc.is-pass { color: #2ecf8f; }
.live-tile-qc.is-suspect { color: #f5a524; }
.live-tile-qc.is-fail { color: #f97373; }
.live-tile-qc.is-na { color: var(--muted); opacity: 0.55; }

/* ── Shared focus bar ────────────────────────────────────────────────
   One statement of what the operator is looking at, shared by every tab.
   Five uncoordinated selection states used to disagree silently; this is
   the visible half of the fix (setFocus() in portal.js is the other). */
.omega-focus-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  margin-inline: 10px;
}
.omega-focus-bar[hidden] { display: none; }
.omega-focus-bar .focus-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid rgba(50, 208, 189, 0.35);
  background: rgba(50, 208, 189, 0.10);
  color: #cfe6e6;
  font-size: 12px;
  line-height: 1.5;
  white-space: nowrap;
  max-width: 30ch;
  overflow: hidden;
  text-overflow: ellipsis;
}
.omega-focus-bar .focus-clear {
  border: 1px solid transparent;
  background: transparent;
  color: #90a9ad;
  font-size: 12px;
  line-height: 1;
  padding: 3px 6px;
  border-radius: 999px;
  cursor: pointer;
}
.omega-focus-bar .focus-clear:hover { color: #edf8f8; border-color: rgba(255,255,255,0.18); }

/* ── Nearby-station comparison rail ──────────────────────────────────
   67 pairs of stations sit within 60 km sharing metrics; this makes the
   cross-station question one click instead of something you had to already
   know how to assemble. */
.neighbour-rail {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  grid-column: 1 / -1;
  padding: 6px 0 2px;
}
.neighbour-rail[hidden] { display: none; }
.neighbour-rail-label { color: #90a9ad; font-size: 12px; margin-right: 2px; }
.neighbour-chip {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(125, 211, 252, 0.35);
  background: rgba(125, 211, 252, 0.10);
  color: #cfe6e6;
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.neighbour-chip:hover { background: rgba(125, 211, 252, 0.20); color: #edf8f8; }

/* ── Question rail ───────────────────────────────────────────────────
   The tab opened on 56 controls and "Choose a visualization tool" — a tool
   menu, not a question. Nobody thinks "I want a Lead-Lag Coherence chart". */
.question-rail {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  padding: 8px 0 10px;
}
.question-rail-label { color: #90a9ad; font-size: 12px; font-weight: 600; margin-right: 2px; }
.question-chip {
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid rgba(50, 208, 189, 0.35);
  background: rgba(50, 208, 189, 0.08);
  color: #cfe6e6;
  font-size: 12.5px;
  cursor: pointer;
  white-space: nowrap;
}
.question-chip:hover { background: rgba(50, 208, 189, 0.18); color: #edf8f8; }

/* Cross-site spread on a live tile. A single number is a lie when several
   stations report the metric — this states the site count and range so a
   one-station reading cannot be mistaken for a network-wide figure. */
.live-tile-spread {
  grid-column: 1 / -1;
  font-size: 10.5px;
  color: #90a9ad;
  padding: 0 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
