:root {
  --bg: #0a0e14;
  --panel: #101722;
  --border: #1f2937;
  --text: #d7e2ee;
  --muted: #7c8ba1;
  --accent: #ff8a2b;
  --mil: #ff4d4d;
  --civ: #4dd0ff;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}

body {
  display: flex;
  flex-direction: column;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.7rem 1.2rem;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  z-index: 1000;
}

.brand { display: flex; align-items: center; gap: 0.9rem; }

.brand-logo-link { display: flex; align-items: center; }
.brand-logo { height: 34px; width: auto; display: block; }

.tagline { color: var(--muted); font-size: 0.85rem; }

.status { font-size: 0.85rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.status #aircraft-count { color: var(--text); font-weight: 700; }

.hotspots {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1.2rem;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  position: relative;
  z-index: 1000;
}

.hotspot-btn {
  flex: none;
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s ease;
}

.hotspot-btn:hover { border-color: var(--accent); color: var(--text); }

.hotspot-btn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: #17110a;
  font-weight: 700;
}

.hotspot-btn.location-btn {
  border-color: var(--civ);
  color: var(--civ);
}

.hotspot-btn.location-btn:hover { border-color: var(--civ); color: #fff; }
.hotspot-btn.location-btn.active { background: var(--civ); border-color: var(--civ); color: #06222c; }

.location-hint {
  background: var(--accent);
  color: #17110a;
  text-align: center;
  padding: 0.4rem;
  font-size: 0.82rem;
  font-weight: 700;
  z-index: 1000;
}

.viewing-note {
  background: rgba(255, 138, 43, 0.12);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-align: center;
  padding: 0.5rem 1rem;
  font-size: 0.82rem;
  z-index: 900;
}

.weather-chip {
  background: rgba(77, 208, 255, 0.1);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-align: center;
  padding: 0.4rem 1rem;
  font-size: 0.78rem;
  z-index: 900;
}

.popup-log-btn {
  display: block;
  width: 100%;
  margin-top: 0.6rem;
  background: var(--accent);
  border: none;
  border-radius: 6px;
  padding: 0.45rem;
  color: #17110a;
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
}
.popup-log-btn:disabled { opacity: 0.7; cursor: default; }

.nav-dropdowns {
  display: flex;
  gap: 0.5rem;
  flex: none;
}

.freq-link {
  text-decoration: none;
  flex: none;
  margin-left: auto;
  border-color: var(--accent);
  color: var(--accent);
}

.freq-link:hover { background: var(--accent); color: #17110a; }

.dropdown { position: relative; flex: none; }

.dropdown-toggle {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s ease;
  display: flex;
  align-items: center;
  gap: 0.3rem;
}

.dropdown-toggle:hover { border-color: var(--accent); color: var(--text); }

.dropdown-toggle.active {
  background: rgba(255, 138, 43, 0.18);
  border-color: var(--accent);
  color: var(--text);
  font-weight: 700;
}

.dropdown-toggle .chevron { font-size: 0.7rem; transition: transform 0.15s ease; }
.dropdown.open .dropdown-toggle .chevron { transform: rotate(180deg); }

.dropdown-menu {
  display: none;
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 220px;
  max-height: 340px;
  overflow-y: auto;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.4rem;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4);
  z-index: 1100;
}

.dropdown.open .dropdown-menu { display: block; }

.dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  text-decoration: none;
  background: transparent;
  border: none;
  border-radius: 6px;
  color: var(--text);
  padding: 0.45rem 0.6rem;
  font-size: 0.82rem;
  cursor: pointer;
}

.dropdown-item:hover { background: rgba(255, 138, 43, 0.12); }
.dropdown-item.active { background: var(--accent); color: #17110a; font-weight: 700; }

.workspace {
  flex: 1;
  display: flex;
  min-height: 0;
  position: relative;
}

#map {
  flex: 1;
  background: var(--bg);
  min-width: 0;
}

.data-panel {
  flex: none;
  width: 340px;
  background: var(--panel);
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: width 0.15s ease, border-color 0.15s ease;
}

/* fully collapses to nothing -- no leftover strip of colour along the edge */
.data-panel.collapsed {
  width: 0;
  border-left-color: transparent;
}

.panel-header {
  padding: 0.7rem 0.9rem;
  font-size: 0.85rem;
  font-weight: 700;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.panel-header #table-count { color: var(--muted); font-weight: 400; margin-left: 0.3rem; }

/* floating tab, always in the same corner regardless of panel state --
   the panel slides in/out beside it, it never disappears itself */
.data-panel-toggle {
  position: absolute;
  top: 64px;
  right: 340px;
  z-index: 900;
  background: var(--panel);
  border: 1px solid var(--border);
  border-right: none;
  color: var(--text);
  padding: 0.55rem 0.6rem;
  border-radius: 8px 0 0 8px;
  cursor: pointer;
  transition: right 0.15s ease;
}

.data-panel.collapsed ~ .data-panel-toggle {
  right: 0;
}

.data-panel-toggle .chevron {
  display: inline-block;
  transition: transform 0.15s ease;
}

.data-panel.collapsed ~ .data-panel-toggle .chevron { transform: rotate(180deg); }

.table-wrap {
  flex: 1;
  overflow: auto;
  min-width: 340px;
}

#aircraft-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.78rem;
}

#aircraft-table thead th {
  position: sticky;
  top: 0;
  background: var(--panel);
  color: var(--muted);
  text-align: left;
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

#aircraft-table thead th:hover { color: var(--text); }

#aircraft-table tbody tr {
  cursor: pointer;
  border-bottom: 1px solid rgba(31, 41, 55, 0.5);
}

#aircraft-table tbody tr:hover { background: rgba(255, 138, 43, 0.08); }

#aircraft-table td {
  padding: 0.4rem 0.6rem;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

#aircraft-table tr.row-mil td:first-child { color: var(--mil); font-weight: 700; }

.legend {
  position: absolute;
  /* The legend now lives inside .workspace, so this is measured from the
     bottom of the map itself rather than from the viewport. */
  bottom: 1rem;
  left: 1.2rem;
  background: rgba(16, 23, 34, 0.9);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.55rem 0.9rem;
  font-size: 0.75rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 0.9rem;
  z-index: 500;
}

.legend .alt-scale { display: flex; flex-direction: column; gap: 0.25rem; }

.legend .alt-gradient {
  width: 200px;
  height: 8px;
  border-radius: 4px;
  /* Altitude spectrum, matching ALT_BANDS in app.js. Keep the two in step:
     a legend that disagrees with the map is worse than no legend. */
  background: linear-gradient(
    to right,
    #e8582a 0%,
    #f5a623 18%,
    #e8dc2a 38%,
    #5fc22a 58%,
    #2ab5c2 78%,
    #8b4ce0 100%
  );
}

.legend .alt-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.65rem;
  white-space: nowrap;
}

