:root {
  --bg: #0a0a14;
  --surface: #141420;
  --surface-2: #1e1e2e;
  --text: #e8e8f0;
  --text-muted: #8888a0;
  --accent: #6366f1;
  --accent-2: #818cf8;
  --border: #2a2a3a;
  --wx-day: #ffffff;
  --wx-day-op: 0.05;
  --wx-night: #1e3a8a;
  --wx-night-op: 0.22;
}

[data-theme="light"] {
  --bg: #f0f2f5;
  --surface: #ffffff;
  --surface-2: #f8f9fa;
  --text: #1a1a2e;
  --text-muted: #6b7280;
  --accent: #4f46e5;
  --accent-2: #6366f1;
  --border: #e5e7eb;
  --wx-day-op: 0.9;
  --wx-night-op: 0.12;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--text);
  min-height: 100vh;
}

.top-bar {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  padding: 0 1.5rem;
  display: flex;
  align-items: center;
  height: 56px;
  position: sticky;
  top: 0;
  z-index: 100;
}

.brand {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  line-height: 1;
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent);
  margin-right: 2rem;
  letter-spacing: 0.1em;
}

/* "hub" under the name: smaller and faded. */
.brand-sub {
  font-size: 0.5em;
  font-weight: 400;
  letter-spacing: 0.3em;
  opacity: 0.55;
  margin-top: 0.15em;
}

.tabs {
  display: flex;
  gap: 0.25rem;
  flex: 1;
}

.tab {
  background: transparent;
  border: none;
  color: var(--text-muted);
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  cursor: pointer;
  border-radius: 6px;
}

.tab:hover { color: var(--text); background: var(--surface-2); }
.tab.active { color: var(--accent); background: var(--surface-2); font-weight: 600; }

/* WX views share one tab: the last used view and an arrow listing the rest,
   drawn as one pill. */
.tab-group { display: inline-flex; border-radius: 6px; flex-shrink: 0; }
.tab-group .tab:first-child { border-radius: 6px 0 0 6px; padding-right: 0.5rem; }
.tab-group .tab-arrow {
  border-radius: 0 6px 6px 0;
  padding: 0.5rem 0.55rem;
  border-left: 1px solid var(--border);
  font-size: 0.75rem;
  line-height: 1;
}
.tab-group:hover .tab, .tab-group.active .tab { background: var(--surface-2); }
.tab-group.active .tab-arrow { font-weight: 400; }

/* Fixed, hung on <body>: the tab bar scrolls sideways on phones and would
   clip anything positioned inside it. */
.tab-menu {
  position: fixed;
  z-index: 200;
  min-width: 10rem;
  max-height: 60vh;
  overflow-y: auto;
  padding: 0.25rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
[data-theme="light"] .tab-menu { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); }
.tab-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  background: transparent;
  border: none;
  color: var(--text);
  padding: 0.5rem 0.75rem;
  font-size: 0.9rem;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
}
.tab-menu-item:hover, .tab-menu-item:focus-visible { background: var(--surface-2); color: var(--accent); outline: none; }

.theme-btn {
  background: transparent;
  border: none;
  color: var(--text-muted);
  font-size: 1.2rem;
  cursor: pointer;
  margin-left: auto;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 1.5rem;
}

.panel { display: none; }
.panel.active { display: block; }

.muted { color: var(--text-muted); font-size: 0.85rem; margin-top: 0.5rem; }

/* Weather */
.weather-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

.weather-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem;
}

.weather-card h3 { font-size: 1rem; margin-bottom: 0.5rem; }
.weather-temp { font-size: 2.5rem; font-weight: 300; color: var(--accent); }
.weather-desc { color: var(--text-muted); font-size: 0.85rem; margin-top: 0.25rem; }

/* Locations */
.locations-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 1rem;
  margin-bottom: 1rem;
}

.location-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.25rem;
}

.location-card h3 { margin-bottom: 0.25rem; }

/* Docs */
.docs-list { display: flex; flex-direction: column; gap: 0.75rem; }

.doc-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  cursor: pointer;
}

.doc-item:hover { border-color: var(--accent); }
.doc-icon { font-size: 1.5rem; }

/* Notes */
.notes-area { margin-top: 0.5rem; }

.note-block {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 1rem;
  margin-top: 0.75rem;
  line-height: 1.6;
}

h2 { font-size: 1.4rem; margin-bottom: 1rem; font-weight: 600; }

/* View sections */
.view-section { margin-bottom: 1.5rem; }
.loc-link { color: var(--accent); line-height: 0; padding: 0.35rem; margin: -0.35rem 0 -0.35rem -0.35rem; border-radius: 6px; flex-shrink: 0; }
.loc-link:hover { filter: brightness(1.3); background: var(--border); }

.view-section-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 1.1rem;
  font-weight: 600;
  cursor: pointer;
  padding: 0.75rem 1rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px 8px 0 0;
  user-select: none;
}

.view-section-header.collapsed { border-radius: 8px; }
.view-section-header:hover { background: var(--surface-2); }

