/* ====== Europa Crisis Sim — tactical theme ====== */
:root {
  --bg-0: #0a0d0e;
  --bg-1: #11161a;
  --bg-2: #161d22;
  --bg-3: #1d262c;
  --line: #2a3640;
  --line-strong: #3e4f5c;
  --text: #d6dde2;
  --text-dim: #8d9aa3;
  --text-faint: #5e6a73;
  --accent: #b9c46c;          /* olive / khaki accent */
  --accent-dim: #6f7741;
  --blufor: #4a86d4;
  --opfor: #cf3b3b;
  --indep: #d3a93a;
  --danger: #cf3b3b;
  --shadow: 0 2px 6px rgba(0,0,0,.5), 0 0 0 1px rgba(0,0,0,.4);
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg-0);
  color: var(--text);
  font-family: ui-monospace, "JetBrains Mono", "Consolas", "Menlo", monospace;
  font-size: 13px;
  overscroll-behavior: none;
}
button { font-family: inherit; font-size: inherit; cursor: pointer; }
input, select { font-family: inherit; font-size: inherit; }

#app {
  display: grid;
  grid-template-columns: 320px 1fr;
  height: 100vh;
  width: 100vw;
}

/* ============ Sidebar ============ */
#sidebar {
  background: linear-gradient(180deg, var(--bg-1) 0%, var(--bg-0) 100%);
  border-right: 1px solid var(--line);
  display: flex; flex-direction: column;
  overflow-y: auto;
  scrollbar-width: thin;
}
.brand {
  padding: 16px 18px 14px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-2);
}
.brand .title {
  font-weight: 700;
  font-size: 18px;
  letter-spacing: .14em;
  color: var(--accent);
}
.brand .title span { color: var(--text); }
.brand .subtitle {
  margin-top: 4px;
  font-size: 10px;
  letter-spacing: .25em;
  color: var(--text-faint);
}

.panel {
  padding: 14px 14px 16px;
  border-bottom: 1px solid var(--line);
}
.panel-title {
  font-size: 10px;
  letter-spacing: .22em;
  color: var(--text-dim);
  margin-bottom: 10px;
}

/* ============ Tools ============ */
.tool-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.tool-btn {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  padding: 8px 4px;
  border-radius: 3px;
  transition: all .15s;
}
.tool-btn span { font-size: 10px; letter-spacing: .12em; }
.tool-btn:hover { color: var(--text); border-color: var(--line-strong); }
.tool-btn.active {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: rgba(185, 196, 108, .08);
  box-shadow: inset 0 0 0 1px rgba(185, 196, 108, .15);
}

/* ============ Faction tabs + palette ============ */
.faction-tabs {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 4px;
  margin-bottom: 10px;
}
.faction-tab {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  padding: 6px 0;
  font-size: 10px;
  letter-spacing: .18em;
  border-radius: 3px;
}
.faction-tab.active[data-faction="blufor"] { color: #fff; background: var(--blufor); border-color: var(--blufor); }
.faction-tab.active[data-faction="opfor"]  { color: #fff; background: var(--opfor);  border-color: var(--opfor);  }
.faction-tab.active[data-faction="indep"]  { color: #1a1300; background: var(--indep); border-color: var(--indep); }

.palette {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
}
.pal-item {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 6px 4px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  transition: all .15s;
}
.pal-item:hover { border-color: var(--line-strong); transform: translateY(-1px); }
.pal-item.selected {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent), inset 0 0 0 1px rgba(185,196,108,.15);
}
.pal-item img { width: 44px; height: 40px; object-fit: contain; }
.pal-item .lbl { font-size: 10px; color: var(--text-dim); text-align: center; line-height: 1.15; }
.palette-hint {
  margin-top: 10px; font-size: 11px; color: var(--text-faint); line-height: 1.4;
}

/* ============ Roster ============ */
.roster {
  display: flex; flex-direction: column; gap: 4px;
  max-height: 240px; overflow-y: auto;
}
.roster-empty { color: var(--text-faint); font-size: 11px; padding: 4px 0; }
.roster-item {
  display: flex; align-items: center; gap: 8px;
  padding: 5px 6px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  cursor: pointer;
  font-size: 11px;
}
.roster-item:hover { border-color: var(--line-strong); }
.roster-item img { width: 22px; height: 20px; object-fit: contain; flex-shrink: 0; }
.roster-item .ri-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.roster-item .ri-faction {
  font-size: 9px; letter-spacing: .12em; padding: 2px 5px; border-radius: 2px; flex-shrink: 0;
}
.ri-faction.blufor { background: rgba(74,134,212,.15); color: var(--blufor); }
.ri-faction.opfor  { background: rgba(207,59,59,.15); color: var(--opfor);  }
.ri-faction.indep  { background: rgba(211,169,58,.15); color: var(--indep);  }

/* ============ Buttons / state row ============ */
.state-row {
  display: flex; gap: 6px; margin-bottom: 6px;
}
.state-row > button { flex: 1; }
.ghost-btn {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 6px 8px;
  border-radius: 3px;
  letter-spacing: .04em;
}
.ghost-btn:hover { border-color: var(--line-strong); background: var(--bg-3); }
.ghost-btn.danger { color: var(--danger); }
.ghost-btn.danger:hover { background: rgba(207,59,59,.08); border-color: var(--danger); }
.primary-btn {
  background: var(--accent-dim);
  border: 1px solid var(--accent);
  color: #0a0d0e;
  padding: 7px 12px;
  border-radius: 3px;
  font-weight: 600;
  letter-spacing: .04em;
}
.primary-btn:hover { background: var(--accent); }
.status-line { font-size: 10px; color: var(--text-faint); margin-top: 4px; letter-spacing: .04em; }
.foot { padding: 10px 14px; color: var(--text-faint); font-size: 10px; letter-spacing: .12em; }

/* ============ Map ============ */
#map-wrap { position: relative; }
#map {
  width: 100%; height: 100%;
  background: #18222c;       /* water color, shows through under vector basemap */
}
.leaflet-container {
  background: #18222c !important;
  font-family: inherit;
  outline: none;
}
.leaflet-control-zoom a {
  background: var(--bg-2) !important;
  color: var(--text) !important;
  border-color: var(--line) !important;
}
.leaflet-control-zoom a:hover { background: var(--bg-3) !important; }
.leaflet-bar { box-shadow: var(--shadow) !important; }
.leaflet-control-attribution {
  background: rgba(10,13,14,.7) !important;
  color: var(--text-faint) !important;
}

.cursor-mode {
  position: absolute;
  top: 12px; left: 50%; transform: translateX(-50%);
  background: rgba(10,13,14,.85);
  border: 1px solid var(--accent-dim);
  color: var(--accent);
  padding: 6px 12px;
  font-size: 11px;
  letter-spacing: .14em;
  border-radius: 3px;
  z-index: 1000;
  pointer-events: none;
}
.cursor-mode.hidden { display: none; }

.toast {
  position: absolute;
  bottom: 18px; left: 50%; transform: translateX(-50%) translateY(20px);
  background: rgba(10,13,14,.95);
  border: 1px solid var(--line-strong);
  color: var(--text);
  padding: 8px 14px;
  font-size: 12px;
  border-radius: 3px;
  box-shadow: var(--shadow);
  opacity: 0; pointer-events: none;
  transition: all .25s;
  z-index: 1000;
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* file:// warning */
#fp-warn {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: rgba(10,13,14,.7);
  z-index: 1500;
}
.fp-warn-card {
  background: var(--bg-1);
  border: 1px solid var(--danger);
  border-radius: 4px;
  padding: 22px 26px;
  max-width: 480px;
  box-shadow: 0 12px 40px rgba(0,0,0,.7);
}
.fp-warn-title {
  color: var(--danger);
  font-size: 13px;
  letter-spacing: .14em;
  margin-bottom: 12px;
}
.fp-warn-body { font-size: 12px; line-height: 1.55; color: var(--text); }
.fp-warn-body code {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 1px 4px;
  font-size: 11px;
}
.fp-warn-body pre {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 8px 10px;
  font-size: 11px;
  margin: 8px 0;
  white-space: pre-wrap;
  color: var(--accent);
}
.fp-warn-close {
  margin-top: 14px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 6px 14px;
  border-radius: 3px;
}
.fp-warn-close:hover { border-color: var(--line-strong); background: var(--bg-3); }

/* ============ Unit markers ============ */
.unit-marker {
  background: transparent;
  border: none;
}
.unit-icon {
  display: flex; flex-direction: column; align-items: center;
  pointer-events: auto;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,.7));
}
.unit-icon img { width: 42px; height: 38px; object-fit: contain; }
.unit-icon .nameplate {
  margin-top: 1px;
  background: rgba(10,13,14,.85);
  border: 1px solid var(--line);
  padding: 1px 6px;
  font-size: 10px;
  letter-spacing: .04em;
  color: var(--text);
  white-space: nowrap;
  border-radius: 2px;
}
.unit-icon[data-faction="blufor"] .nameplate { border-color: rgba(74,134,212,.5); }
.unit-icon[data-faction="opfor"]  .nameplate { border-color: rgba(207,59,59,.5); }
.unit-icon[data-faction="indep"]  .nameplate { border-color: rgba(211,169,58,.5); }
.unit-icon[data-faction="wdp"]    .nameplate { border-color: rgba(59,139,226,.55); }
.unit-icon[data-faction="esa"]    .nameplate { border-color: rgba(226,59,59,.55); }
.unit-icon[data-faction="snam"]   .nameplate { border-color: rgba(160,64,200,.55); }
.unit-icon.dim { opacity: .65; }