.legend .mil-key { display: flex; align-items: center; gap: 0.4rem; }

.legend .outline-swatch {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #f5a623;
  border: 2.5px solid #b3121b;
  display: inline-block;
}

.plane-icon-wrap { background: transparent; border: none; }

/* Bold black "sticker" outline, matching the real-tracker convention
   (checked against airplanes.live's own live map directly) -- a thin white
   outline reads as delicate/flat, a thick dark one is what actually gives
   these a solid, professional, toy-plane look regardless of fill colour.
   Military aircraft get a red outline instead so they still read instantly
   regardless of what altitude colour sits underneath. */
/* Realistic shaded icons carry all their own fills/strokes inline (metallic
   gradients, engine/cockpit shading, red military outline) -- the only shared
   styling here is a soft drop shadow that lifts each plane off the map. */
.plane-icon svg { display: block; filter: drop-shadow(0 1.4px 1.6px rgba(0,0,0,0.5)); }

.plane-icon.mil svg .rotor-disc { stroke: var(--mil); }

/* theme Leaflet's own layer switcher to match the site rather than its default white box */
.leaflet-control-layers {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 8px;
}

.leaflet-control-layers-toggle {
  filter: invert(0.9);
}

.leaflet-control-layers-expanded {
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
}

.leaflet-control-layers-selector { margin-right: 0.4rem; }

.popup-title {
  font-weight: 700;
  margin-bottom: 0.35rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}

/* Sits directly under the callsign in the compact popup. Deliberately quiet:
   it's context, not a headline, and the popup has to stay slim. */
.popup-callsign-note {
  font-size: 0.7rem;
  line-height: 1.3;
  color: var(--muted);
  margin: -0.15rem 0 0.4rem;
}

.popup-callsign-note strong {
  color: var(--accent);
  font-weight: 600;
}

/* A tactical callsign tells you less than an operator one, so it reads as
   plain context rather than an identification. */
.popup-callsign-note.tactical strong { color: var(--muted); font-weight: 600; }

.badge.mil {
  background: var(--mil);
  color: #1a0a0a;
  font-size: 0.65rem;
  font-weight: 800;
  padding: 0.1rem 0.4rem;
  border-radius: 4px;
  letter-spacing: 0.03em;
}

.popup-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.82rem;
  padding: 0.1rem 0;
}

.popup-row span { color: var(--muted); }

.popup-log-btn { margin-top: 0.4rem; }

.popup-route {
  margin-top: 0.5rem;
  padding: 0.4rem 0.5rem;
  background: rgba(77, 208, 255, 0.08);
  border: 1px solid rgba(77, 208, 255, 0.25);
  border-radius: 6px;
  font-size: 0.78rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  flex-wrap: wrap;
}

.popup-route.loading { color: var(--muted); background: none; border-style: dashed; }
.route-arrow { color: var(--muted); }
.popup-row.route-pending strong { color: var(--muted); font-weight: 400; font-style: italic; }

/* The expanded "trump card" is kept compact: the photo is height-capped so a
   tall image can't balloon the popup, and the facts grid / padding are tight. */
.popup-photo {
  display: block;
  margin-top: 0.4rem;
  border-radius: 6px;
  overflow: hidden;
  text-decoration: none;
  border: 1px solid var(--border);
}

.popup-photo img { display: block; width: 100%; height: auto; max-height: 92px; object-fit: cover; }

.popup-photo .photo-credit {
  display: block;
  font-size: 0.64rem;
  color: var(--muted);
  padding: 0.25rem 0.45rem;
  background: rgba(0, 0, 0, 0.25);
}

.facts-card {
  margin-top: 0.4rem;
  padding: 0.4rem 0.5rem;
  background: linear-gradient(160deg, rgba(255, 138, 43, 0.14), rgba(255, 138, 43, 0.03));
  border: 1px solid rgba(255, 138, 43, 0.35);
  border-radius: 8px;
}

/* The trivia line, separated from the spec grid above it because it reads
   as a sentence rather than a field. */
.facts-trivia {
  margin-top: 0.45rem;
  padding-top: 0.4rem;
  border-top: 1px solid rgba(255, 138, 43, 0.25);
  font-size: 0.74rem;
  line-height: 1.45;
  color: var(--text);
}

.facts-title {
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.25rem;
}

/* ⚠️ Still used by aircraft-guide.html, which is a browsable reference list
   rather than a card to compare. Do not delete these with the card styles. */
.facts-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.12rem 0.5rem;
}

.facts-item {
  display: flex;
  flex-direction: column;
  font-size: 0.72rem;
}

.facts-item span { color: var(--muted); font-size: 0.64rem; }
.facts-item strong { color: var(--text); }

/* What the aircraft IS, above the numbers. Not part of the stat grid: a role
   is not a figure you compare against another card. */
.facts-lead {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  margin-bottom: 0.45rem;
  font-size: 0.74rem;
}
.facts-lead strong { color: var(--text); }
.facts-lead span { color: var(--muted); white-space: nowrap; }

/* The stat block. The number leads and the label sits under it, which is the
   whole visual idea of a Top Trumps card: you compare figures at a glance.
   auto-fit rather than a fixed column count so it stays honest at 336px on the
   desktop panel and at 390px as a phone sheet, and so a type with six stats
   does not leave a hole where the missing two would be. */
.facts-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 0.3rem;
}

.facts-stat {
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid rgba(255, 138, 43, 0.18);
  border-radius: 6px;
  padding: 0.28rem 0.35rem;
  min-width: 0; /* or a long figure widens its own column and breaks the grid */
}

.facts-stat b {
  display: block;
  font-size: 1.02rem;
  font-weight: 800;
  line-height: 1.15;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* The unit rides with the number but must not compete with it. */
.facts-stat b i {
  font-style: normal;
  font-size: 0.62rem;
  font-weight: 600;
  color: var(--muted);
  margin-left: 0.15rem;
}

.facts-stat span {
  display: block;
  margin-top: 0.05rem;
  font-size: 0.56rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
}

.flag-icon {
  display: inline-block;
  vertical-align: -1px;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15);
}

.popup-photo.loading,
.popup-photo.none {
  margin-top: 0.5rem;
  padding: 0.6rem;
  text-align: center;
  font-size: 0.75rem;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: 6px;
}

.leaflet-popup-content-wrapper {
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
}

.leaflet-popup-tip { background: var(--panel); }

/* The map background is matched to whichever base layer is showing (see
   app.js). Browser zoom levels that aren't a whole number make Leaflet round
   each tile independently and leave a 1px gap, and what shows through that
   gap is this background -- against the dark default it read as a black line
   drawn across the map. Matching the background to the tiles makes the gap
   invisible instead.

   The previous fix grew each tile by half a pixel to close the gap. That
   worked on CARTO's 512px retina tiles but resampled OpenStreetMap's 256px
   ones, turning the dark seams into light ones at every zoom level. */

