/* ===== Theme Variables — HeroUI-inspired ===== */
[data-theme="light"] {
  --bg-body: #f4f4f5;
  --bg-sidebar: rgba(255, 255, 255, 0.82);
  --bg-sidebar-solid: #ffffff;
  --bg-input: #ffffff;
  --bg-panel: #ffffff;
  --bg-bar-track: #e4e4e7;
  --bg-modal: rgba(255, 255, 255, 0.88);
  --bg-modal-solid: #ffffff;
  --border: #e4e4e7;
  --border-light: #f4f4f5;
  --text-primary: #18181b;
  --text-secondary: #3f3f46;
  --text-muted: #71717a;
  --text-faint: #a1a1aa;
  --accent: #6366f1;
  --accent-hover: #4f46e5;
  --accent-subtle: rgba(99, 102, 241, 0.1);
  --btn-secondary-bg: #f4f4f5;
  --btn-secondary-hover: #e4e4e7;
  --btn-secondary-text: #18181b;
  --overlay-bg: rgba(0, 0, 0, 0.4);
  --shadow: rgba(0, 0, 0, 0.05);
  --shadow-strong: rgba(0, 0, 0, 0.1);
  --fab-bg: rgba(255, 255, 255, 0.82);
  --fab-border: #e4e4e7;
  --fab-hover: #f4f4f5;
  --info-overlay-bg: rgba(255, 255, 255, 0.82);
  --badge-green-bg: #dcfce7;  --badge-green-fg: #16a34a;
  --badge-yellow-bg: #fef9c3; --badge-yellow-fg: #ca8a04;
  --badge-orange-bg: #ffedd5; --badge-orange-fg: #ea580c;
  --badge-red-bg: #fee2e2;    --badge-red-fg: #dc2626;
  --popup-bg: #ffffff;
  --popup-text: #18181b;
  --popup-shadow: rgba(0, 0, 0, 0.12);
  --zoom-bg: rgba(255, 255, 255, 0.82);
  --zoom-text: #18181b;
  --zoom-border: #e4e4e7;
  --zoom-hover: #f4f4f5;
  --attribution-bg: rgba(255, 255, 255, 0.7);
  --attribution-text: #71717a;
  --attribution-link: #6366f1;
  --checkbox-accent: #6366f1;
  --live-status-color: #16a34a;
  --stat-strong: #18181b;
  --noise-stat-border: #e4e4e7;
  --sidebar-blur: blur(20px) saturate(1.4);
  --switch-bg: #d4d4d8;
  --switch-bg-active: #6366f1;
  --switch-knob: #ffffff;
}

[data-theme="dark"] {
  --bg-body: #09090b;
  --bg-sidebar: rgba(24, 24, 27, 0.78);
  --bg-sidebar-solid: #18181b;
  --bg-input: #27272a;
  --bg-panel: #1c1c1f;
  --bg-bar-track: #27272a;
  --bg-modal: rgba(24, 24, 27, 0.88);
  --bg-modal-solid: #18181b;
  --border: #27272a;
  --border-light: #27272a;
  --text-primary: #fafafa;
  --text-secondary: #d4d4d8;
  --text-muted: #71717a;
  --text-faint: #52525b;
  --accent: #818cf8;
  --accent-hover: #6366f1;
  --accent-subtle: rgba(129, 140, 248, 0.1);
  --btn-secondary-bg: #27272a;
  --btn-secondary-hover: #3f3f46;
  --btn-secondary-text: #fafafa;
  --overlay-bg: rgba(0, 0, 0, 0.6);
  --shadow: rgba(0, 0, 0, 0.3);
  --shadow-strong: rgba(0, 0, 0, 0.5);
  --fab-bg: rgba(24, 24, 27, 0.78);
  --fab-border: #3f3f46;
  --fab-hover: #27272a;
  --info-overlay-bg: rgba(24, 24, 27, 0.82);
  --badge-green-bg: rgba(22, 163, 106, 0.15);  --badge-green-fg: #4ade80;
  --badge-yellow-bg: rgba(202, 138, 4, 0.15);   --badge-yellow-fg: #fbbf24;
  --badge-orange-bg: rgba(234, 88, 12, 0.15);   --badge-orange-fg: #fb923c;
  --badge-red-bg: rgba(220, 38, 38, 0.15);      --badge-red-fg: #f87171;
  --popup-bg: #18181b;
  --popup-text: #fafafa;
  --popup-shadow: rgba(0, 0, 0, 0.5);
  --zoom-bg: rgba(24, 24, 27, 0.78);
  --zoom-text: #fafafa;
  --zoom-border: #3f3f46;
  --zoom-hover: #27272a;
  --attribution-bg: rgba(24, 24, 27, 0.7);
  --attribution-text: #52525b;
  --attribution-link: #71717a;
  --checkbox-accent: #818cf8;
  --live-status-color: #4ade80;
  --stat-strong: #fafafa;
  --noise-stat-border: #27272a;
  --sidebar-blur: blur(20px) saturate(1.2);
  --switch-bg: #3f3f46;
  --switch-bg-active: #818cf8;
  --switch-knob: #fafafa;
}

/* ===== Reset & Base ===== */
*, *::before, *::after {
  box-sizing: border-box;
}

html, body {
  height: 100%;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  background: var(--bg-body);
  color: var(--text-primary);
  transition: background 0.3s, color 0.3s;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ===== Sidebar ===== */
.sidebar {
  position: fixed;
  left: 0;
  top: 0;
  width: 320px;
  height: 100vh;
  background: var(--bg-sidebar);
  backdrop-filter: var(--sidebar-blur);
  -webkit-backdrop-filter: var(--sidebar-blur);
  color: var(--text-primary);
  overflow-y: auto;
  z-index: 1000;
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 0.3s, color 0.3s;
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border);
}

.sidebar.collapsed {
  transform: translateX(-280px);
}

.sidebar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 14px 14px 18px;
  border-bottom: 1px solid var(--border);
}

.sidebar-header h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
  white-space: nowrap;
  letter-spacing: -0.01em;
}

.sidebar-header-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.home-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  border: 1px solid var(--border);
  color: var(--text-muted);
  flex-shrink: 0;
  text-decoration: none;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.home-link svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.home-link:hover {
  background: var(--btn-secondary-bg);
  color: var(--text-primary);
  border-color: var(--text-muted);
}

.collapse-btn {
  background: none;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 0.85rem;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  cursor: pointer;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s, transform 0.3s;
}

.collapse-btn:hover {
  background: var(--btn-secondary-bg);
  color: var(--text-primary);
}

.sidebar.collapsed .collapse-btn {
  transform: rotate(180deg);
}

.sidebar-content {
  flex: 1;
  overflow-y: auto;
  padding-bottom: 16px;
}

/* ===== Sidebar Sections ===== */
.sidebar-section {
  padding: 14px 18px;
  border-bottom: 1px solid var(--border);
}

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

.sidebar-section h3 {
  margin: 0 0 10px 0;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
}

/* Section heading with icon */
.section-heading {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.section-icon {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: var(--text-muted);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

.accordion-toggle:hover .section-icon {
  stroke: var(--accent);
}

/* When the section body is open, give an extra hint that headings interact */
.accordion:not(.collapsed) .accordion-toggle .section-icon {
  stroke: var(--accent);
}

/* ===== Accordion ===== */
.accordion-toggle {
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  user-select: none;
  border-radius: 8px;
  margin: -4px -6px 6px;
  padding: 6px;
  transition: background 0.15s;
}

.accordion.collapsed .accordion-toggle {
  margin-bottom: -4px;
}

.accordion-toggle:hover {
  background: var(--accent-subtle);
  color: var(--text-primary);
}

.accordion-arrow {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: var(--text-faint);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1), stroke 0.15s;
  flex-shrink: 0;
}

.accordion-toggle:hover .accordion-arrow {
  stroke: var(--text-secondary);
}

.accordion.collapsed .accordion-arrow {
  transform: rotate(-90deg);
}

.accordion-body {
  overflow: hidden;
  max-height: 600px;
  transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease;
  opacity: 1;
}

.accordion.collapsed .accordion-body {
  max-height: 0;
  opacity: 0;
}

/* ===== Form Controls ===== */
.form-group {
  margin-bottom: 12px;
}

.form-group > label {
  display: block;
  font-size: 0.75rem;
  color: var(--text-muted);
  margin-bottom: 5px;
  font-weight: 500;
}

input[type="date"],
input[type="number"],
select {
  background: var(--bg-input);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 8px 12px;
  font-size: 0.82rem;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s, background 0.3s, color 0.3s;
  width: 100%;
}

input[type="date"]:focus,
input[type="number"]:focus,
select:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-subtle);
}