/* Placeholder glyph used by the OOB-driven loader transition. Replaced when
   the tactical-icon system lands and unit `type` drives a real symbol. */
.unit-icon .unit-glyph {
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  color: #0a0d0e;
  font-weight: 700;
  font-size: 18px;
  border: 1px solid rgba(0,0,0,.4);
  border-radius: 2px;
}

/* OOB browser panel placeholder (replaces the old UNIT PALETTE). */
.oob-tree { padding: 8px 0; min-height: 60px; }

/* Roster swatch (placeholder until OOB loader lands). */
.roster-item .ri-swatch {
  width: 20px; height: 18px;
  border: 1px solid var(--line);
  border-radius: 2px;
  flex-shrink: 0;
}
.ri-faction.wdp     { background: rgba(59,139,226,.15); color: #82b8ee; }
.ri-faction.esa     { background: rgba(226,59,59,.15);  color: #ee8585; }
.ri-faction.snam    { background: rgba(160,64,200,.15); color: #c489d8; }
.ri-faction.unknown { background: rgba(120,120,120,.15); color: #aaa; }

/* ============ Modal ============ */
.modal-back {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.55);
  display: flex; align-items: center; justify-content: center;
  z-index: 2000;
}
.modal-back.hidden { display: none; }
.modal {
  width: 360px;
  background: var(--bg-1);
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  padding: 18px 20px;
  box-shadow: 0 10px 30px rgba(0,0,0,.7);
}
.modal-title {
  font-size: 12px; letter-spacing: .22em;
  color: var(--accent);
  margin-bottom: 14px;
}
.modal label {
  display: block;
  margin-bottom: 12px;
  font-size: 10px; letter-spacing: .14em; color: var(--text-dim);
}
.modal label .hint { color: var(--text-faint); letter-spacing: 0; }
.modal input, .modal select {
  display: block;
  width: 100%;
  margin-top: 5px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 7px 9px;
  border-radius: 3px;
  letter-spacing: 0;
}
.modal input:focus, .modal select:focus {
  border-color: var(--accent-dim); outline: none;
}
.modal label.checkbox {
  display: flex; align-items: center; gap: 8px;
  letter-spacing: .04em;
}
.modal label.checkbox input { width: auto; margin: 0; }
.modal-row {
  display: flex; gap: 8px; justify-content: flex-end;
  margin-top: 6px;
}

/* Scrollbar */
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
*::-webkit-scrollbar-thumb:hover { background: var(--line-strong); }

/* Responsive: collapse sidebar on narrow screens */
@media (max-width: 760px) {
  #app { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  #sidebar { max-height: 45vh; }
}

/* ============ Map labels (constant size, zoom-fade) ============ */
.map-label-marker {
  background: none !important;
  border: none !important;
  pointer-events: none;
  width: 0; height: 0;
}
.map-label {
  text-align: center;
  position: absolute;
  white-space: nowrap;
  font-family: "Bahnschrift Condensed", "Oswald", ui-monospace, monospace;
  letter-spacing: .15em;
  text-transform: uppercase;
  pointer-events: none;
  transform: translate(-50%, -50%);
  text-shadow: 0 0 4px #0f1418, 0 0 4px #0f1418, 0 0 2px #0f1418;
  transition: opacity .15s ease-out;
}
.map-label.country {
  color: #d6dde2;
  font-weight: 500;
  opacity: var(--country-label-opacity, 1);
}
.map-label.ocean {
  color: #5a7896;
  font-style: italic;
  letter-spacing: .35em;
  opacity: var(--ocean-label-opacity, .9);
}
.leaflet-control-layers {
  background: var(--bg-2) !important;
  border: 1px solid var(--line) !important;
  color: var(--text) !important;
}
/* SVG-overlay text (country & ocean labels — scale with map zoom) */
.leaflet-overlay-pane svg .label-group text {
  paint-order: stroke fill;
  stroke: #0f1418;
  stroke-width: 8;
  stroke-linejoin: round;
}
.leaflet-overlay-pane svg .country-labels text { fill: #d6dde2; }
.leaflet-overlay-pane svg .ocean-labels text  { fill: #5a7896; font-style: italic; }

/* ============ Crisis-sim panels (added 2026-05-25) ============ */

/* Collapsible panels — click the title to toggle. Panels start expanded. */
.panel.collapsible .panel-title {
  cursor: pointer;
  user-select: none;
}
.panel.collapsible .panel-title::after {
  content: " ▾";
  font-size: 10px;
  color: var(--text-dim);
}
.panel.collapsible.collapsed .panel-title::after { content: " ▸"; }
.panel.collapsible.collapsed .panel-body,
.panel.collapsible.collapsed > div:not(.panel-title) { display: none; }

/* Placeholder body for not-yet-wired panels. */
.panel-stub {
  font-size: 11.5px;
  color: var(--text-dim);
  font-style: italic;
  line-height: 1.5;
  padding: 6px 4px;
}
.panel-stub code {
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 1px 4px;
  border-radius: 2px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  color: var(--text);
  font-style: normal;
}

/* Turn-status panel rows. Stacked layout: dim label on top, monospace value
   below — works cleanly for both short ("Turn 0") and long ("Continuation
   War / Volnian Civil War") values in the narrow sidebar. */
.turn-status { padding: 4px 0 8px; }
.turn-row {
  display: block;
  padding: 5px 4px;
  border-bottom: 1px dotted var(--line);
  line-height: 1.35;
}
.turn-row:last-child { border-bottom: none; }
.turn-label {
  display: inline-block;
  color: var(--text-dim);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  margin-right: 6px;
}
.turn-value {
  display: inline;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: var(--text);
  word-break: break-word;
}

/* Turn action bar (Advance / Download). */
.turn-actions {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 8px;
}
.turn-actions .primary-btn,
.turn-actions .ghost-btn { width: 100%; }

/* GM-only controls — hidden when running in read-only player view (?view=1).
   The .view-only class is added to <html> by app.js when VIEW_ONLY is true. */
html.view-only .gm-only { display: none !important; }

/* Player-view banner — only visible when the tracker is in player view.
   The banner element lives in the sidebar header so it's always on-screen
   without consuming map real estate. */
.view-only-banner {
  display: none;
  margin-top: 6px;
  padding: 3px 6px;
  background: #2a3640;
  border: 1px solid #46c46c;
  border-radius: 2px;
  font-size: 9.5px;
  letter-spacing: 0.18em;
  color: #46c46c;
  text-align: center;
  font-weight: 700;
}
html.view-only .view-only-banner { display: block; }

/* Nation picker dropdown. */
.nation-picker {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 5px 6px;
  border-radius: 2px;
  font-size: 12px;
  margin-bottom: 6px;
}
.nation-picker:focus { border-color: var(--line-strong); outline: none; }
.nation-status { font-size: 12px; }

/* ============ Grid overlay (1000 km cells + 333 km sub-grid) ============ */
.grid-label-marker { pointer-events: none; }
.grid-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  font-weight: 700;
  color: rgba(220, 228, 232, 0.92);
  /* Dual shadow gives readability over both bright land tones and dark water */
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.95),
    0 0 4px rgba(0, 0, 0, 0.8),
    1px 1px 0 rgba(0, 0, 0, 0.7);
  letter-spacing: 0.08em;
  white-space: nowrap;
  user-select: none;
  padding: 1px 3px;
}

/* Sub-grid labels are smaller and slightly dimmer so they don't compete with
   the main grid labels at high zoom; centered in each sub-cell, not top-left. */
.subgrid-label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 8.5px;
  font-weight: 600;
  color: rgba(180, 196, 152, 0.78);     /* olive-tinted to read as the finer tier */
  text-shadow:
    0 0 2px rgba(0, 0, 0, 0.9),
    0 0 3px rgba(0, 0, 0, 0.7);
  letter-spacing: 0.06em;
  white-space: nowrap;
  user-select: none;
  transform: translate(-50%, -50%);     /* center the label on the sub-cell midpoint */
  padding: 0 2px;
}

/* Grid-cell readout near the cursor, top-right corner of the map. */
#grid-readout {
  position: absolute;
  top: 12px;
  right: 56px;
  background: rgba(10, 13, 14, 0.88);
  border: 1px solid var(--line-strong);
  color: var(--accent);
  padding: 4px 10px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  border-radius: 3px;
  z-index: 700;
  pointer-events: none;
  min-width: 56px;
  max-width: 380px;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
}
/* Zoom-level indicator — sits directly below the Leaflet +/- zoom buttons
   in the top-left corner. Default Leaflet zoom control is ~32px wide
   starting at top:10/left:10 and stacks two 30px buttons + borders
   (~64px total), so we sit at top:80 left:10 to clear it. */
#zoom-readout {
  position: absolute;
  top: 80px;
  left: 10px;
  background: rgba(10, 13, 14, 0.88);
  border: 1px solid var(--line-strong);
  color: var(--text);
  padding: 2px 6px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  border-radius: 3px;
  z-index: 700;
  pointer-events: none;
  text-align: center;
  white-space: nowrap;
  min-width: 20px;
  text-overflow: ellipsis;
}