/* ---- Sites on the map (bases, airports, viewing areas) --------------------
   Small and low-contrast on purpose. These are ground reference, not the
   subject: the aircraft have to stay the thing your eye goes to. */
.site-marker { background: none; border: none; }

/* A teardrop pin whose point sits on the actual coordinate, rather than a
   dot centred on it -- at an airfield the difference is a runway's width. */
.site-pin {
  display: block;
  width: 14px;
  height: 14px;
  background: var(--site-colour);
  border: 1.5px solid rgba(10, 14, 20, 0.8);
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  transform-origin: center;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}

.site-pin::after {
  content: '';
  position: absolute;
  inset: 4px;
  background: rgba(10, 14, 20, 0.75);
  border-radius: 50%;
}

.site-pin:hover { filter: brightness(1.25); }

.site-label.leaflet-tooltip {
  background: rgba(16, 22, 32, 0.92);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: 5px;
  padding: 0.2rem 0.4rem;
  font-size: 0.68rem;
  line-height: 1.25;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.45);
  white-space: nowrap;
}

.site-label.leaflet-tooltip::before { border-top-color: var(--border); }

.site-label-name { display: block; font-weight: 600; }
.site-label-code { display: block; color: var(--muted); letter-spacing: 0.04em; }

/* ---- Map tag (single click) ----------------------------------------------
   Deliberately tiny. While you're watching something move, the squawk and the
   trail are the whole job -- anything more just covers the map. */
.popup-tag { min-width: 8.5rem; }

.popup-tag-callsign {
  font-weight: 700;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.25rem;
}

.popup-tag-squawk {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.85rem;
}

.popup-tag-squawk span { color: var(--muted); }
.popup-tag-squawk strong { font-size: 1.05rem; letter-spacing: 0.04em; }

.popup-tag-hint {
  margin-top: 0.35rem;
  font-size: 0.63rem;
  color: var(--muted);
  opacity: 0.85;
}

/* ---- Trump card (double click) -------------------------------------------
   Overlays the left edge of the map rather than sitting in the flex row, so
   opening it doesn't reflow the map and shift every aircraft sideways. */
.trump-panel {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  width: 21rem;
  max-width: calc(100% - 1.5rem);
  /* Height follows the content instead of filling the map: a stretched panel
     left a big empty block at the bottom and buried the altitude legend. */
  max-height: calc(100% - 1.5rem);
  z-index: 1000; /* above Leaflet panes, below the nav dropdowns */
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  overflow-y: auto;
  overflow-x: hidden;
}

.trump-panel[hidden] { display: none; }

.trump-card { position: relative; }

.trump-close {
  position: absolute;
  top: 0.4rem;
  right: 0.4rem;
  z-index: 1;
  background: rgba(0, 0, 0, 0.45);
  color: var(--text);
  border: none;
  border-radius: 50%;
  width: 1.6rem;
  height: 1.6rem;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.trump-close:hover { background: rgba(0, 0, 0, 0.7); }

.trump-header {
  padding: 0.7rem 2.4rem 0.5rem 0.8rem;
  border-bottom: 1px solid var(--border);
}

.trump-body { padding: 0.6rem 0.8rem 0.9rem; }

/* ---- Site card (a base or airport, in the same panel) ---- */
.site-meta {
  font-size: 0.7rem;
  color: var(--muted);
  margin-top: 0.15rem;
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: wrap;
}

.site-section-title {
  font-size: 0.63rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0.6rem 0 0.3rem;
}

.site-section-title:first-child { margin-top: 0; }

.site-weather-item {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.8rem;
  padding: 0.1rem 0;
}

.site-weather-item span { color: var(--muted); }
.site-weather-none { font-size: 0.76rem; color: var(--muted); padding: 0.2rem 0; }

.site-note {
  margin-top: 0.5rem;
  font-size: 0.73rem;
  line-height: 1.45;
  color: var(--muted);
  border-left: 2px solid var(--border);
  padding-left: 0.5rem;
}

.site-traffic { display: flex; flex-direction: column; gap: 1px; }

.site-traffic-row {
  display: grid;
  grid-template-columns: 4.6rem 1fr auto;
  gap: 0.5rem;
  align-items: center;
  width: 100%;
  text-align: left;
  background: rgba(255, 255, 255, 0.03);
  border: none;
  border-left: 2px solid var(--muted);
  color: var(--text);
  font-size: 0.74rem;
  padding: 0.28rem 0.4rem;
  cursor: pointer;
}

.site-traffic-row.mil { border-left-color: var(--mil); }
.site-traffic-row:hover { background: rgba(255, 138, 43, 0.12); }
.site-traffic-cs { font-weight: 700; }
.site-traffic-type { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.site-traffic-alt { color: var(--muted); font-variant-numeric: tabular-nums; }

.trump-card .popup-photo { margin: 0; border-radius: 0; background: #0b0f14; }
/* ⛔ Do NOT let this inherit the map popup's `max-height: 92px; object-fit:
   cover`. On the card that cropped the top and bottom off every aircraft, which
   Daz reported on 2026-08-20: "the image of aircraft doesnt fully show". The
   whole point of the photo here is seeing the aircraft. `contain` letterboxes
   an odd shape rather than cutting it. */
.trump-card .popup-photo img {
  width: 100%;
  display: block;
  height: auto;
  max-height: 240px;
  object-fit: contain;
}

/* On a phone the card would swallow the whole map as a side panel, so it
   becomes a bottom sheet: still off the aircraft, still leaves the map
   readable above it. */
@media (max-width: 640px) {
  .trump-panel {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: auto;
    max-width: none;
    /* Measured 2026-08-20 on a 390x844 phone: 62% gave a 299px sheet holding
       606px of content, so the type, registration and every fact sat below the
       fold and the card opened on a photo and a button. The map is still
       visible above, and the card closes with a tap. */
    max-height: 85%;
    border-radius: 12px 12px 0 0;
  }
}

/* Frequencies reference page */
.freq-page { height: auto; min-height: 100%; overflow-y: auto; }

.header-actions { display: flex; align-items: center; gap: 0.6rem; position: relative; }
.header-actions .dropdown-menu { top: calc(100% + 8px); left: auto; right: 0; }

/* Guides is always the right-most dropdown wherever it appears (main nav row
   or a content page's header) -- right-align its menu so it opens inward
   from the edge instead of overflowing off-screen. */
.dropdown:has(.guides-toggle) .dropdown-menu { left: auto; right: 0; }

.freq-main {
  max-width: 900px;
  width: 100%;
  margin: 0 auto;
  padding: 2rem 1.2rem 4rem;
  /* A different, subtler flexbox trap than the min-width:auto one already
     documented elsewhere in this project: main is a flex item of
     body{display:flex}, and per the flexbox spec, `margin: auto` on a flex
     item's cross axis (the left/right margins here, since body is a column
     flex container) makes the browser skip align-items:stretch entirely and
     size the item to its own content instead -- so a wide table row was
     quietly forcing this element (and the page) 35px past the viewport on
     mobile despite `width` never being explicitly set to anything but auto.
     Making width explicit (100%, capped by max-width) sidesteps the auto-
     margin/stretch interaction rather than fighting it. min-width:0 still
     needed too, in case content is wider than 100% before it can wrap. */
  min-width: 0;
}

.freq-intro h1 { font-size: 1.4rem; margin: 0 0 0.8rem; }
.freq-intro p { color: var(--text); line-height: 1.6; margin: 0 0 0.8rem; }
.freq-sources { color: var(--muted) !important; font-size: 0.85rem; }

.freq-section { margin-top: 2.2rem; overflow-x: auto; }
.freq-section h2 {
  font-size: 1.05rem;
  color: var(--accent);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.5rem;
  margin-bottom: 0.8rem;
}

.freq-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.88rem;
}

.freq-table th {
  text-align: left;
  color: var(--muted);
  font-weight: 600;
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--border);
}

.freq-table td {
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid rgba(31, 41, 55, 0.5);
  font-variant-numeric: tabular-nums;
}

.freq-table tr:hover td { background: rgba(255, 138, 43, 0.06); }

.freq-note {
  margin-top: 0.8rem;
  color: var(--muted);
  font-size: 0.85rem;
  font-style: italic;
}

.freq-unconfirmed { color: var(--accent); font-style: normal; font-weight: 700; }

/* Shared footer (injected by footer.js on every page) -- deliberately a
   slim single row, not a big multi-column block, so it doesn't eat into
   the map's screen space on index.html while still being present there. */
.site-footer {
  flex: none;
  background: var(--panel);
  border-top: 1px solid var(--border);
  z-index: 900;
}

.site-footer-inner {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0.55rem 1.2rem;
  display: flex;
  align-items: center;
  gap: 1.2rem;
  flex-wrap: wrap;
  font-size: 0.78rem;
  color: var(--muted);
}

.footer-links { display: flex; gap: 0.9rem; }
.footer-links a,
.footer-credit { color: var(--muted); text-decoration: none; }
.footer-links a:hover,
.footer-credit:hover { color: var(--accent); }
.footer-credit { margin-left: auto; }
.footer-credit strong { color: var(--text); }
/* ODbL requires the data source to be attributed wherever the data is shown.
   This is a licence condition, not a courtesy credit, so it stays visible. */
.footer-attrib { color: var(--muted); }
.footer-attrib a { color: var(--muted); text-decoration: underline; }
.footer-attrib a:hover { color: var(--accent); }

/* Aircraft type guide page */
.guide-controls {
  display: flex;
  gap: 1rem;
  flex-wrap: wrap;
  align-items: center;
  margin-bottom: 0.8rem;
}

.guide-search {
  flex: 1;
  min-width: 220px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem 0.8rem;
  color: var(--text);
  font-size: 0.85rem;
}

.guide-filters { display: flex; gap: 0.5rem; }

.guide-filter {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  font-size: 0.82rem;
  cursor: pointer;
}

.guide-filter:hover { border-color: var(--accent); color: var(--text); }
.guide-filter.active { background: var(--accent); border-color: var(--accent); color: #17110a; font-weight: 700; }

.guide-count { color: var(--muted); font-size: 0.8rem; margin-bottom: 0.8rem; }

.guide-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 0.9rem;
}

.guide-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.9rem 1rem;
}

