:root {
  --color-bg: #07111f; --color-bg-deep: #050b14; --color-surface: #0d1b2b; --color-surface-raised: #14283d;
  --color-text: #f5f9fc; --color-text-secondary: #d8e5ee; --color-text-muted: #8fa6b7;
  --color-border: rgba(216, 229, 238, 0.12);
  --color-signal: #22d3ee; --color-signal-highlight: #67e8f9; --color-forecast: #6366f1; --color-fusion: #a855f7;
  --color-ok: #22c55e; --color-warning: #f59e0b; --color-danger: #ef4444; --color-unknown: #64748b;
  --radius-control: 8px; --radius-panel: 12px;
  --font-sans: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Consolas, monospace;
  --shadow-panel: 0 12px 36px rgba(0, 0, 0, 0.32);
  --duration-fast: 150ms; --duration-standard: 240ms; --duration-data: 450ms;
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --rail-w: 340px;
}
* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; }
body { background: var(--color-bg); color: var(--color-text); font: 500 14px/20px var(--font-sans); font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); font-weight: 400; }
#app { position: relative; height: 100%; overflow: hidden; }
#map { position: absolute; inset: 0; right: var(--rail-w); background: var(--color-bg-deep); }
.leaflet-container { font-family: var(--font-sans); background: var(--color-bg-deep); }
.leaflet-tile-pane { filter: saturate(0.45) brightness(0.9); }
/* OSM standard tiles are light: invert + hue-rotate gives a dark basemap that keeps roads/labels legible */
.tiles-osm .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) saturate(0.35) brightness(0.8) contrast(0.9); }
.leaflet-control-attribution { background: rgba(7,17,31,.7) !important; color: var(--color-text-muted) !important; font-size: 10px; }
.leaflet-control-attribution a { color: var(--color-signal) !important; }