/* ============ Unit status bar (combat model rendering) ============ */
/* Colored bar directly under the NATO symbol, matching the symbol's 42px
   width. Green = full, Yellow = degraded, Red = combat-ineffective. */
.unit-icon .status-bar {
  width: 42px;
  height: 5px;
  margin: 2px auto 0;
  border-radius: 1px;
  border: 1px solid rgba(0, 0, 0, 0.65);
  background: #2cb84a;             /* green default */
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
}
.unit-icon[data-tier="green"]  .status-bar { background: #2cb84a; }
.unit-icon[data-tier="yellow"] .status-bar { background: #f0c33b; }
.unit-icon[data-tier="red"]    .status-bar { background: #e23b3b; }

/* When a unit is combat-ineffective (red tier), dim the whole icon slightly. */
.unit-icon[data-tier="red"] { opacity: 0.78; }

/* ============ Unit modal — grid cell readout row ============ */
.modal-cell-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  margin-bottom: 10px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 11px;
}
.modal-cell-label {
  color: var(--text-dim);
  letter-spacing: 0.08em;
}
.modal-cell-value {
  color: var(--accent);
  font-weight: 600;
  font-family: 'JetBrains Mono', monospace;
  letter-spacing: 0.06em;
}

/* ============ Unit modal — supply/casualty grid + tier preview ============ */
/* Two-column grid for Supply + Casualties number inputs, plus a live
   "status bar" tier badge that mirrors the colored strip on the map icon. */
.modal-status-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-bottom: 8px;
}
.modal-status-grid label { margin: 0; }
.modal-tier-preview {
  margin: 4px 0 12px;
  padding: 8px 10px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
}
.modal-tier-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}
.modal-tier-label {
  color: var(--text-dim);
  letter-spacing: 0.08em;
  font-size: 11px;
}
.m-tier-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 2px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #0a0a0a;
  border: 1px solid rgba(0, 0, 0, 0.45);
}
.m-tier-badge.tier-green  { background: #2cb84a; }
.m-tier-badge.tier-yellow { background: #f0c33b; }
.m-tier-badge.tier-red    { background: #e23b3b; color: #fff; }

/* ============ Parent-buff pip stack (Tracker L1) ============ */
/* Rendered top-right of the unit icon. One small green dot per qualifying
   parent connection; up to 3 visible, then a "+N" badge for the rest. */
.buff-pips {
  position: absolute;
  top: -2px;
  right: -4px;
  display: flex;
  flex-direction: row;
  gap: 1.5px;
  pointer-events: none;
  z-index: 2;
}
.buff-pip {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid rgba(0,0,0,0.65);
  box-shadow: 0 0 2px rgba(46,200,80,0.6);
}
.buff-pip-more {
  display: inline-block;
  font-size: 8px;
  line-height: 9px;
  font-weight: 700;
  color: rgba(46,200,80,1);
  padding: 0 2px;
  text-shadow: 0 0 2px rgba(0,0,0,0.8);
}
/* Position context for the pip stack — the existing .unit-icon is the
   anchor. Force position:relative without overriding any inline style. */
.unit-icon { position: relative; }

/* ============ Parent-buff modal section (Tracker L2) ============ */
/* Lists each parent connection and its qualifying / disqualifying status. */
.modal-buff {
  margin: .6rem 0 .4rem 0;
  padding: .55rem .7rem;
  background: rgba(46,200,80,0.06);
  border: 1px solid rgba(46,200,80,0.25);
  border-radius: 4px;
}
.modal-buff-title {
  font-size: .82rem;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--text, #d6d6d6);
  margin-bottom: .35rem;
}
.modal-buff-count {
  display: inline-block;
  margin-left: .35rem;
  padding: 1px 6px;
  background: rgba(46,200,80,0.9);
  color: #0d1014;
  border-radius: 8px;
  font-size: .7rem;
  font-weight: 700;
}
.modal-buff-count[data-count="0"] {
  background: rgba(120,120,120,0.6);
}
.modal-buff-list {
  display: flex;
  flex-direction: column;
  gap: .3rem;
  margin-bottom: .35rem;
}
.modal-buff-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: .5rem;
  padding: .3rem .45rem;
  background: rgba(255,255,255,0.025);
  border-left: 3px solid #2cb84a;
  border-radius: 2px;
  font-size: .8rem;
}
.modal-buff-row.disqualified {
  border-left-color: #707070;
  opacity: 0.65;
}
.modal-buff-row-name {
  font-weight: 600;
  color: var(--text, #d6d6d6);
}
.modal-buff-row-detail {
  font-size: .72rem;
  color: var(--text-dim, #999);
  margin-top: 1px;
}
.modal-buff-row-detail .ok    { color: #46c46c; }
.modal-buff-row-detail .fail  { color: #e23b3b; }
.modal-buff-row-status {
  font-size: .68rem;
  font-weight: 700;
  letter-spacing: .06em;
  padding: 2px 6px;
  border-radius: 8px;
}
.modal-buff-row-status.active {
  background: rgba(46,200,80,0.9);
  color: #0d1014;
}
.modal-buff-row-status.inactive {
  background: rgba(120,120,120,0.5);
  color: var(--text, #d6d6d6);
}
.modal-buff-empty {
  font-size: .78rem;
  color: var(--text-dim, #999);
  font-style: italic;
}

/* ============ OOB Tree Component (Tracker M) ============
   Recursive tree, two distinct interactions:
     - Chevron button: expand/collapse only (stopPropagation on click)
     - Row click: select the unit, populate side panel
   Leaf nodes have no chevron (rendered as a spacer).
   Keyboard: arrows navigate visible rows; right expands, left collapses,
   enter selects. Focus visible via outline. Aria tree roles applied. */

.oob-tree-body {
  display: grid !important;
  grid-template-columns: 1fr 320px;
  min-height: 0;
  background: var(--bg-0);
}
.oob-tree-pane {
  overflow-y: auto;
  padding: 8px 6px 12px 6px;
  border-right: 1px solid var(--line);
  font-family: 'JetBrains Mono', monospace;
  outline: none;
}
.oob-tree-pane:focus-visible {
  outline: 2px solid var(--accent-dim);
  outline-offset: -2px;
}
.oob-details-pane {
  overflow-y: auto;
  padding: 18px 18px 22px 18px;
  background: var(--bg-1);
  font-family: 'JetBrains Mono', monospace;
}

/* === Tree row ===
   Belt-and-suspenders: every child (chevron, side-dot, badge, name) ALSO
   has its own margin so spacing reads correctly even if the parent's flex
   `gap` doesn't apply for whatever reason (older browser, cascade weirdness,
   stylesheet cache miss). */
.oob-tree-pane .tree-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 30px;
  padding: 2px 8px 2px 4px;
  font-size: 12px;
  color: var(--text);
  border-radius: 3px;
  cursor: pointer;
  user-select: none;
  transition: background-color 80ms;
  position: relative;
}
.oob-tree-pane .tree-row > * + * { margin-left: 0; }  /* gap handles this; keep explicit fallback below */
.tree-row:hover {
  background: rgba(255,255,255,0.04);
}
.tree-row:focus {
  outline: 1px solid var(--accent-dim);
  outline-offset: -1px;
}
.tree-row:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
}
.tree-row[aria-selected="true"] {
  background: rgba(185, 196, 108, 0.16);
  color: var(--accent);
}
.tree-row[aria-selected="true"]:hover {
  background: rgba(185, 196, 108, 0.22);
}
.tree-row[aria-selected="true"] .tree-row-name { font-weight: 700; }

/* Chevron button — clickable independent of row.
   Scoped under the tree pane so we don't fight any global button reset. */
.oob-tree-pane .tree-chevron {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  color: var(--text-dim);
  border-radius: 3px;
  transition: color 80ms, background-color 80ms, transform 150ms;
}
.oob-tree-pane .tree-chevron:hover {
  color: var(--accent);
  background: rgba(185, 196, 108, 0.10);
}
.oob-tree-pane .tree-chevron[aria-expanded="true"] {
  transform: rotate(90deg);
}
/* SVG chevron icon — the path strokes inherit from inline SVG attributes
   (set in JS), not from CSS, so the glyph renders regardless of cascade. */
.oob-tree-pane .tree-chevron svg {
  width: 12px;
  height: 12px;
  display: block;
}
/* Leaf nodes: chevron spacer keeps name alignment consistent */
.oob-tree-pane .tree-chevron-spacer {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
}

/* Echelon badge — small pill on the left of the name */
.tree-badge {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 38px;
  height: 18px;
  padding: 0 6px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--text-dim);
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 2px;
  font-family: 'JetBrains Mono', monospace;
  text-transform: uppercase;
}
.tree-row[aria-selected="true"] .tree-badge {
  color: var(--accent);
  border-color: var(--accent-dim);
  background: rgba(185, 196, 108, 0.12);
}

/* Side dot for nation rows */
.tree-side-dot {
  width: 8px; height: 8px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.4);
}
.tree-side-dot.side-blufor { background: var(--blufor); }
.tree-side-dot.side-opfor  { background: var(--opfor);  }
.tree-side-dot.side-indep  { background: var(--indep);  }

.oob-tree-pane .tree-row-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  margin-left: 0;
}

/* Already-on-map dot inline with name */
.oob-tree-pane .tree-row-placed {
  color: var(--accent);
  font-size: 10px;
  line-height: 10px;
  margin-left: 5px;
  flex-shrink: 0;
}

/* Indentation per depth — 20px per level so the hierarchy is unmistakable.
   Plus a vertical guide line at each indent step (classic file-tree look). */
.oob-tree-pane .tree-row[data-depth="1"],
.oob-tree-pane .tree-section-header[data-depth="1"] { padding-left: 8px; }
.oob-tree-pane .tree-row[data-depth="2"],
.oob-tree-pane .tree-section-header[data-depth="2"] { padding-left: 28px; }
.oob-tree-pane .tree-row[data-depth="3"],
.oob-tree-pane .tree-section-header[data-depth="3"] { padding-left: 48px; }
.oob-tree-pane .tree-row[data-depth="4"],
.oob-tree-pane .tree-section-header[data-depth="4"] { padding-left: 68px; }
.oob-tree-pane .tree-row[data-depth="5"],
.oob-tree-pane .tree-section-header[data-depth="5"] { padding-left: 88px; }
.oob-tree-pane .tree-row[data-depth="6"],
.oob-tree-pane .tree-section-header[data-depth="6"] { padding-left: 108px; }
.oob-tree-pane .tree-row[data-depth="7"],
.oob-tree-pane .tree-section-header[data-depth="7"] { padding-left: 128px; }
.oob-tree-pane .tree-row[data-depth="8"],
.oob-tree-pane .tree-section-header[data-depth="8"] { padding-left: 148px; }

/* Vertical indent guide — a thin line at each indent level.
   Rendered via repeating-linear-gradient on the row background so it scales
   with depth without per-depth duplicate rules. The first 8px is padding,
   then guide lines at 18px, 38px, 58px, 78px... (20px apart). */
.oob-tree-pane .tree-row[data-depth="2"],
.oob-tree-pane .tree-row[data-depth="3"],
.oob-tree-pane .tree-row[data-depth="4"],
.oob-tree-pane .tree-row[data-depth="5"],
.oob-tree-pane .tree-row[data-depth="6"],
.oob-tree-pane .tree-row[data-depth="7"],
.oob-tree-pane .tree-row[data-depth="8"] {
  background-image:
    linear-gradient(to right, transparent 17px, rgba(255,255,255,0.06) 17px, rgba(255,255,255,0.06) 18px, transparent 18px);
  background-repeat: no-repeat;
}
.oob-tree-pane .tree-row[data-depth="3"] {
  background-image:
    linear-gradient(to right,
      transparent 17px, rgba(255,255,255,0.06) 17px, rgba(255,255,255,0.06) 18px,
      transparent 18px, transparent 37px,
      rgba(255,255,255,0.06) 37px, rgba(255,255,255,0.06) 38px,
      transparent 38px);
}
.oob-tree-pane .tree-row[data-depth="4"] {
  background-image:
    linear-gradient(to right,
      transparent 17px, rgba(255,255,255,0.06) 17px, rgba(255,255,255,0.06) 18px,
      transparent 18px, transparent 37px,
      rgba(255,255,255,0.06) 37px, rgba(255,255,255,0.06) 38px,
      transparent 38px, transparent 57px,
      rgba(255,255,255,0.06) 57px, rgba(255,255,255,0.06) 58px,
      transparent 58px);
}
.oob-tree-pane .tree-row[data-depth="5"] {
  background-image:
    linear-gradient(to right,
      transparent 17px, rgba(255,255,255,0.06) 17px, rgba(255,255,255,0.06) 18px,
      transparent 18px, transparent 37px,
      rgba(255,255,255,0.06) 37px, rgba(255,255,255,0.06) 38px,
      transparent 38px, transparent 57px,
      rgba(255,255,255,0.06) 57px, rgba(255,255,255,0.06) 58px,
      transparent 58px, transparent 77px,
      rgba(255,255,255,0.06) 77px, rgba(255,255,255,0.06) 78px,
      transparent 78px);
}

/* Section header — non-clickable label that groups rows by echelon
   ("FIELD ARMIES", "CORPS", "DIVISIONS", "INDEPENDENT BRIGADES", etc.).
   Inserted between rows when a node's children mix multiple echelons. */
.oob-tree-pane .tree-section-header {
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 700;
  padding-top: 12px;
  padding-bottom: 4px;
  margin: 0;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  user-select: none;
  pointer-events: none;
}
.oob-tree-pane .tree-section-header + .tree-row {
  margin-top: 2px;
}

/* === Details panel === */
.oob-details-empty {
  font-size: 12px;
  color: var(--text-faint);
  font-style: italic;
  text-align: center;
  padding: 60px 12px;
}
.oob-details-header {
  margin-bottom: 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.oob-details-badges {
  display: flex;
  gap: 5px;
  margin-bottom: 8px;
}
.oob-details-name {
  font-size: 16px;
  font-weight: 700;
  color: var(--text);
  line-height: 22px;
  word-break: break-word;
}
.oob-details-subtitle {
  margin-top: 3px;
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.oob-details-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 11.5px;
}
.oob-details-row {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 12px;
  padding: 4px 0;
}
.oob-details-row-label {
  color: var(--text-dim);
  font-size: 10.5px;
  letter-spacing: 0.04em;
}
.oob-details-row-value {
  color: var(--text);
  text-align: right;
  word-break: break-word;
}
.oob-details-actions {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.oob-details-action {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 8px 14px;
  font-size: 11px;
  border-radius: 3px;
  cursor: pointer;
  font-family: 'JetBrains Mono', monospace;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: background-color 80ms, border-color 80ms, color 80ms;
}
.oob-details-action.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg-0);
}
.oob-details-action.primary:hover {
  background: var(--accent-dim);
  border-color: var(--accent-dim);
}
.oob-details-action:hover {
  color: var(--accent);
  border-color: var(--accent-dim);
}

/* Mobile / narrow modal: stack tree above details */
@media (max-width: 720px) {
  .oob-tree-body { grid-template-columns: 1fr !important; }
  .oob-details-pane { border-top: 1px solid var(--line); max-height: 280px; }
}

/* ============ OOB / Installations Browsers — redesigned UX (v2) ============
/* ============ OOB Browser — drill-down navigation ============ */
/*
 * Old approach was a recursive <details>/<summary> tree with cascading indent
 * CSS. With an 8-level military hierarchy in a ~280px sidebar, that always
 * looked bad. Browser default <details> rendering also kept escaping our
 * overrides. So: replaced with a flat-list-per-level drill-down. The sidebar
 * shows ONE level at a time. A breadcrumb at the top tracks where you are
 * and lets you jump back. Zero horizontal indent. Scales to any depth.
 *
 * DOM shape (built in app.js renderOOBBrowser):
 *   #oob-tree
 *     .oob-filter > input.oob-search
 *     .oob-breadcrumb       (skipped when search is active)
 *       button.oob-breadcrumb-back  (only when path.length > 1)
 *       span.oob-breadcrumb-crumb [.oob-breadcrumb-current]
 *       span.oob-breadcrumb-sep
 *       ... more crumbs ...
 *     .oob-list             (the items at the current level)
 *       .oob-list-row[.oob-list-row-clickable]
 *         span.oob-side-dot (nations only)
 *         span.oob-list-name
 *         span.oob-placed   (if deployed on map)
 *         span.oob-chevron  (›  — shown if hasChildren)
 *         button.oob-deploy (+ button — shown if deployable)
 *     .oob-list.oob-search-list  (alternate; when search active)
 *       .oob-list-row.oob-search-result
 *         div.oob-search-main { name, deploy }
 *         div.oob-search-path { breadcrumb path of where match lives }
 */

.oob-tree {
  padding: 0;
  max-height: 480px;
  overflow-y: auto;
}

/* --- Search input --- */
.oob-filter {
  padding: 6px 6px 8px;
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0;
  background: var(--bg-1);
  z-index: 2;
}
.oob-filter input {
  width: 100%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 5px 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  border-radius: 3px;
  box-sizing: border-box;
}
.oob-filter input:focus { outline: none; border-color: var(--accent-dim); }

/* --- Breadcrumb bar --- */
.oob-breadcrumb {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 6px;
  padding: 8px 8px 8px 6px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line);
  font-size: 10.5px;
  font-family: 'JetBrains Mono', monospace;
}
.oob-breadcrumb-back {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  font-size: 12px;
  line-height: 14px;
  padding: 1px 7px;
  border-radius: 2px;
  cursor: pointer;
  margin-right: 4px;
}
.oob-breadcrumb-back:hover { color: var(--accent); border-color: var(--accent-dim); }
.oob-breadcrumb-crumb {
  color: var(--text-dim);
  cursor: pointer;
  padding: 1px 2px;
}
.oob-breadcrumb-crumb:hover { color: var(--accent); }
.oob-breadcrumb-current {
  color: var(--text);
  font-weight: 600;
  cursor: default;
}
.oob-breadcrumb-current:hover { color: var(--text); }
.oob-breadcrumb-sep {
  color: var(--text-faint);
  user-select: none;
}

/* --- List of items at the current level --- */
.oob-list {
  display: block;
}
.oob-list-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 8px 7px 10px;
  border-bottom: 1px solid var(--bg-2);
  font-size: 11px;
  color: var(--text);
  font-family: 'JetBrains Mono', monospace;
}
.oob-list-row-clickable { cursor: pointer; }
.oob-list-row-clickable:hover { background: var(--bg-2); }

.oob-list-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Side color dot (BLUFOR/OPFOR/INDEP) --- */
.oob-side-dot {
  width: 8px; height: 8px;
  border-radius: 2px;
  display: inline-block;
  flex-shrink: 0;
}
.oob-side-dot.side-blufor { background: var(--blufor); }
.oob-side-dot.side-opfor  { background: var(--opfor);  }
.oob-side-dot.side-indep  { background: var(--indep);  }

/* --- Drill chevron — shows on rows that have children --- */
.oob-chevron {
  color: var(--text-faint);
  font-size: 14px;
  line-height: 12px;
  flex-shrink: 0;
  user-select: none;
}
.oob-list-row-clickable:hover .oob-chevron { color: var(--accent); }

/* --- "deployed" indicator on rows that are already on the map --- */
.oob-placed {
  font-size: 8.5px;
  color: var(--accent);
  letter-spacing: 0.08em;
  padding: 1px 5px;
  background: rgba(185, 196, 108, 0.12);
  border: 1px solid var(--accent-dim);
  border-radius: 2px;
  flex-shrink: 0;
  text-transform: uppercase;
}

/* --- + deploy button (in both drill-down rows and search results) --- */
.oob-deploy {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  padding: 0 8px;
  font-size: 14px;
  line-height: 18px;
  border-radius: 2px;
  flex-shrink: 0;
  cursor: pointer;
  font-family: inherit;
}
.oob-deploy:hover { color: var(--accent); border-color: var(--accent-dim); }

/* --- Empty / "no matches" / "+N more" placeholder text --- */
.oob-empty {
  padding: 14px 10px;
  font-size: 10.5px;
  color: var(--text-faint);
  font-style: italic;
  text-align: center;
}

/* --- Search results: each row is a unit + its breadcrumb path --- */
.oob-search-list .oob-list-row {
  flex-direction: column;
  align-items: stretch;
  padding: 6px 8px 6px 10px;
  gap: 2px;
}
.oob-search-main {
  display: flex;
  align-items: center;
  gap: 6px;
}
.oob-search-main .oob-list-name { flex: 1; }
.oob-search-path {
  font-size: 9px;
  color: var(--text-faint);
  letter-spacing: 0.04em;
  padding-left: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============ NATO unit symbol (PNG) ============ */
.unit-icon .unit-symbol {
  width: 44px;
  height: 44px;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.65));
  display: block;
  margin: 0 auto;
}
/* When the PNG fails to load (no matching file), onerror reveals the glyph
   fallback — keep the glyph's flex display intact for that path. */