.guide-card.is-military { border-color: rgba(255, 77, 77, 0.35); }

.guide-card-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.3rem; }
.guide-code { font-weight: 800; font-size: 1rem; letter-spacing: 0.02em; }
.guide-role { color: var(--muted); font-size: 0.85rem; }
.guide-empty { color: var(--muted); padding: 2rem 0; text-align: center; grid-column: 1 / -1; }

/* Airshow calendar page */
.airshow-date {
  margin-top: 0.4rem;
  font-weight: 700;
  color: var(--accent);
  font-size: 0.9rem;
}

.airshow-status {
  margin-top: 0.4rem;
  color: var(--muted);
  font-size: 0.82rem;
  line-height: 1.5;
}

.guide-card.is-cancelled { opacity: 0.7; }

.airshow-link {
  display: inline-block;
  margin-top: 0.6rem;
  color: var(--accent);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
}

.airshow-link:hover { text-decoration: underline; }

/* Legal pages (terms/privacy/cookies) */
.legal-main { max-width: 760px; }
.legal-main h1 { font-size: 1.4rem; margin: 0 0 0.3rem; }
.legal-updated { color: var(--muted); font-size: 0.8rem; margin: 0 0 2rem; }

.legal-section {
  margin-bottom: 1.8rem;
  padding-bottom: 1.8rem;
  border-bottom: 1px solid var(--border);
}

.legal-section:last-child { border-bottom: none; }

.legal-section h2 {
  font-size: 1rem;
  color: var(--accent);
  margin: 0 0 0.6rem;
}

.legal-section p { color: var(--text); line-height: 1.7; margin: 0 0 0.8rem; font-size: 0.9rem; }
.legal-section ul { margin: 0 0 0.8rem; padding-left: 1.4rem; }
.legal-section li { color: var(--text); line-height: 1.7; font-size: 0.9rem; margin-bottom: 0.3rem; }
.legal-section a { color: var(--accent); }

/* Account nav (Sign in/Register, or avatar+dropdown when logged in) */
#account-nav { display: flex; align-items: center; gap: 0.5rem; }
.account-register-btn { background: var(--accent); border-color: var(--accent); color: #17110a; font-weight: 700; }
.notif-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--mil);
  color: #1a0a0a;
  font-size: 0.65rem;
  font-weight: 800;
}
.account-toggle { display: flex; align-items: center; gap: 0.5rem; }
.account-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: #17110a;
  font-weight: 800;
  font-size: 0.75rem;
}
.dropdown-item.dropdown-item { /* button variant of .dropdown-item needs the same reset as the <a> version */
  background: none;
  border: none;
  font: inherit;
  cursor: pointer;
}

/* Auth forms (register/login/settings) */
.auth-main { max-width: 420px; }
.auth-main h1 { font-size: 1.4rem; margin: 0 0 0.4rem; }
.auth-sub { color: var(--muted); font-size: 0.85rem; margin: 0 0 1.6rem; }
/* :not([hidden]) rather than a bare .auth-form -- an unqualified display:flex
   here silently beats the browser's built-in [hidden]{display:none} rule
   (author CSS always wins over user-agent CSS at equal importance), so any
   .auth-form using the hidden attribute -- e.g. log.html's #alert-form --
   would stay visible despite being marked hidden. Real bug, found via a
   computed-style check, not a hypothetical. */