.collapse-arrow { font-size: 0.8rem; color: var(--text-muted); width: 1rem; }
.item-count { margin-left: auto; font-size: 0.75rem; color: var(--text-muted); font-weight: 400; }

.view-section-body {
  border: 1px solid var(--border);
  border-top: none;
  border-radius: 0 0 8px 8px;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.item-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.75rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  text-decoration: none;
  color: var(--text);
  transition: border-color 0.15s;
}

.item-link:hover { border-color: var(--accent); }
.item-desc { font-size: 0.85rem; color: var(--text-muted); }
.item-url { font-size: 0.75rem; color: var(--accent-2); opacity: 0.7; }
.loc-head { display: flex; align-items: center; gap: 0.4rem; }
.loc-line { font-size: 0.85rem; color: var(--text-muted); }
.loc-line a { color: var(--accent-2); text-decoration: none; }
.loc-line a:hover { text-decoration: underline; }
.item-linked { display: flex; flex-direction: column; gap: 0.4rem; margin-top: 0.35rem; }
.item-linked .item-card { background: var(--surface); }
.linked-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; }
.linked-chip { font-size: 0.8rem; color: var(--accent-2); text-decoration: none; border: 1px solid var(--border); border-radius: 999px; padding: 0.1rem 0.6rem; }
.linked-chip:hover { border-color: var(--accent); }
.item-body { font-size: 0.9rem; line-height: 1.5; margin-top: 0.25rem; }

.item-iframe iframe {
  width: 100%;
  height: 400px;
  border-radius: 4px;
  margin-top: 0.5rem;
}

/* Preview card shown instead of an iframe the target refuses to serve framed */
.item-embed-card:hover { border-color: var(--accent); }
.item-embed-card .embed-card-img {
  width: 100%;
  max-height: 180px;
  object-fit: cover;
  border-radius: 4px;
  margin-bottom: 0.5rem;
  background: var(--surface);
}
.embed-card-hint { opacity: 0.6; margin-left: 0.4rem; }

.item-photo img {
  max-width: 100%;
  border-radius: 4px;
  margin-top: 0.5rem;
}