.unit-icon .unit-glyph.fallback {
  width: 38px; height: 38px;
  align-items: center; justify-content: center;
}

/* ============ Installations ============
 * Map markers for fixed positions (capitals, bases, depots, etc.) and the
 * sidebar roster panel that lists them grouped by nation. Markers are
 * intentionally a bit smaller than unit icons so they read as "background"
 * features that units sit on top of. */

/* Reset Leaflet's default marker styling — we draw the icon entirely inside
   our own .install-icon container. Use !important to win against any other
   .leaflet-marker-icon defaults. */
.leaflet-marker-icon.install-marker {
  background: transparent !important;
  border: 0 !important;
}
.leaflet-marker-icon.install-marker .install-icon {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  width: 60px !important;
  pointer-events: auto;
  user-select: none;
}
/* Symbol PNG size — match unit symbols at 44x44 per user spec. The
   !important + .leaflet-marker-icon prefix beats any other rule that could
   try to set the img's natural dimensions. */
.leaflet-marker-icon.install-marker .install-symbol {
  width: 44px !important;
  height: 44px !important;
  max-width: 44px !important;
  max-height: 44px !important;
  object-fit: contain !important;
  display: block !important;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.7));
}
/* Side-tinted glow — subtle hue cast so the same shape reads as
   blufor / opfor / indep at a glance. */