.auth-form:not([hidden]) { display: flex; flex-direction: column; gap: 1rem; }
.auth-field { display: flex; flex-direction: column; gap: 0.35rem; }
.auth-field label { font-size: 0.82rem; color: var(--muted); font-weight: 600; }
.auth-field input {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  color: var(--text);
  font-size: 0.9rem;
}
.auth-field input:focus { outline: none; border-color: var(--accent); }
.auth-field textarea {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  color: var(--text);
  font-size: 0.9rem;
  font-family: inherit;
  resize: vertical;
}
.auth-field textarea:focus { outline: none; border-color: var(--accent); }

.avatar-settings-row { display: flex; align-items: center; gap: 1.2rem; margin-bottom: 1rem; }
.avatar-settings-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem; }
.avatar-upload-btn { display: inline-block; width: auto; padding: 0.55rem 1.1rem; cursor: pointer; }
.auth-submit {
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 0.7rem;
  color: #17110a;
  font-weight: 700;
  font-size: 0.9rem;
  cursor: pointer;
  margin-top: 0.4rem;
}
.auth-submit:hover { filter: brightness(1.08); }
.auth-submit:disabled { opacity: 0.6; cursor: default; }
.auth-error {
  background: rgba(255, 77, 77, 0.1);
  border: 1px solid rgba(255, 77, 77, 0.3);
  color: #ff9d9d;
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
}
.auth-success {
  background: rgba(77, 208, 255, 0.1);
  border: 1px solid rgba(77, 208, 255, 0.3);
  color: var(--text);
  border-radius: 8px;
  padding: 0.6rem 0.8rem;
  font-size: 0.85rem;
}
.auth-switch { margin-top: 1.4rem; font-size: 0.85rem; color: var(--muted); }
.auth-switch a { color: var(--accent); text-decoration: none; }
.auth-switch a:hover { text-decoration: underline; }
.auth-divider { border-top: 1px solid var(--border); margin: 2rem 0; }

/* Community section */
.community-main { max-width: 1280px; margin: 0 auto; padding: 1.5rem 1.2rem 4rem; width: 100%; min-width: 0; }
.community-layout { display: grid; grid-template-columns: 230px 1fr 300px; gap: 1.5rem; align-items: start; }
.community-feed-col { min-width: 0; }

.community-banner {
  background: rgba(255, 138, 43, 0.1);
  border: 1px solid rgba(255, 138, 43, 0.3);
  border-radius: 10px;
  padding: 0.8rem 1rem;
  font-size: 0.85rem;
  line-height: 1.5;
  margin-bottom: 1.2rem;
}

.profile-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1.2rem 1rem;
  text-align: center;
  position: sticky;
  top: 1rem;
}
/* A plain block wrapper, not itself .mini-avatar -- its JS-injected child
   (an <img> or a letter <span>, both .mini-avatar) carries the actual
   circle styling. Needs to be block-level for `margin:0 auto` to actually
   centre it -- inline-flex children (.mini-avatar's own display) ignore
   auto margins, so centering this on the wrapper itself is what's real. */
.profile-card-avatar { display: block; width: 56px; margin: 0 auto 0.6rem; }
.profile-card h2 { font-size: 0.95rem; margin: 0 0 0.2rem; color: var(--text); }
.profile-card-meta { color: var(--muted); font-size: 0.72rem; margin: 0 0 0.8rem; }
.profile-card-stats {
  display: flex;
  justify-content: center;
  gap: 1.4rem;
  padding: 0.7rem 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  margin-bottom: 0.8rem;
}
.profile-card-stats div { display: flex; flex-direction: column; }
.profile-card-stats strong { font-size: 1rem; color: var(--text); }
.profile-card-stats span { font-size: 0.68rem; color: var(--muted); }
.profile-card-nav { display: flex; flex-direction: column; gap: 0.5rem; text-align: left; }
.profile-card-nav a {
  color: var(--text);
  text-decoration: none;
  font-size: 0.82rem;
  padding: 0.4rem 0.6rem;
  border-radius: 6px;
}
.profile-card-nav a:hover { background: rgba(255, 138, 43, 0.1); color: var(--accent); }

.safe-space-card p { color: var(--muted); font-size: 0.8rem; line-height: 1.5; margin: 0; }

/* profile.html's own header -- real pre-existing gap, these classes were
   referenced in the markup/JS since Phase 3 shipped but never had any CSS
   at all, so the page rendered as unstyled stacked text. */
.profile-header { display: flex; align-items: center; gap: 1rem; background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 1.2rem; margin-bottom: 1rem; }
.profile-header h1 { font-size: 1.2rem; margin: 0; }
.profile-avatar { flex: none; }
#profile-friend-action { margin-left: auto; flex: none; }
.profile-badges { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem; }
.badge-chip {
  background: rgba(255, 138, 43, 0.12);
  border: 1px solid rgba(255, 138, 43, 0.3);
  border-radius: 999px;
  padding: 0.3rem 0.8rem;
  font-size: 0.78rem;
  color: var(--text);
}

.mini-avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--accent);
  color: #17110a;
  font-weight: 800;
  flex: none;
}

.composer {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
  margin-bottom: 1.2rem;
}
.composer textarea {
  width: 100%;
  min-height: 70px;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 0.9rem;
  font-family: inherit;
  resize: vertical;
  outline: none;
}
.composer-preview { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.5rem; }
.composer-preview img { width: 64px; height: 64px; object-fit: cover; border-radius: 6px; }
.composer-row { display: flex; align-items: center; gap: 0.7rem; margin-top: 0.6rem; padding-top: 0.6rem; border-top: 1px solid var(--border); }
.composer-photo-btn { cursor: pointer; color: var(--muted); font-size: 0.85rem; }
.composer-photo-btn:hover { color: var(--accent); }
.composer-visibility {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  padding: 0.4rem 0.5rem;
  font-size: 0.8rem;
}
.composer-submit { margin: 0 0 0 auto; padding: 0.5rem 1.4rem; width: auto; }