/* Date & hour range rows */
.date-range,
.hour-range {
  display: flex;
  align-items: center;
  gap: 6px;
}

.date-range input,
.hour-range input {
  flex: 1;
  min-width: 0;
}

.range-sep {
  font-size: 0.75rem;
  color: var(--text-faint);
  flex-shrink: 0;
}

/* ===== Checkbox Grid ===== */
.checkbox-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px 12px;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.82rem;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 8px;
  padding: 3px 4px;
  transition: background 0.15s;
}

.checkbox-label:hover {
  background: var(--accent-subtle);
}

.checkbox-label input[type="checkbox"] {
  accent-color: var(--checkbox-accent);
  width: 15px;
  height: 15px;
  cursor: pointer;
  border-radius: 4px;
}

/* ===== Layer Toggles ===== */
.layer-toggles {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* Switch-style toggles for layers */
.layer-toggles .checkbox-label {
  justify-content: space-between;
  flex-direction: row-reverse;
  padding: 6px 8px;
  border-radius: 10px;
}

.layer-toggles .checkbox-label input[type="checkbox"] {
  position: relative;
  width: 36px;
  height: 20px;
  -webkit-appearance: none;
  appearance: none;
  background: var(--switch-bg);
  border-radius: 20px;
  outline: none;
  cursor: pointer;
  transition: background 0.2s;
  flex-shrink: 0;
}

.layer-toggles .checkbox-label input[type="checkbox"]::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  background: var(--switch-knob);
  border-radius: 50%;
  transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.layer-toggles .checkbox-label input[type="checkbox"]:checked {
  background: var(--switch-bg-active);
}

.layer-toggles .checkbox-label input[type="checkbox"]:checked::after {
  transform: translateX(16px);
}

/* ===== Buttons ===== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 18px;
  border: none;
  border-radius: 14px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.1s, transform 0.25s, box-shadow 0.1s;
}

.btn:active {
  transform: scale(0.97);
}

.btn-primary {
  background: var(--accent);
  color: #fff;
  width: 100%;
}

.btn-primary:hover {
  background: var(--accent-hover);
  box-shadow: 0 4px 14px var(--accent-subtle);
}

.btn-primary.fetching {
  opacity: 0.7;
  pointer-events: none;
}

.btn-primary.fetching .btn-label {
  opacity: 0.6;
}

.btn-primary.fetching .spinner {
  display: inline-block;
}

/* Solid dark button — sits more prominently than the surrounding controls. */
.btn-apply {
  background: var(--text-primary);
  color: var(--bg-sidebar-solid);
  width: 100%;
  margin-top: 4px;
}

.btn-apply:hover {
  background: var(--text-secondary);
}

/* ===== Stats Display ===== */
.stats-display {
  margin-top: 10px;
  font-size: 0.82rem;
  color: var(--text-muted);
  line-height: 1.6;
}

.stats-display .stat-row {
  display: flex;
  justify-content: space-between;
}

.stats-display .stat-value {
  color: var(--text-primary);
  font-weight: 600;
}

/* ===== Noise Panel ===== */
.noise-panel {
  background: var(--bg-panel);
  border-radius: 14px;
  margin: 8px 10px;
  padding: 14px 16px;
  border-bottom: none;
}

.noise-panel.hidden {
  display: none;
}

.noise-level {
  font-size: 1.6rem;
  font-weight: 700;
  margin: 4px 0 2px;
  letter-spacing: -0.02em;
}

.noise-level-label {
  font-size: 0.75rem;
  margin-bottom: 10px;
}

/* Noise color coding */
.noise-green  { color: #4ade80; }
.noise-yellow { color: #fbbf24; }
.noise-orange { color: #fb923c; }
.noise-red    { color: #f87171; }

/* Hourly chart bars */
.hourly-chart {
  margin-top: 10px;
}

.hourly-chart .chart-title {
  font-size: 0.72rem;
  color: var(--text-muted);
  margin-bottom: 6px;
}

.hourly-bar-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 3px;
  font-size: 0.7rem;
}

.hourly-bar-row .bar-label {
  width: 28px;
  text-align: right;
  color: var(--text-muted);
  flex-shrink: 0;
}

.hourly-bar-row .bar-track {
  flex: 1;
  height: 8px;
  background: var(--bg-bar-track);
  border-radius: 4px;
  overflow: hidden;
}

.hourly-bar-row .bar-fill {
  height: 100%;
  border-radius: 4px;
  transition: width 0.3s ease;
}

.hourly-bar-row .bar-value {
  width: 32px;
  text-align: left;
  color: var(--text-muted);
  flex-shrink: 0;
}

/* ===== Noise Results (from noise.js) ===== */
.noise-results .noise-label {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 2px 0;
  line-height: 1.3;
}

.noise-results .noise-coords {
  font-size: 0.72rem;
  color: var(--text-muted);
  margin: 0 0 10px 0;
}

.noise-stat {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 6px 0;
  font-size: 0.82rem;
  border-bottom: 1px solid var(--noise-stat-border);
}

.noise-badge {
  padding: 3px 12px;
  border-radius: 20px;
  font-weight: 700;
  font-size: 0.82rem;
}

.badge-green  { background: var(--badge-green-bg);  color: var(--badge-green-fg); }
.badge-yellow { background: var(--badge-yellow-bg); color: var(--badge-yellow-fg); }
.badge-orange { background: var(--badge-orange-bg); color: var(--badge-orange-fg); }
.badge-red    { background: var(--badge-red-bg);    color: var(--badge-red-fg); }

.noise-description {
  margin: 10px 0;
  font-size: 0.82rem;
  color: var(--text-muted);
  font-style: italic;
}

.noise-hourly h4 {
  font-size: 0.75rem;
  color: var(--text-muted);
  margin: 12px 0 6px 0;
}

.noise-bar-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 2px;
  font-size: 0.7rem;
}

.noise-bar-row.busiest {
  font-weight: 700;
}

.noise-bar-row.busiest .noise-bar-label {
  color: var(--accent);
}

.noise-bar-label {
  width: 38px;
  text-align: right;
  color: var(--text-muted);
  flex-shrink: 0;
}

.noise-bar-track {
  flex: 1;
  height: 6px;
  background: var(--bg-bar-track);
  border-radius: 3px;
  overflow: hidden;
}

.noise-bar-fill {
  height: 100%;
  border-radius: 3px;
  transition: width 0.3s ease;
}

.noise-bar-value {
  width: 36px;
  text-align: left;
  color: var(--text-muted);
  flex-shrink: 0;
}

.noise-loading, .noise-error {
  padding: 12px 0;
  font-size: 0.82rem;
  color: var(--text-muted);
}

.noise-freshness {
  margin-top: 12px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 0.7rem;
  color: var(--text-faint);
  text-align: right;
}

.noise-error {
  color: #f87171;
}

.stat-item {
  font-size: 0.82rem;
  color: var(--text-muted);
  padding: 2px 0;
}

.stat-item strong {
  color: var(--stat-strong);
}

/* ===== Live Mode ===== */
.live-toggle {
  font-weight: 600;
}

.live-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.live-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #f87171;
  animation: pulse-dot 1.5s infinite;
}

/* When toggle is unchecked, the dot becomes muted (dot is now nested
   inside .live-label, so use a descendant selector). */
.live-toggle input:not(:checked) ~ .live-label .live-dot {
  background: var(--text-faint);
  animation: none;
}

@keyframes pulse-dot {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

.live-status {
  padding: 8px 0 0;
  font-size: 0.78rem;
  color: var(--live-status-color);
  line-height: 1.7;
}

/* Each callsign in the live-status line is a clickable chip — clicking
   pans the map to that aircraft and opens its popup. Inherits color from
   the surrounding text but underlines on hover to signal interactivity. */
.live-callsign {
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: underline dotted transparent;
  text-underline-offset: 3px;
  transition: color 0.12s, text-decoration-color 0.12s;
}

.live-callsign:hover,
.live-callsign:focus-visible {
  color: var(--accent);
  text-decoration-color: currentColor;
  outline: none;
}

.live-aircraft-icon {
  background: none !important;
  border: none !important;
}

.plane-marker {
  font-size: 28px;
  color: #fbbf24;
  text-shadow: 0 0 8px rgba(0, 0, 0, 0.7);
  line-height: 1;
  text-align: center;
}

.live-popup strong {
  color: #fbbf24;
}

/* ===== Spinner ===== */
.spinner {
  width: 16px;
  height: 16px;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

.spinner.hidden {
  display: none;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* Loading overlay spinner */
.loading-spinner {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.loading-spinner::after {
  content: '';
  width: 24px;
  height: 24px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

/* ===== Map ===== */
/* Sidebar floats over the map — no margin shift on collapse */
#map {
  margin-left: 0;
  height: 100vh;
  width: 100vw;
}

/* Soften sidebar background so map remains visible underneath */
.sidebar {
  box-shadow: 0 8px 32px var(--shadow);
}

/* Push Leaflet's top-left controls clear of the floating sidebar.
   When sidebar is collapsed, slide them back to the left edge. */
.leaflet-top.leaflet-left {
  left: 332px;
  transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Collapsed sidebar still shows a ~40px strip with the toggle button —
   keep the map controls clear of it. */
.sidebar.collapsed ~ #map .leaflet-top.leaflet-left {
  left: 52px;
}

@media (max-width: 768px) {
  /* On mobile, the sidebar is a bottom drawer that slides vertically — it
     never overlaps the top-left where leaflet controls live. Pin the
     controls there regardless of sidebar state, overriding the desktop
     `.sidebar.collapsed ~ #map ...` shift rule above. */
  .leaflet-top.leaflet-left,
  .sidebar.collapsed ~ #map .leaflet-top.leaflet-left {
    left: 12px;
  }
}

/* ===== Info Overlay ===== */
.info-overlay {
  position: absolute;
  bottom: 20px;
  right: 20px;
  background: var(--info-overlay-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--text-muted);
  font-size: 0.75rem;
  padding: 8px 14px;
  border-radius: 12px;
  z-index: 900;
  pointer-events: none;
  border: 1px solid var(--border);
}

/* ===== Leaflet Theme Overrides ===== */
.leaflet-popup-content-wrapper {
  background: var(--popup-bg);
  color: var(--popup-text);
  border-radius: 14px;
  box-shadow: 0 4px 24px var(--popup-shadow);
  border: 1px solid var(--border);
}

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

.leaflet-popup-content {
  margin: 12px 16px;
  font-size: 0.82rem;
  line-height: 1.5;
}

.leaflet-popup-close-button {
  color: var(--text-muted) !important;
}

.leaflet-popup-close-button:hover {
  color: var(--accent) !important;
}

.leaflet-control-zoom {
  border: 1px solid var(--zoom-border) !important;
  border-radius: 12px !important;
  overflow: hidden;
  box-shadow: 0 2px 8px var(--shadow) !important;
}

.leaflet-control-zoom a {
  background: var(--zoom-bg) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--zoom-text) !important;
  border-color: var(--zoom-border) !important;
  width: 34px !important;
  height: 34px !important;
  line-height: 34px !important;
  font-size: 16px !important;
}

.leaflet-control-zoom a:hover {
  background: var(--zoom-hover) !important;
}

/* Touch devices: Leaflet adds .leaflet-touch which bumps default control
   sizes (44x44) — that breaks alignment with our 34px stack. Pin them. */
.leaflet-touch .leaflet-bar a {
  width: 34px;
  height: 34px;
}

/* ===== Map Nav Controls (recenter + locate) =====
   Visual width matches Leaflet zoom buttons (34px) so all map
   controls in the top-left stack align cleanly. */
.map-nav-controls {
  margin-top: 10px !important;
  border: 1px solid var(--zoom-border) !important;
  border-radius: 12px !important;
  overflow: hidden;
  box-shadow: 0 2px 8px var(--shadow) !important;
  width: 36px;
}

.map-nav-btn {
  display: flex !important;
  align-items: center;
  justify-content: center;
  /* border-box so the 1px divider doesn't push the button taller than the
     leaflet zoom buttons it stacks beneath. (Without this, each btn was 35px
     and the second-group container was visibly taller.) */
  box-sizing: border-box;
  width: 34px;
  height: 34px;
  background: var(--zoom-bg) !important;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--zoom-text) !important;
  border-bottom: 1px solid var(--zoom-border) !important;
  cursor: pointer;
  text-decoration: none !important;
}

/* Match Leaflet's default zoom-control width so stacked controls align */
.leaflet-control-zoom {
  width: 36px;
}

.map-nav-btn:last-child {
  border-bottom: none !important;
}

.map-nav-btn:hover {
  background: var(--zoom-hover) !important;
}

.map-nav-btn svg {
  /* 18px icons read at the same visual weight as the bold +/- glyphs in
     the zoom group; 16px looked floaty and made the second group feel
     lighter than the first. */
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--zoom-text);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: block;
}

.map-nav-btn.locating svg {
  animation: pulse-locate 1s ease-in-out infinite;
}

@keyframes pulse-locate {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.3; }
}

/* User location marker */
.user-location-icon {
  background: none !important;
  border: none !important;
}

.user-dot {
  width: 14px;
  height: 14px;
  background: #818cf8;
  border: 3px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(129, 140, 248, 0.5);
}

/* Toast notification — horizontally centered at the top of the viewport so
   it's clearly visible regardless of sidebar state, and not crowded by any
   map control on either side. */
.map-toast {
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translate(-50%, -8px);
  background: var(--bg-sidebar);
  backdrop-filter: var(--sidebar-blur);
  -webkit-backdrop-filter: var(--sidebar-blur);
  color: var(--text-primary);
  border: 1px solid var(--border);
  padding: 10px 16px;
  border-radius: 14px;
  font-size: 0.82rem;
  box-shadow: 0 4px 20px var(--shadow-strong);
  z-index: 1200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s, transform 0.3s;
  max-width: min(420px, calc(100% - 32px));
  white-space: normal;
  text-align: center;
}

.map-toast.visible {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}

/* Center ping animation */
.center-ping {
  pointer-events: none;
}

.center-ping-ring {
  width: 24px;
  height: 24px;
  border: 2px solid var(--accent);
  border-radius: 50%;
  animation: ping-expand 0.8s ease-out forwards;
  position: relative;
}

.center-ping-ring::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  background: var(--accent);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  animation: ping-dot 0.8s ease-out forwards;
}

