/* FLIGHT DECK — FlightLoft's glass-cockpit visual identity.
   Loaded AFTER each page's own <style>, so everything here wins the cascade.
   Strategy: every page already consumes one canonical token set (Phase 7
   interstitial), so redefining those tokens restyles the whole app at once;
   the rest of this file is shared chrome (fonts, panel bezels, headers).
   Color = EFIS display semantics: cyan=data/accent, green=normal,
   amber=caution, red=warning, magenta=active plan / yours.
   Deliberately single-theme dark — there is no light mode on a flight deck. */

@font-face { font-family: "B612"; font-weight: 400; font-style: normal; src: url("fonts/b612-regular.woff2") format("woff2"); }
@font-face { font-family: "B612"; font-weight: 700; font-style: normal; src: url("fonts/b612-bold.woff2") format("woff2"); }
@font-face { font-family: "B612 Mono"; font-weight: 400; font-style: normal; src: url("fonts/b612mono-regular.woff2") format("woff2"); }
@font-face { font-family: "B612 Mono"; font-weight: 700; font-style: normal; src: url("fonts/b612mono-bold.woff2") format("woff2"); }

:root {
  --bg: #06090c;
  --surface: #0c1116;
  --surface-solid: #0c1116;
  --surface-hover: #10161d;
  --border: #1b252e;
  --border-strong: #2c3c49;
  --text: #e9f1f5;
  --muted: #7c8b96;
  --muted-2: #46545f;
  --accent: #35e1f2;
  --accent-2: #ff52d9;
  /* flat — gradients don't exist on an EFIS */
  --accent-grad: linear-gradient(#35e1f2, #35e1f2);
  --good: #2fe86f;
  --warn: #ffb302;
  --bad: #ff453a;
  --radius: 3px;
  --radius-sm: 2px;
  /* index/logbook floating-over-map cards: opaque instrument panel */
  --panel: rgba(9, 14, 18, 0.96);
}

html { color-scheme: dark; }

body {
  font-family: "B612", -apple-system, "Segoe UI", sans-serif;
  font-variant-numeric: tabular-nums;
  /* instrument-black canvas with a faint dot grid */
  background-color: var(--bg);
  background-image: radial-gradient(circle, #10181e 1px, transparent 1px);
  background-size: 26px 26px;
}
button, input, select, textarea { font-family: inherit; }

/* Panel headers as instrument labels: tick-prefixed uppercase mono */
h1, h2, h3, h4, .sec-head {
  font-family: "B612 Mono", monospace;
  text-transform: uppercase;
  letter-spacing: 0.07em;
}
h2::before, h3::before, .sec-head::before {
  content: "\258D "; /* ▍ tick */
  color: var(--accent);
}

/* Kill leftover soft-glass treatments so panels read as hairline bezels */
.card, .panel, #sidebar { backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none; }
/* hardcoded radii that predate the tokens: flatten to instrument bezels */
#sidebar, .panel, .layer-btn, .icon-btn,
button, input, select, textarea { border-radius: var(--radius); }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 0; }
::-webkit-scrollbar-track { background: transparent; }

::selection { background: var(--accent-2); color: var(--bg); }

/* ---- Nav shell geometry (left rail + top status bar, from nav.js) ---- */
/* Was `padding: 52px 0 0 76px` on a normally-scrolling body — but padding
   only insets CONTENT, not the element's own box, so the document's own
   scrollbar (owned by the root, not by body) still spanned the full
   viewport height, including the 52px strip behind the fixed status bar.
   The native scrollbar paints above everything on the page (it isn't part
   of the document's own stacking context), so it visibly cut through/
   sat over the bar there instead of staying confined below it. Fixed by
   making body ITSELF the scroll container, sized and positioned to start
   exactly at the bar/rail's edges (nav.js sets `html`'s overflow to hidden
   alongside this class, so there's no separate root scrollbar left to
   conflict with this one) — its scrollbar now only ever exists within
   that box, never behind the fixed bar above/beside it.
   Scoped to its own `fl-scroll-body` class (added by nav.js only on pages
   with no #map canvas) rather than the shared `fl-has-topnav` class below:
   `position:fixed` on body makes body a positioning context for any
   position:absolute descendant, and index.html/logbook.html's #map/
   #sidebar/#layerRail are absolutely positioned assuming body has NO
   positioning of its own (so they resolve against the viewport) — those
   pages never scroll at the body level in the first place, so they don't
   need this rule at all. */
body.fl-scroll-body {
  position: fixed;
  inset: 52px 0 0 76px;
  margin: 0;
  overflow-y: auto;
  scrollbar-gutter: stable;
}
/* map pages: fixed-position elements ignore body padding, shift them */
body.fl-has-topnav #map { top: 52px; left: 76px; }
body.fl-has-topnav #sidebar { top: 66px; left: 90px; }
/* Higher specificity than plain #sidebar.expanded (which the base page CSS
   uses to drive top from the JS-computed --expanded-top var) would silently
   pin expanded mode back to a fixed 66px, defeating the map-floor math in
   computeExpandedPanelHeight() — restate the var() here too so this rule
   still wins the cascade without clobbering it. */
body.fl-has-topnav #sidebar.expanded { top: var(--expanded-top, 50vh); left: 90px; }

/* Expanded flight-detail panel: #layerRail is a sibling of #sidebar (not a
   descendant), still absolutely positioned over the now-short map strip.
   Re-anchor it to sit just above the panel's top edge (--expanded-top is
   mirrored onto :root by layoutExpandedTop() specifically so this sibling
   can read it) and lay it out as a horizontal toolbar instead of a vertical
   column — a tall column would eat most of the shrunken map strip. */
body:has(#sidebar.expanded) #layerRail {
  top: auto;
  bottom: calc(100vh - var(--expanded-top, 50vh) + 10px);
  /* Same 14px the expanded card itself sits from the browser's right edge
     (#sidebar.expanded's own "right" is untouched at the base 14px) —
     previously 24px, visibly out of step with the card below it. */
  right: 14px;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: calc(100vw - 90px - 14px - 28px);
}
body:has(#sidebar.expanded) #layerRail .rail-group { flex-direction: row; }
body:has(#sidebar.expanded) #layerRail .rail-divider {
  width: 3px; height: 40px; margin: 0 3px;
}
body.fl-has-topnav #layerRail { top: 66px; }

/* Electron desktop app only: content BrowserView documents (see
   desktop/main.js), added by nav.js only when window.__flContentFrame is
   true. The separate persistent shell window already renders the rail +
   statusbar, and the BrowserView's own bounds already exclude that space --
   so unlike fl-has-topnav above, this document must NOT reserve any extra
   space for chrome that isn't here. #sidebar/#layerRail/#mapControls
   already have sensible standalone defaults in each page's own <style>
   (written before nav.js existed) that apply automatically since this class
   deliberately does NOT also add fl-has-topnav/fl-scroll-body -- the only
   two rules that genuinely need a content-frame override are ones that
   hardcode rail/statusbar clearance unconditionally in the page itself. */
body.fl-content-frame #map { top: 0; }
body.fl-content-frame #appScreen { min-height: 100vh; }
/* index.html/logbook.html's #sidebar/#layerRail default to top:70px --
   sized for the in-page status bar (52px) plus their own ~18px margin.
   The content BrowserView's bounds already exclude that status bar here,
   same as #map above, so the unmodified 70px just left a redundant blank
   gap at the top of both. 14px matches their own left/right/bottom
   margins on the same elements. */
/* #sidebar's own `transition: top 0.25s ease, ...` (for its real expand/
   collapse animation) has a genuine, confirmed-live interaction with this
   override: since flightdeck.css finishes loading asynchronously (it's the
   last thing linked in the document) after nav.js has already added
   fl-content-frame, the value change this rule causes is treated as a
   post-paint transition trigger rather than baked into the very first
   style resolution -- and that transition never visibly settles to the
   new value here. `transition: none` only within this override (which
   itself stops matching once .expanded is added) sidesteps it entirely
   without touching the real expand/collapse transition. */
body.fl-content-frame #sidebar:not(.expanded) { top: 14px; transition: none; }
body.fl-content-frame #layerRail { top: 14px; }
/* Same hardcoded-clearance issue as above, on the expanded panel's floating
   Camera row: left:90px is sized for the in-page 76px rail + 14px margin,
   which doesn't exist in content-frame mode. No transition on this
   element, so no equivalent stuck-value issue to guard against. */
body.fl-content-frame #sidebar.expanded #mapControls { left: 14px; }

/* Focus toolbar (top-left, expanded mode): match the layer rail's own
   button sizing/panel treatment exactly instead of the narrower flex:1
   .icon-btn it borrows from the collapsed sidebar's "Camera" row. */
#sidebar.expanded #mapControls .icon-btn {
  flex: 0 0 auto; width: 46px; height: 40px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 6px 20px rgba(0,0,0,0.35); font-size: 11px;
}
#sidebar.expanded #mapControls .icon-btn:hover { border-color: var(--accent); }
/* .icon-btn has no custom focus style (unlike .layer-btn, which resets the
   native outline and draws its own accent ring) — clicking one otherwise
   shows the browser's default focus outline, mismatched from the rail. */
#sidebar.expanded #mapControls .icon-btn:focus { outline: none; }
#sidebar.expanded #mapControls .icon-btn:focus-visible {
  box-shadow: 0 6px 20px rgba(0,0,0,0.35), 0 0 0 2px var(--accent);
}
/* The unconditional background above (needed to match the rail's resting
   look) has higher specificity than the shared .icon-btn.active rule
   elsewhere, so it was silently overriding it — Follow never actually
   filled with the accent color while toggled on, just showed the focus
   ring above with a plain dark button underneath. Restated here so the
   pressed/active state still fills solid, same as every rail toggle. */