.leaflet-marker-icon.install-marker .install-icon[data-side="blufor"] .install-symbol { filter: drop-shadow(0 0 2px rgba(80, 150, 220, .65)) drop-shadow(0 1px 2px rgba(0,0,0,.7)); }
.leaflet-marker-icon.install-marker .install-icon[data-side="opfor"]  .install-symbol { filter: drop-shadow(0 0 2px rgba(220, 80,  80, .65)) drop-shadow(0 1px 2px rgba(0,0,0,.7)); }
.leaflet-marker-icon.install-marker .install-icon[data-side="indep"]  .install-symbol { filter: drop-shadow(0 0 2px rgba(180, 130, 220, .65)) drop-shadow(0 1px 2px rgba(0,0,0,.7)); }
/* Letter fallback shown only when the PNG fails to load (onerror handler reveals it). */
.leaflet-marker-icon.install-marker .install-fallback {
  display: none;
  width: 38px;
  height: 38px;
  align-items: center;
  justify-content: center;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 11px;
  font-family: 'JetBrains Mono', monospace;
  font-weight: 700;
  color: var(--text);
}
.leaflet-marker-icon.install-marker .install-name {
  margin-top: 1px;
  background: rgba(10, 13, 14, .85);
  border: 1px solid var(--line);
  padding: 1px 6px;
  font-size: 10px;
  font-family: 'JetBrains Mono', monospace;
  color: var(--text);
  white-space: nowrap;
  max-width: 130px;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: 0.02em;
}