@keyframes ping-expand {
  0%   { transform: scale(0.3); opacity: 1; }
  70%  { transform: scale(2.5); opacity: 0.4; }
  100% { transform: scale(3);   opacity: 0; }
}

@keyframes ping-dot {
  0%   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  60%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
}

.leaflet-control-attribution {
  background: var(--attribution-bg) !important;
  color: var(--attribution-text) !important;
  border-radius: 8px 0 0 0 !important;
  font-size: 0.65rem !important;
}

.leaflet-control-attribution a {
  color: var(--attribution-link) !important;
}

/* ===== Floating Action Buttons ===== */
.fab-group {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 1100;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.fab {
  width: 40px;
  height: 40px;
  border-radius: 14px;
  border: 1px solid var(--fab-border);
  background: var(--fab-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--accent);
  font-size: 1.1rem;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, transform 0.25s, box-shadow 0.15s;
  box-shadow: 0 2px 8px var(--shadow);
}

.fab:hover {
  background: var(--fab-hover);
  transform: scale(1.05);
  box-shadow: 0 4px 16px var(--shadow-strong);
}

.fab:active {
  transform: scale(0.97);
}

.fab svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ===== Modal ===== */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 2000;
  background: var(--overlay-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.modal-overlay.hidden {
  display: none !important;
}

.modal {
  background: var(--bg-modal);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  border: 1px solid var(--border);
  border-radius: 24px;
  width: 90%;
  max-width: 640px;
  max-height: 85vh;
  display: flex;
  flex-direction: column;
  box-shadow: 0 8px 40px var(--shadow-strong);
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.modal-header h2 {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

.modal-close {
  background: var(--btn-secondary-bg);
  border: none;
  color: var(--text-muted);
  font-size: 1.2rem;
  cursor: pointer;
  padding: 0;
  width: 30px;
  height: 30px;
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: background 0.15s, color 0.15s;
}

.modal-close:hover {
  background: var(--btn-secondary-hover);
  color: var(--text-primary);
}

.modal-body {
  padding: 20px 24px;
  overflow-y: auto;
  font-size: 0.85rem;
  line-height: 1.7;
  color: var(--text-secondary);
}

.modal-body h3 {
  color: var(--text-primary);
  font-size: 0.82rem;
  font-weight: 700;
  margin: 22px 0 8px 0;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.modal-body h3:first-child {
  margin-top: 0;
}

.modal-body p {
  margin: 0 0 10px 0;
}

.modal-body ul {
  margin: 0 0 10px 0;
  padding-left: 20px;
}

.modal-body li {
  margin-bottom: 4px;
}

.noise-ref-table {
  width: 100%;
  border-collapse: collapse;
  margin: 8px 0 12px;
}

.noise-ref-table td {
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
  font-size: 0.82rem;
}

.noise-ref-table td:first-child {
  color: var(--text-primary);
  font-weight: 600;
  width: 70px;
}

/* ===== Address Search Bar (floating bottom-center) ===== */
.address-bar {
  position: fixed;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 1100;
  width: min(420px, calc(100% - 32px));
  pointer-events: none;
}

.address-form {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-sidebar);
  backdrop-filter: var(--sidebar-blur);
  -webkit-backdrop-filter: var(--sidebar-blur);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 8px 10px 8px 14px;
  box-shadow: 0 8px 32px var(--shadow-strong);
  pointer-events: auto;
  position: relative;
}

.address-icon {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: var(--text-muted);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex-shrink: 0;
}

#address-input {
  flex: 1;
  border: none;
  background: transparent;
  color: var(--text-primary);
  font-size: 0.9rem;
  outline: none;
  padding: 6px 0;
  min-width: 0;
}

#address-input::placeholder {
  color: var(--text-faint);
}

.address-submit {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 10px;
  border: none;
  background: var(--accent);
  color: #fff;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.15s, transform 0.15s;
}

.address-submit:hover {
  background: var(--accent-hover);
}

.address-submit:active {
  transform: scale(0.94);
}

.address-submit svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: #fff;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.address-submit.loading {
  opacity: 0.7;
  pointer-events: none;
}

.address-status {
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: -28px;
  font-size: 0.75rem;
  color: var(--text-muted);
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s;
}

.address-status.visible {
  opacity: 1;
}

.address-status.error {
  color: #f87171;
}

/* Suggestion dropdown — appears above the address bar */
.address-suggestions {
  list-style: none;
  margin: 0;
  padding: 4px;
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 8px);
  background: var(--bg-sidebar);
  backdrop-filter: var(--sidebar-blur);
  -webkit-backdrop-filter: var(--sidebar-blur);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 8px 32px var(--shadow-strong);
  max-height: 280px;
  overflow-y: auto;
}