#sidebar.expanded #mapControls .icon-btn.active {
  background: var(--accent); color: var(--bg); border-color: var(--accent);
}

/* Raw-telemetry/aircraft-facts chips: the pre-FLIGHT-DECK page CSS uses a
   flat translucent-white fill (reads as a plain gray box) — restyle as a
   miniature instrument readout instead, matching .fd-dre's dark cell +
   hairline border + mono value. */
.fd-chip {
  background: var(--surface-hover) !important;
  border: 1px solid var(--border) !important;
  border-radius: var(--radius) !important;
}
.fd-chip .k { font-family: "B612 Mono", monospace; letter-spacing: 0.14em !important; }
.fd-chip .v { font-family: "B612 Mono", monospace; color: var(--text); }

/* MapLibre's default attribution control ships light-themed (white pill,
   dark text) — restyle for the dark canvas everywhere, and while the
   flight-detail panel is expanded (map shrinks to a thin strip, and the
   layer rail relocates to the strip's bottom-right — see above) relocate
   it to the now-empty top-right corner instead of colliding with the
   panel's rounded top edge down at the strip's bottom. */
/* MapLibre's own stylesheet has a same-or-higher-specificity rule for the
   compact (collapsed-to-an-i-icon) variant's background, so plain
   .maplibregl-ctrl-attrib alone loses that fight — !important, matching
   the compact-show class explicitly too. */