/* --- Sidebar roster panel: placed installations grouped by nation --- */
#installations-list { padding: 0; max-height: 360px; overflow-y: auto; }
.inst-nation-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  background: var(--bg-1);
  border-top: 1px solid var(--line);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.03em;
  color: var(--text);
  position: sticky;
  top: 0;
  z-index: 1;
}
.inst-nation-name { flex: 1; }
.inst-nation-count {
  font-size: 9px;
  color: var(--text-dim);
  background: var(--bg-2);
  padding: 1px 5px;
  border-radius: 8px;
  font-family: 'JetBrains Mono', monospace;
}
.inst-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 4px 8px 4px 14px;
  border-bottom: 1px dotted var(--bg-2);
  font-size: 10.5px;
  cursor: pointer;
  color: var(--text);
}
.inst-row:hover { background: var(--bg-2); }
.inst-row-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: 'JetBrains Mono', monospace;
}
.inst-row-type {
  font-size: 9px;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  flex-shrink: 0;
}

/* ===== Install-modal garrison rows + ferry-to dropdown ===== */
.inst-garrison-title {
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin: 12px 0 6px;
  padding-bottom: 4px;
  border-bottom: 1px dotted var(--line);
}
.inst-garrison-list {
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: rgba(0,0,0,0.18);
}
.inst-garrison-empty {
  padding: 12px;
  font-size: 11px;
  color: var(--text-faint);
  text-align: center;
  font-style: italic;
}
.inst-garrison-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-bottom: 1px dotted var(--bg-2);
  font-size: 11px;
  font-family: 'JetBrains Mono', monospace;
}
.inst-garrison-row:last-child { border-bottom: 0; }
.inst-garrison-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.inst-garrison-meta {
  font-size: 9px;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.inst-ferry-to {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 2px 4px;
  font-size: 9.5px;
  font-family: 'JetBrains Mono', monospace;
  border-radius: 2px;
  max-width: 140px;
  cursor: pointer;
}
.inst-ferry-to:hover { border-color: var(--accent-dim); }
.inst-garrison-sortie {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  padding: 2px 10px;
  font-size: 10px;
  font-family: inherit;
  border-radius: 2px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.inst-garrison-sortie:hover { color: var(--accent); border-color: var(--accent-dim); }

/* Range-ring toggle button on garrison rows + carrier air-wing rows.
   Visually distinct from sortie button so GMs can tell them apart at a glance. */
.inst-garrison-range,
.modal-airwing-range {
  background: var(--bg-2);
  border: 1px solid #3a4d62;
  color: #7fb3ff;
  padding: 2px 8px;
  font-size: 10px;
  font-family: inherit;
  border-radius: 2px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.inst-garrison-range:hover,
.modal-airwing-range:hover { border-color: #5d7da5; color: #a8c8ff; }

/* Carrier air-wing section in the unit modal (Tracker D).
   Same shape as the installation garrison list. */
.modal-airwing {
  margin: 6px 0 12px;
  padding: 8px 10px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
}
.modal-airwing-title {
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 6px;
}
.modal-airwing-list { display: flex; flex-direction: column; gap: 4px; }
.modal-airwing-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 11px;
  font-family: 'JetBrains Mono', monospace;
}
.modal-airwing-name {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.modal-airwing-meta {
  font-size: 9px;
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.modal-airwing-launch {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text-dim);
  padding: 2px 10px;
  font-size: 10px;
  font-family: inherit;
  border-radius: 2px;
  cursor: pointer;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.modal-airwing-launch:hover { color: var(--accent); border-color: var(--accent-dim); }

/* VIEW_ONLY (player view): visually mute disabled/readonly inputs in the
   installation modal so it's obvious they're for display, not editing. */
html.view-only input[readonly],
html.view-only select:disabled,
html.view-only textarea[readonly] {
  background: var(--bg-1);
  color: var(--text-dim);
  cursor: default;
  opacity: 0.85;
}

/* ============ Nation Status / Battle Log / Diplomatic State (Tracker J) ============ */
.nation-status-body {
  font-size: 11px;
  line-height: 1.45;
}
.nation-status-section {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dotted var(--line);
}
.nation-status-section:first-child { border-top: none; margin-top: 0; padding-top: 0; }
.nation-status-section-title {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 3px;
}
/* Block layout with inline label+value so long values wrap cleanly under
   the label in the narrow sidebar (same lesson as Turn Status panel). */
.ns-row {
  display: block;
  padding: 3px 0;
  line-height: 1.4;
}
.ns-label {
  display: inline-block;
  color: var(--text-dim);
  font-size: 10.5px;
  margin-right: 6px;
}
.ns-value {
  display: inline;
  color: var(--text);
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  word-break: break-word;
}
.ns-note {
  font-size: 10px;
  color: var(--text-faint);
  font-style: italic;
  margin-top: 4px;
  line-height: 1.4;
}
.ns-bar {
  display: inline-block;
  height: 6px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 1px;
  vertical-align: middle;
  width: 60px;
  margin-right: 4px;
  position: relative;
  overflow: hidden;
}
.ns-bar > span {
  position: absolute; top: 0; left: 0; bottom: 0;
  background: var(--accent);
}
.ns-bar.low > span     { background: #e23b3b; }
.ns-bar.medium > span  { background: #f0c33b; }
.ns-bar.high > span    { background: #2cb84a; }

/* Battle Log */
.battle-log-list { display: flex; flex-direction: column; gap: 3px; }
.battle-row {
  display: flex; flex-direction: column;
  gap: 1px;
  padding: 5px 7px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  cursor: pointer;
  font-size: 11px;
}
.battle-row:hover { border-color: var(--accent-dim); }
.battle-row-head { display: flex; justify-content: space-between; gap: 6px; align-items: baseline; }
.battle-name { color: var(--text); font-weight: 500; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.battle-date { color: var(--text-faint); font-family: 'JetBrains Mono', monospace; font-size: 9.5px; flex-shrink: 0; }
.battle-meta { font-size: 9.5px; color: var(--text-dim); }
.battle-outcome { font-style: italic; }
.battle-outcome.win  { color: #46c46c; }
.battle-outcome.loss { color: #e23b3b; }
.battle-outcome.draw { color: #f0c33b; }
.battle-outcome.gain { color: #7fb3ff; }

/* Diplomatic State */
.diplo-section {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dotted var(--line);
}
.diplo-section:first-child { border-top: none; margin-top: 0; padding-top: 0; }
.diplo-section-title {
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 4px;
}
.diplo-alliance {
  margin-bottom: 6px;
  padding: 4px 6px;
  background: var(--bg-2);
  border-left: 2px solid var(--accent-dim);
  font-size: 11px;
}
.diplo-alliance-name {
  font-weight: 600;
  color: var(--text);
  font-size: 11.5px;
}
.diplo-alliance-meta { color: var(--text-dim); font-size: 10px; margin-top: 2px; }
.diplo-chips { display: flex; flex-wrap: wrap; gap: 3px; margin-top: 4px; }
.diplo-chip {
  display: inline-block;
  padding: 1px 6px;
  background: var(--bg-1);
  border: 1px solid var(--line);
  border-radius: 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9.5px;
  color: var(--text);
}
.diplo-chip.belligerent { border-color: #e23b3b; color: #ee8585; }
.diplo-chip.neutral     { border-color: #7d8085; color: var(--text-dim); }
.diplo-item {
  font-size: 11px;
  color: var(--text);
  margin-bottom: 4px;
  padding-left: 6px;
  border-left: 2px solid var(--line);
}
.diplo-item-title { font-weight: 600; }
.diplo-item-meta  { font-size: 10px; color: var(--text-dim); }

/* Info modal (battle report viewer + generic read-only content) */
.modal-wide {
  max-width: 760px;
  width: 90vw;
  max-height: 86vh;
  display: flex;
  flex-direction: column;
}
.info-meta {
  font-size: 11px;
  color: var(--text-dim);
  font-family: 'JetBrains Mono', monospace;
  padding: 4px 6px 8px;
  border-bottom: 1px dotted var(--line);
  margin-bottom: 8px;
}
.info-body {
  flex: 1;
  overflow: auto;
  background: var(--bg-2);
  border: 1px solid var(--line);
  padding: 12px 14px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--text);
  font-family: 'JetBrains Mono', monospace;
  white-space: pre-wrap;
  word-break: break-word;
  border-radius: 3px;
  margin-bottom: 8px;
  max-height: 60vh;
}

/* ============ Air Ops Plan (Tracker F) ============ */
/* Sidebar mission list — each mission is a compact row with type badge,
   target grid, squadron count, and an edit/remove affordance. */
.airops-list {
  display: flex; flex-direction: column; gap: 4px;
  margin-bottom: 8px;
}
.airops-empty {
  font-size: 11px;
  color: var(--text-faint);
  font-style: italic;
  padding: 6px 4px;
}
.airops-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  font-size: 11px;
  cursor: pointer;
}
.airops-row:hover { border-color: var(--accent-dim); }
.airops-type {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 2px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: #0a0a0a;
}
.airops-type.t-cas    { background: #f0c33b; }
.airops-type.t-strike { background: #e23b3b; color: #fff; }
.airops-type.t-cap    { background: #3b8be2; color: #fff; }
.airops-type.t-sead   { background: #a040c8; color: #fff; }
.airops-type.t-awacs  { background: #2cb84a; }
.airops-type.t-recon  { background: #8a98a0; color: #fff; }
.airops-target {
  font-family: 'JetBrains Mono', monospace;
  color: var(--text);
  font-size: 11px;
}
.airops-meta {
  flex: 1;
  font-size: 10px;
  color: var(--text-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Air-mission modal — cascading squadron picker.
   Selected squadrons live as chips at the top; nation→base dropdowns
   below filter the squadron checkbox list so users aren't drowning in
   every squadron across every nation. */
.ao-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  min-height: 28px;
  padding: 4px;
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 3px;
  margin-bottom: 6px;
}
.ao-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 6px 2px 8px;
  background: var(--bg-1);
  border: 1px solid var(--accent-dim);
  border-radius: 12px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  color: var(--text);
}
.ao-chip-x {
  cursor: pointer;
  font-size: 13px;
  line-height: 13px;
  color: var(--text-dim);
  padding: 0 2px;
}
.ao-chip-x:hover { color: var(--accent); }
.ao-chips-empty {
  font-style: italic;
  color: var(--text-faint);
  font-size: 10.5px;
  padding: 4px 6px;
}
.ao-picker-row {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 6px;
  margin-bottom: 4px;
}
.ao-cascade-sel {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 4px 6px;
  font-size: 11px;
  border-radius: 3px;
}
.ao-cascade-sel:disabled { opacity: 0.5; cursor: not-allowed; }
.ao-cascade-sel:focus { outline: none; border-color: var(--accent-dim); }

.ao-squadron-list {
  max-height: 160px;
  overflow-y: auto;
  border: 1px solid var(--line);
  border-radius: 3px;
  background: var(--bg-2);
  padding: 4px;
  margin-bottom: 6px;
}
.ao-sqn-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 3px 6px;
  font-size: 11px;
  font-family: 'JetBrains Mono', monospace;
}
.ao-sqn-row:hover { background: var(--bg-1); }
.ao-sqn-row input[type="checkbox"] { cursor: pointer; }
.ao-sqn-name { color: var(--text); }
.ao-sqn-loc  { color: var(--text-faint); font-size: 10px; margin-left: auto; }
.ao-sqn-empty {
  font-style: italic;
  color: var(--text-faint);
  font-size: 11px;
  padding: 6px;
}

/* ============ OOB Explorer modal ============ */
.modal-explorer {
  max-width: 920px;
  width: 92vw;
  max-height: 88vh;
  padding: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-1);
}
.explorer-titlebar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--line);
  border-radius: 4px 4px 0 0;
}
.explorer-title {
  font-size: 11px;
  letter-spacing: 0.22em;
  color: var(--accent);
  font-weight: 700;
}
.explorer-close {
  background: transparent;
  border: none;
  color: var(--text-dim);
  font-size: 22px;
  line-height: 22px;
  cursor: pointer;
  padding: 0 4px;
}
.explorer-close:hover { color: var(--accent); }

.explorer-addressbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--bg-1);
  border-bottom: 1px solid var(--line);
}
.explorer-nav-btn {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 2px 9px;
  font-size: 13px;
  border-radius: 3px;
  cursor: pointer;
}
.explorer-nav-btn:hover { border-color: var(--accent-dim); color: var(--accent); }
.explorer-breadcrumb {
  flex: 1;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  color: var(--text-dim);
  background: var(--bg-0);
  border: 1px solid var(--line);
  border-radius: 3px;
  padding: 4px 8px;
  min-height: 24px;
}
.explorer-crumb { cursor: pointer; padding: 1px 2px; }
.explorer-crumb:hover { color: var(--accent); }
.explorer-crumb-current { color: var(--text); font-weight: 600; cursor: default; }
.explorer-crumb-current:hover { color: var(--text); }
.explorer-crumb-sep { color: var(--text-faint); user-select: none; }
.explorer-search {
  background: var(--bg-2);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 4px 8px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  border-radius: 3px;
  width: 200px;
}
.explorer-search:focus { outline: none; border-color: var(--accent-dim); }

.explorer-body {
  flex: 1;
  display: grid;
  grid-template-columns: 240px 1fr;
  min-height: 0;
  background: var(--bg-0);
}
/* Single-column variant: used by the OOB drill-down browser and the
   Installations browser, both of which render their content into a single
   wide list pane (no separate tree column). */
.explorer-body-single {
  grid-template-columns: 1fr;
}
.explorer-tree-pane {
  border-right: 1px solid var(--line);
  overflow-y: auto;
  padding: 4px 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
}
.explorer-list-pane {
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.modal-oob #oob-tree {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  overflow-y: auto;
  padding: 0;
}
/* The drill-down renderer creates its own .oob-filter (search input) inside
   #oob-tree on every render. Since we also have an addressbar search input,
   we hide the in-pane duplicate — the addressbar one is the active control. */
.modal-oob .oob-filter { display: none; }

/* ============ Roster: nation headers (Tracker player-view) ============ */
/* Section heads above the roster items, one per nation; tinted by side. */
.ri-nation-head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  margin-top: 6px;
  background: var(--bg-1);
  border-top: 1px solid var(--line);
  border-left: 2px solid var(--text-faint);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--text);
  position: sticky;
  top: 0;
  z-index: 1;
}
.ri-nation-head.side-blufor { border-left-color: var(--blufor); }
.ri-nation-head.side-opfor  { border-left-color: var(--opfor); }
.ri-nation-head.side-indep  { border-left-color: var(--indep); }
.ri-nation-name  { flex: 1; }
.ri-nation-count {
  font-size: 9px;
  color: var(--text-dim);
  background: var(--bg-2);
  padding: 1px 6px;
  border-radius: 8px;
  font-family: 'JetBrains Mono', monospace;
}

/* ============ Unit Orders Plan — order-type badge colors ============ */
/* Reuse .airops-type pill shape; just add color palette for our types. */
.airops-type.t-form-up    { background: #f0c33b; }                /* yellow */
.airops-type.t-move       { background: #3b8be2; color: #fff; }   /* blue */
.airops-type.t-hold       { background: #8a98a0; color: #fff; }   /* grey */
.airops-type.t-attack     { background: #e23b3b; color: #fff; }   /* red */
.airops-type.t-embark     { background: #2cb84a; }                /* green */
.airops-type.t-disembark  { background: #46c46c; }                /* light green */
.airops-type.t-garrison   { background: #a040c8; color: #fff; }   /* purple */
.airops-type.t-sortie     { background: #d39a3a; }                /* amber */
.airops-type.t-other      { background: #5e6a73; color: #fff; }


/* ============ Unit modal — widened layout + dynamic header ============
   Unit modal needs more horizontal space than the default 360px because of
   the embarked-units list and parent-buff section. Also subtitle row. */
.modal.modal-unit {
  width: 600px;
  max-width: 92vw;
}
.modal.modal-unit .modal-title {
  font-size: 14px;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--text);
  margin-bottom: 4px;
  line-height: 1.3;
  word-break: break-word;
}
.modal-subtitle {
  font-size: 11px;
  color: var(--text-dim);
  letter-spacing: 0.08em;
  margin-bottom: 14px;
  font-family: 'JetBrains Mono', monospace;
}

/* ============ OOB details pane — wider + scrollable ============
   The right-hand details pane in the OOB Browser was 320px which clipped
   long unit names ("1st Armored Brigade Combat Team, 2nd Armored Division")
   to the first letter when drilling deep. Widen + give it both axes of scroll. */
.oob-tree-body {
  grid-template-columns: 1fr 460px !important;
}
.oob-details-pane {
  overflow-x: auto;
  overflow-y: auto;
  word-break: break-word;
}
.oob-details-name {
  word-break: break-word;
}
@media (max-width: 900px) {
  .oob-tree-body { grid-template-columns: 1fr !important; }
}