.address-suggestion {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  border-radius: 10px;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--text-primary);
  transition: background 0.1s;
}

.address-suggestion:hover,
.address-suggestion.active {
  background: var(--accent-subtle);
}

.address-suggestion .suggestion-title {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.address-suggestion .suggestion-detail {
  font-size: 0.72rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.suggestion-loading {
  padding: 10px 12px;
  font-size: 0.8rem;
  color: var(--text-muted);
  font-style: italic;
}

@media (max-width: 768px) {
  /* When the sidebar drawer is open it occupies the bottom 40vh, so we
     park the address bar just above it. When the user collapses the drawer
     it slides down to a 48px header, and the address bar should follow it
     down so users get the screen real estate back. */
  .address-bar {
    bottom: calc(40vh + 16px);
    transition: bottom 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .sidebar.collapsed ~ .address-bar,
  body:has(.sidebar.collapsed) .address-bar {
    bottom: 64px;
  }
}

/* ===== Recent Pins List ===== */
.pin-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.pin-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  border-radius: 10px;
  font-size: 0.82rem;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s;
}

.pin-item:hover {
  background: var(--accent-subtle);
  color: var(--text-primary);
}

.pin-item .pin-label {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Pin row icon buttons (rename, save, delete). All share the same square
   chrome so the row keeps a consistent rhythm. The delete button only
   appears on hover; the rename button stays visible so it's discoverable. */
.pin-item .pin-edit-btn,
.pin-item .pin-delete {
  border: none;
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  padding: 4px;
  border-radius: 6px;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: opacity 0.15s, background 0.15s, color 0.15s;
}

.pin-item .pin-edit-btn svg,
.pin-item .pin-delete svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Hide rename + delete by default; reveal on row hover. The save variant
   stays visible while editing because we're already in an active state. */
.pin-item .pin-edit-btn,
.pin-item .pin-delete {
  opacity: 0;
}

.pin-item:hover .pin-edit-btn,
.pin-item:hover .pin-delete,
.pin-item .pin-edit-btn--save {
  opacity: 1;
}

.pin-item .pin-edit-btn:hover {
  background: var(--btn-secondary-bg);
  color: var(--accent);
}

.pin-item .pin-edit-btn--save {
  color: var(--accent);
}

.pin-item .pin-edit-btn--save:hover {
  background: var(--accent-subtle);
}

.pin-item .pin-delete:hover {
  background: var(--btn-secondary-bg);
  color: #f87171;
}

/* Inline rename input — fills the row, matches the surrounding type scale */
.pin-item .pin-edit-input {
  flex: 1;
  min-width: 0;
  background: var(--bg-input);
  color: var(--text-primary);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 0.82rem;
  font-family: inherit;
  outline: none;
}

.pin-empty {
  font-size: 0.78rem;
  color: var(--text-faint);
  font-style: italic;
  padding: 6px 4px;
}

/* ===== Share button (standalone, beneath the map-nav stack) ===== */
.share-control {
  margin-top: 10px !important;
  border: 1px solid var(--zoom-border) !important;
  border-radius: 12px !important;
  overflow: hidden;
  box-shadow: 0 2px 8px var(--shadow) !important;
  width: 36px;
}

.share-btn {
  /* Same chrome as map-nav-btn — keeps the stack visually consistent. */
  border-bottom: none !important;
}

/* ===== Share modal contents ===== */
.share-intro {
  margin: 0 0 14px 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.share-include-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: var(--text-primary);
  margin-bottom: 12px;
  cursor: pointer;
}

.share-include-row input[type="checkbox"] {
  accent-color: var(--checkbox-accent);
  width: 16px;
  height: 16px;
}

.share-include-row input[type="checkbox"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.share-pin-count {
  color: var(--text-muted);
  margin-left: 4px;
}

.share-link-row {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}

.share-link-row input {
  flex: 1;
  min-width: 0;
  background: var(--bg-input);
  color: var(--text-primary);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 8px 12px;
  font-size: 0.78rem;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  outline: none;
}

.share-link-row input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-subtle);
}

.share-copy-btn {
  background: var(--accent);
  color: #fff;
  padding: 8px 16px;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  flex-shrink: 0;
  transition: background 0.15s;
}

.share-copy-btn:hover {
  background: var(--accent-hover);
}

.share-copy-btn--ok {
  background: #16a34a;
}

.share-copy-btn--ok:hover {
  background: #16a34a;
}

.share-privacy {
  margin: 0;
  font-size: 0.72rem;
  color: var(--text-muted);
  font-style: italic;
}

/* ===== Import modal contents ===== */
.import-pin-list {
  list-style: none;
  margin: 0 0 16px 0;
  padding: 8px 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  max-height: 220px;
  overflow-y: auto;
}

.import-pin-list li {
  padding: 6px 4px;
  font-size: 0.85rem;
  color: var(--text-primary);
}

.import-pin-list li + li {
  border-top: 1px solid var(--border-light);
}

.import-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}

.import-actions .btn {
  width: auto;
  padding: 8px 16px;
}

/* ===== Hidden Utility ===== */
.hidden {
  display: none !important;
}

/* ===== Responsive: Mobile Bottom Drawer ===== */
@media (max-width: 768px) {
  .sidebar {
    width: 100%;
    height: 40vh;
    top: auto;
    bottom: 0;
    left: 0;
    transform: none;
    border-top: 1px solid var(--border);
    border-right: none;
    border-radius: 24px 24px 0 0;
  }

  .sidebar.collapsed {
    transform: translateY(calc(40vh - 48px));
  }

  .sidebar.collapsed .collapse-btn {
    transform: rotate(90deg);
  }

  .collapse-btn {
    transform: rotate(-90deg);
  }

  /* Map stays full-height; sidebar floats over the bottom */
  .info-overlay {
    bottom: calc(40vh + 12px);
    right: 12px;
  }

  /* Reorder sidebar sections on mobile so the most action-relevant panel
     (Point Analysis, when present) sits at the top, then Saved Pins, then
     the rest. Use flex + `order` so we don't have to duplicate markup. */
  .sidebar-content {
    display: flex;
    flex-direction: column;
  }
  .sidebar-content > #noise-panel { order: 1; }
  .sidebar-content > #pins-section { order: 2; }
  .sidebar-content > .sidebar-section:not(#noise-panel):not(#pins-section) {
    order: 3;
  }
}

/* Image overlays — clip to circle */
.heatmap-overlay,
.density-overlay {
  border-radius: 50%;
}

/* ===== Scrollbar ===== */
.sidebar-content::-webkit-scrollbar,
.modal-body::-webkit-scrollbar {
  width: 6px;
}

.sidebar-content::-webkit-scrollbar-track,
.modal-body::-webkit-scrollbar-track {
  background: transparent;
}

.sidebar-content::-webkit-scrollbar-thumb,
.modal-body::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 3px;
}