.maplibregl-ctrl-attrib,
.maplibregl-ctrl-attrib.maplibregl-compact-show {
  background: rgba(12,17,22,0.85) !important;
  border-radius: var(--radius) !important;
}
.maplibregl-ctrl-attrib, .maplibregl-ctrl-attrib a { color: var(--muted) !important; font-size: 10px; }
.maplibregl-ctrl-attrib a:hover { color: var(--accent) !important; }
.maplibregl-ctrl-attrib-button { filter: invert(1) brightness(1.4); }
body:has(#sidebar.expanded) #map .maplibregl-ctrl-bottom-right {
  top: 8px; right: 8px; bottom: auto;
}

/* ---- CDU-key buttons (concept .key), applied to the shared .btn family */
.btn, .seg-btn {
  font-family: "B612 Mono", monospace; font-size: 11px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; background: var(--surface-hover); color: var(--text);
  border: 1px solid var(--border-strong); border-radius: 3px !important;
  transition: border-color 0.13s, color 0.13s, box-shadow 0.13s;
}
.btn:hover, .seg-btn:hover { border-color: var(--accent); color: var(--accent); box-shadow: 0 0 12px -4px var(--accent); }
.btn-primary { border-color: var(--accent); color: var(--bg); background: var(--accent); }
.btn-primary:hover { color: var(--bg); box-shadow: 0 0 18px -4px var(--accent); }
.btn-danger { border-color: rgba(255,69,58,0.5); color: var(--bad); background: var(--surface-hover); }
.btn-danger:hover { border-color: var(--bad); color: var(--bad); box-shadow: 0 0 12px -4px var(--bad); }
.seg-btn.active { border-color: var(--accent); color: var(--accent); background: rgba(53,225,242,0.07); box-shadow: none; }