.feed-tabs { display: flex; gap: 0.5rem; margin-bottom: 1rem; }
.feed-tab {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.4rem 1rem;
  border-radius: 999px;
  font-size: 0.85rem;
  cursor: pointer;
}
.feed-tab.active { background: var(--accent); border-color: var(--accent); color: #17110a; font-weight: 700; }
.feed-empty { color: var(--muted); font-size: 0.85rem; text-align: center; padding: 1.5rem 0; }

.post-card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem;
  margin-bottom: 1rem;
}
.post-header { display: flex; align-items: center; gap: 0.6rem; }
.post-header-text { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.post-author { color: var(--text); font-weight: 700; font-size: 0.85rem; text-decoration: none; }
.post-author:hover { color: var(--accent); }
.post-meta { color: var(--muted); font-size: 0.72rem; }
.post-content { margin-top: 0.6rem; font-size: 0.88rem; line-height: 1.6; white-space: pre-wrap; }
.content-tag { color: var(--accent); text-decoration: none; font-weight: 600; }
.content-tag:hover { text-decoration: underline; }
.content-mention { color: var(--civ); font-weight: 600; }

.post-media { margin-top: 0.7rem; display: grid; gap: 4px; border-radius: 8px; overflow: hidden; }
.post-media.grid-1 { grid-template-columns: 1fr; }
.post-media.grid-2 { grid-template-columns: 1fr 1fr; }
.post-media.grid-3 { grid-template-columns: 1fr 1fr; }
.post-media.grid-4 { grid-template-columns: 1fr 1fr; }
.post-media img { width: 100%; height: 100%; max-height: 320px; object-fit: cover; display: block; }
/* A single photo shows in full rather than being cropped to fill a fixed
   box -- cover-cropping was chopping the bottom off tall/uneven images
   (e.g. a logo with a wordmark underneath it). Multi-photo grids (2-4)
   keep object-fit:cover, since cropping into even tiles is the expected
   look there, same as Facebook/Instagram's own multi-photo grids. */
.post-media.grid-1 img { object-fit: contain; max-height: 480px; background: var(--bg); }

.post-actions { display: flex; gap: 0.5rem; margin-top: 0.7rem; padding-top: 0.6rem; border-top: 1px solid var(--border); flex-wrap: wrap; }
.reaction-btn {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  padding: 0.3rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
}
.reaction-btn:hover { border-color: var(--accent); }
.reaction-btn.active { background: rgba(255, 138, 43, 0.15); border-color: var(--accent); color: var(--text); }

.post-menu { position: relative; margin-left: auto; }
.post-menu-toggle { background: none; border: none; color: var(--muted); font-size: 1.1rem; cursor: pointer; padding: 0.2rem 0.5rem; }
.post-menu-items {
  display: none;
  position: absolute;
  top: 100%;
  right: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.3rem;
  min-width: 130px;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4);
  z-index: 10;
}
.post-menu.open .post-menu-items { display: block; }
.post-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: var(--text);
  padding: 0.4rem 0.6rem;
  font-size: 0.8rem;
  border-radius: 6px;
  cursor: pointer;
}
.post-menu-item:hover { background: rgba(255, 138, 43, 0.12); }

.post-comments { margin-top: 0.7rem; padding-top: 0.7rem; border-top: 1px solid var(--border); }
.comment-row { display: flex; gap: 0.5rem; margin-bottom: 0.6rem; }
.comment-body { flex: 1; min-width: 0; }
.comment-bubble { background: var(--bg); border-radius: 10px; padding: 0.5rem 0.7rem; font-size: 0.82rem; }
.comment-bubble .post-author { font-size: 0.8rem; }
.comment-meta { color: var(--muted); font-size: 0.7rem; margin-top: 0.2rem; display: flex; gap: 0.6rem; }
.comment-delete-btn, .comment-report-btn { background: none; border: none; color: var(--muted); font-size: 0.7rem; cursor: pointer; padding: 0; }
.comment-delete-btn:hover, .comment-report-btn:hover { color: var(--accent); }
.comment-composer { display: flex; gap: 0.5rem; margin-top: 0.4rem; }
.comment-input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.45rem 0.9rem;
  color: var(--text);
  font-size: 0.82rem;
}
.comment-submit-btn {
  background: var(--accent);
  border: none;
  border-radius: 999px;
  padding: 0.45rem 1rem;
  color: #17110a;
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
}

.community-sidebar { display: flex; flex-direction: column; gap: 1rem; }
.sidebar-card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px; padding: 1rem; }
.sidebar-card h2 { font-size: 0.85rem; margin: 0 0 0.6rem; color: var(--text); }
.sidebar-card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.6rem; }
.sidebar-card-header h2 { margin: 0; }
.sidebar-link-btn { background: none; border: none; color: var(--accent); font-size: 0.72rem; cursor: pointer; }

.notifications-list { display: flex; flex-direction: column; gap: 0.4rem; max-height: 260px; overflow-y: auto; }
.notification-row { font-size: 0.78rem; color: var(--muted); padding: 0.4rem; border-radius: 6px; display: flex; justify-content: space-between; gap: 0.5rem; }
.notification-row.unread { background: rgba(255, 138, 43, 0.08); color: var(--text); }
.notif-time { color: var(--muted); white-space: nowrap; font-size: 0.7rem; }

.log-stats { display: flex; gap: 1.5rem; margin-bottom: 1.5rem; }
.log-stat {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.8rem 1.4rem;
  text-align: center;
  display: flex;
  flex-direction: column;
}
.log-stat strong { font-size: 1.3rem; color: var(--accent); }
.log-stat span { font-size: 0.72rem; color: var(--muted); }

.log-entry {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 0.8rem 2.6rem 0.8rem 1rem;
  margin-bottom: 0.6rem;
}
.log-entry-main { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.log-entry-type { color: var(--muted); font-size: 0.85rem; }
.log-entry-meta { color: var(--muted); font-size: 0.75rem; margin-top: 0.3rem; }
.log-delete-btn {
  position: absolute;
  top: 0.7rem;
  right: 0.7rem;
  background: none;
  border: none;
  color: var(--muted);
  font-size: 0.9rem;
  cursor: pointer;
  padding: 0.2rem;
}
.log-delete-btn:hover { color: var(--mil); }

.alert-toggle {
  position: absolute;
  top: 0.9rem;
  right: 0.8rem;
  cursor: pointer;
}
.alert-active-toggle { width: 2.2rem; height: 1.2rem; cursor: pointer; accent-color: var(--accent); }

.friends-list { display: flex; flex-direction: column; gap: 0.5rem; max-height: 220px; overflow-y: auto; }
.friend-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; }
.friend-row a { color: var(--text); text-decoration: none; flex: 1; }
.friend-row a:hover { color: var(--accent); }
.friend-accept-btn {
  background: var(--accent);
  border: none;
  border-radius: 999px;
  padding: 0.25rem 0.6rem;
  color: #17110a;
  font-weight: 700;
  font-size: 0.72rem;
  cursor: pointer;
}

/* ---- Mobile ----
   Never actually tested at a real phone viewport until Daz pointed out
   dropdowns and info were getting cut off -- this whole block is the fix,
   not a "nice to have" pass. Key real problems found and fixed here:
   .nav-dropdowns had no flex-wrap of its own (only the outer .hotspots did),
   so location dropdowns were forced onto one unbreakable row that ran off
   the right edge of the screen; .data-panel's fixed 340px width would eat
   almost an entire phone screen when opened; the topbar's tagline+status
   text wrapped over multiple lines and pushed the map down. */