.sidebar-content::-webkit-scrollbar-thumb:hover,
.modal-body::-webkit-scrollbar-thumb:hover {
  background: var(--text-faint);
}

/* ===== Landing / directory page ===== */

body.directory-page {
  display: block;
  /* Let the body grow with content. The base ``html, body { height:
     100% }`` rule is right for the airport page (scroll inside the
     map) but here it pins body to the viewport, so a fixed background
     only paints in the first 100vh — everything below would fall back
     to <html>'s solid colour. */
  height: auto;
  min-height: 100vh;
  /* Layered radial gradients give the page a "space" backdrop that
     stays visible behind every section (globe, SEO copy, nav). Fixed
     attachment + viewport-anchored ellipses mean the same gradient
     persists behind whatever you're scrolled to. The center halo keeps
     the middle of the viewport from going flat when the
     edge-anchored top/bottom gradients fade out. */
  background:
    radial-gradient(ellipse 70% 50% at 50% 50%, var(--accent-subtle), transparent 70%),
    radial-gradient(ellipse at 50% 0%, var(--accent-subtle), transparent 60%),
    var(--bg-body);
  background-attachment: fixed;
  color: var(--text-primary);
}

[data-theme="dark"] body.directory-page {
  background:
    radial-gradient(ellipse 65% 45% at 50% 50%, rgba(99, 102, 241, 0.12), transparent 72%),
    radial-gradient(ellipse at 50% 0%, rgba(99, 102, 241, 0.22), transparent 60%),
    radial-gradient(ellipse at 50% 100%, rgba(99, 102, 241, 0.14), transparent 55%),
    #05060a;
  background-attachment: fixed;
}

.directory-page .fab-theme {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 1100;
}

.directory-page main {
  display: block;
}

.directory-header {
  text-align: center;
  padding: 40px 24px 16px;
}

.directory-header h1 {
  margin: 0 0 12px 0;
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -0.02em;
  background: linear-gradient(135deg, var(--accent), var(--accent-hover));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.directory-tagline {
  margin: 0 auto;
  max-width: 560px;
  color: var(--text-secondary);
  font-size: 16px;
  line-height: 1.55;
}

/* Globe — almost-fullscreen hero. The frame fills the viewport with a
   ~50px gutter on every side; the sphere inside is square and centered
   (smaller of the two axes minus heading height + bottom breathing
   space). The frame can be a wide rectangle on landscape screens; the
   starfield fills the corners. */
#globe-section {
  position: relative;
  margin: 8px auto 56px;
  width: calc(100vw - 100px);
  height: calc(100vh - 200px);
  max-width: 1600px;
  max-height: 1100px;
  border-radius: 24px;
  overflow: hidden;
  background:
    radial-gradient(circle at 50% 50%, rgba(99, 102, 241, 0.05), transparent 70%);
}

.directory-wrap {
  max-width: 880px;
  margin: 0 auto;
  padding: 0 24px 80px;
  box-sizing: border-box;
}

#globe-viz {
  position: absolute;
  inset: 0;
}

#globe-viz canvas {
  display: block;
  cursor: grab;
}

#globe-viz canvas:active { cursor: grabbing; }

/* Globe marker — circular heatmap thumbnail floating on the sphere.
   globe.gl owns the outer position via translate3d; we just paint it. */
.globe-marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  pointer-events: auto;
  text-decoration: none;
  color: var(--text-primary);
  transition: transform 0.18s ease;
  /* Default depth so we have a stable z-axis to lift from on hover. */
  z-index: 1;
}

.globe-marker:hover,
.globe-marker:focus-visible {
  /* Lift hovered marker above its neighbours. The CSS3D layer in
     globe.gl uses absolute positioning with stacking-context-aware
     z-index, so a higher value reliably wins. */
  z-index: 50;
}

.globe-marker-thumb {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  overflow: hidden;
  border: 2px solid rgba(255, 255, 255, 0.8);
  background: rgba(12, 14, 24, 0.9);
  box-shadow:
    0 6px 20px rgba(0, 0, 0, 0.45),
    0 0 0 1px rgba(99, 102, 241, 0.15);
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
  display: block;
}

.globe-marker-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.globe-marker-label {
  margin-top: 6px;
  padding: 3px 9px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
  background: rgba(15, 17, 25, 0.85);
  color: #fafafa;
  border-radius: 999px;
  white-space: nowrap;
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.globe-marker:hover .globe-marker-thumb,
.globe-marker:focus-visible .globe-marker-thumb {
  transform: scale(1.12);
  border-color: var(--accent);
  box-shadow:
    0 8px 28px rgba(99, 102, 241, 0.45),
    0 0 0 2px var(--accent);
}

.globe-marker:hover .globe-marker-label,
.globe-marker:focus-visible .globe-marker-label {
  opacity: 1;
  transform: translateY(0);
}

@media (max-width: 640px) {
  .directory-wrap { padding: 32px 16px 56px; }
  .directory-header h1 { font-size: 32px; }
  .globe-marker-thumb { width: 56px; height: 56px; }
  .globe-marker-label { font-size: 11px; padding: 2px 7px; }
}

#about {
  max-width: 640px;
  margin: 0 auto 48px;
  font-size: 16px;
  line-height: 1.7;
  color: var(--text-secondary);
}

#about h2 {
  margin: 0 0 16px 0;
  font-size: 24px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

#about p {
  margin: 0 0 16px 0;
}

#about ul {
  margin: 0 0 20px 0;
  padding-left: 22px;
}

#about li {
  margin-bottom: 8px;
}

#about strong {
  color: var(--text-primary);
  font-weight: 600;
}

#airport-list {
  max-width: 640px;
  margin: 0 auto 48px;
}