/* MapLibre popups on instrument-black */
.maplibregl-popup-content { border-radius: var(--radius); }

/* ---- FLIGHT DECK components (ported from the approved concept) ---- */
/* Flush panel: header bar + full-bleed body instead of a padded card */
.fd-flush { padding: 0 !important; position: relative; }
.fd-flush::before, .fd-flush::after {
  content: ""; position: absolute; width: 10px; height: 10px;
  border: 0 solid var(--accent); opacity: 0; transition: opacity 0.18s; pointer-events: none;
}
.fd-flush::before { top: -1px; left: -1px; border-top-width: 1.5px; border-left-width: 1.5px; }
.fd-flush::after { top: -1px; right: -1px; border-top-width: 1.5px; border-right-width: 1.5px; }
.fd-flush:hover::before, .fd-flush:hover::after { opacity: 0.9; }

.fd-ph { display: flex; align-items: center; gap: 10px; padding: 10px 16px; border-bottom: 1px solid var(--border); }
.fd-ph::before { content: ""; width: 14px; height: 2px; background: var(--accent); flex: none; }
.fd-ph h2 { font-size: 11px; font-weight: 700; letter-spacing: 0.22em; margin: 0; color: var(--text); }
.fd-ph h2::before { content: none; } /* header bar replaces the generic tick */
.fd-ph .sub { font-family: "B612 Mono", monospace; font-size: 10px; color: var(--muted-2); letter-spacing: 0.1em; margin-left: auto; text-transform: uppercase; white-space: nowrap; }
.fd-pb { padding: 16px; }

/* Data readout strip (DRE): hairline-divided stat cells */
.fd-dre-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1px; background: var(--border); }
.fd-dre { background: var(--surface-solid); padding: 14px 16px; }
.fd-dre .l { font-family: "B612 Mono", monospace; font-size: 9.5px; letter-spacing: 0.18em; color: var(--muted); margin-bottom: 6px; text-transform: uppercase; }
.fd-dre .v { font-family: "B612 Mono", monospace; font-size: 26px; font-weight: 700; letter-spacing: 0.02em; color: var(--text); }
.fd-dre .v small { font-size: 12px; color: var(--muted); font-weight: 400; margin-left: 2px; }
.fd-dre .v.cyan { color: var(--accent); }
.fd-dre .v.green { color: var(--good); }
.fd-dre .v.amber { color: var(--warn); }
.fd-dre .v.magenta { color: var(--accent-2); }

/* Annunciator pill */
.fd-ann {
  display: inline-block; font-family: "B612 Mono", monospace; font-size: 9px; font-weight: 700;
  letter-spacing: 0.14em; padding: 3px 8px 2px; border-radius: 2px; border: 1px solid; text-transform: uppercase;
}
.fd-ann.g { color: var(--good); border-color: rgba(47,232,111,0.4); background: rgba(47,232,111,0.07); }
.fd-ann.a { color: var(--warn); border-color: rgba(255,179,2,0.4); background: rgba(255,179,2,0.07); }
.fd-ann.m { color: var(--accent-2); border-color: rgba(255,82,217,0.4); background: rgba(255,82,217,0.07); }
.fd-ann.c { color: var(--accent); border-color: rgba(53,225,242,0.4); background: rgba(53,225,242,0.07); }
.fd-ann.dim { color: var(--muted-2); border-color: var(--border); }