@media (max-width: 640px) {
  /* .nav-dropdowns had `flex: none` (no shrink) on desktop, sized to fit
     its full unwrapped content -- adding flex-wrap alone did nothing since
     the box itself never got narrower than the viewport to wrap within.
     Forcing it to its own full-width row (flex-basis 100%) is what actually
     makes the wrapping visible on screen. This is the fix for the "Airshows"
     dropdown getting cut off at the screen edge that Daz reported. */
  .nav-dropdowns { flex: 1 1 100%; min-width: 0; flex-wrap: wrap; }

  /* Same underlying bug as .nav-dropdowns above, just on content pages'
     header instead of the map's: .header-actions (Guides dropdown +
     account-nav + back link) never got its own wrap rule, so a logged-in
     user's header ran off the right edge of the screen on every content
     page (community.html, frequencies.html, etc.) -- found via a real
     scrollWidth check during the community-page rebuild, not the map page
     this class of bug was originally fixed on. */
  .header-actions { flex: 1 1 100%; min-width: 0; flex-wrap: wrap; justify-content: flex-end; }

  .topbar { flex-wrap: wrap; gap: 0.4rem; padding: 0.6rem 0.8rem; }
  .tagline { display: none; }
  .status { font-size: 0.75rem; }
  .brand-logo { height: 28px; }

  .hotspots { padding: 0.5rem 0.8rem; gap: 0.4rem; }
  .hotspot-btn, .dropdown-toggle { font-size: 0.76rem; padding: 0.35rem 0.65rem; }

  /* the panel becomes a full-width overlay on top of the map instead of
     squeezing it down to a sliver -- there's no room to show both at once
     on a phone screen */
  .data-panel {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100vw;
    z-index: 950;
  }
  .data-panel.collapsed { width: 0; }
  .table-wrap { min-width: 0; }
  /* fixed in the same spot whether the panel is open or closed, above it
     (z-index), rather than trying to track the panel's changing width like
     on desktop -- simpler and always reachable on a small screen.
     Vertically centred on the right edge specifically -- every corner is
     already taken (top-left zoom controls, top-right Leaflet layer
     switcher, bottom-left legend, bottom-right Leaflet attribution link),
     confirmed two of those the hard way via real Playwright click timeouts
     ("element intercepts pointer events") before landing here. */
  .data-panel-toggle,
  .data-panel.collapsed ~ .data-panel-toggle {
    position: fixed;
    top: 50%;
    bottom: auto;
    right: 8px;
    transform: translateY(-50%);
    z-index: 960;
  }

  .dropdown-menu { max-width: calc(100vw - 1.6rem); }
  .header-actions .dropdown-menu,
  .dropdown:has(.guides-toggle) .dropdown-menu { right: -0.8rem; }

  .legend {
    left: 0.6rem;
    bottom: 0.6rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.68rem;
    gap: 0.5rem;
  }
  .legend .alt-gradient { width: 120px; }
  .legend .alt-labels span:nth-child(2) { display: none; }

  .leaflet-popup-content { width: 240px !important; }

  .freq-main { padding: 1.2rem 0.9rem 3rem; }
  .guide-grid { grid-template-columns: 1fr; }
  .guide-controls { flex-direction: column; align-items: stretch; }

  .site-footer-inner { flex-direction: column; align-items: flex-start; gap: 0.4rem; }
  .footer-credit { margin-left: 0; }

  .community-layout { grid-template-columns: 1fr; }
  .profile-card { position: static; }
  .composer-row { flex-wrap: wrap; }
  .composer-submit { margin-left: 0; width: 100%; }

  .profile-header { flex-wrap: wrap; }
  #profile-friend-action { margin-left: 0; width: 100%; }
}

/* ---- Heard, no position --------------------------------------------------
   Mode S contacts: an identity with no position. Presented as a plain list,
   visually separate from the aircraft table, so it never reads as though
   these are on the map. */
.heard-only {
  border-top: 1px solid var(--border);
  padding: 0.7rem 0.6rem 0.9rem;
  min-width: 340px;
}

.heard-only-title {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.04em;
}

.heard-only-title span { color: var(--muted); font-weight: 400; }

.heard-only-note {
  margin: 0.2rem 0 0.5rem;
  font-size: 0.68rem;
  line-height: 1.35;
  color: var(--muted);
}

.heard-row {
  display: grid;
  grid-template-columns: 5.2rem 1fr auto;
  gap: 0.5rem;
  align-items: center;
  font-size: 0.74rem;
  padding: 0.25rem 0.3rem;
  border-left: 2px solid var(--mil);
  background: rgba(255, 255, 255, 0.03);
  margin-bottom: 1px;
}