#airport-list h2 {
  margin: 0 0 16px 0;
  font-size: 20px;
  font-weight: 600;
  color: var(--text-primary);
  letter-spacing: -0.01em;
}

#airport-list ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 8px;
}

#airport-list li a {
  display: block;
  padding: 12px 14px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text-primary);
  text-decoration: none;
  font-weight: 600;
  font-size: 15px;
  transition: border-color 0.15s, transform 0.15s;
}

#airport-list li a:hover {
  border-color: var(--accent);
  transform: translateY(-1px);
}

#airport-list .airport-list-meta {
  display: block;
  margin-top: 2px;
  font-weight: 400;
  font-size: 12px;
  color: var(--text-muted);
}

.directory-footer {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  font-size: 13px;
  color: var(--text-faint);
}

.directory-footer p {
  margin: 0;
}

/* ===== Airport page (per-airport SEO + interactive map) =====
   Same inset-frame + fixed-gradient backdrop as the directory page.
   Map and its overlays (sidebar, address bar, FABs, modals) live inside
   #airport-hero rather than the viewport. SEO long-form content sits
   below the hero in normal document flow.
*/

body.airport-page {
  display: block;
  height: auto;
  min-height: 100vh;
  /* Mirrors body.directory-page — radial gradient + fixed attachment so
     the backdrop stays consistent behind both the map hero and the
     scrollable SEO article below. */
  background:
    radial-gradient(ellipse 70% 50% at 50% 50%, var(--accent-subtle), transparent 70%),
    radial-gradient(ellipse at 50% 0%, var(--accent-subtle), transparent 60%),
    var(--bg-body);
  background-attachment: fixed;
  color: var(--text-primary);
}

[data-theme="dark"] body.airport-page {
  background:
    radial-gradient(ellipse 65% 45% at 50% 50%, rgba(99, 102, 241, 0.12), transparent 72%),
    radial-gradient(ellipse at 50% 0%, rgba(99, 102, 241, 0.22), transparent 60%),
    radial-gradient(ellipse at 50% 100%, rgba(99, 102, 241, 0.14), transparent 55%),
    #05060a;
  background-attachment: fixed;
}

/* The inset hero frame: ~50px gutter on every side, rounded corners,
   contains everything that used to be viewport-fixed (map, sidebar, FABs,
   address bar, modals). New positioning context for the children below.
   No max-width — frame grows with the viewport so wide screens feel
   filled rather than letterboxed. */
body.airport-page #airport-hero {
  position: relative;
  width: calc(100vw - 100px);
  height: calc(100vh - 100px);
  margin: 50px auto 56px;
  border-radius: 24px;
  overflow: hidden;
  background: var(--bg-body);
  box-shadow: 0 4px 24px var(--shadow);
}

/* Theme button is page-level (not hero-scoped) so it stays visible
   regardless of scroll. Matches the directory page's positioning. */
body.airport-page .fab-theme {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 1100;
}

/* Scope the previously-viewport-fixed elements to the hero frame. */
body.airport-page #airport-hero #map {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}

body.airport-page #airport-hero .sidebar {
  position: absolute;
}

body.airport-page #airport-hero .fab-group {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 1100;
}

body.airport-page #airport-hero .modal-overlay {
  position: absolute;
}

body.airport-page #airport-hero .address-bar {
  position: absolute;
}

/* Scroll cue — small chip at bottom-center of the hero hinting at content
   below. Animated with a gentle bounce so users notice without it being
   shouty. Hides on small screens where the SEO content is already nearly
   in view. */
body.airport-page .scroll-cue {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px 6px 14px;
  background: var(--bg-sidebar);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 12px;
  font-weight: 500;
  z-index: 900;
  box-shadow: 0 2px 8px var(--shadow);
  transition: background 0.2s, transform 0.2s;
  animation: scroll-cue-bounce 2.4s ease-in-out infinite;
}

body.airport-page .scroll-cue:hover {
  background: var(--bg-sidebar-solid);
  color: var(--text-primary);
}

body.airport-page .scroll-cue svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@keyframes scroll-cue-bounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50%      { transform: translateX(-50%) translateY(4px); }
}

/* Long-form SEO area below the hero. Two-column on desktop:
   sticky left rail (stats card + jump-to-section nav) | main article.
   Stacks to a single column on narrower screens. */
body.airport-page .airport-seo-layout {
  display: grid;
  grid-template-columns: 220px minmax(0, 720px);
  gap: 56px;
  max-width: 1080px;
  margin: 0 auto 64px;
  padding: 0 24px;
}

body.airport-page .airport-seo-aside {
  position: sticky;
  top: 24px;
  align-self: start;
  font-size: 14px;
  color: var(--text-secondary);
}

/* Stats card — header (airport code + live local time) then a divider
   then up to two stat blocks (flights/day, busiest hour + peak dB at
   that hour). Omits anything missing gracefully. */
body.airport-page .aside-stats {
  padding: 16px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  margin-bottom: 24px;
  /* Subtle accent glow so the card lifts off the page background a touch */
  box-shadow:
    0 1px 3px var(--shadow),
    0 0 0 1px color-mix(in srgb, var(--accent) 6%, transparent);
}

body.airport-page .aside-stats-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}

body.airport-page .aside-stats-airport {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  text-transform: uppercase;
}

body.airport-page .aside-stats-clock {
  font-size: 16px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
  color: var(--text-primary);
  /* Tiny pulse so users notice the time is "live" — runs only on first
     load, then settles. Subtle. */
  position: relative;
  padding-right: 12px;
}

body.airport-page .aside-stats-clock::after {
  content: '';
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.85;
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 50%, transparent);
  animation: aside-clock-pulse 2.4s ease-in-out infinite;
}

@keyframes aside-clock-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 50%, transparent);
    opacity: 0.85;
  }
  50% {
    box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent) 0%, transparent);
    opacity: 1;
  }
}

body.airport-page .aside-stats-divider {
  height: 1px;
  background: var(--border);
  margin: 0 -16px 14px;
}

body.airport-page .aside-stat {
  display: block;
  margin-bottom: 14px;
}

body.airport-page .aside-stat:last-child {
  margin-bottom: 0;
}

body.airport-page .aside-stat .stat-value {
  display: block;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--text-primary);
}

body.airport-page .aside-stat .stat-label {
  display: block;
  margin-top: 3px;
  font-size: 12px;
  color: var(--text-muted);
}

body.airport-page .aside-stat .stat-sub {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 4px 9px 4px 8px;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border-radius: 999px;
  font-size: 12px;
  color: var(--text-secondary);
  width: fit-content;
}

/* dB severity colour-coding — palette matches the map heatmap (green
   → yellow → orange → red). Tuned for source dB at the aircraft:
   < 75 quiet · 75–84 medium · 85–89 loud · 90+ very loud. The tinted
   chip background + saturated dot give the same visual cue as the
   heatmap without being shouty when used as text chrome. */
body.airport-page .aside-stat .stat-sub-db .db-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}

body.airport-page .aside-stat .stat-sub-db strong {
  font-weight: 600;
}

/* Light theme — saturated dot, tinted background, darker text for contrast */
body.airport-page .aside-stat .db-green   { background: var(--badge-green-bg);  color: var(--badge-green-fg); }
body.airport-page .aside-stat .db-yellow  { background: var(--badge-yellow-bg); color: var(--badge-yellow-fg); }
body.airport-page .aside-stat .db-orange  { background: var(--badge-orange-bg); color: var(--badge-orange-fg); }
body.airport-page .aside-stat .db-red     { background: var(--badge-red-bg);    color: var(--badge-red-fg); }

body.airport-page .aside-stat .db-green   .db-dot { background: var(--badge-green-fg); }
body.airport-page .aside-stat .db-yellow  .db-dot { background: var(--badge-yellow-fg); }
body.airport-page .aside-stat .db-orange  .db-dot { background: var(--badge-orange-fg); }
body.airport-page .aside-stat .db-red     .db-dot { background: var(--badge-red-fg); }