.leaflet-top.leaflet-right { top: 52px; }
.leaflet-bar a { background: var(--color-surface); color: var(--color-text); border-bottom-color: var(--color-border); }
.leaflet-bar a:hover { background: var(--color-surface-raised); }
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--color-surface-raised); color: var(--color-text); box-shadow: var(--shadow-panel); }
.leaflet-popup-content { margin: 12px 14px; font: 500 13px/18px var(--font-sans); }
.leaflet-tooltip { background: var(--color-surface-raised); color: var(--color-text); border: 1px solid var(--color-border); font: 500 12px/16px var(--font-sans); box-shadow: none; padding: 3px 8px; border-radius: 6px; }
.leaflet-tooltip-top:before { border-top-color: var(--color-surface-raised); }
.leaflet-tooltip.chip-class { background: var(--color-fusion); color: var(--color-bg); border: 0; font-weight: 600; }
.leaflet-tooltip.map-label { background: transparent; border: 0; color: #fff; font: 550 11px/14px var(--font-mono); letter-spacing: .04em; text-shadow: 0 1px 2px #000; padding: 0; }

/* top bar */
.topbar { position: absolute; top: 0; left: 0; right: var(--rail-w); display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; pointer-events: none; z-index: 800; }
.topbar > * { pointer-events: auto; }
.brand { display: flex; align-items: center; gap: 10px; background: rgba(13,27,43,.85); backdrop-filter: blur(8px); padding: 6px 12px 6px 6px; border-radius: 999px; border: 1px solid var(--color-border); }
.brand img { border-radius: 8px; }
.wordmark { font-weight: 650; font-size: 15px; letter-spacing: -.01em; }
.scenario { color: var(--color-text-muted); font-size: 12px; }
.netstat { color: var(--color-text-secondary); font-size: 12px; border-left: 1px solid var(--color-border); padding-left: 10px; max-width: 460px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topright { display: flex; gap: 10px; align-items: center; }
#clock { background: rgba(13,27,43,.85); padding: 6px 10px; border-radius: 999px; border: 1px solid var(--color-border); color: var(--color-text-secondary); font-size: 12px; }

.badge { display: inline-block; font-size: 10px; line-height: 14px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; padding: 1px 7px; border-radius: 999px; vertical-align: middle; }
.badge-replay { background: rgba(245,158,11,.2); color: #fcd34d; border: 1px solid rgba(245,158,11,.5); font-size: 12px; padding: 3px 10px; }

.chip { display: inline-flex; align-items: center; gap: 6px; padding: 6px 10px; border-radius: 999px; background: rgba(13,27,43,.85); border: 1px solid var(--color-border); font-size: 12px; }
.chip .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--color-unknown); }
.chip-ok .dot { background: var(--color-ok); } .chip-warn .dot { background: var(--color-warning); } .chip-danger .dot { background: var(--color-danger); }

/* layer control */
.layers { position: absolute; left: 16px; top: 64px; z-index: 800; background: rgba(13,27,43,.9); backdrop-filter: blur(8px); border: 1px solid var(--color-border); border-radius: var(--radius-panel); padding: 8px 10px; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.layers label { display: flex; align-items: center; gap: 8px; padding: 3px 2px; cursor: pointer; }
.layers input { accent-color: var(--color-signal); width: 16px; height: 16px; }
.layers .btn { margin-top: 6px; }
.source-legend { display: flex; flex-direction: column; gap: 2px; padding: 0 2px 2px 26px; color: var(--color-text-muted, #8fa6b7); font-size: 12px; }
.source-legend:empty { display: none; }
.source-legend span, .legend .src-row { display: inline-flex; align-items: center; gap: 6px; }
.src-key { display: inline-block; width: 8px; height: 8px; flex: none; }
.src-key.src-dot { border-radius: 50%; }
.src-key.src-diamond, .src-diamond { transform: rotate(45deg); }
.src-diamond { width: 9px; height: 9px; margin: 1.5px; border: 1px solid #07111f; }
.src-square { width: 9px; height: 9px; margin: 1.5px; border: 1px solid #07111f; }
.src-key.src-triangle, .src-triangle { clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.src-triangle { width: 12px; height: 11px; }
.layers-toggle { display: none; position: absolute; left: 16px; top: 64px; z-index: 801; }

/* empty state */
.empty-card { position: absolute; left: calc(50% - var(--rail-w) / 2); top: 50%; transform: translate(-50%, -50%); z-index: 750; max-width: 360px; display: flex; flex-direction: column; gap: 6px; text-align: center; background: rgba(13,27,43,.92); backdrop-filter: blur(8px); border: 1px solid var(--color-border); border-radius: var(--radius-panel); box-shadow: var(--shadow-panel); padding: 16px 20px; }
.empty-card strong { font-size: 15px; }
.empty-card span { color: var(--color-text-secondary); font-size: 13px; line-height: 18px; }
.empty-card code { color: var(--color-signal); font-size: 12px; }
@media (max-width: 900px) { .empty-card { top: 27.5%; } }

/* stale overlay */
.stale-overlay { position: absolute; left: 0; right: var(--rail-w); top: 0; bottom: 0; z-index: 700; pointer-events: none; background: repeating-linear-gradient(135deg, rgba(245,158,11,.05) 0 12px, transparent 12px 24px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; }
.stale-overlay strong, .stale-overlay span { background: rgba(7,17,31,.9); padding: 6px 12px; border-radius: var(--radius-control); border: 1px solid var(--color-warning); }
.stale-overlay span { border-color: var(--color-border); color: var(--color-text-secondary); font-family: var(--font-mono); font-size: 12px; }

/* rail */
.rail { position: absolute; top: 0; right: 0; bottom: 0; width: var(--rail-w); background: var(--color-surface); border-left: 1px solid var(--color-border); display: flex; flex-direction: column; gap: 8px; padding: 12px; overflow-y: auto; z-index: 900; }
.card { background: var(--color-bg); border: 1px solid var(--color-border); border-radius: var(--radius-panel); padding: 12px; }
.card h3 { margin: 0 0 8px; font-size: 13px; font-weight: 600; color: var(--color-text-secondary); display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.card-grow { flex: 1 1 160px; min-height: 140px; display: flex; flex-direction: column; }
.count { color: var(--color-text-muted); font-weight: 500; font-size: 12px; }
.label { color: var(--color-text-muted); font-size: 12px; }
.muted { color: var(--color-text-muted); margin: 0; font-size: 13px; }
.status { font-size: 15px; font-weight: 600; margin-bottom: 10px; line-height: 20px; }
.status.warn { color: #fcd34d; } .status.ok { color: var(--color-signal-highlight); }
.row-between { display: flex; justify-content: space-between; align-items: baseline; }
.bar { height: 10px; background: var(--color-surface-raised); border-radius: 999px; overflow: hidden; margin: 6px 0 2px; }
.bar i { display: block; height: 100%; width: 0; background: var(--color-signal); border-radius: 999px; transition: width var(--duration-standard) var(--ease-standard), background var(--duration-standard); }
.bar i.low { background: var(--color-unknown); } .bar i.medium { background: var(--color-warning); } .bar i.high { background: var(--color-signal); }
.bands { display: flex; justify-content: space-between; font-size: 10px; color: var(--color-text-muted); text-transform: lowercase; }
.stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px; margin: 10px 0 0; }
.stats div { display: flex; justify-content: space-between; gap: 6px; } .stats dt { color: var(--color-text-muted); font-size: 12px; } .stats dd { margin: 0; font-size: 12px; white-space: nowrap; }

.classes .cls { display: grid; grid-template-columns: 96px 1fr 44px; align-items: center; gap: 8px; font-size: 13px; margin: 4px 0; }
.classes .cls .bar { margin: 0; height: 8px; } .classes .cls .bar i { background: var(--color-fusion); }
.classes .cls.none .bar i { background: var(--color-unknown); }
.classes .cls span:last-child { text-align: right; }
.classes.stale { opacity: .55; }

.fan-note { margin: 0; font-size: 12px; color: var(--color-text-secondary); }
.fan-legend { height: 10px; margin: 8px 0 2px; border-radius: 5px; border: 1px solid var(--color-border); background: linear-gradient(90deg, rgba(79,70,229,.35), #6366f1 33%, #a855f7 60%, #c4b5fd 80%, #eef2ff); }


.nodes { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 4px; }
.node { display: flex; align-items: center; gap: 6px; font-size: 12px; padding: 3px 6px; border-radius: 6px; background: var(--color-surface); cursor: pointer; border: 1px solid transparent; }
.node:hover { border-color: var(--color-border); }
.node .g { width: 10px; height: 10px; border-radius: 50%; background: var(--color-signal); flex: none; }
.node.t1 .g { background: var(--color-fusion); } .node.t2 .g { background: var(--color-forecast); border-radius: 2px; transform: rotate(45deg); } .node.phone .g { background: var(--color-ok); border-radius: 3px; }
.node.dead { color: var(--color-text-muted); } .node.dead .g { background: var(--color-unknown) !important; opacity: .5; }
.node.stale .g { outline: 1px dashed var(--color-unknown); outline-offset: 1px; }
.node .age { margin-left: auto; color: var(--color-text-muted); font-family: var(--font-mono); font-size: 11px; }

.log { list-style: none; margin: 0; padding: 0; overflow-y: auto; flex: 1; font-size: 12px; line-height: 16px; min-height: 80px; }
.log li { padding: 3px 0; border-bottom: 1px solid var(--color-border); display: flex; gap: 8px; }
.log li .t { color: var(--color-text-muted); font-family: var(--font-mono); flex: none; }
.log li.warn { color: #fcd34d; } .log li.alert { color: #fca5a5; }

.btn { font: 500 13px/18px var(--font-sans); padding: 6px 10px; min-height: 32px; border-radius: var(--radius-control); border: 1px solid var(--color-border); background: var(--color-surface-raised); color: var(--color-text); cursor: pointer; }
.btn:hover { border-color: var(--color-text-muted); }
.btn:focus-visible, input:focus-visible, select:focus-visible { outline: 2px solid var(--color-signal); outline-offset: 2px; }
.btn-primary { background: var(--color-signal); color: var(--color-bg); border-color: transparent; font-weight: 600; }
.btn-ghost { background: rgba(13,27,43,.9); }

/* timeline */
.timeline { position: absolute; left: 16px; bottom: 16px; right: calc(var(--rail-w) + 16px); z-index: 800; display: flex; align-items: center; gap: 10px; }
.timeline-body { flex: 1; display: flex; align-items: center; gap: 10px; background: rgba(13,27,43,.9); backdrop-filter: blur(8px); border: 1px solid var(--color-border); border-radius: var(--radius-panel); padding: 8px 12px; }
.timeline-body input { flex: 1; accent-color: var(--color-signal); }
#scrub-time { font-size: 12px; color: var(--color-text-secondary); min-width: 60px; text-align: right; }

/* map glyphs */
.node-icon { width: 18px; height: 18px; position: relative; }
.node-icon i { position: absolute; inset: 4px; border-radius: 50%; background: var(--color-signal); box-shadow: 0 0 0 2px var(--color-bg); opacity: .9; }
.node-icon.t0:after { content: ""; position: absolute; inset: 0; border-radius: 50%; border: 1.5px solid var(--color-signal); opacity: .7; }
.node-icon.t1 i { background: var(--color-fusion); }
.node-icon.t1:after { content: ""; position: absolute; inset: -1px; border-radius: 50%; border: 1.5px solid var(--color-fusion); border-left-color: transparent; border-right-color: transparent; opacity: .8; }
.node-icon.t2 i { background: var(--color-forecast); border-radius: 2px; transform: rotate(45deg); inset: 4px; }
.node-icon.phone i { background: var(--color-ok); border-radius: 4px; inset: 3px; }
.node-icon.dead i { background: var(--color-unknown) !important; opacity: .45; }
.node-icon.dead:after { border-color: var(--color-unknown) !important; opacity: .4; }
.node-icon.dead:before { content: "×"; position: absolute; right: -6px; top: -8px; color: var(--color-unknown); font: 600 11px/11px var(--font-sans); }
.node-icon.stale:after { border-style: dashed; }
.node-icon.pulse:before { content: ""; position: absolute; inset: -2px; border-radius: 50%; border: 2px solid var(--color-signal); animation: pulse 600ms var(--ease-standard) 1 forwards; }
.node-icon.t1.pulse:before { border-color: var(--color-fusion); } .node-icon.t2.pulse:before { border-color: var(--color-forecast); } .node-icon.phone.pulse:before { border-color: var(--color-ok); }
@keyframes pulse { from { transform: scale(1); opacity: .9; } to { transform: scale(3.2); opacity: 0; } }
.est-icon { width: 16px; height: 16px; border-radius: 50%; background: #fff; box-shadow: 0 0 0 2px var(--color-signal), 0 0 12px rgba(34,211,238,.6); }
.arrow-icon { width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 12px solid var(--color-signal); transform-origin: 50% 70%; }
.fc-label { background: transparent; border: 0; color: #c7d2fe; font: 500 11px/14px var(--font-mono); text-shadow: 0 1px 2px #000; padding: 0; }
@keyframes emphasize { 50% { fill-opacity: .3; } }

@media (prefers-reduced-motion: reduce) { .node-icon.pulse:before { animation: none; box-shadow: 0 0 0 3px var(--color-signal); } .bar i { transition: none; } }
@media (max-width: 900px) {
  :root { --rail-w: 0px; }
  .rail { top: auto; left: 0; height: 45%; width: 100%; border-left: 0; border-top: 1px solid var(--color-border); }
  #map, .topbar, .stale-overlay { right: 0; } #map, .stale-overlay { bottom: 45%; }
  .layers-toggle { display: block; }
  .layers { top: 104px; font-size: 12px; display: none; }
  .layers.open { display: flex; }
  .timeline { right: 16px; bottom: calc(45% + 12px); }
}

/* Viewers (not logged in as operator) see the picture, not the controls. The server refuses their writes anyway. */
body:not(.operator) .op-only { display: none !important; }
body:not(.operator) .unplaced-item { pointer-events: none; cursor: default; }
.auth { display: inline-flex; align-items: center; gap: 6px; }
.auth-user { color: var(--muted, #94a3b8); font-size: 12px; }

/* Track layer and Tracks card (#43): tracks are drawn on one canvas (web/track-layer.js); the card lists them in threat order. */
.track-canvas { pointer-events: none; }
.tracks { max-height: 320px; overflow-y: auto; }
.tracks .track { display: grid; grid-template-columns: 16px auto 1fr; gap: 6px; align-items: baseline; font-size: 12px; padding: 4px 0; border-bottom: 1px solid var(--color-border); cursor: pointer; }
.tracks .track:hover { background: var(--color-surface-raised); }
.tracks .track.sel { box-shadow: inset 2px 0 0 var(--color-text); }
.tracks .track.coasting { opacity: .65; }
.tracks .track.quiet { opacity: .55; } /* probably a civil aircraft, unconfirmed (#60): honest but quiet */
.threats { max-height: 280px; overflow-y: auto; }
.threats .threat { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; font-size: 12px; padding: 4px 0; border-bottom: 1px solid var(--color-border); cursor: pointer; }
.threats .threat:hover { background: var(--color-surface-raised); }
.threats .threat.sel { box-shadow: inset 2px 0 0 #c4b5fd; }
.threats .threat > span:last-child { grid-column: 1 / -1; color: var(--color-text-muted); }
.threats .threat.later, .threats .threat.gone { opacity: .7; } /* could reach later, or no longer reached: muted */
.threats .threat.later b, .threats .threat.gone b { font-weight: 500; }
.threats .small-drones { border-bottom: 1px solid var(--color-border); }
.threats .small-drones > summary { font-size: 12px; padding: 4px 0; cursor: pointer; color: var(--color-text-muted); }
.threats .small-drones .threat:last-child { border-bottom: 0; }
.threats .threats-later { margin: 10px 0 2px; font-size: 12px; font-weight: 600; color: var(--color-text-muted); }
.threats .threats-later span { font-weight: 400; }
.track-detail { margin: 8px 0; padding: 8px; border: 1px solid var(--color-border); border-radius: var(--radius-control); background: var(--color-surface-raised); }
.track-detail .btn { padding: 2px 8px; font-size: 12px; }
.track-detail dl { display: grid; gap: 4px; margin: 6px 0 0; }
.track-detail dl div { display: grid; grid-template-columns: 92px 1fr; gap: 8px; font-size: 12px; }
.track-detail dt { color: var(--color-text-muted); } .track-detail dd { margin: 0; overflow-wrap: anywhere; }

/* Sources view (no grid nodes, sources declared): the Kraków single-drone readouts have nothing to say. */
#app[data-view=sources] .legacy-only { display: none !important; }
/* ...and the other way round: the Kraków view has its own probability field and fan, so no "where tracks can be" (#57). */
#app:not([data-view=sources]) .sources-only { display: none !important; }
#app:not([data-coverage]) .coverage-only { display: none !important; }
/* coverage (#36): which reference drone is shown, and its fading chance */
.coverage-ref { display: flex; flex-direction: column; gap: 0; padding-left: 24px; font-size: 12px; }
.coverage-ref label { padding: 1px 2px; }
.coverage-ref input { width: 13px; height: 13px; }
.coverage-legend { display: flex; flex-direction: column; gap: 3px; padding: 0 2px 2px 26px; max-width: 230px; color: var(--color-text-muted, #8fa6b7); font-size: 11px; line-height: 1.35; }
.coverage-legend:empty { display: none; }
.coverage-legend strong { color: var(--color-text, #e6edf3); font-weight: 600; font-size: 12px; }
.coverage-bar { display: block; height: 8px; border-radius: 2px; border: 1px solid var(--color-border); background-color: rgba(13,27,43,.9); }
.coverage-scale { display: flex; justify-content: space-between; }
.next-legend { display: flex; flex-direction: column; gap: 3px; padding: 0 2px 2px 26px; max-width: 230px; color: var(--color-text-muted, #8fa6b7); font-size: 11px; line-height: 1.35; }
.next-legend .fan-legend { margin: 2px 0 0; height: 8px; border-radius: 2px; background-color: rgba(13,27,43,.9); }
.next-legend #next-here:empty { display: none; }
.next-legend #next-status { color: var(--color-text, #d8e3ec); font-style: italic; }
.next-legend #next-status:empty { display: none; }
/* launch warnings (#50, web/launch-warnings.js): the caution colour, never red; an ended one goes muted */
.banner.launch-banner { white-space: normal; max-width: min(680px, calc(100% - var(--rail-w) - 48px)); text-align: center; line-height: 1.4; }
.banner.launch-banner.ended { background: rgba(100,116,139,.18); border-color: #64748b; color: #cbd5e1; }
.launch-label span { position: absolute; color: #fcd34d; font-size: 11px; font-weight: 600; white-space: nowrap; text-shadow: 0 0 3px #050b14, 0 0 6px #050b14; transform: translate(-50%, -50%); }