/* Weather widget (see docs/wx.md) */
.item-wx { gap: 0.5rem; }
.wx-station-line { font-size: 0.75rem; color: var(--text-muted); }
.cwx-line { display: flex; align-items: center; gap: 0.2rem; }
.cwx-edit { background: none; border: none; padding: 0 0.25rem; color: var(--text-muted); cursor: pointer; font-size: 0.85rem; line-height: 1; }
.cwx-edit:hover, .cwx-edit:focus-visible { color: var(--accent, #60a5fa); }
.cwx-badge { display: inline-block; margin-left: 0.25rem; padding: 0 0.3rem; border-radius: 3px; border: 1px solid var(--border, #333); color: var(--text-muted); font-size: 0.65rem; font-weight: 600; letter-spacing: 0.04em; vertical-align: middle; }
.cwx-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 0.5rem 0.75rem; margin-top: 0.5rem; font-size: 0.85rem; }
.cwx-form label { display: flex; flex-direction: column; gap: 0.2rem; color: var(--text-muted); font-size: 0.75rem; }
.cwx-form input { width: 17rem; max-width: calc(100vw - 4rem); }
/* Airport search results: fixed on <body>, name first, code on the right. */
.cwx-list {
  position: fixed;
  z-index: 200;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
  font-size: 0.85rem;
}
[data-theme="light"] .cwx-list { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); }
.cwx-list [role=option] {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
  cursor: pointer;
}
.cwx-list [role=option]:hover, .cwx-list [aria-selected=true] { background: var(--surface-2); color: var(--accent); }
.cwx-opt-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cwx-opt-code { flex: none; color: var(--text-muted); font-size: 0.75rem; font-variant-numeric: tabular-nums; }
.cwx-form label[hidden] { display: none; }
.cwx-form select[name=near] { max-width: calc(100vw - 4rem); }
.cwx-opt-name small { display: block; color: var(--text-muted); font-size: 0.7rem; overflow: hidden; text-overflow: ellipsis; }
.cwx-opt-search .cwx-opt-name { color: var(--accent); font-style: italic; }
.cwx-list-note { padding: 0.25rem 0.6rem; color: var(--text-muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }
.cwx-form input, .cwx-form select { font: inherit; font-size: 0.85rem; padding: 0.3rem 0.4rem; background: var(--bg, transparent); color: inherit; border: 1px solid var(--border, #333); border-radius: 4px; }
.cwx-status { font-size: 0.75rem; color: var(--text-muted); }
.wx-body { display: flex; flex-direction: column; gap: 0.5rem; }
.wx-loading { font-size: 0.85rem; color: var(--text-muted); }

.wx-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 0.6rem 0.75rem;
}
.wx-panel-empty { font-size: 0.8rem; color: var(--text-muted); }

.wx-panel-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}
.wx-panel-title { font-weight: 600; font-size: 0.85rem; }
.wx-age { margin-left: auto; font-size: 0.7rem; color: var(--text-muted); }
/* Shown when the last refresh failed and the panel is on older data. */
.wx-stale {
  margin-left: 0.3rem;
  padding: 0 0.3rem;
  border-radius: 3px;
  background: #f0a83c;
  color: #1a1a1a;
  font-weight: 600;
  cursor: help;
}

/* Flight category. Standard aviation colours, not the theme accent - these are
   read by colour, and VFR green / IFR red is the convention. */
.wx-cat {
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  padding: 0.1rem 0.35rem;
  border-radius: 3px;
  color: #0a0a14;
}
.wx-cat-vfr { background: #4ade80; }
.wx-cat-mvfr { background: #60a5fa; }
.wx-cat-ifr { background: #f87171; }
.wx-cat-lifr { background: #f472b6; }
.wx-cat-unk { background: var(--border); color: var(--text-muted); }

.wx-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 0.4rem 0.75rem;
}
.wx-cell { display: flex; flex-direction: column; }
.wx-k { font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.wx-v { font-size: 0.9rem; }
/* Cloud layers wrap at the dots between them, never inside one. The ceiling
   layer is bold: it is the ceiling, so there is no separate Ceiling cell. */
.wx-sky-layer { white-space: nowrap; }
.wx-nowrap { white-space: nowrap; }
.wx-sky-layer-ceil { font-weight: 600; }
.wx-sky-layer-note { color: var(--text-muted); }

.wx-raw {
  display: block;
  margin-top: 0.5rem;
  font-size: 0.7rem;
  line-height: 1.4;
  color: var(--text-muted);
  word-break: break-word;
}

.wx-table-wrap { overflow-x: auto; }
.wx-table { width: 100%; border-collapse: collapse; font-size: 0.75rem; }
.wx-table th {
  text-align: left;
  font-weight: 500;
  color: var(--text-muted);
  padding: 0.2rem 0.4rem 0.2rem 0;
  white-space: nowrap;
}
.wx-table td { padding: 0.2rem 0.4rem 0.2rem 0; white-space: nowrap; }
.wx-table tbody tr + tr td { border-top: 1px solid var(--border); }

/* Tier switch: all three ranges come out of one payload, so this is a
   re-render and never a refetch. */
.wx-tabs { display: flex; gap: 0.25rem; margin-bottom: 0.5rem; }
.wx-tab {
  background: none;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-muted);
  font: inherit;
  font-size: 0.75rem;
  padding: 0.2rem 0.6rem;
  cursor: pointer;
}
.wx-tab:hover { color: var(--text); background: var(--surface-2); }
/* The selected tab is filled, not just outlined, so it reads at a glance in
   both themes. White on the accent holds contrast on light and dark cards. */
.wx-tab.active,
.wx-tab.active:hover { color: #fff; background: var(--accent); border-color: var(--accent); font-weight: 600; }

.wx-chart + .wx-chart { margin-top: 0.75rem; }
.wx-chart-head { display: flex; align-items: baseline; gap: 0.5rem; }
.wx-chart-title { font-size: 0.8rem; font-weight: 600; }
.wx-unit { font-weight: 400; color: var(--text-muted); }
.wx-chart-note { margin-left: auto; font-size: 0.65rem; color: var(--text-muted); }

/* Sky cover row. The glyphs sit in unstretched SVGs positioned by percentage
   so the circles stay round at any card width - the charts below use
   preserveAspectRatio="none" and would squash anything drawn inside them. */
.wx-glyph-row { position: relative; height: 17px; margin-top: 0.2rem; }
.wx-cloud-row { margin-bottom: 0.1rem; }
.wx-wind-row { margin-top: 0.1rem; }
/* Width is set inline, sized off the axis tick spacing; the SVG fills it and
   the row centres what it gets, so one geometry covers every tier and every
   card width. */
.wx-glyph-cell {
  position: absolute; top: 50%; transform: translate(-50%, -50%);
  display: block; line-height: 0; cursor: default;
}
.wx-glyph { display: block; width: 100%; height: auto; overflow: visible; }
/* The same glyphs inline in the current observation, where there is no axis to
   size them from - a fixed 13px sits on the cell's own type. */
.wx-cell-glyph {
  display: inline-block; width: 13px; vertical-align: -0.15em; margin-right: 0.3rem;
}
/* Sky and cloud are the same two colours in both themes, on purpose. They were
   `--text` and `--surface` before, which flip with the theme - so the discs read
   correctly on the light card and exactly backwards on the dark one, where an
   overcast hour drew almost solid white. These say what they mean regardless of
   which theme is on, and the ring keeps the disc bounded against either
   background. Cloud is a mid grey rather than simply something dark: on the dark
   card a dark fill sinks into the surface and an overcast hour would look like
   an empty disc, which is the picture for clear. */
.wx-okta-ring { fill: #b9d4ee; stroke: var(--text-muted); stroke-width: 1; }
.wx-okta-fill { fill: #6b7086; }
/* No forecast for the hour. An unfilled disc now means clear, so this cannot be
   one - it takes the card surface and reads as absent rather than as weather. */
.wx-okta-none { fill: var(--surface); }
/* Disagreement arc. Amber rather than the indigo accent: the disc it wraps is
   sky blue now, and two blues touching read as one shape rather than as a mark
   and its annotation. Not red or green - red already means IFR two rows down,
   and the arc's length carries the magnitude, so hue would only repeat it. */
.wx-okta-arc { fill: none; stroke: #f0a83c; stroke-width: 2; stroke-linecap: round; opacity: 0.95; }

/* Arrows fly with the wind - from the north points down the card. Hollow when
   the models do not agree on a direction, which is itself the useful reading. */
.wx-arrow {
  fill: none; stroke: var(--text); stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}
.wx-arrow-weak .wx-arrow { stroke: var(--text-muted); stroke-width: 1.2; opacity: 0.55; }

.wx-svg { width: 100%; height: 120px; display: block; }
.wx-agree { width: 100%; height: 14px; display: block; margin-top: 0.15rem; }

.wx-gridline { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.wx-axis-label { fill: var(--text-muted); font-size: 9px; }

/* Full min-max across models, then the interquartile core inside it. Band
   width is the confidence: a narrow ribbon means the models agree. */
.wx-envelope { fill: var(--accent); fill-opacity: 0.12; }
.wx-iqr { fill: var(--accent); fill-opacity: 0.3; }
.wx-median { fill: none; stroke: var(--accent-2); stroke-width: 2; vector-effect: non-scaling-stroke; }
.wx-companion { fill: none; stroke: var(--accent-2); stroke-width: 1.5; stroke-dasharray: 4 3; opacity: 0.7; vector-effect: non-scaling-stroke; }
.wx-model-line { fill: none; stroke-width: 1.5; vector-effect: non-scaling-stroke; }

/* Hours where a model has stopped reporting. Shaded so a band that narrows
   because members left is not read as rising confidence. */
.wx-dropout { fill: var(--text-muted); fill-opacity: 0.07; }

.wx-legend { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 0.5rem; }
.wx-legend-item { display: flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; color: var(--text-muted); }
.wx-legend-item i { width: 10px; height: 2px; border-radius: 1px; }

.wx-attrib { font-size: 0.65rem; color: var(--text-muted); line-height: 1.5; opacity: 0.8; }

/* Clock switch. Same chrome as the tier tabs - it is the same kind of choice,
   a re-render of data already in hand. */
.wx-tz { display: flex; gap: 0.25rem; }

/* Midnight rules through every chart, so the day boundaries line up with the
   strip above. Hour boundaries a step fainter again - present enough to count
   columns against, quiet enough to read the lines through.
   --text-muted, not --border: border is a shade of the card background, which
   at these opacities left both rules invisible on the dark theme. The only
   vertical anyone could see was the day strip's own divider, which reads as a
   tick at the top of the card and nothing below it. */
.wx-dayline {
  stroke: var(--text-muted);
  stroke-width: 1;
  stroke-opacity: 0.45;
  stroke-dasharray: 3 3;
  vector-effect: non-scaling-stroke;
}
.wx-hourline { stroke: var(--text-muted); stroke-width: 1; stroke-opacity: 0.16; vector-effect: non-scaling-stroke; }

/* Hover readout. The charts are drawn with preserveAspectRatio="none", so the
   SVG is stretched horizontally and nothing inside it can be measured in
   pixels - the crosshair is positioned as a percentage of the wrapper and the
   tooltip in wrapper-relative pixels from the pointer itself.
   pan-y: a vertical swipe still scrolls the page, while a horizontal drag
   reaches the script as a scrub across the chart instead of being eaten as a
   pan. */
.wx-hover {
  position: relative;
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}
.wx-crosshair {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--accent-2);
  opacity: 0.6;
  pointer-events: none;
}
.wx-tip {
  position: absolute;
  z-index: 3;
  transform: translate(8px, -100%);
  max-width: 15rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface-2, var(--surface));
  color: var(--text);
  font-size: 0.7rem;
  line-height: 1.35;
  white-space: pre-line;
  pointer-events: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.wx-tip.flip { transform: translate(-100%, -100%) translateX(-8px); }

/* Day and night behind every chart, so the shape of the day is readable
   without counting hour labels. Day is white, night is midnight blue, and both
   are painted - an unpainted stretch would read as neither. Opacity is per
   theme: on the dark card white at full strength would bury the strokes drawn
   over it, and on the light card the night wash has to stay light enough to
   read a chart through. */
.wx-day { fill: var(--wx-day); fill-opacity: var(--wx-day-op); }
.wx-night { fill: var(--wx-night); fill-opacity: var(--wx-night-op); }

/* Controls above the card: clock switch and the layer checkboxes. */
/* Settings live behind a gear: eighteen checkboxes and three switches are a
   lot of furniture for things touched once a week. */
.wx-settings { margin-bottom: 0.4rem; }
/* Red and bold so the gear is found - it was easy to miss in grey. */
.wx-settings-toggle {
  display: inline-flex; align-items: center; gap: 0.35rem; cursor: pointer;
  font-size: 0.7rem; font-weight: 600; color: #f85149; list-style: none; user-select: none;
}
.wx-settings-toggle > span { font-size: 0.9rem; line-height: 1; }
.wx-settings-toggle::-webkit-details-marker { display: none; }
.wx-settings-toggle:hover { color: #ff7b72; }
.wx-settings[open] .wx-controls { margin-top: 0.4rem; }
/* Two-value switches read as one thing, checkboxes as another - they sit in
   separate rows so a glance does not have to sort them out. */
.wx-controls-layers { margin-top: 0.35rem; padding-top: 0.35rem; border-top: 1px solid var(--border); }
.wx-model-gust { stroke-dasharray: 4 3; opacity: 0.8; }
.wx-pick { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.7rem; color: var(--text-muted); }
.wx-pick select {
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 4px; font-size: 0.7rem; padding: 0.1rem 0.2rem;
}

.wx-controls { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; }
.wx-layers { display: flex; flex-wrap: wrap; gap: 0.25rem 0.75rem; }
.wx-layer {
  display: inline-flex; align-items: center; gap: 0.3rem;
  font-size: 0.7rem; color: var(--text-muted); cursor: pointer; user-select: none;
}
.wx-layer:hover { color: var(--text); }
.wx-layer input { accent-color: var(--accent); cursor: pointer; margin: 0; }

/* NBM's own hourly standard deviation, behind the between-model bands. A
   different quantity from the consensus spread, so it is drawn as its own
   band rather than merged into one. */
.wx-nbm-sd { fill: var(--text-muted); fill-opacity: 0.16; }

.wx-note-left { margin-left: 0; }
.wx-legend-note { font-size: 0.65rem; color: var(--text-muted); }
.wx-strip-wrap { display: flex; flex-direction: column; }
.wx-strip { width: 100%; height: 22px; display: block; border: 1px solid var(--border); border-radius: 3px; }
.wx-strip-day { fill: var(--text-muted); font-size: 10px; font-weight: 600; }
.wx-strip-time { fill: var(--text-muted); font-size: 8px; }
.wx-strip-divider { stroke: var(--border); stroke-width: 1; vector-effect: non-scaling-stroke; }
.wx-sunrise { stroke: #fbbf24; stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.wx-sunset { stroke: #fb923c; stroke-width: 1.5; vector-effect: non-scaling-stroke; }

/* Ceiling and cloud base. Log height axis, fitted to the forecast - a linear
   one spends its room on the 10k-30k ft cases and squashes the 400 ft one that
   matters, and a fixed log one draws an ordinary high-cloud day as two flat
   lines on the top edge. */
.wx-nbh-svg { width: 100%; height: 160px; display: block; }
.wx-nbh-wind-svg { width: 100%; height: 90px; display: block; }
.wx-nbh-temp-svg { width: 100%; height: 90px; display: block; }
.wx-nbh-precip-svg { width: 100%; height: 80px; display: block; }

/* Compact precipitation strip under the sky cover circles. Faded fill where
   the models are split on whether anything falls at all - the reading the
   agreement strip used to carry under the chart this replaces. */
.wx-precip-row { width: 100%; height: 26px; display: block; margin-top: 0.1rem; }
.wx-tier-precip { height: 40px; }
.wx-precip-bar { fill: var(--accent); fill-opacity: 0.85; }
.wx-precip-split { fill-opacity: 0.35; }

/* One rect per model on the chart floor. Translucent so four of them harden
   the colour and one leaves a ghost - the agreement is the opacity, and there
   is no second encoding saying the same thing. */
.wx-precip-model { fill: var(--accent); fill-opacity: 0.32; }
.wx-precip-num { fill: var(--text-muted); font-size: 8px; }

/* Sky cover on the NBM panel. Inverted axis, so the trace sinks as the sky
   fills in - the same direction the ceiling moves on the chart above. */
.wx-nbh-cover-svg { width: 100%; height: 80px; display: block; }
.wx-nbh-cover { fill: none; stroke: #6b7086; stroke-width: 2; vector-effect: non-scaling-stroke; }
.wx-nbh-cover-band { fill: #6b7086; fill-opacity: 0.22; }

/* Usable-sky index, off by default. */
.wx-good-svg { width: 100%; height: 70px; display: block; }
.wx-good-line { fill: none; stroke: var(--text, #ddd); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.wx-good-dot { fill: var(--text, #ddd); }
.wx-comfort-line { fill: none; stroke: #58a6ff; stroke-width: 1.25; vector-effect: non-scaling-stroke; }
.wx-comfort-approx { stroke-dasharray: 3 2; }
.wx-comfort-dot { fill: #58a6ff; }
.wx-comfort-legend i { display: inline-block; width: 1rem; height: 0; border-top: 2px solid var(--text, #ddd); vertical-align: middle; margin-left: 0.5rem; }
.wx-comfort-legend i.wx-key-comfort { border-top-color: #58a6ff; }
.wx-comfort-legend i.wx-key-approx { border-top-style: dashed; }
/* The four score bands behind the line, and hours outside the jump window. */
.wx-band-green { fill: #3fb950; fill-opacity: 0.16; }
.wx-band-yellow { fill: #d4c21c; fill-opacity: 0.16; }
.wx-band-orange { fill: #f0883e; fill-opacity: 0.16; }
.wx-band-red { fill: #f85149; fill-opacity: 0.14; }
.wx-jump-out { fill: #888; fill-opacity: 0.45; }
/* Hop & Pop hours: ceiling too low for full altitude, fine for a low exit. */
.wx-hop-col { fill: #a371f7; fill-opacity: 0.22; }
.wx-hop-strip { fill: #a371f7; }
.wx-comfort-legend i.wx-key-hop { width: 0.8rem; height: 0.6rem; border: 0; background: #a371f7; vertical-align: -1px; }
.wx-hop-badge {
  flex: none;
  background: #a371f7;
  color: #fff;
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
  cursor: help;
}
/* Burble loads beside the Current score: next load and its minutes. */
.wx-loads-slot { flex: none; }
.wx-loads-slot:empty { display: none; }
.wx-loads-badge {
  flex: none;
  display: inline-block;
  background: #238636;
  color: #fff;
  font-weight: 700;
  font-size: 0.95rem;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
  text-decoration: none;
}
.wx-loads-badge:hover { filter: brightness(1.15); }
.wx-loads-slot { display: inline-flex; align-items: center; gap: 0.3rem; }
.wx-loads-refresh {
  background: none;
  border: 1px solid var(--border, #333);
  color: var(--text-muted);
  border-radius: 999px;
  width: 1.9rem;
  height: 1.9rem;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.wx-loads-refresh:hover { color: var(--accent); }
.wx-loads-refresh.is-loading { animation: wx-loads-spin 0.9s linear infinite; cursor: default; }
@keyframes wx-loads-spin { to { transform: rotate(360deg); } }
/* Past NBS on the 3-7 day chart, where cloud height is approximated. */
.wx-good-fade { fill: var(--surface, #111); fill-opacity: 0.5; }
.wx-good-fade-label { fill: var(--text-muted); font-size: 8px; }

/* Card tabs: Forecast / Experimental / Winds Aloft, a step bigger than the
   tier and sub-tab rows they sit above. */
.wx-view-tabs { margin: 0.25rem 0 0.75rem; }
.wx-view-tabs .wx-tab { font-size: 0.85rem; padding: 0.3rem 0.8rem; }
.wx-exp-tabs { margin-top: 0.5rem; }

/* Winds Aloft tab. Speed bands tint the decoded winds: light, moderate,
   strong, jet-level. */
.wx-aloft-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.5rem; }
.wx-sat-time { font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.wx-sat-link { display: block; line-height: 0; }
.wx-sat-img { width: 100%; height: auto; border-radius: 4px; background: var(--surface); min-height: 120px; }
.wx-aloft-bar .wx-tabs { margin-bottom: 0; }
.wx-aloft-site { margin-left: auto; font-size: 0.75rem; color: var(--text-muted); }
.wx-aloft-site strong { color: var(--text); }
.wx-aloft-table td.wx-aloft-alt { font-weight: 600; color: var(--text-muted); }
.wx-aloft-blank { color: var(--text-muted); }
.wx-aloft-temp { color: var(--text-muted); }
.wx-aloft-s0 { color: #4ade80; fill: #4ade80; stroke: #4ade80; }
.wx-aloft-s1 { color: #facc15; fill: #facc15; stroke: #facc15; }
.wx-aloft-s2 { color: #fb923c; fill: #fb923c; stroke: #fb923c; }
.wx-aloft-s3 { color: #f87171; fill: #f87171; stroke: #f87171; }
[data-theme="light"] .wx-aloft-s0 { color: #15803d; fill: #15803d; stroke: #15803d; }
[data-theme="light"] .wx-aloft-s1 { color: #a16207; fill: #a16207; stroke: #a16207; }
[data-theme="light"] .wx-aloft-s2 { color: #c2410c; fill: #c2410c; stroke: #c2410c; }
[data-theme="light"] .wx-aloft-s3 { color: #b91c1c; fill: #b91c1c; stroke: #b91c1c; }
/* On white the text colours alone wash out: speeds sit on a tinted chip. */
.wx-aloft-chip { padding: 0 0.25rem; border-radius: 3px; }
[data-theme="light"] .wx-aloft-chip { font-weight: 600; }
[data-theme="light"] .wx-aloft-chip.wx-aloft-s0 { background: #dcfce7; color: #166534; }
[data-theme="light"] .wx-aloft-chip.wx-aloft-s1 { background: #fef3c7; color: #854d0e; }
[data-theme="light"] .wx-aloft-chip.wx-aloft-s2 { background: #ffedd5; color: #9a3412; }
[data-theme="light"] .wx-aloft-chip.wx-aloft-s3 { background: #fee2e2; color: #991b1b; }
.wx-aloft-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 0.3rem 0.9rem; margin-top: 0.4rem; font-size: 0.75rem; }
.wx-aloft-key { color: var(--text-muted); }
.wx-aloft-arrow { stroke-width: 2; }
.wx-aloft-head { stroke: none; }
.wx-aloft-stepper { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.4rem; }
.wx-aloft-stepper button:disabled { opacity: 0.35; cursor: default; }
.wx-aloft-when { min-width: 7rem; text-align: center; font-weight: 600; }
.wx-aloft-az { width: auto; }
.wx-aloft-az td { padding-top: 1px; padding-bottom: 1px; }
.wx-aloft-az-cell { width: 22px; }
.wx-aloft-az-arrow { width: 20px; height: 20px; display: block; }
.wx-aloft-deg { font-variant-numeric: tabular-nums; }
/* Derived rows: between two pressure levels, or from the surface values. */
.wx-aloft-interp, .wx-aloft-surface { opacity: 0.62; }
.wx-aloft-sfc {
  font-size: 0.62rem; margin-left: 0.25rem; padding: 0 0.2rem;
  border: 1px solid var(--text-muted); border-radius: 3px; color: var(--text-muted);
}
/* Raw FB: preformatted and never wrapped, so the columns line up as issued. */
.wx-fb-raw {
  margin: 0.25rem 0 0.4rem;
  padding: 0.5rem;
  background: var(--surface-2);
  border-radius: 4px;
  font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
  font-size: 0.7rem;
  line-height: 1.35;
  white-space: pre;
  overflow-x: auto;
}

/* Experimental, Current: the METAR hour's score in its band colour. */
.wx-exp-now-row { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem; margin: 0.5rem 0; }
.wx-exp-score {
  flex: none;
  width: 5.5rem;
  height: 5.5rem;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: #fff;
}
.wx-exp-score { border: 0; cursor: pointer; font: inherit; width: 7rem; height: 7rem; }
.wx-band-bg-green { background: #3fb950; }
.wx-band-bg-yellow { background: #c9b400; }
.wx-band-bg-orange { background: #f0883e; }
.wx-band-bg-red { background: #f85149; }
.wx-band-bg-none { background: #6b7086; }
.wx-exp-top { font-size: 0.95rem; font-weight: 600; }
.wx-exp-comfort { font-size: 0.8rem; color: var(--text-muted, #999); margin-top: 0.2rem; }
.wx-exp-obs { display: flex; flex-wrap: wrap; gap: 0.3rem 1.2rem; margin-top: 0.6rem; font-size: 0.85rem; }
.wx-exp-obs .wx-k { margin-right: 0.3rem; }
.wx-sun { font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.3rem; }
.wx-sun-left { font-size: 0.75rem; white-space: nowrap; margin-left: 0.6rem; padding-left: 0.6rem; border-left: 1px solid var(--border); }
.wx-fresh { font-size: 0.75rem; color: var(--text-muted); margin-bottom: 0.2rem; }
.wx-fresh:empty { display: none; }
.wx-offline { display: inline-block; padding: 0 0.35rem; border-radius: 3px; background: #b45309; color: #fff; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.03em; }
.wx-exp-num { font-size: 2.4rem; font-weight: 700; line-height: 1; }
.wx-exp-verdict { font-size: 0.75rem; font-weight: 600; }

/* Current: the sub-score breakdown under the circle, and the admin rating. */
.wx-jump-breakdown { margin: 0.25rem 0 0.5rem; max-width: 26rem; }
.wx-jump-gate { color: #f85149; font-size: 0.8rem; font-weight: 600; margin-bottom: 0.3rem; }
.wx-jump-row { display: flex; align-items: center; gap: 0.5rem; font-size: 0.8rem; margin: 0.15rem 0; }
.wx-jump-label { flex: none; width: 8rem; }
.wx-jump-bar { flex: 1; height: 0.5rem; background: var(--border, #333); border-radius: 3px; overflow: hidden; }
.wx-jump-bar i { display: block; height: 100%; background: var(--text-muted, #999); }
.wx-jump-bar-comfort i { background: #58a6ff; }
.wx-jump-val { flex: none; width: 2rem; text-align: right; }
.wx-jump-log { margin-top: 0.75rem; padding-top: 0.5rem; border-top: 1px solid var(--border, #333); display: flex; flex-direction: column; gap: 0.35rem; max-width: 26rem; font-size: 0.8rem; }
.wx-jump-log-head { font-weight: 600; }
.wx-jump-log-row { display: flex; align-items: center; gap: 0.5rem; }
.wx-jump-log-row input[type=range] { flex: 1; }
.wx-jump-log textarea { width: 100%; box-sizing: border-box; font: inherit; }

/* Heights worth reading against: two flying minimums and jump altitude. */
.wx-nbh-ref { stroke: var(--text-muted); stroke-width: 1; stroke-dasharray: 2 4; opacity: 0.75; vector-effect: non-scaling-stroke; }
.wx-nbh-ref-label { fill: var(--text-muted); font-size: 8px; }

/* Temperature solid, dew point dashed, each over its own spread band. The gap
   between the two lines is the thing to read. */
.wx-nbh-temp-band { fill: var(--accent-2); fill-opacity: 0.14; }
.wx-nbh-dewp-band { fill: var(--accent); fill-opacity: 0.12; }
.wx-nbh-temp { fill: none; stroke: var(--accent-2); stroke-width: 2; vector-effect: non-scaling-stroke; }
.wx-nbh-dewp {
  fill: none; stroke: var(--accent); stroke-width: 1.5;
  stroke-dasharray: 4 3; vector-effect: non-scaling-stroke;
}

/* An hour with a chance but no type breakdown: neutral rather than assigned to
   a kind the bulletin did not name. */
.wx-nbh-pop-plain { fill: var(--text-muted); fill-opacity: 0.55; }

/* Wind solid, gusts dashed - the same grammar the tier charts use, so the two
   panels read alike. The bands are NBM's own standard deviation. */
.wx-nbh-wind-band { fill: var(--accent); fill-opacity: 0.16; }
.wx-nbh-gust-band { fill: var(--accent-2); fill-opacity: 0.1; }
.wx-nbh-wind { fill: none; stroke: var(--accent); stroke-width: 2; vector-effect: non-scaling-stroke; }
.wx-nbh-gust {
  fill: none; stroke: var(--accent-2); stroke-width: 1.5;
  stroke-dasharray: 4 3; vector-effect: non-scaling-stroke;
}
.wx-nbh-deck { fill: var(--accent-2); fill-opacity: 0.14; }
.wx-nbh-ceil { fill: none; stroke: var(--accent-2); stroke-width: 2; vector-effect: non-scaling-stroke; }
.wx-nbh-base { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 4 3; opacity: 0.8; vector-effect: non-scaling-stroke; }
.wx-nbh-ceil-dot { fill: var(--accent-2); }
.wx-nbh-base-dot { fill: var(--accent); opacity: 0.8; }
/* The three flight-category boundaries, when the fitted axis reaches them. */
.wx-nbh-cat-line { stroke-dasharray: 3 3; opacity: 0.9; }
/* An hour with no ceiling at all, marked above the chart. Drawn as a path so
   it does not depend on the reader's font, and muted because "nothing there"
   should not be the loudest thing on the panel. */
.wx-open-row { margin-bottom: 0.1rem; }
.wx-infinity { fill: none; stroke: var(--text-muted); stroke-width: 1.4; opacity: 0.75; }
.wx-nbh-cat { width: 100%; height: 12px; display: block; margin-top: 0.15rem; border-radius: 2px; }
.wx-nbh-prob { width: 100%; height: 18px; display: block; margin-top: 0.15rem; opacity: 0.75; }
.wx-nbh-ptype { width: 100%; height: 18px; display: block; margin-top: 0.15rem; }
.wx-nbh-tstm { width: 100%; height: 16px; display: block; margin-top: 0.15rem; }
.wx-nbh-table th, .wx-nbh-table td { font-size: 0.7rem; }

@media (max-width: 600px) {
  .tabs { overflow-x: auto; }
  .tab { padding: 0.4rem 0.75rem; font-size: 0.8rem; white-space: nowrap; }
  .tab-group .tab-arrow { padding: 0.4rem 0.6rem; }
  .tab-menu-item { padding: 0.7rem 0.9rem; font-size: 0.95rem; }
  .cwx-list [role=option] { padding: 0.65rem 0.7rem; }
}

/* Edit mode: admins only, toggled by the pencil in the header. */
.edit-btn {
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-muted);
  font-size: 1.1rem;
  cursor: pointer;
  margin-left: auto;
  padding: 0.1rem 0.4rem;
}
.edit-btn:not([hidden]) + .theme-btn { margin-left: 0.5rem; }
.edit-btn.active { color: var(--accent-2); border-color: var(--accent); }

.edit-item {
  border: 1px dashed var(--accent);
  border-radius: 10px;
  padding: 0.4rem;
}
.edit-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}
.edit-field {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
  padding: 0.3rem 0.5rem;
  min-width: 0;
}
.edit-field:focus { outline: none; border-color: var(--accent); }
.edit-title { flex: 1 1 12rem; font-weight: 600; }
.edit-desc { flex: 2 1 16rem; }
.edit-open {
  color: var(--accent-2);
  text-decoration: none;
  font-size: 1rem;
  padding: 0 0.25rem;
}
.edit-status { font-size: 0.75rem; color: var(--text-muted); }
.edit-status a { color: inherit; }
.edit-status.edit-ok { color: #22c55e; }
.edit-status.edit-err { color: #ef4444; }

/* WX card: the Sat tab at night, and the note it opens instead of the loop. */
.wx-tab.wx-tab-night:not(.active) { opacity: 0.6; }
.wx-sat-night { font-size: 0.85rem; color: var(--text-muted); display: flex; flex-direction: column; gap: 0.5rem; }
.wx-sat-night .wx-tab { margin-left: 0.25rem; }