/* Jump-to-section nav — vertical TOC that highlights as user scrolls.
   Subtle by default; the airport content is the focus, the nav is
   just orientation. */
body.airport-page .aside-toc-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
  margin-bottom: 8px;
}

body.airport-page .aside-toc ol {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--border);
}

body.airport-page .aside-toc li {
  margin: 0;
}

body.airport-page .aside-toc a {
  display: block;
  padding: 6px 0 6px 12px;
  margin-left: -1px;
  border-left: 2px solid transparent;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 13px;
  line-height: 1.4;
  transition: color 0.15s, border-color 0.15s;
}

body.airport-page .aside-toc a:hover {
  color: var(--text-primary);
  border-left-color: var(--accent);
}

body.airport-page .aside-toc a.active,
body.airport-page .aside-toc a[aria-current="true"] {
  color: var(--accent);
  border-left-color: var(--accent);
  font-weight: 600;
}

/* Reading-friendly typography for the main article column. */
body.airport-page #airport-seo {
  font-size: 16px;
  line-height: 1.7;
  color: var(--text-secondary);
}

body.airport-page #airport-seo h1 {
  margin: 0 0 12px 0;
  font-size: 32px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  background: linear-gradient(135deg, var(--accent), var(--accent-hover));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

body.airport-page #airport-seo h2 {
  margin: 36px 0 12px 0;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--text-primary);
}

body.airport-page #airport-seo h3 {
  margin: 24px 0 8px 0;
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
}

body.airport-page #airport-seo p,
body.airport-page #airport-seo ul,
body.airport-page #airport-seo ol {
  margin: 0 0 16px 0;
}

body.airport-page #airport-seo ul,
body.airport-page #airport-seo ol {
  padding-left: 22px;
}

body.airport-page #airport-seo li {
  margin-bottom: 6px;
}

body.airport-page #airport-seo strong {
  color: var(--text-primary);
  font-weight: 600;
}

body.airport-page #airport-seo a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  transition: border-color 0.15s, color 0.15s;
}

body.airport-page #airport-seo a:hover {
  color: var(--accent-hover);
  border-bottom-color: var(--accent-hover);
}

body.airport-page #airport-seo table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 20px 0;
  font-size: 14px;
}

body.airport-page #airport-seo th,
body.airport-page #airport-seo td {
  padding: 8px 12px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

body.airport-page #airport-seo th {
  font-weight: 600;
  color: var(--text-primary);
  background: color-mix(in srgb, var(--accent) 5%, transparent);
}

/* Live-stats freshness section — dashboard grid of stat cards. Three
   columns on desktop, two on tablet, one on mobile. Cards lift slightly
   on hover so the section feels alive. */
body.airport-page #airport-seo .live-stats-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  margin: 0 0 24px 0;
}

@media (max-width: 720px) {
  body.airport-page #airport-seo .live-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 480px) {
  body.airport-page #airport-seo .live-stats-grid {
    grid-template-columns: 1fr;
  }
}

body.airport-page #airport-seo .live-stat-card {
  padding: 14px 16px 16px;
  background: var(--bg-panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: border-color 0.15s, transform 0.15s;
}

body.airport-page #airport-seo .live-stat-card:hover {
  border-color: color-mix(in srgb, var(--accent) 35%, var(--border));
  transform: translateY(-1px);
}

/* Full-row card — spans every grid column at every breakpoint, used
   for the hourly-distribution chart at the top of the dashboard. */
body.airport-page #airport-seo .live-stat-card-wide {
  grid-column: 1 / -1;
}

body.airport-page #airport-seo .live-stat-card-wide:hover {
  /* No lift on the chart card — feels too jumpy for something that wide. */
  transform: none;
}

/* Two-column card — used for content that's text-heavy enough to need
   the extra width (e.g. suburb names + editorial notes). At 2-col and
   below, this card naturally fills its row already. */
body.airport-page #airport-seo .live-stat-card-double {
  grid-column: span 2;
}

@media (max-width: 480px) {
  body.airport-page #airport-seo .live-stat-card-double {
    grid-column: span 1;
  }
}

/* Loudest-area card: static map on the left, text on the right. The
   map is a simple OSM raster — small, lazy-loaded, and scoped via a
   subtle border so it reads as a visual anchor not a full map. */
body.airport-page #airport-seo .live-stat-card-loudest {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 16px;
  padding: 14px;
  align-items: stretch;
}

body.airport-page #airport-seo .loudest-area-map {
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg-input);
  align-self: stretch;
  display: flex;
  /* Min-height so the map remains visible while loading on slow connections. */
  min-height: 140px;
}

body.airport-page #airport-seo .loudest-area-map img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* In dark mode, gently tone the OSM tiles down so the bright map
     doesn't fight with the rest of the dark UI. */
}

[data-theme="dark"] body.airport-page #airport-seo .loudest-area-map img {
  filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.9) saturate(0.8);
}

body.airport-page #airport-seo .loudest-area-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

/* Local-language name beneath the English name. Slightly smaller, muted,
   and in any script the source provides (Thai, Spanish, etc). */
body.airport-page #airport-seo .live-stat-value-local {
  font-size: 16px;
  font-weight: 500;
  color: var(--text-muted);
  letter-spacing: 0;
  line-height: 1.3;
  margin-top: -2px;
  word-break: break-word;
}

/* On the smallest screens, stack the map above the text so text isn't
   squeezed into a sliver. */
@media (max-width: 480px) {
  body.airport-page #airport-seo .live-stat-card-loudest {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  body.airport-page #airport-seo .loudest-area-map {
    min-height: 120px;
    max-height: 160px;
  }
}

/* Chart card header: label + flights/noise toggle on the right */
body.airport-page #airport-seo .hourly-chart-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

body.airport-page #airport-seo .hourly-chart-toggle {
  display: inline-flex;
  background: color-mix(in srgb, var(--text-muted) 8%, transparent);
  border-radius: 999px;
  padding: 2px;
  font-size: 12px;
}

body.airport-page #airport-seo .chart-toggle-btn {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 4px 12px 4px 8px;
  border-radius: 999px;
  color: var(--text-muted);
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

body.airport-page #airport-seo .chart-toggle-btn .toggle-icon {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The plane icon (Lucide) is a filled glyph rather than stroked; let it
   render solid so it reads as a plane silhouette. */
body.airport-page #airport-seo .chart-toggle-btn[data-chart-mode-set="flights"] .toggle-icon {
  fill: currentColor;
  stroke: none;
}

body.airport-page #airport-seo .chart-toggle-btn:hover {
  color: var(--text-secondary);
}

body.airport-page #airport-seo .chart-toggle-btn[aria-selected="true"] {
  background: var(--bg-panel);
  color: var(--text-primary);
  box-shadow: 0 1px 3px var(--shadow);
}

/* Hourly column chart inside the wide card. 24 bars laid out as a grid
   so the bars and the hour-labels below stay perfectly aligned even
   when bars have varying heights. */
body.airport-page #airport-seo .hourly-chart {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 8px;
}

body.airport-page #airport-seo .hourly-bars,
body.airport-page #airport-seo .hourly-axis {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  gap: 3px;
}

/* `display: grid` above otherwise overrides the [hidden] attribute's
   default `display: none`, leaving both bar variants visible at once. */
body.airport-page #airport-seo .hourly-bars[hidden],
body.airport-page #airport-seo [data-chart-label-for][hidden] {
  display: none;
}

body.airport-page #airport-seo .hourly-bars {
  height: 80px;
  align-items: end;
}

body.airport-page #airport-seo .hourly-bar {
  /* Reserve full height so a thin baseline shows for empty hours; the
     coloured fill grows from the bottom by --bar-h. */
  height: 100%;
  position: relative;
  border-radius: 3px 3px 1px 1px;
  background: color-mix(in srgb, var(--text-muted) 8%, transparent);
  transition: filter 0.15s;
  cursor: default;
}

body.airport-page #airport-seo .hourly-bar:hover {
  filter: brightness(1.15);
}