/* Dense mono flight rows */
.fd-frow {
  display: flex; align-items: center; gap: 14px; padding: 10px 16px;
  border-bottom: 1px solid var(--border); font-family: "B612 Mono", monospace; font-size: 12px;
}
.fd-frow:last-child { border-bottom: 0; }
.fd-frow:hover { background: rgba(53,225,242,0.04); }
.fd-frow .d { color: var(--muted-2); font-size: 10.5px; width: 78px; flex: none; }
.fd-frow .fn { font-weight: 700; width: 84px; flex: none; color: var(--text); }
.fd-frow .rt { color: var(--accent); letter-spacing: 0.04em; }
.fd-frow .who { color: var(--muted); font-size: 11px; }
.fd-frow .fill { flex: 1; }
.fd-frow .lr { font-weight: 700; }
.fd-frow .lr.g { color: var(--good); }
.fd-frow .lr.a { color: var(--warn); }
.fd-frow .lr.r { color: var(--bad); }

/* Phase annunciator strip */
.fd-phases { display: flex; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: 2px; overflow: hidden; }
.fd-phase { flex: 1; text-align: center; font-family: "B612 Mono", monospace; font-size: 9.5px; letter-spacing: 0.1em; padding: 6px 0 5px; background: var(--surface-hover); color: var(--muted-2); }
/* A phase the flight actually flew through -- needs a real lit look, not
   just a one-shade-lighter text color (which read as unlit/no different
   from an unreached phase at a glance). */
.fd-phase.done { color: var(--good); background: color-mix(in srgb, var(--good) 16%, var(--surface-hover)); }
.fd-phase.act { color: var(--bg); background: var(--good); font-weight: 700; box-shadow: 0 0 14px -2px var(--good); }

/* PFD-style landing-rate tape gauge */
.fd-tape { display: flex; gap: 12px; align-items: stretch; }
/* Bands match the same |fpm| <=200 good / <=400 warn / >400 bad thresholds
   used everywhere else in the app (VA flight log, dashboard readout) over
   the gauge's 0..-600+ range — 200/600=33.33%, 400/600=66.67%, which also
   land exactly on the "-200"/"-400" tick marks below (4 ticks, evenly
   space-between'd, put the middle two at 1/3 and 2/3 automatically).
   Previously an arbitrary 14/38/76% split lifted from the design mockup,
   inconsistent with those thresholds — e.g. a real -317fpm landing (amber
   by the shared rule) fell inside this gauge's old "green" band. */
.fd-tape .scale { position: relative; width: 46px; border-radius: 2px; overflow: hidden;
  background: linear-gradient(180deg, var(--good) 0%, var(--good) 33.33%, var(--warn) 33.33%, var(--warn) 66.67%, var(--bad) 66.67%, var(--bad) 100%);
  opacity: 0.92; }
.fd-tape .scale::after { content: ""; position: absolute; inset: 0; background: repeating-linear-gradient(180deg, transparent 0 11px, rgba(6,9,12,0.55) 11px 12px); }
.fd-tape .bug { position: absolute; left: 0; right: 0; height: 3px; background: #fff; box-shadow: 0 0 8px #fff; z-index: 2; }
.fd-tape .bug::after { content: ""; position: absolute; right: -8px; top: -5px; border: 6px solid transparent; border-right-color: #fff; }
.fd-tape .ticks { display: flex; flex-direction: column; justify-content: space-between; font-family: "B612 Mono", monospace; font-size: 9px; color: var(--muted-2); padding: 2px 0; }
.fd-tape .facts { font-family: "B612 Mono", monospace; font-size: 10.5px; color: var(--muted); line-height: 1.9; letter-spacing: 0.06em; }
.fd-tape .facts b { color: var(--text); font-size: 14px; }
.fd-tape .facts b.g { color: var(--good); }

/* Map HUD readout (top-left over a map/mini-map) */
.fd-hud { position: absolute; top: 10px; left: 12px; z-index: 2; font-family: "B612 Mono", monospace; font-size: 10px; color: var(--accent); letter-spacing: 0.1em; opacity: 0.9; pointer-events: none; }
.fd-hud div { margin-bottom: 2px; }