.heard-cs { font-weight: 700; }
.heard-type { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.heard-reg { color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- Base activity pulse -------------------------------------------------
   Three numbers answering "is this place busy", then who was actually here. */
.activity-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.4rem;
  margin-bottom: 0.35rem;
}

.activity-stat {
  background: rgba(255, 138, 43, 0.1);
  border: 1px solid rgba(255, 138, 43, 0.3);
  border-radius: 6px;
  padding: 0.35rem 0.2rem;
  text-align: center;
}

.activity-stat strong { display: block; font-size: 1.15rem; line-height: 1.1; color: var(--accent); }
.activity-stat span { font-size: 0.6rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }

.activity-note {
  margin: 0 0 0.4rem;
  font-size: 0.64rem;
  color: var(--muted);
}

.activity-list { display: flex; flex-direction: column; gap: 1px; }

.activity-row {
  display: grid;
  grid-template-columns: 4.8rem 1fr auto;
  gap: 0.4rem;
  align-items: center;
  font-size: 0.72rem;
  padding: 0.22rem 0.35rem;
  background: rgba(255, 255, 255, 0.03);
}

.activity-cs { font-weight: 700; }
.activity-type { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.activity-when { color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- Seven day history chart ---------------------------------------------
   One series, so no legend: the section heading names it. Bars are thin with
   a 2px surface gap, rounded only at the data end, anchored to the baseline.
   Values are direct-labelled on the busiest day and today only; every bar
   carries its own hover title, and the type list below doubles as the table
   view of the same data. */
.hchart {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  align-items: end;
  height: 76px;
  margin-bottom: 0.4rem;
}

.hbar {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  height: 100%;
  gap: 2px;
  cursor: default;
}

.hbar-track {
  width: 100%;
  flex: 1;
  display: flex;
  align-items: flex-end;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 2px;
}

.hbar-fill {
  width: 100%;
  min-height: 2px;
  background: var(--accent);
  border-radius: 4px 4px 0 0; /* rounded at the data end only */
}

.hbar:hover .hbar-fill { filter: brightness(1.2); }

/* Fixed height whether or not it holds a number: an empty inline span
   collapses, which left labelled bars with a shorter track than the rest and
   made identical counts draw at different heights. */
.hbar-value {
  display: block;
  height: 0.8rem;
  line-height: 0.8rem;
  font-size: 0.6rem;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.hbar-day { font-size: 0.58rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; }

.htypes {
  list-style: none;
  margin: 0 0 0.2rem;
  padding: 0;
}

.htypes li {
  display: flex;
  justify-content: space-between;
  gap: 0.6rem;
  font-size: 0.71rem;
  color: var(--muted);
  padding: 0.13rem 0.35rem;
  background: rgba(255, 255, 255, 0.03);
  margin-bottom: 1px;
}

.htypes li span { color: var(--text); font-variant-numeric: tabular-nums; }

/* ---- Emergency squawks ---------------------------------------------------
   7500/7600/7700. Rare, and the reason a spotter drops everything, so they
   are allowed to shout. Colour is never the only signal: every one of these
   carries the word as well. */
.plane-icon-wrap.plane-emergency { animation: emergency-pulse 1.1s ease-in-out infinite; }

@keyframes emergency-pulse {
  0%, 100% { filter: drop-shadow(0 0 3px rgba(255, 60, 60, 0.9)); }
  50% { filter: drop-shadow(0 0 11px rgba(255, 60, 60, 1)); }
}

/* Anyone who prefers no motion still gets the glow, just not the pulse. */
@media (prefers-reduced-motion: reduce) {
  .plane-icon-wrap.plane-emergency {
    animation: none;
    filter: drop-shadow(0 0 8px rgba(255, 60, 60, 1));
  }
}

.emergency-flag {
  background: var(--mil);
  color: #2b0000;
  font-weight: 800;
  font-size: 0.62rem;
  letter-spacing: 0.05em;
  padding: 0.15rem 0.35rem;
  border-radius: 4px;
  margin-bottom: 0.3rem;
  text-align: center;
}

.emergency-banner {
  display: block;
  background: rgba(255, 77, 77, 0.16);
  border-top: 1px solid var(--mil);
  border-bottom: 1px solid var(--mil);
  padding: 0.45rem 0.8rem;
  text-decoration: none;
  color: var(--text);
}

.emergency-banner strong {
  display: block;
  color: var(--mil);
  font-size: 0.78rem;
  letter-spacing: 0.05em;
}

.emergency-banner span { font-size: 0.68rem; color: var(--muted); }
.emergency-banner:hover { background: rgba(255, 77, 77, 0.24); }

/* ---- Share ---------------------------------------------------------------- */
.share-btn {
  display: block;
  width: 100%;
  margin-bottom: 0.5rem;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--accent);
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.32rem;
  cursor: pointer;
}

.share-btn:hover { border-color: var(--accent); background: rgba(255, 138, 43, 0.08); }

.share-miss {
  background: rgba(255, 138, 43, 0.12);
  border-bottom: 1px solid var(--border);
  color: var(--text);
  text-align: center;
  padding: 0.45rem 1rem;
  font-size: 0.8rem;
  z-index: 900;
}


/* Feed problem notice. Sits over the map because that is where the absence
   of aircraft is being read, and a visitor must not conclude the sky is empty
   when the source is simply not answering. */
.feed-notice {
  position: absolute;
  top: 0.9rem;
  left: 50%;
  transform: translateX(-50%);
  max-width: min(30rem, calc(100% - 2rem));
  background: rgba(120, 30, 20, 0.94);
  border: 1px solid #a8342a;
  color: #ffe7e2;
  padding: 0.55rem 0.9rem;
  border-radius: 8px;
  font-size: 0.8rem;
  line-height: 1.4;
  text-align: center;
  z-index: 600;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
}

/* About page lists. Same rhythm as .freq-intro paragraphs so the page reads as
   one piece rather than a bolted-on section. */
.freq-section p { color: var(--text); line-height: 1.6; margin: 0 0 0.8rem; }

.about-list {
  list-style: none;
  padding: 0;
  margin: 0 0 1rem;
}

.about-list li {
  color: var(--text);
  line-height: 1.6;
  padding: 0.5rem 0 0.5rem 1.1rem;
  border-bottom: 1px solid var(--border);
  position: relative;
}

.about-list li:last-child { border-bottom: none; }

.about-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 1.05rem;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

.about-list strong { color: var(--text); }
.about-list a, .freq-section p a { color: var(--accent); }

/* "Seen here" on a base card. Deliberately quiet: it is observed evidence,
   not an authoritative squadron list, and should not shout louder than the
   live activity above it. */
.seen-list { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.5rem; }

.seen-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.6rem;
  padding: 0.28rem 0;
  border-bottom: 1px solid rgba(31, 41, 55, 0.6);
  font-size: 0.78rem;
}
.seen-row:last-child { border-bottom: none; }
.seen-name { color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.seen-days { color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }

/* Seen on more than one day, so it is a pattern rather than a one off. */
.seen-row.seen-regular .seen-name { font-weight: 700; }
.seen-row.seen-regular .seen-days { color: var(--accent); }

.seen-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-bottom: 0.4rem; }
.seen-chip {
  background: rgba(255, 138, 43, 0.1);
  border: 1px solid rgba(255, 138, 43, 0.3);
  color: var(--text);
  border-radius: 999px;
  padding: 0.15rem 0.5rem;
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
}
.seen-chip em { color: var(--muted); font-style: normal; }

/* Past flights on the aircraft card. Same card styling as the facts block so
   the panel reads as one thing. */
.flight-list { display: flex; flex-direction: column; }
.flight-row {
  padding: 0.4rem 0;
  border-bottom: 1px solid rgba(31, 41, 55, 0.6);
  font-size: 0.76rem;
}
.flight-row:last-child { border-bottom: none; }
.flight-when { color: var(--muted); font-size: 0.7rem; }
.flight-route { color: var(--text); font-weight: 700; margin: 0.1rem 0; }
.flight-arrow { color: var(--muted); font-weight: 400; }
.flight-unknown { color: var(--muted); font-weight: 400; }
.flight-meta { color: var(--muted); font-variant-numeric: tabular-nums; }
.flight-empty { color: var(--muted); font-size: 0.76rem; line-height: 1.5; }

/* Recent movements on a base card. Denser than the seen-here list because it
   is a feed of events rather than a summary. */
.move-list { display: flex; flex-direction: column; margin-bottom: 0.5rem; }
.move-row {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  font-size: 0.78rem;
  padding-top: 0.35rem;
}
.move-who { color: var(--text); font-weight: 700; flex: none; }
.move-what { color: var(--muted); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.move-when { color: var(--muted); flex: none; font-variant-numeric: tabular-nums; }
.move-meta {
  font-size: 0.7rem;
  color: var(--muted);
  padding-bottom: 0.35rem;
  border-bottom: 1px solid rgba(31, 41, 55, 0.6);
}
.move-list > .move-meta:last-child { border-bottom: none; }