body.airport-page #airport-seo .hourly-bar .bar-fill {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: var(--bar-h, 0%);
  border-radius: 3px 3px 1px 1px;
  transition: height 0.3s ease;
  /* Minimum visible bar even at very low counts so non-zero hours
     don't disappear visually. */
  min-height: 2px;
}

body.airport-page #airport-seo .hourly-bar.db-empty .bar-fill { display: none; }

/* Tooltip floating above each bar on hover. CSS-only (no JS) — the
   tooltip is a child element pre-rendered server-side, hidden until
   the parent bar is hovered. Pointer-events: none so it doesn't steal
   focus from the bar itself. */
body.airport-page #airport-seo .bar-tooltip {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 10px;
  background: var(--bg-modal-solid);
  border: 1px solid var(--border);
  border-radius: 8px;
  white-space: nowrap;
  box-shadow: 0 4px 12px var(--shadow-strong);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s, transform 0.15s;
  z-index: 10;
}

/* Small triangular tail pointing down at the bar */
body.airport-page #airport-seo .bar-tooltip::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, -1px);
  border: 5px solid transparent;
  border-top-color: var(--bg-modal-solid);
  /* Stack a slightly larger tinted triangle behind for the border edge */
  filter: drop-shadow(0 1px 0 var(--border));
}

body.airport-page #airport-seo .bar-tooltip strong {
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

body.airport-page #airport-seo .bar-tooltip strong small {
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
  margin-left: 1px;
}

body.airport-page #airport-seo .bar-tooltip-sub {
  font-size: 11px;
  color: var(--text-muted);
}

body.airport-page #airport-seo .hourly-bar:hover .bar-tooltip,
body.airport-page #airport-seo .hourly-bar:focus-visible .bar-tooltip {
  opacity: 1;
  transform: translateX(-50%) translateY(-2px);
}

/* Hours with no peak-dB classification (count > 0 but no aircraft join)
   fall back to a neutral fill so they're still visible on the chart. */
body.airport-page #airport-seo .hourly-bar.db-empty {
  background: color-mix(in srgb, var(--text-muted) 12%, transparent);
}
body.airport-page #airport-seo .hourly-bar.db-green  .bar-fill { background: var(--badge-green-fg); }
body.airport-page #airport-seo .hourly-bar.db-yellow .bar-fill { background: var(--badge-yellow-fg); }
body.airport-page #airport-seo .hourly-bar.db-orange .bar-fill { background: var(--badge-orange-fg); }
body.airport-page #airport-seo .hourly-bar.db-red    .bar-fill { background: var(--badge-red-fg); }

body.airport-page #airport-seo .hourly-axis {
  font-size: 11px;
  color: var(--text-muted);
}

body.airport-page #airport-seo .bar-axis-label {
  text-align: center;
  font-variant-numeric: tabular-nums;
}

body.airport-page #airport-seo .live-stat-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

body.airport-page #airport-seo .live-stat-value {
  font-size: 26px;
  line-height: 1.15;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-primary);
  /* Allow wrap for long suburb names (e.g. "Nimman (Nimmanhaemin)").
     Hyphenate as a fallback to avoid horizontal overflow on tight cards. */
  word-break: break-word;
  hyphens: auto;
}

/* Drop the value font-size a notch when the value is text-heavy (a
   suburb name) rather than a single number, so it doesn't overpower
   the card on wrap. Applied via the loudest-area card variant. */
body.airport-page #airport-seo .live-stat-card .live-stat-value:not(:has(strong)) {
  font-size: 22px;
}

body.airport-page #airport-seo .live-stat-value strong {
  font-weight: 700;
}

body.airport-page #airport-seo .live-stat-sub {
  font-size: 12px;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 6px;
}

body.airport-page #airport-seo .live-stat-sub strong {
  color: var(--text-secondary);
  font-weight: 600;
}

/* dB-coloured sub for peak-dB lines: same palette as the aside chip,
   inline-flex pill rather than full-width bar so cards stay airy. */
body.airport-page #airport-seo .live-stat-sub-db {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px 3px 8px;
  border-radius: 999px;
  font-size: 12px;
  width: fit-content;
}

body.airport-page #airport-seo .live-stat-sub-db .db-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}

body.airport-page #airport-seo .live-stat-sub-db.db-green   { background: var(--badge-green-bg);  color: var(--badge-green-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-yellow  { background: var(--badge-yellow-bg); color: var(--badge-yellow-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-orange  { background: var(--badge-orange-bg); color: var(--badge-orange-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-red     { background: var(--badge-red-bg);    color: var(--badge-red-fg); }

body.airport-page #airport-seo .live-stat-sub-db.db-green   .db-dot { background: var(--badge-green-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-yellow  .db-dot { background: var(--badge-yellow-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-orange  .db-dot { background: var(--badge-orange-fg); }
body.airport-page #airport-seo .live-stat-sub-db.db-red     .db-dot { background: var(--badge-red-fg); }

body.airport-page #airport-seo .live-stat-sub-db strong {
  font-weight: 700;
  color: inherit;
}

/* Card-value dB tint — used on the "Peak dB observed" card where the
   number itself is the key signal. */
body.airport-page #airport-seo .live-stat-value.db-green  { color: var(--badge-green-fg); }
body.airport-page #airport-seo .live-stat-value.db-yellow { color: var(--badge-yellow-fg); }
body.airport-page #airport-seo .live-stat-value.db-orange { color: var(--badge-orange-fg); }
body.airport-page #airport-seo .live-stat-value.db-red    { color: var(--badge-red-fg); }

body.airport-page #airport-seo .yoy-note {
  padding: 12px 16px;
  background: color-mix(in srgb, var(--accent) 8%, var(--bg-panel));
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
  border-radius: 10px;
}

/* FAQ as a definition list — Q&A pairs read naturally, dt/dd styling
   gives a clear visual rhythm for both humans and FAQPage schema. */
body.airport-page #airport-seo .faq {
  margin: 0 0 24px 0;
}

body.airport-page #airport-seo .faq dt {
  margin-top: 16px;
  font-weight: 600;
  color: var(--text-primary);
  font-size: 16px;
}

body.airport-page #airport-seo .faq dd {
  margin: 6px 0 0 0;
  padding-left: 0;
  color: var(--text-secondary);
}

body.airport-page #airport-seo .sources {
  list-style: none;
  padding: 0;
  margin: 0 0 24px 0;
  font-size: 14px;
}

body.airport-page #airport-seo .sources li {
  padding: 8px 0;
  border-bottom: 1px solid var(--border-light);
  color: var(--text-muted);
}

body.airport-page #airport-seo .last-updated {
  margin-top: 32px;
  padding-top: 16px;
  border-top: 1px solid var(--border-light);
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
}

/* Mid-width: 2-col layout doesn't quite fit, drop to single column but
   keep the aside above the article. Sticky positioning is dropped here
   because the aside above article doesn't need to follow scroll. */
@media (max-width: 980px) {
  body.airport-page .airport-seo-layout {
    grid-template-columns: minmax(0, 720px);
    gap: 32px;
  }
  body.airport-page .airport-seo-aside {
    position: static;
  }
  /* Stats card and TOC shown side-by-side on tablet, full-width otherwise */
  body.airport-page .airport-seo-aside {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    align-items: start;
  }
  body.airport-page .aside-stats { margin-bottom: 0; }
}

/* Mobile: tighter hero gutter (~16px instead of 50px), hero shorter so the
   start of the SEO content peeks above the fold. Aside collapses to a
   single column above the article — TOC is most useful here. */
@media (max-width: 640px) {
  body.airport-page #airport-hero {
    width: calc(100vw - 32px);
    height: 75vh;
    margin: 16px auto 32px;
    border-radius: 18px;
  }
  body.airport-page .airport-seo-layout {
    padding: 0 16px;
    gap: 24px;
  }
  body.airport-page .airport-seo-aside {
    grid-template-columns: 1fr;
  }
  body.airport-page #airport-seo {
    font-size: 15px;
  }
  body.airport-page #airport-seo h1 { font-size: 26px; }
  body.airport-page #airport-seo h2 { font-size: 19px; }
  body.airport-page .scroll-cue { display: none; }
}
