html, body {
  margin: 0;
  height: 100%;
  font-family: system-ui, sans-serif;
  background: #111;
  color: #e6e6e6;
}

#map {
  position: absolute;
  inset: 0;
  background: #000;
}

/* No free keyless black base map exists, so the Esri dark grey tiles are recolored to black land
   and dark navy water by the #black-land SVG filter in index.html. */
.base-map {
  filter: url(#black-land);
}

#controls {
  position: absolute;
  left: 50%;
  bottom: 24px;
  transform: translateX(-50%);
  z-index: 1000;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(30, 30, 30, 0.95);
  border: 1px solid #333;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
  max-width: calc(100% - 32px);
  box-sizing: border-box;
}

#controls button {
  min-width: 36px;
  padding: 6px 10px;
  border: 1px solid #444;
  border-radius: 4px;
  background: #2a2a2a;
  color: #e6e6e6;
  cursor: pointer;
  white-space: nowrap;
}

/* The radar follows the map (and the View menu's site boxes), so its dropdown isn't shown; app.js
   still keeps the choice in it. */
#radar {
  display: none;
  padding: 6px;
  border: 1px solid #444;
  border-radius: 4px;
  background: #2a2a2a;
  color: #e6e6e6;
  min-width: 0;
  max-width: 260px;
}

#controls button:hover {
  background: #3a3a3a;
}

#controls button[aria-pressed="true"] {
  background: #4da3ff;
  border-color: #4da3ff;
  color: #000;
}

#slider {
  width: 200px;
  flex-shrink: 1;
  min-width: 60px;
  accent-color: #4da3ff;
}

#time {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* In the top right column (#top-right), under the alert feed, the same width as the boxes above. */
#spc-panel {
  position: relative;
  width: 420px;
  max-width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  background: rgba(30, 30, 30, 0.95);
  border: 1px solid #333;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
  font-size: calc(13px * var(--text-scale, 1));
}

#spc-panel[hidden] {
  display: none;
}

/* A button that reads as the panel's heading; clicking it opens the written outlook. */
.spc-title {
  display: block;
  margin: 0 0 8px;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  font-weight: 600;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  text-shadow: inherit;
  cursor: pointer;
}

.spc-title:hover {
  text-decoration: underline;
}

/* The written outlook (spc.js): a scrolling panel in the middle of the map, in the plainer prose font
   (SPC writes in capitals already). */
#spc-text-panel {
  position: absolute;
  top: 70px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1003;
  width: 640px;
  max-width: calc(100% - 40px);
  max-height: calc(100% - 200px);
  overflow-y: auto;
  box-sizing: border-box;
  padding: 28px 18px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
}

#spc-text-panel[hidden] {
  display: none;
}

#spc-text-body {
  white-space: pre-wrap;
  font-family: var(--prose-font, "IBM Plex Mono", ui-monospace, monospace);
  font-size: calc(13px * var(--text-scale, 1));
  line-height: 1.5;
  text-transform: none;
}

.segmented {
  display: flex;
  margin-bottom: 6px;
}

.segmented button {
  flex: 1;
  padding: 5px 6px;
  border: 1px solid #444;
  background: #2a2a2a;
  color: #e6e6e6;
  cursor: pointer;
}

.segmented button:disabled {
  color: #666;
  cursor: not-allowed;
}

.segmented button[aria-pressed="true"] {
  background: #4da3ff;
  border-color: #4da3ff;
  color: #000;
}

#spc-valid {
  color: #aaa;
  margin: 6px 0;
}

#spc-legend,
#outlook-legend {
  list-style: none;
  margin: 0;
  padding: 0;
}

#spc-legend li,
#outlook-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 3px 0;
}

.swatch {
  flex: none;
  width: 14px;
  height: 14px;
  border-radius: 2px;
}

.swatch.dashed {
  border: 2px dashed #fff;
  box-sizing: border-box;
}

/* Leaflet's own controls default to white; match them to the dark map. */
.leaflet-bar a,
.leaflet-bar a:hover {
  background: #2a2a2a;
  color: #e6e6e6;
  border-bottom-color: #444;
}

.leaflet-control-attribution.leaflet-control {
  background: rgba(30, 30, 30, 0.8);
  color: #aaa;
  /* The data-source credits along the bottom edge: kept, but small. */
  font-size: 8px;
  line-height: 1.2;
}

.leaflet-control-attribution a {
  color: #8cc4ff;
}

/* ---------- VHS look ----------
   Overrides the plain dark styling above: VCR on-screen-display font, chunky blue tape-menu
   panels, and red/cyan color fringing on text. */
/* VCR OSD Mono, served from public/fonts. */
@font-face {
  font-family: "VCR OSD Mono";
  src: url("fonts/VCR_OSD_MONO.ttf") format("truetype");
  font-display: swap;
}

:root {
  --vhs-font: "VCR OSD Mono", ui-monospace, monospace;
  --vhs-blue: #1a1aa6;
  --vhs-blue-light: #3a3aff;
  --vhs-text: #f4f4f4;
  --vhs-green: #39ff7a;
  --vhs-fringe: 1px 0 rgba(255, 0, 60, 0.75), -1px 0 rgba(0, 220, 255, 0.75);
}

body,
#controls,
#controls button,
#radar,
#spc-panel,
.segmented button,
.rating-toggle-all,
.leaflet-tooltip {
  font-family: var(--vhs-font);
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
}

#controls,
#spc-panel {
  background: var(--panel-bg, rgba(16, 16, 120, 0.88));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-size: calc(20px * var(--text-scale, 1));
  text-shadow: var(--vhs-fringe);
}

#controls button,
#radar,
.segmented button,
.rating-toggle-all {
  font-size: calc(18px * var(--text-scale, 1));
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  text-shadow: var(--vhs-fringe);
}

#controls button:hover,
.segmented button:hover:not(:disabled),
.rating-toggle-all:hover {
  background: var(--vhs-blue-light);
}

#controls button[aria-pressed="true"],
.segmented button[aria-pressed="true"] {
  background: var(--vhs-text);
  border-color: var(--vhs-text);
  color: var(--vhs-blue);
  text-shadow: none;
}

.segmented button:disabled {
  color: #7a7ab8;
  border-color: #7a7ab8;
}

#time {
  color: var(--vhs-green);
  font-size: calc(24px * var(--text-scale, 1));
}

#spc-valid {
  color: var(--vhs-green);
}

#slider {
  accent-color: var(--vhs-text);
}

.swatch {
  border-radius: var(--radius, 0);
  border: 1px solid var(--vhs-text);
}

.leaflet-tooltip {
  background: var(--vhs-blue);
  color: var(--vhs-text);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  font-size: calc(16px * var(--text-scale, 1));
}

.leaflet-bar a,
.leaflet-bar a:hover {
  background: var(--vhs-blue);
  color: var(--vhs-text);
  border-radius: var(--radius, 0) !important;
  font-family: var(--vhs-font);
}

.leaflet-bar {
  border: var(--line, 2px solid var(--vhs-text)) !important;
  border-radius: var(--radius, 0);
}

/* Town names on the map, in the VHS font. The span is centered on the town's location. */
.town-label span {
  position: absolute;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  color: var(--vhs-text);
  text-shadow: var(--vhs-fringe), 0 0 3px #000, 0 0 3px #000;
}

/* Cities of 1,000,000+ people. town-labels.js sizes their overlap boxes with the same 19/14 ratio. */
.town-label.big span {
  font-size: calc(19px * var(--text-scale, 1));
}

/* ---------- Dual pane ----------
   Off: only #map, full screen, with one product dropdown at the top center. On: #map on the left
   half and #second-map on the right half (stacked top/bottom on narrow screens), each with its own
   product dropdown at the top of its pane. */
#second-map,
#second-product-bar {
  display: none;
}

#second-map {
  position: absolute;
  inset: 0;
  background: #000;
}

body.dual #map {
  right: 50%;
}

body.dual #second-map {
  display: block;
  left: 50%;
  border-left: 2px solid var(--vhs-text);
}

/* Product dropdowns. Products the current radar doesn't have are greyed out in the list. */
#product-bar,
#second-product-bar {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.88));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(20px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
}

#product-bar {
  display: none;
}

/* Both a little lower, level with each other: centered on the left pane, the first would run into the
   town search and alerts at the top left. Outside split screen the product dropdown is in the bottom
   bar instead (app.js setDual). */
body.dual #product-bar {
  display: flex;
  left: 25%;
  top: 52px;
}

body.dual #second-product-bar {
  display: flex;
  left: 75%;
  top: 52px;
}

#product,
#second-product {
  padding: 4px 6px;
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: inherit;
  font-size: calc(18px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
}

/* The bottom bar, compact: smaller text and tighter padding than the panels and their buttons. */
#controls {
  gap: 6px;
  padding: 4px 8px;
  font-size: calc(15px * var(--text-scale, 1));
}

/* A set line height: the arrows in Back and Replay come from a fallback font with taller lines, which
   made those buttons taller than the rest. */
#controls button,
#controls #product {
  min-width: 28px;
  padding: 3px 7px;
  font-size: calc(14px * var(--text-scale, 1));
  line-height: 1;
}

#controls #time {
  font-size: calc(17px * var(--text-scale, 1));
}

#second-note {
  position: absolute;
  top: 50%;
  left: 75%;
  z-index: 1000;
  transform: translate(-50%, -50%);
  padding: 10px 14px;
  text-align: center;
  background: var(--panel-bg, rgba(16, 16, 120, 0.88));
  border: var(--line, 2px solid var(--vhs-text));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(20px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  text-shadow: var(--vhs-fringe);
  pointer-events: none;
}

#second-note[hidden] {
  display: none;
}

@media (max-width: 700px) {
  body.dual #map {
    right: 0;
    bottom: 50%;
  }

  body.dual #second-map {
    left: 0;
    top: 50%;
    border-left: none;
    border-top: 2px solid var(--vhs-text);
  }

  body.dual #product-bar,
  body.dual #second-product-bar {
    left: 50%;
  }

  body.dual #second-product-bar {
    top: calc(50% + 10px);
  }

  #second-note {
    left: 50%;
    top: 75%;
  }
}

/* View menu: opens above the bottom bar. */
#view-panel {
  position: absolute;
  bottom: 84px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 220px;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(16px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
}

#view-panel[hidden] {
  display: none;
}

.view-title {
  font-size: calc(18px * var(--text-scale, 1));
  margin-bottom: 2px;
}

#view-panel label {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
}

#view-panel input {
  accent-color: var(--vhs-text);
  margin: 0;
}

#view-panel fieldset {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 4px 0 0;
  padding: 6px 8px;
  border: 1px solid var(--vhs-text);
}

#view-panel legend {
  padding: 0 4px;
}

#set-screen-saver,
#set-home-view {
  padding: 3px 8px;
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

#set-screen-saver:hover,
#set-home-view:hover {
  background: var(--vhs-blue-light);
}

/* ---------- TOR History view ----------
   body.history hides live-radar controls and shows the date search at the top. */
#history-search,
#hurricane-search {
  display: none;
}

body.history #history-search,
body.hurricanes #hurricane-search {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 520px; /* compact; the summary and chips wrap inside it */
  max-width: calc(100% - 100px);
  padding: 8px 12px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(18px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
}

#history-search input,
#history-search button,
#hurricane-search input,
#hurricane-search button {
  padding: 4px 8px;
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: inherit;
  font-size: calc(18px * var(--text-scale, 1));
  color-scheme: dark;
}

/* The search box fills its row beside the Search button. */
#history-query,
#hurricane-query {
  flex: 1 1 300px;
  min-width: 0;
  text-transform: none;
}

#history-query::placeholder,
#hurricane-query::placeholder {
  color: #9a9ad8;
  text-transform: var(--case, uppercase);
}


#history-summary,
#hurricane-summary {
  flex-basis: 100%;
  text-align: center;
  font-size: calc(16px * var(--text-scale, 1));
  color: var(--vhs-green);
}

body.history .radar-control,
body.history #screen-saver,
body.history #spc-panel,
body.history #home-search,
body.history #product-bar,
body.history #second-product-bar,
body.history #second-note {
  display: none !important;
}

/* Tornado popups: the VHS panel look instead of Leaflet's white box. */
.tornado-popup .leaflet-popup-content-wrapper,
.tornado-popup .leaflet-popup-tip {
  background: var(--panel-bg, rgba(16, 16, 120, 0.97));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
}

.tornado-popup .leaflet-popup-tip {
  border-width: 0 2px 2px 0;
}

.tornado-popup .leaflet-popup-content {
  margin: 10px 12px;
}

.tornado-popup a.leaflet-popup-close-button {
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(20px * var(--text-scale, 1));
}

.tornado-details {
  max-height: 260px;
  overflow-y: auto;
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  line-height: 1.4;
  letter-spacing: var(--tracking, 0.03em);
  scrollbar-color: var(--vhs-text) transparent;
}

.tornado-details b {
  color: var(--vhs-green);
  font-weight: normal;
  text-transform: var(--case, uppercase);
}

.tornado-details p {
  margin: 8px 0 0;
  padding-top: 6px;
  border-top: 1px solid #5a5ab8;
  /* Long text (write-ups, comments, alert text) in a plainer font than the VHS one, which is hard
     to read in paragraphs. Modern uses its own font (--prose-font below). */
  font-family: var(--prose-font, "IBM Plex Mono", ui-monospace, monospace);
  font-size: calc(13px * var(--text-scale, 1));
  letter-spacing: 0;
  line-height: 1.5;
  text-shadow: none;
}

/* A tornado write-up split into paragraphs (history.js paragraphs): the line sits above the first
   one only; the rest are set apart by a blank gap. */
.tornado-details .tornado-comments + .tornado-comments,
.tornado-details .hurricane-summary + .hurricane-summary {
  margin-top: 0.9em;
  padding-top: 0;
  border-top: 0;
}

body.modern {
  --prose-font: var(--vhs-font);
}

/* TOR History EF scale panel: rating checkboxes, top right. */
#history-ratings-panel,
#hurricane-category-panel {
  display: none;
}

body.history #history-ratings-panel,
body.hurricanes #hurricane-category-panel {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1001;
  display: block;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
}

#history-ratings,
#hurricane-categories {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  font-size: calc(15px * var(--text-scale, 1));
}

#history-ratings label,
#hurricane-categories label {
  display: flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}

/* The tornado count sits in its own right-aligned column, apart from the rating. */
.rating-count {
  min-width: 4.5em;
  margin-left: auto;
  padding-left: 12px;
  text-align: right;
}

/* Plain white squares instead of the browser's checkboxes: outlined = hidden, filled = shown. */
#history-ratings input,
#hurricane-categories input {
  appearance: none;
  width: 14px;
  height: 14px;
  margin: 0;
  border: var(--line, 2px solid var(--vhs-text));
  background: transparent;
  cursor: pointer;
}

/* Checked: a white box with a blocky VHS-blue check mark. */
#history-ratings input:checked,
#hurricane-categories input:checked {
  background: var(--vhs-text) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' shape-rendering='crispEdges'%3E%3Cpath d='M1 5h2v1h1v1h1V6h1V5h1V4h1V2h1v2H9v1H8v1H7v1H6v1H5v1H4V8H3V7H2V6H1z' fill='%231a1aa6'/%3E%3C/svg%3E") center / 10px 10px no-repeat;
}

#history-ratings input:focus-visible,
#hurricane-categories input:focus-visible {
  outline: 2px solid var(--vhs-green);
  outline-offset: 1px;
}

/* The ratings' Show all / Hide all button, full width under the checkboxes, in the panels' button look
(the rules shared with .segmented buttons) at the checkboxes' text size. */
.rating-toggle-all {
  display: block;
  width: 100%;
  margin-top: 8px;
  padding: 3px 8px;
  font-size: calc(15px * var(--text-scale, 1));
  cursor: pointer;
}

.rating-swatch {
  width: 12px;
  height: 12px;
  border: 1px solid var(--vhs-text);
}

/* Hometown search: top, right of the tool buttons, so those stay in one place on every tool. */
#home-search {
  position: absolute;
  top: 10px;
  left: 170px; /* tool buttons (10 px + 150 px wide) + 10 px gap */
  z-index: 1001;
  display: flex;
  gap: 8px;
}

#home-query {
  width: 200px;
  max-width: 30vw;
  padding: 6px 8px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(16px * var(--text-scale, 1));
  text-shadow: var(--vhs-fringe);
  color-scheme: dark;
}

#home-query::placeholder {
  color: #9a9ad8;
  text-transform: var(--case, uppercase);
}

/* The last searched town: gold, on a dark backing so the regular white label under it
   doesn't show through. Centered on the town like the other labels. */
.searched-town > span {
  position: absolute;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  padding: 1px 4px;
  background: rgba(0, 0, 0, 0.75);
  border: 1px solid #ffd700;
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1)); /* same as the white town names */
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  color: #ffd700;
  text-shadow: 0 0 6px rgba(255, 215, 0, 0.6), 1px 0 rgba(255, 0, 60, 0.6), -1px 0 rgba(0, 220, 255, 0.6);
}

/* Popup heading: the tornado's date, a link that searches that day. */
.tornado-date {
  display: block;
  margin-bottom: 6px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(18px * var(--text-scale, 1));
  text-decoration: underline;
  cursor: pointer;
}

.tornado-date:hover {
  color: var(--vhs-green);
}

/* TOR History search chips: one per part of the search, click to remove it. */
#history-chips,
#hurricane-chips {
  display: flex;
  flex-basis: 100%;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}

#history-chips:empty,
#hurricane-chips:empty {
  display: none;
}

#history-search .history-chip,
#hurricane-search .history-chip {
  padding: 2px 8px;
  font-size: calc(14px * var(--text-scale, 1));
  cursor: pointer;
}

#history-search .history-chip:hover,
#hurricane-search .history-chip:hover {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

/* The Tornadoes and Hurricanes Stats chips stand apart from the search's own chips, like the hazard
   views'. */
#history-search .stats-chip,
#hurricane-search .stats-chip {
  border-color: var(--vhs-green);
  color: var(--vhs-green);
}

/* The gold searched town opens its weather when clicked. */
.searched-town {
  cursor: pointer;
}

body.history .searched-town {
  cursor: default;
}

/* The X that removes the gold name, shown while hovering it (a right-click removes it too). */
.searched-town-close {
  display: none;
  margin-left: 6px;
  padding: 0 2px;
  border: none;
  background: none;
  font: inherit;
  line-height: 1;
  color: #ffd700;
  cursor: pointer;
}

.searched-town:hover .searched-town-close {
  display: inline;
}

.searched-town-close:hover {
  color: #fff;
}

/* Top right, radar view only: the home town's warnings above the weather panel (weather.js). */
#top-right {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1002;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  max-width: calc(100% - 20px);
}

/* In the Tornadoes view the column is hidden, but the Storm Chasers card (opened there from a photo
   credit's name, hub.js showOwnProfile) pops up on the right side, below the Rating box. */
body.history #top-right {
  top: 50%;
  transform: translateY(-50%);
}

body.history #top-right > :not(#hub-panel) {
  display: none;
}

#home-warnings {
  width: 420px;
  max-width: 100%;
  box-sizing: border-box;
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

/* Just the red box, with no panel around it; a solid dark red so it reads over the map. */
#home-warnings .alert-home {
  margin: 0;
  background: rgba(90, 0, 0, 0.92);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
}

#home-warnings[hidden] {
  display: none;
}

#weather-panel {
  position: relative;
  width: 420px;
  max-width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0); /* rounded in the modern style, like the alert feed below it */
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
  text-shadow: var(--vhs-fringe);
}

#weather-panel[hidden] {
  display: none;
}

#weather-close,
#spc-text-close,
#analytics-close,
#user-close {
  position: absolute;
  top: 6px;
  right: 8px;
  padding: 0 4px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font-family: inherit;
  font-size: calc(18px * var(--text-scale, 1));
  cursor: pointer;
}

.weather-now {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 6px 0;
}

.weather-temperature {
  font-size: calc(34px * var(--text-scale, 1));
}

.weather-condition {
  font-size: calc(18px * var(--text-scale, 1));
  color: var(--vhs-green);
}

/* Feels like, humidity and dew point side by side, then wind (the longest) across the whole row;
   each a small green label over its value. */
.weather-details {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px 16px;
  margin: 10px 0 4px;
}

.weather-detail:last-child {
  grid-column: 1 / -1;
}

.weather-detail-label {
  color: var(--vhs-green);
  font-size: 0.75em;
}

.weather-detail-value {
  font-size: calc(17px * var(--text-scale, 1));
}

.forecast-title {
  color: var(--vhs-green);
  font-weight: normal;
}

.forecast-title {
  margin: 10px 0 4px;
  border-top: 2px solid var(--vhs-text);
  padding-top: 8px;
}

.weather-forecast {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 4px;
  text-align: center;
  font-size: calc(12px * var(--text-scale, 1));
}

.forecast-name {
  font-size: calc(14px * var(--text-scale, 1));
}

.forecast-condition {
  min-height: 2.6em;
  color: #c8c8ff;
}

/* Forecast icons (weather.js): one per day, above its condition. */
.forecast-icon svg {
  display: block;
  width: 34px;
  height: 34px;
  margin: 4px auto 2px;
}

.forecast-high {
  color: #ff9a2e;
}

.forecast-low {
  color: #8fd3ff;
}

/* Modern theme (View menu, Style: Modern): the same layout as Retro, restyled through the theme
   variables above (each falls back to its Retro value), plus a few rules the variables can't reach. */
body.modern {
  --vhs-font: "Barlow", "Segoe UI", sans-serif;
  --vhs-blue: #1f2937;
  --vhs-blue-light: #374151;
  --vhs-text: #f3f4f6;
  --vhs-green: #7dd3fc;
  --vhs-fringe: 0 0 0 transparent;
  --panel-bg: rgba(17, 24, 39, 0.82);
  --panel-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
  --line: 1px solid rgba(255, 255, 255, 0.14);
  --radius: 8px;
  --case: none;
  --tracking: 0.01em;
  --text-scale: 0.9;
  font-variant-numeric: tabular-nums;
}

body.modern #controls,
body.modern #analytics-panel,
body.modern #leaderboard-panel,
body.modern #spc-panel,
body.modern #view-panel,
body.modern #history-search,
body.modern #history-ratings-panel,
body.modern #weather-panel,
body.modern #alerts-panel,
body.modern #product-bar select,
body.modern #second-note,
body.modern .tornado-popup .leaflet-popup-content-wrapper,
body.modern #hurricane-search,
body.modern #hurricane-category-panel {
  backdrop-filter: blur(8px);
}

body.modern #controls button,
body.modern #radar,
body.modern #product,
body.modern .segmented button,
body.modern .rating-toggle-all,
body.modern #history-search button,
body.modern #history-query,
body.modern #home-query,
body.modern #hurricane-search button,
body.modern #hurricane-query {
  border-radius: 6px;
  font-weight: 500;
}

body.modern #controls button[aria-pressed="true"],
body.modern .segmented button[aria-pressed="true"] {
  background: #3b82f6;
  border-color: #3b82f6;
  color: #fff;
}

body.modern .view-title,
body.modern .forecast-title {
  font-weight: 600;
}

/* Map names: plain white with a dark halo instead of the VHS fringe. */
body.modern .town-label span {
  font-weight: 600;
  text-shadow: 0 0 3px #000, 0 0 3px #000, 0 0 2px #000;
}

body.modern .searched-town span {
  font-weight: 700;
  text-shadow: 0 0 3px #000, 0 0 3px #000, 0 0 6px rgba(255, 215, 0, 0.5);
}

body.modern #history-ratings input,
body.modern .rating-swatch,
body.modern #hurricane-categories input {
  border-radius: 3px;
}

body.modern #history-ratings input:checked,
body.modern #hurricane-categories input:checked {
  background: #3b82f6 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1.5 5.2 4 7.6 8.6 2.4' fill='none' stroke='white' stroke-width='1.6'/%3E%3C/svg%3E") center / 10px 10px no-repeat;
  border-color: #3b82f6;
}

body.modern .town-label span {
  font-size: 14px;
}

body.modern .town-label.big span {
  font-size: 18px;
}

/* Panels of detail text read better at full size in the narrower modern font. */
body.modern #weather-panel,
body.modern #home-warnings,
body.modern #alerts-panel,
body.modern #spc-panel,
body.modern #hub-panel,
body.modern #history-ratings-panel,
body.modern .tornado-popup,
body.modern #hurricane-category-panel {
  --text-scale: 1;
}

/* The top right column's boxes share one width, so they line up. */
body.modern #weather-panel,
body.modern #home-warnings,
body.modern #alerts-panel,
body.modern #spc-panel,
body.modern #hub-panel {
  width: 380px;
}

/* TOR History has no SPC outlooks or radar sites, so its View menu leaves those switches out. */
body.history #view-panel .radar-only {
  display: none;
}

/* Weather panel: Set as home (top right, beside the close x) and the gold house by the home town. */
.weather-set-home {
  position: absolute;
  top: 7px;
  right: 40px;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(12px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  cursor: pointer;
}

.weather-set-home:hover {
  background: var(--vhs-blue-light);
}

.home-button-icon svg {
  display: block;
  width: 12px;
  height: 12px;
}

.weather-title {
  display: flex;
  align-items: center;
  gap: 6px;
}

.home-badge svg {
  display: block;
  width: 1em;
  height: 1em;
}

#home:disabled {
  opacity: 0.45;
  cursor: default;
}

/* Active alerts (alerts.js): the bubble beside the town search, and its list. */
#alerts-button {
  padding: 4px 12px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(16px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  text-shadow: var(--vhs-fringe);
  cursor: pointer;
}

/* In the color of the strongest alert active (alerts.js render: --strongest-alert). */
#alerts-button.has-alerts {
  color: var(--strongest-alert, #fbbf24);
}

/* An alert covers the home town. */
#alerts-button.home-alert {
  border: 3px solid #ff2a2a;
  color: #fff;
  background: rgba(150, 0, 0, 0.9);
  animation: alert-pulse 1.4s ease-in-out infinite;
}

@keyframes alert-pulse {
  50% {
    box-shadow: 0 0 14px 3px rgba(255, 42, 42, 0.8);
  }
}

/* The live alert feed: in the top right column (#top-right), under the forecast box, scrolling when
   there are more alerts than fit. */
#alerts-panel {
  position: relative;
  width: 420px;
  max-width: 100%;
  box-sizing: border-box;
  max-height: 45vh;
  overflow-y: auto;
  /* The popups' scroll bar, thin, its room kept when the list fits: Clear and the rows stayed put only
     while it showed, and jumped right when an ✕ made the list fit. It stands in for the right padding. */
  scrollbar-color: var(--vhs-text) transparent;
  scrollbar-width: thin;
  scrollbar-gutter: stable;
  padding: 10px 4px 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

#alerts-panel[hidden],
body.history #alerts-panel {
  display: none;
}

.alerts-updated {
  color: var(--vhs-green);
  font-size: 0.8em;
}

/* The feed's Clear, at the right of its updated time: on the title's line, retro's wider letters ran
   into it (alerts.js). */
.alerts-subhead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 6px; /* below the box's ✕, which reaches a little under the title */
}

#alerts-clear {
  flex: none;
  padding: 1px 8px;
  background: var(--vhs-blue);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(12px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  cursor: pointer;
}

#alerts-clear:hover {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

#alerts-close,
#spc-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font-size: 18px;
  cursor: pointer;
}

/* A feed row (alerts.js alertRow): the alert, which opens it, and an ✕ that clears it off the feed. */
.alert-row {
  display: flex;
  align-items: flex-start;
  margin-top: 6px;
  background: rgba(0, 0, 0, 0.25);
  border-left: 6px solid;
  border-radius: var(--radius, 0);
}

.alert-open {
  flex: 1;
  min-width: 0;
  padding: 5px 8px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font: inherit;
  text-align: left;
  text-transform: inherit;
  cursor: pointer;
}

.alert-row-clear {
  flex: none;
  padding: 4px 8px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font-size: 15px;
  cursor: pointer;
}

.alert-row-clear:hover {
  background: rgba(255, 255, 255, 0.15);
}

.alert-row:hover {
  background: rgba(255, 255, 255, 0.1);
}

/* Alert details popup (alerts.js), in the tornado popup's panel style. */
.alert-details-name {
  font-size: 1.2em;
  font-weight: bold;
}

.alert-details-meta {
  margin-top: 2px;
  color: #c8c8ff;
  text-transform: none;
}

.alert-details-text {
  white-space: pre-line;
  text-transform: none;
}

.alert-area,
.alert-until {
  font-size: 0.85em;
  color: #c8c8ff;
  text-transform: none;
}

.alert-empty {
  margin-top: 8px;
  color: var(--vhs-green);
}

/* The home town's alerts, outlined in red at the bottom of the list. */
.alert-home {
  margin-top: 12px;
  padding: 8px 10px;
  border: 3px solid #ff2a2a;
  border-radius: var(--radius, 0);
  background: rgba(150, 0, 0, 0.35);
}

.alert-home-title {
  color: #ff8080;
}

.alert-home-message {
  margin-top: 4px;
  font-weight: bold;
  text-transform: none;
}

/* SEEK SHELTER NOW, highlighted in the alert's color (set in alerts.js). */
.alert-shelter {
  padding: 0 4px;
  color: #000;
  font-weight: bold;
  text-shadow: none;
  white-space: nowrap;
}

/* Warning outlines (alerts.js) are live radar information, so TOR History hides them. */
body.history .leaflet-alerts-pane {
  display: none;
}

/* View menu "Hide buttons" (auto-hide.js): the controls fade out, leaving the map. */
#controls,
#product-bar,
#second-product-bar,
#home-search,
#history-search,
#history-ratings-panel,
#view-panel,
#spc-panel,
.leaflet-control-zoom,
#hurricane-search,
#hurricane-category-panel {
  transition: opacity 0.4s ease;
}

body.buttons-hidden #controls,
body.buttons-hidden #product-bar,
body.buttons-hidden #second-product-bar,
body.buttons-hidden #home-search,
body.buttons-hidden #history-search,
body.buttons-hidden #history-ratings-panel,
body.buttons-hidden #view-panel,
body.buttons-hidden .leaflet-control-zoom,
body.buttons-hidden #hurricane-search,
body.buttons-hidden #hurricane-category-panel {
  opacity: 0;
  pointer-events: none;
}

/* Hurricane History uses body.history (live-radar controls hidden) plus body.hurricanes, which swaps
   TOR History's search and rating panel for the hurricane ones. */
#hurricane-search,
#hurricane-category-panel {
  display: none;
}

body.hurricanes #history-search,
body.hurricanes #history-ratings-panel {
  display: none;
}

/* The storm name in a hurricane popup: a link that shows only that storm. */
.hurricane-title {
  display: block;
  margin-bottom: 4px;
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--vhs-font);
  font-size: 1.2em;
  font-weight: bold;
  text-align: left;
  text-transform: var(--case, uppercase);
  text-decoration: underline;
  cursor: pointer;
}

/* Small print under a hurricane write-up: where the death toll comes from. */
.hurricane-note-source {
  font-size: 0.8em;
  color: #c8c8ff;
  text-transform: none;
}

/* The star after a max wind that links to its source (history.js maxWindValue); a.wind-source in the
   map beats Leaflet's own link color. */
.leaflet-container a.wind-source {
  padding: 0 4px;
  color: #ffd84d;
  font-weight: bold;
  text-decoration: none;
}

/* Hurricane popups hold longer write-ups, so their text area is taller; it scrolls only up and down. */
.hurricane-popup .tornado-details {
  max-height: 55vh;
  overflow-x: hidden;
}

/* NHC write-ups come in several paragraphs. */
.hurricane-summary {
  white-space: pre-line;
  text-transform: none;
}

/* A storm's picture in its popup (hurricanes.js): top right, beside the facts. */
.hurricane-image {
  float: right;
  width: 150px;
  margin: 0 0 6px 10px;
}

.hurricane-image img {
  display: block;
  width: 100%;
  border: var(--line, 1px solid var(--vhs-text));
  border-radius: var(--radius, 0);
}

.hurricane-image figcaption {
  margin-top: 2px;
  font-size: 0.7em;
  color: #c8c8ff;
  text-align: right;
  text-transform: none;
}

/* The site user's name in a photo credit (history.js creditParts): a link to their profile. */
.credit-profile-link {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.credit-profile-link:hover {
  color: var(--vhs-green);
}

/* The write-up starts below the picture. */
.hurricane-popup .hurricane-summary {
  clear: both;
}

/* A tornado's write-up or comments start below its picture and Videos button too, so the line above
   them doesn't run under a tall picture's button. */
.tornado-details.has-image > p:first-of-type {
  clear: right;
}

/* Black-on-white radar drawings: their white is made see-through (hurricanes.js clearWhiteBackground). */
.hurricane-image img.white-background {
  border-color: transparent;
}

/* Tool buttons (app.js), in the top left corner (the zoom buttons are bottom left): Radar, Tornadoes,
   Hurricanes, minus the one in use. They sit in the same spot on every tool; the town search (Radar
   only) is to their right. */
#tool-switcher {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1001;
  display: flex;
  flex-direction: column;
  gap: 6px;
  transition: opacity 0.4s ease;
}

#tool-switcher button {
  min-width: 150px; /* "Storm Chasers" in the retro font; the same in every style, so what sits beside the buttons can count on it */
  padding: 5px 12px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(16px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  text-shadow: var(--vhs-fringe);
  text-align: left;
  cursor: pointer;
}

#tool-switcher button:hover {
  background: var(--vhs-blue-light);
}

/* The tool in use: its button is lit (filled), like a pressed segmented button. */
#tool-switcher button[aria-pressed="true"] {
  background: var(--vhs-text);
  color: var(--vhs-blue);
  text-shadow: none;
  cursor: default;
}

body.buttons-hidden #tool-switcher {
  opacity: 0;
  pointer-events: none;
}

/* A popup with a picture stays wide enough that the facts beside it keep normal line lengths. */
.hurricane-popup .tornado-details.has-image {
  min-width: 380px;
}

/* The hurricane summary fits on one line under the search box. */
#hurricane-summary {
  font-size: calc(12px * var(--text-scale, 1));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Retro: the picture's outline sat outside its 100% width, so the popup clipped the right edge. */
body:not(.modern) .hurricane-image img {
  box-sizing: border-box;
}

/* Tornado write-ups (comments) keep their own capitals; Retro's all-caps is hard to read in paragraphs. */
.tornado-popup .tornado-details p {
  text-transform: none;
}

/* User button (user-profile.js): bottom right, level with the control bar, in every tool. */
#user-button {
  position: absolute;
  right: 12px;
  bottom: 34px;
  z-index: 1001;
  padding: 6px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(18px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
  cursor: pointer;
  transition: opacity 0.4s ease;
}

#user-button:hover,
#user-button[aria-pressed="true"] {
  background: var(--vhs-blue-light);
}

/* The profile opens above the user button. */
#user-panel {
  position: absolute;
  right: 12px;
  bottom: 84px;
  z-index: 1002;
  width: 280px;
  max-width: calc(100% - 24px);
  box-sizing: border-box;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(15px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

#user-panel[hidden] {
  display: none;
}

.user-header {
  display: flex;
  align-items: center;
  gap: 12px;
}

/* profile.webp is the photo inside a green ring on a white glow; the background is sized and
   placed so just the photo, inside the ring (centered at 459, 462 px, radius about 330), fills
   the circle. */
.user-photo {
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  border: 2px solid var(--vhs-green);
  background: url("profile.webp") 50.2% 49.6% / 139% no-repeat;
}

.user-name {
  font-size: calc(20px * var(--text-scale, 1));
}

.user-note {
  font-size: 0.8em;
  color: #c8c8ff;
}

#user-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid #5a5ab8;
}

/* Sign-in form and Sign out (user-profile.js). */
.account-form {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-bottom: 8px;
  border-bottom: 1px solid #5a5ab8;
}

.account-form input {
  padding: 5px 8px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid #5a5ab8;
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  text-transform: none;
  letter-spacing: normal;
}

.account-buttons {
  display: flex;
  gap: 6px;
}

.account-buttons button,
.account-sign-out {
  flex: 1;
  padding: 5px 8px;
  background: var(--vhs-blue-light);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  text-transform: inherit;
  cursor: pointer;
}

.account-form .user-note:empty {
  display: none;
}

body.buttons-hidden #user-button,
body.buttons-hidden #user-panel {
  opacity: 0;
  pointer-events: none;
}

/* Storm lists (storm-lists.js): the popup's title line holds the title, a + button that opens the
   list menu, and a badge per list the storm is on. The menu opens just below that line, in the
   popup's flow, so the popup's scrolling never clips it. */
.storm-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 8px;
  margin-right: 18px; /* clear of the popup's close x */
}

.list-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.list-badge {
  padding: 0 6px;
  border-radius: var(--radius, 0);
  background: #8fd3ff;
  color: #0b0b3a;
  font-size: 0.75em;
  text-transform: var(--case, uppercase);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

.list-badge.chased {
  background: #3ec46d;
}

.list-badge.favorite {
  background: #f2e33a;
}

.list-button {
  width: 22px;
  height: 22px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-green);
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.list-button:hover,
.list-button[aria-expanded="true"] {
  background: var(--vhs-green);
  color: var(--vhs-blue);
}

/* Floats over the popup (positioned by storm-lists.js from the + button) and grows out of it. */
.list-menu {
  position: absolute;
  z-index: 10;
  display: flex;
  flex-direction: column;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.55);
  transform-origin: top left;
  animation: list-menu-grow 0.14s ease-out;
  gap: 2px;
  width: 170px;
  padding: 6px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.98));
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
}

.list-menu[hidden] {
  display: none;
}

.list-menu-item {
  padding: 3px 6px;
  background: transparent;
  border: 0;
  color: var(--vhs-text);
  font: inherit;
  font-size: 0.85em;
  text-align: left;
  text-transform: var(--case, uppercase);
  letter-spacing: inherit;
  cursor: pointer;
}

.list-menu-item:hover,
.list-menu-item:focus-visible {
  background: var(--vhs-blue-light);
}

.list-menu-item[aria-pressed="true"] {
  color: var(--vhs-green);
}

.list-menu-new {
  display: flex;
  gap: 4px;
  margin-top: 4px;
  padding-top: 6px;
  border-top: 1px solid #5a5ab8;
}

.list-menu-new input {
  flex: 1;
  min-width: 0;
  padding: 2px 4px;
  background: transparent;
  border: 1px solid var(--vhs-text);
  color: var(--vhs-text);
  font: inherit;
  font-size: 0.85em;
}

.list-menu-new button {
  padding: 2px 6px;
  background: transparent;
  border: 1px solid var(--vhs-green);
  color: var(--vhs-green);
  font: inherit;
  font-size: 0.85em;
  cursor: pointer;
}

/* The storm lists in the user profile (user-profile.js). */
.chased-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-top: 8px;
  border-top: 1px solid #5a5ab8;
}

.chased-title {
  color: var(--vhs-green);
}

.chased-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 40vh;
  overflow-y: auto;
}

.chased-item {
  padding: 3px 6px;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
  font-size: 0.9em;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.chased-item:hover,
.chased-item:focus-visible {
  background: var(--vhs-blue-light);
}

/* List view (list-view.js): a storm list's storms on the map, named in a banner at the top center.
   The Tornadoes search and Rating panel belong to Tornadoes, so they stay hidden here. */
#list-banner,
#radar-pick-banner {
  display: none;
}

body.list-view #list-banner,
body.radar-picking #radar-pick-banner,
body.radar-notice #radar-pick-banner {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 16px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(18px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
}

body.list-view #history-search,
body.list-view #history-ratings-panel {
  display: none;
}

/* A list name in the profile that opens the list view. */
button.chased-title {
  padding: 0;
  background: none;
  border: 0;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

button.chased-title:hover {
  text-decoration: underline;
}

@keyframes list-menu-grow {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
}

@media (prefers-reduced-motion: reduce) {
  .list-menu {
    animation: none;
  }
}

/* The list menu is placed within the popup's frame (storm-lists.js). */
.tornado-popup .leaflet-popup-content-wrapper {
  position: relative;
}

/* A storm list's summary in the profile (user-profile.js): kinds, then strengths, then a toggle
   for the storms themselves (folded away by default). */
.list-summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.9em;
}

.list-strengths {
  color: #c8c8ff;
  font-size: 0.9em;
}

.list-toggle {
  align-self: flex-start;
  padding: 0;
  background: none;
  border: 0;
  color: var(--vhs-green);
  font: inherit;
  font-size: 0.85em;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.list-toggle:hover {
  text-decoration: underline;
}

.chased-list[hidden] {
  display: none;
}

/* The list banner's Analytics button (list-view.js). */
#list-analytics-button,
#list-show-all,
#radar-pick-banner button {
  padding: 2px 10px;
  background: transparent;
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-green);
  font: inherit;
  font-size: 0.8em;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

#list-analytics-button:hover,
#list-show-all:hover,
#radar-pick-banner button:hover {
  background: var(--vhs-green);
  color: var(--vhs-blue);
}

/* A storm list's analytics (list-analytics.js): a scrolling panel in the middle of the map, with
   total tiles, record holders and plain HTML bar charts. */
#analytics-panel {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1003;
  width: 560px;
  max-width: calc(100% - 40px);
  max-height: calc(100% - 180px);
  overflow-y: auto;
  box-sizing: border-box;
  padding: 26px 20px 18px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.97));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

#analytics-panel[hidden] {
  display: none;
}

.analytics-content {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.analytics-title {
  margin: 0;
  font-size: 1.4em;
  font-weight: normal;
}

.analytics-tiles {
  display: grid;
  grid-template-columns: repeat(var(--tile-columns, 4), minmax(0, 1fr)); /* list-analytics.js tileColumns */
  gap: 10px;
}

.analytics-tile {
  padding: 8px 10px;
  border: 1px solid #5a5ab8;
  border-radius: var(--radius, 0);
}

.analytics-tile-value {
  font-size: 1.6em;
  font-variant-numeric: tabular-nums;
}

.analytics-tile-label,
.analytics-note,
.analytics-record-none {
  color: #c8c8ff;
  font-size: 0.85em;
}

.analytics-note {
  margin: -8px 0 0;
}

.analytics-charts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px 24px;
}

.analytics-chart {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.analytics-heading {
  margin: 0 0 4px;
  color: var(--vhs-green);
  font-size: 1em;
  font-weight: normal;
}

.analytics-bar-row {
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) 32px;
  align-items: center;
  gap: 8px;
}

.analytics-bar-track {
  height: 10px;
}

.analytics-bar {
  height: 100%;
  min-width: 2px;
  border-radius: 0 4px 4px 0;
}

.analytics-bar-count {
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* One grid for all the record rows (title, value, date, tornado), each column as wide as its
   widest entry, so the columns line up in either style's font. The rows share it via subgrid. */
.analytics-records {
  display: grid;
  grid-template-columns: max-content max-content max-content minmax(0, 1fr);
  column-gap: 14px;
  row-gap: 2px;
}

.analytics-record {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: baseline;
}

.analytics-record-link,
.analytics-record-none {
  display: grid;
  grid-column: 2 / -1;
  grid-template-columns: subgrid;
}

.analytics-record-title {
  color: var(--vhs-green);
}

.analytics-record-link {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: var(--case, uppercase); /* the modern style keeps the records' own case */
  letter-spacing: 0;
  cursor: pointer;
}

.analytics-record-link:hover {
  text-decoration: underline;
}

.analytics-records.is-one-day {
  grid-template-columns: max-content max-content minmax(0, 1fr);
}

.analytics-records.is-one-day .analytics-record-date {
  display: none;
}

/* The town is cut short ("Tuscaloosa-Birmingh...") before the rating beside it is. */
.analytics-record-place {
  display: flex;
  gap: 0.4em;
  min-width: 0;
}

.analytics-record-town {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.analytics-record-rating {
  flex: none;
}

@media (max-width: 640px) {
  .analytics-tiles,
  .analytics-charts {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .analytics-charts {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* A radar site with no recent scans (app.js downRadarMarker): a red box over the site, so an outage
   is plain to see. The translate centers the box on the site. */
.radar-down-text {
  position: absolute;
  padding: 2px 6px;
  background: #c40000;
  border: 2px solid #fff;
  color: #fff;
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  letter-spacing: var(--tracking, 0.04em);
  white-space: nowrap;
  transform: translate(-50%, -50%);
}

/* Radar outages are about now, not the history views, and only matter zoomed in to a site. */
body.history .radar-down-box,
body.composite-radar .radar-down-box {
  display: none;
}

/* A chart row with storms is a button that shows just those storms (list-view.js). */
button.analytics-bar-row {
  cursor: pointer;
}

button.analytics-bar-row:hover .analytics-bar-label,
button.analytics-bar-row:hover .analytics-bar-count {
  text-decoration: underline;
}

.analytics-content + .analytics-content {
  margin-top: 8px;
}

/* The Tornado Analytics title goes back to the whole list (list-view.js showAll). */
.analytics-title-button {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.analytics-title-button:hover {
  text-decoration: underline;
}

/* Radar sites (View > Radar sites, app.js siteIcon): a box with the site's name over the site, blue
   while live, red when down, outlined white when it's the radar on screen. The translate centers it. */
.radar-site-text {
  position: absolute;
  padding: 1px 5px;
  background: #1f5fd6;
  border: 1px solid #9cc0ff;
  color: #fff;
  font-family: var(--vhs-font);
  font-size: calc(12px * var(--text-scale, 1));
  letter-spacing: var(--tracking, 0.04em);
  white-space: nowrap;
  transform: translate(-50%, -50%);
  cursor: pointer;
}

.radar-site-text.down {
  background: #c40000;
  border-color: #fff;
}

/* A radar site picked for a tornado replay's radar history (radar-history.js). */
.radar-site-text.picked {
  background: #1f8a3a;
  border: 2px solid #fff;
}

.radar-site-text.selected {
  border: 2px solid #fff;
  font-size: calc(14px * var(--text-scale, 1));
}

/* Split screen has no room for the town forecast box (weather.js); it comes back with one pane. */
body.dual #weather-panel {
  display: none;
}

/* A warning's name in its popup zooms to it (alerts.js alertDetails). */
button.alert-details-name {
  display: block;
  padding: 0;
  background: none;
  border: 0;
  font-family: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

button.alert-details-name:hover {
  text-decoration: underline;
}

/* The alert's name, with a watch's Hide button at the right, clear of the popup's close button. */
.alert-details-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* Highs and lows (boundaries.js): a blue H or a red L, its pressure under it. */
.boundary-center {
  font-family: var(--vhs-font);
  text-align: center;
  text-shadow: 0 0 3px #000, 0 0 3px #000;
}

.boundary-letter {
  display: block;
  font-size: 26px;
  font-weight: bold;
  line-height: 26px;
}

.boundary-letter.high {
  color: #3b82ff;
}

.boundary-letter.low {
  color: #ff3b3b;
}

.boundary-pressure {
  display: block;
  color: #fff;
  font-size: 11px;
}

/* A watch's popup can hide its outline (alerts.js hideButton). */
.alert-hide-button {
  flex: none;
  margin-right: 16px;
  padding: 2px 8px;
  background: var(--vhs-blue);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(13px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  cursor: pointer;
}

.alert-hide-button:hover {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

/* The forecast box's town name is a button for another town's forecast (weather.js searchFromTitle). */
.weather-title {
  cursor: pointer;
}

.weather-title:hover {
  text-decoration: underline;
}

.weather-title-search {
  width: calc(100% - 150px); /* clear of Set as home and the close x */
  margin: 0 0 4px;
  padding: 4px 6px;
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  text-transform: none;
}

/* The house beside the home town's gold name on the map (town-labels.js). */
.town-home-icon svg {
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-left: 4px;
  vertical-align: -0.12em;
}

body.history .forecast-town {
  display: none;
}

/* The retro style's VCR font is always all caps: popups, records, search boxes, alert text and all
   (tornado descriptions aside, below). !important because many boxes switch caps off for the modern style's sake. */
body:not(.modern),
body:not(.modern) *,
body:not(.modern) *::placeholder {
  text-transform: uppercase !important;
}

/* The one exception: a tornado's description (NOAA's comments, or its note's write-up) keeps its own
   case, as long text reads better that way. */
body:not(.modern) .tornado-comments,
body:not(.modern) .tornado-details .hurricane-summary,
body:not(.modern) .century-s {
  text-transform: none !important;
}

/* The SPC box reads like the forecast box and alert feed above it: 14 px text, an 18 px title in the
   same weight as their titles, and its Day / product buttons at the text size. */
#spc-panel {
  font-size: calc(14px * var(--text-scale, 1));
}

#spc-panel .spc-title {
  font-size: calc(18px * var(--text-scale, 1));
  font-weight: normal;
}

body.modern #spc-panel .spc-title {
  font-weight: 600; /* as the modern style's other box titles */
}

#spc-panel .segmented button {
  font-size: calc(14px * var(--text-scale, 1));
}

/* Storm Chasers (hub.js): a card in the top right column like the forecast box and alert feed, with
   the Live Feed of catches, a Chasers list and chaser profiles, scrolling when long. */
#hub-panel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 420px;
  max-width: 100%;
  max-height: 55vh;
  overflow: hidden; /* its body scrolls (#hub-body); the title and tabs stay put */
  box-sizing: border-box;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.97));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

#hub-panel[hidden] {
  display: none;
}

/* The Storm Chasers card's scroll bar, retro: a square white slider on a VHS-blue track. */
#hub-body::-webkit-scrollbar {
  width: 12px;
}

#hub-body::-webkit-scrollbar-track {
  background: var(--vhs-blue);
}

#hub-body::-webkit-scrollbar-thumb {
  background: var(--vhs-text);
  border: 2px solid var(--vhs-blue);
}

/* Firefox has no scroll bar parts to style, only its colors. */
@supports not selector(::-webkit-scrollbar) {
  #hub-body {
    scrollbar-color: var(--vhs-text) var(--vhs-blue);
  }
}

.hub-title {
  margin: 0 24px 0 0; /* clear of the close x */
  font-weight: normal;
}

#hub-close {
  position: absolute;
  top: 8px;
  right: 10px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font-size: 18px;
  cursor: pointer;
}

.hub-preview,
.hub-sample {
  margin-left: 6px;
  padding: 1px 6px;
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-green);
  font-size: 11px;
  vertical-align: middle;
}

#hub-tabs button {
  font-size: calc(14px * var(--text-scale, 1));
}

/* The part of the card that scrolls, below the title and tabs. */
#hub-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}

.hub-loading {
  color: #c8c8ff;
}

.hub-avatar {
  flex: none;
  display: inline-grid;
  place-items: center;
  border-radius: 50%;
  color: #fff;
  font-weight: 700;
}

.hub-avatar.small {
  width: 26px;
  height: 26px;
  font-size: 11px;
}

.hub-avatar.medium {
  width: 40px;
  height: 40px;
  font-size: 15px;
}

.hub-avatar.large {
  width: 64px;
  height: 64px;
  font-size: 22px;
}

.hub-initials {
  border: 2px solid rgba(255, 255, 255, 0.8);
  box-sizing: border-box;
}

.hub-catch {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 10px;
  background: rgba(0, 0, 0, 0.25);
  border-left: 3px solid var(--vhs-green);
  border-radius: var(--radius, 0);
}

.hub-catch-who {
  display: flex;
  align-items: center;
  gap: 8px;
}

.hub-chaser-name,
.hub-catch-what,
.hub-back,
.hub-chaser-card {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.hub-chaser-name {
  color: var(--vhs-green);
}

.hub-catch-what {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: baseline;
}

.hub-catch-rating {
  font-weight: 700;
}

.hub-catch-date {
  color: #c8c8ff;
  font-size: 0.9em;
}

/* A profile's Tornado Stats (hub.js toggleStats), small and tight enough to fit the card: the compact box's text size, closer sections
   and chart rows. */
#hub-panel .analytics-content .analytics-content {
  gap: 10px;
  font-size: calc(12px * var(--text-scale, 1));
}

#hub-panel .analytics-charts {
  gap: 10px 18px;
}

#hub-panel .analytics-chart {
  gap: 1px;
}

/* The profile above already gives the totals and records, so its Stats show only the charts. */
#hub-panel .hub-profile .analytics-content .analytics-title,
#hub-panel .hub-profile .analytics-content .analytics-tiles,
#hub-panel .hub-profile .analytics-content .analytics-note,
#hub-panel .hub-profile .analytics-content .analytics-records {
  display: none;
}

/* A profile's Show on map, Stats and Photos buttons, side by side. */
.hub-profile-buttons {
  display: flex;
  gap: 8px;
}

/* A chaser's photos (hub.js photoGallery): two cards a row, each its picture, rating, town and date. */
.hub-photos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}

.hub-photo {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 4px;
  background: rgba(0, 0, 0, 0.25);
  border: 0;
  border-radius: var(--radius, 0);
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.hub-photo:hover {
  background: rgba(255, 255, 255, 0.08);
}

.hub-photo-image {
  width: 100%;
  height: 110px;
  object-fit: cover;
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
}

.hub-photo-caption {
  display: flex;
  gap: 6px;
  min-width: 0;
}

.hub-photo-caption .hub-catch-town {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

/* A profile's list of every catch (hub.js catchList): one compact row each. */
/* Its rows share one set of columns (date, rating, town), so every rating lines up; a town too long
   for its row is cut short rather than wrapping. */
.hub-catch-list {
  display: grid;
  grid-template-columns: max-content max-content minmax(0, 1fr);
  gap: 4px;
}

.hub-catch-list-title {
  grid-column: 1 / -1;
  margin-top: 4px;
  color: var(--vhs-green);
}

.hub-catch-row {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: subgrid;
  column-gap: 10px;
  align-items: baseline;
  padding: 3px 6px;
  background: rgba(0, 0, 0, 0.25);
  border-radius: var(--radius, 0);
}

.hub-catch-row .hub-catch-town {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.hub-catch-photo {
  width: 100%;
  max-height: 200px;
  object-fit: cover;
  border-radius: var(--radius, 0);
  cursor: pointer;
}

.hub-chaser-name:hover,
.hub-catch-what:hover,
.hub-back:hover {
  text-decoration: underline;
}

.hub-chaser-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  background: rgba(0, 0, 0, 0.25);
  border-radius: var(--radius, 0);
}

.hub-chaser-card:hover {
  background: rgba(255, 255, 255, 0.08);
}

.hub-chaser-card-name,
.hub-profile-name {
  font-size: 1.15em;
}

.hub-profile-name {
  font-size: 1.4em;
}

.hub-chaser-meta {
  color: #c8c8ff;
  font-size: 0.9em;
}

.hub-profile {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* "‹ Profile" / "‹ All chasers" stays at the top while the rest scrolls under it. */
.hub-back {
  position: sticky;
  top: 0;
  z-index: 1;
  align-self: stretch;
  padding-bottom: 4px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.97));
  color: var(--vhs-green);
}

.hub-profile-head {
  display: flex;
  align-items: center;
  gap: 14px;
}

.hub-bio {
  margin: 0;
}

.hub-show-map {
  align-self: flex-start;
  padding: 4px 12px;
  background: transparent;
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-green);
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

/* Hovered, or on (a Stats button while its Stats are open): filled green. */
.hub-show-map:hover,
.hub-show-map[aria-pressed="true"] {
  background: var(--vhs-green);
  color: var(--vhs-blue);
}

/* The leaderboard's Stats (leaderboard.js) leave out their "Tornado Stats" title; the green Stats
   button beside the lookup opens and closes them. */
#leaderboard-stats .analytics-content > .analytics-title {
  display: none;
}

#leaderboard-stats {
  padding: 6px 0 10px;
}


/* A chaser profile's facts (hub.js profileFacts): label and value in two columns. */
.hub-facts {
  display: grid;
  grid-template-columns: max-content minmax(0, 1fr);
  gap: 4px 14px;
}

.hub-fact-label {
  color: var(--vhs-green);
}

/* The chaser's social accounts, under their home town. */
.hub-socials {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

.hub-social {
  padding: 1px 8px;
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-green);
  font-size: 0.85em;
  text-decoration: none;
}

.hub-social:hover {
  background: var(--vhs-green);
  color: var(--vhs-blue);
}

/* Each social link in its site's colors. */
.hub-social.hub-social-youtube,
.hub-social.hub-social-x,
.hub-social.hub-social-instagram {
  color: #fff;
  text-shadow: none;
}

.hub-social.hub-social-youtube {
  background: #ff0000;
  border-color: #ff0000;
}

.hub-social.hub-social-x {
  background: #000;
  border-color: #fff;
}

.hub-social.hub-social-instagram {
  background: linear-gradient(90deg, #ff00cc, #ffcc00);
  border-color: transparent;
}

.hub-social.hub-social-youtube:hover,
.hub-social.hub-social-x:hover,
.hub-social.hub-social-instagram:hover {
  color: #fff;
  filter: brightness(1.15);
}

/* Chaser Leaderboard (leaderboard.js): a card in the Tornadoes view, right of the tool buttons (150 px
   wide from 10 px) so it never covers them, and below the Tornadoes search; the Rating panel has the
   top right. Not in Hurricanes or the list view. */
#leaderboard-panel {
  position: absolute;
  top: 136px;
  left: 172px;
  z-index: 1002;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 470px; /* the retro font's names need it beside four number columns */
  max-width: calc(100% - 182px);
  max-height: calc(100% - 220px);
  overflow-y: auto;
  box-sizing: border-box;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

#leaderboard-panel[hidden],
body:not(.history) #leaderboard-panel,
body.hurricanes #leaderboard-panel,
body.list-view #leaderboard-panel {
  display: none;
}

/* The leaderboard inside the Storm Chasers card's Leaderboard tab (hub.js): no box, title or close
   button of its own (the card has them). */
#hub-body #leaderboard-panel {
  position: static;
  width: auto;
  max-width: none;
  max-height: none;
  overflow: visible;
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
}

#hub-body #leaderboard-close,
#hub-body .leaderboard-title-row .view-title {
  display: none;
}

#hub-body .leaderboard-title-row {
  padding-right: 0;
}

#leaderboard-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font-size: 18px;
  cursor: pointer;
}

.leaderboard-head,
.leaderboard-row {
  display: grid;
  grid-template-columns: 34px 26px minmax(0, 1fr) 56px 50px 44px;
  align-items: center;
  gap: 8px;
}

.leaderboard-head {
  grid-template-columns: 34px minmax(0, 1fr) 56px 50px 44px;
  color: var(--vhs-green);
  font-size: 0.8em;
}

.leaderboard-head span:nth-child(2) {
  padding-left: 34px; /* past the picture column */
}

.leaderboard-head span:nth-child(n + 3) {
  text-align: right;
}

#leaderboard-body {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.leaderboard-row,
.leaderboard-tornado {
  width: 100%;
  padding: 5px 6px;
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid transparent;
  border-radius: var(--radius, 0);
  color: inherit;
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.leaderboard-row:hover,
.leaderboard-tornado:hover {
  background: rgba(255, 255, 255, 0.08);
}

.leaderboard-row.selected {
  border-color: var(--vhs-green);
}

.leaderboard-rank {
  color: var(--vhs-green);
}

.leaderboard-name {
  display: flex;
  align-items: center;
  min-width: 0;
}

.leaderboard-name-text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.leaderboard-name .hub-sample {
  flex: none;
}

.leaderboard-count,
.leaderboard-score,
.leaderboard-best {
  font-weight: 700;
  text-align: right;
}

.leaderboard-caught {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 2px 0 4px 18px;
}

.leaderboard-tornado {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) max-content;
  gap: 8px;
  padding: 3px 6px;
  font-size: 0.9em;
}

.leaderboard-tornado .leaderboard-best {
  text-align: left;
}

#leaderboard-tabs button {
  font-size: calc(14px * var(--text-scale, 1));
}

/* The year tab's right-click menu: the last ten years, in a row of buttons under the tabs. */
#leaderboard-year-menu {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 4px;
  padding: 6px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
}

#leaderboard-year-menu[hidden] {
  display: none;
}

.leaderboard-year {
  padding: 3px 0;
  background: var(--vhs-blue);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  cursor: pointer;
}

.leaderboard-year:hover,
.leaderboard-year.selected {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

/* The Stats panel is never on the radar, and in Hurricanes only its own Stats box shows there (not a
   leftover from Tornadoes or the list view). */
body:not(.history) #analytics-panel,
body.hurricanes #analytics-panel:not([data-hazard="hurricanes"]) {
  display: none;
}


/* The Chaser Leaderboard's lookup box, beside its title (leaderboard.js); room is left on the right
   for the close button. */
.leaderboard-title-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 24px;
}

#leaderboard-lookup {
  flex: 1;
  min-width: 0;
  padding: 2px 6px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--vhs-green);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font: inherit;
  text-transform: inherit;
  letter-spacing: inherit;
}

/* The Count, Score and Best headings: clicking one ranks the leaderboard by it; the one in use is lit. */
.leaderboard-sort {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: right;
  text-transform: inherit;
  letter-spacing: inherit;
  text-decoration: underline dotted;
  cursor: pointer;
}

.leaderboard-sort[aria-pressed="true"] {
  color: var(--vhs-text);
  text-decoration: underline;
}

/* A clicked chaser's social links, indented with their tornado list under their row. */
#leaderboard-body .hub-socials {
  margin: 2px 0 0 18px;
}

/* One tornado's stats (history.js): its top where a big outbreak day's box starts (the box sits
   120px up, and April 27, 2011's is 445px tall). */
body:not(.list-view) #analytics-panel.chaser-analytics.one-tornado[data-hazard="tornadoes"] {
  top: calc(100% - 120px - 445px);
  bottom: auto;
}

/* The Chaser Leaderboard's All Time analytics (leaderboard.js): a smaller box in the bottom right,
   above the profile button (#user-button) and the bottom toolbar. */
body:not(.list-view) #analytics-panel.chaser-analytics {
  top: auto;
  bottom: 120px;
  width: 460px;
  max-height: calc(100% - 204px);
  padding: 18px 14px 12px;
  font-size: calc(12px * var(--text-scale, 1));
}

/* In the smaller box the tiles' numbers stay on one line, and the records sit closer together (a
   long town is cut short, .analytics-record-town). */
body:not(.list-view) #analytics-panel.chaser-analytics .analytics-tiles,
#hub-panel .analytics-tiles {
  gap: 6px;
}

body:not(.list-view) #analytics-panel.chaser-analytics .analytics-tile,
#hub-panel .analytics-tile {
  padding: 6px 8px;
}

body:not(.list-view) #analytics-panel.chaser-analytics .analytics-tile-value,
#hub-panel .analytics-tile-value {
  font-size: 1.25em;
  white-space: nowrap;
}

body:not(.list-view) #analytics-panel.chaser-analytics .analytics-records,
#hub-panel .analytics-records {
  column-gap: 8px;
}


/* ---------- Hazard databases (hazards.js: Earthquakes, Tsunamis, Volcanoes) ----------
   body.history (live-radar controls hidden) plus body.hazard, which swaps Tornadoes' search, rating
   panel and leaderboard for the hazard's own, styled like Hurricanes'. */
.hazard-search,
.hazard-class-panel {
  display: none;
}


body.hazard #history-search,
body.hazard #history-ratings-panel,
body.hazard #leaderboard-panel {
  display: none !important;
}

body.hazard-earthquakes #earthquakes-search,
body.hazard-tsunamis #tsunamis-search,
body.hazard-volcanoes #volcanoes-search,
body.hazard-meteors #meteors-search,
body.hazard-landslides #landslides-search,
body.hazard-floods #floods-search,
body.hazard-wildfires #wildfires-search {
  position: absolute;
  top: 10px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1001;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 560px;
  max-width: calc(100% - 100px);
  padding: 8px 12px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(18px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
  transition: opacity 0.4s ease;
}

.hazard-search input,
.hazard-search button {
  padding: 4px 8px;
  background: var(--vhs-blue);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: inherit;
  font-size: calc(18px * var(--text-scale, 1));
  color-scheme: dark;
}

.hazard-query {
  flex: 1 1 300px;
  min-width: 0;
  text-transform: none;
}

.hazard-query::placeholder {
  color: #9a9ad8;
  text-transform: var(--case, uppercase);
}

.hazard-summary {
  flex-basis: 100%;
  text-align: center;
  font-size: calc(16px * var(--text-scale, 1));
  color: var(--vhs-green);
}

.hazard-chips {
  display: flex;
  flex-basis: 100%;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}

.hazard-chips:empty {
  display: none;
}

.hazard-search .history-chip,
.hazard-links .history-chip {
  padding: 2px 8px;
  font-size: calc(14px * var(--text-scale, 1));
  cursor: pointer;
}

.hazard-search .history-chip:hover,
.hazard-links .history-chip:hover {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

/* The Analytics chip stands apart from the search's own chips. */
.hazard-search .hazard-analytics-chip {
  border-color: var(--vhs-green);
  color: var(--vhs-green);
}

body.hazard-earthquakes #earthquakes-class-panel,
body.hazard-tsunamis #tsunamis-class-panel,
body.hazard-volcanoes #volcanoes-class-panel,
body.hazard-meteors #meteors-class-panel,
body.hazard-landslides #landslides-class-panel,
body.hazard-floods #floods-class-panel,
body.hazard-wildfires #wildfires-class-panel {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 1001;
  display: block;
  padding: 10px 14px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
  transition: opacity 0.4s ease;
}

.hazard-classes {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 6px;
  font-size: calc(15px * var(--text-scale, 1));
}

.hazard-classes label,
.hazard-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  cursor: pointer;
}

/* A config's extra switch (all volcanoes, say), under the classes. */
.hazard-toggle {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid #5a5ab8;
  font-size: calc(14px * var(--text-scale, 1));
}

.hazard-classes input,
.hazard-toggle input {
  appearance: none;
  width: 14px;
  height: 14px;
  margin: 0;
  border: var(--line, 2px solid var(--vhs-text));
  background: transparent;
  cursor: pointer;
}

.hazard-classes input:checked,
.hazard-toggle input:checked {
  background: var(--vhs-text) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10' shape-rendering='crispEdges'%3E%3Cpath d='M1 5h2v1h1v1h1V6h1V5h1V4h1V2h1v2H9v1H8v1H7v1H6v1H5v1H4V8H3V7H2V6H1z' fill='%231a1aa6'/%3E%3C/svg%3E") center / 10px 10px no-repeat;
}

body.modern .hazard-search,
body.modern .hazard-class-panel {
  backdrop-filter: blur(8px);
  --text-scale: 1;
}

body.modern .hazard-search button,
body.modern .hazard-query {
  border-radius: 6px;
  font-weight: 500;
}

body.modern .hazard-classes input,
body.modern .hazard-toggle input {
  border-radius: 3px;
}

body.modern .hazard-classes input:checked,
body.modern .hazard-toggle input:checked {
  background: #3b82f6 url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1.5 5.2 4 7.6 8.6 2.4' fill='none' stroke='white' stroke-width='1.6'/%3E%3C/svg%3E") center / 10px 10px no-repeat;
  border-color: #3b82f6;
}

body.buttons-hidden .hazard-search,
body.buttons-hidden .hazard-class-panel {
  opacity: 0;
  pointer-events: none;
}

/* A hazard popup's links: to related events in the other databases, and NOAA's own record. */
.hazard-links {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 8px;
}

.hazard-links .history-chip {
  background: var(--vhs-blue);
  border: 1px solid var(--vhs-text);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  text-transform: var(--case, uppercase);
  text-decoration: none;
}

/* The list a click on overlapping hazard dots opens (hazards.js showClicked): one row per event,
   newest first, each opening that event's popup. */
.hazard-pick-title {
  margin-bottom: 6px;
  color: var(--vhs-green);
}

/* Wide enough for a name and a date side by side; a long name is cut off with … rather than
   wrapping under the date. */
.hazard-pick {
  min-width: 400px;
}

.hazard-pick-row > span:nth-child(2) {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hazard-pick-date {
  white-space: nowrap;
}

/* A famous event (one with a write-up) in the list: yellow, with a gold star. */
.hazard-pick-row.famous,
.hazard-pick-row.famous .hazard-pick-date {
  color: #ffe066;
}

.hazard-pick-star {
  color: #ffd700;
  text-shadow: 0 0 4px rgba(255, 215, 0, 0.7);
}

.hazard-pick-row {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) max-content;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 3px 4px;
  background: none;
  border: 0;
  color: var(--vhs-text);
  font: inherit;
  text-align: left;
  text-transform: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.hazard-pick-row:hover {
  background: rgba(255, 255, 255, 0.1);
}

.hazard-pick-date {
  color: #c8c8ff;
}

/* A panel switch's key (the Earthquakes fault lines' kinds): a short line in each color. */
.hazard-legend {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 6px 0 0 19px;
  font-size: calc(12px * var(--text-scale, 1));
}

.hazard-legend-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.hazard-legend-line {
  width: 18px;
  border-top: 3px solid;
}

.hazard-legend-line.dashed {
  border-top-style: dashed;
}

/* Hazard analytics charts: country names need a wider label column than ratings do, and each label
   stays on one line (cut off with … if it is ever longer) so the rows keep their spacing. */
.hazard-analytics .analytics-bar-row {
  grid-template-columns: 104px minmax(0, 1fr) 32px;
}

.hazard-analytics .analytics-bar-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The "s" of "1900s" in the analytics Century chart: small and lower case, even in all-caps retro
   (the exception to its capitals is with the tornado descriptions'). */
.century-s {
  font-size: 0.75em;
}

/* A hazard popup can hold a long write-up, so it gets more room before it scrolls. */
.hazard-popup .tornado-details {
  max-height: 380px;
}

/* Only the first paragraph of a write-up has the divider line; the rest just follow it. */
.hazard-popup .hurricane-summary + .hurricane-summary {
  margin-top: 6px;
  padding-top: 0;
  border-top: 0;
}

/* A volcano's name beside its dot when "All volcanoes" is on and the map is zoomed in (volcanoes.js):
   small orange text like the map's town names, with no tooltip box. */
.leaflet-tooltip.volcano-label {
  padding: 0;
  background: none;
  border: 0;
  box-shadow: none;
  color: #ff9a62;
  font-family: var(--vhs-font);
  font-size: calc(12px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
  text-shadow: 0 0 3px #000, 0 0 3px #000;
}

.leaflet-tooltip.volcano-label::before {
  display: none;
}

/* A popup's date: a button that searches that date (hazards.js dateLink). */
.hazard-date-link {
  padding: 0;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  text-decoration: underline dotted;
  cursor: pointer;
}

.hazard-date-link:hover {
  color: #ffd34d;
}

/* Hurricane replay: the storm symbol spins, counterclockwise north of the equator (hurricanes.js). */
.storm-replay-icon svg {
  display: block;
  animation: storm-spin 1.2s linear infinite;
  filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.9));
}

.storm-replay-icon.is-north svg {
  animation-direction: reverse;
}

@keyframes storm-spin {
  to {
    transform: rotate(360deg);
  }
}

/* The replay time window (replay-range.js): two range inputs stacked on one track, so each dot drags
   on its own; the tracks ignore the mouse so the dot underneath can still be grabbed. */
/* Only the history views wrap the bar, for the time row; the radar bar stays one row. */
body.history #controls {
  flex-wrap: wrap;
  justify-content: center;
  /* As wide as its buttons need (centered from the screen's middle, the bar would otherwise get only
     half the screen before wrapping), never wider than the screen. */
  width: max-content;
}

/* Inside the bottom bar: a slim first row as wide as the bar, the times beside the track. */
#replay-range {
  order: -1;
  flex-basis: 100%;
  /* Fills the bar's width without adding to it: the buttons' row sets how wide the bar is. */
  width: 0;
  min-width: 100%;
  display: flex;
  align-items: center;
  gap: 10px;
}

/* The Replay and Camera buttons line up and space like the bar's own buttons. */
#replay-controls {
  display: contents;
}

#replay-range[hidden] {
  display: none;
}

.replay-range-track {
  position: relative;
  flex: 1;
  min-width: 200px;
  height: 16px;
}

/* The bar: black outside the window, lit between its handles (--from and --to, set by replay-range.js). */
.replay-range-track::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 6px;
  height: 4px;
  background: linear-gradient(to right, #000 var(--from, 0%), var(--vhs-text, #ccc) var(--from, 0%), var(--vhs-text, #ccc) var(--to, 100%), #000 var(--to, 100%));
  border: 1px solid #000;
  box-sizing: border-box;
}

.replay-range-track input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  background: none;
  pointer-events: none;
  -webkit-appearance: none;
  appearance: none;
}

.replay-range-track input::-webkit-slider-runnable-track {
  height: 100%;
  background: none;
}

.replay-range-track input::-moz-range-track {
  height: 100%;
  background: none;
}

/* The window's handles sit above the playhead: a replay starts with the playhead on the start handle
   and ends with it on the end handle, where it would otherwise catch every grab. */
#replay-from,
#replay-to {
  z-index: 1;
}

/* The window's handles: upright lines. */
#replay-from::-webkit-slider-thumb,
#replay-to::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 4px;
  height: 16px;
  background: #ffd34d;
  border: 1px solid #000;
  pointer-events: auto;
  cursor: ew-resize;
}

#replay-from::-moz-range-thumb,
#replay-to::-moz-range-thumb {
  width: 3px;
  height: 14px;
  border-radius: 0;
  background: #ffd34d;
  border: 1px solid #000;
  pointer-events: auto;
  cursor: ew-resize;
}

/* The playhead: a circle at the moment on screen, shown once a replay has started. */
#replay-at {
  visibility: hidden;
}

#replay-range.has-playhead #replay-at {
  visibility: visible;
}

#replay-at::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 12px;
  height: 12px;
  margin-top: 2px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #000;
  pointer-events: auto;
  cursor: grab;
}

#replay-at::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #fff;
  border: 2px solid #000;
  pointer-events: auto;
  cursor: grab;
}

#replay-range-label {
  font-family: var(--vhs-font, inherit);
  font-size: calc(12px * var(--text-scale, 1));
  color: var(--vhs-text, #e6e6e6);
  text-transform: var(--case, uppercase);
  white-space: nowrap;
}

/* Bottom right in Tornadoes: the user button, level with the Atmosphere and SPC Outlook buttons
   (#history-tools) on the left. */
body.history:not(.hurricanes):not(.list-view) #user-button {
  bottom: 30px;
}

body.history:not(.hurricanes):not(.list-view) #user-panel {
  bottom: 80px;
}

/* A search bar's summary line with its Stats button at the end. */
.summary-row {
  flex-basis: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.summary-row > #history-summary,
.summary-row > #hurricane-summary,
.summary-row > .hazard-summary {
  flex-basis: auto;
  min-width: 0;
}

.summary-row .stats-chip {
  flex: none;
  padding: 1px 6px;
  font-size: calc(12px * var(--text-scale, 1));
  border-color: var(--vhs-green);
  color: var(--vhs-green);
  cursor: pointer;
}

/* Random: gold, like the searched town, so it stands out from the plain chips. */
#history-search .random-chip,
#hurricane-search .random-chip,
.hazard-search .random-chip {
  background: #ffd700;
  border-color: #ffd700;
  color: #1a1400;
  text-shadow: none;
  font-weight: bold;
  align-self: stretch; /* as tall as the search box beside it */
}

#history-search .random-chip:hover,
#hurricane-search .random-chip:hover,
.hazard-search .random-chip:hover {
  background: #ffe55c;
  border-color: #ffe55c;
}

/* The radar pick banner (and its "no radar" message) sits above the bottom bar, clear of the tornado
   search at the top. */
body.radar-picking #radar-pick-banner,
body.radar-notice #radar-pick-banner {
  top: auto;
  bottom: 90px;
}

/* The Radar button while a tornado replay waits for its radar scan to load (radar-history.js). */
#radar-history.loading {
  opacity: 0.55;
}

/* Radar history tiles show at once instead of fading in (Leaflet sets each tile's opacity inline
   while it fades), so one scan can replace the next in a single frame (radar-history.js). */
.leaflet-radar-history-pane .leaflet-tile {
  opacity: 1 !important;
  transition: none !important;
}

/* Hide tracks (radar-history.js): the tornado tracks and replay dots off, the radar alone. */
body.tracks-hidden .tornado-track-pane {
  display: none;
}

/* A tornado's Videos button: in the popup's right-hand column, under the picture (or where the
   picture would be), the width of the column. */
.tornado-aside {
  float: right;
  width: 150px;
  margin: 0 0 6px 10px;
}

.video-chip {
  display: block;
  box-sizing: border-box;
  width: 100%;
  margin-top: 6px;
  padding: 2px 8px;
  background: var(--vhs-blue);
  border: 1px solid var(--vhs-text);
  border-radius: var(--radius, 0);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(13px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  cursor: pointer;
}

.tornado-aside .video-chip {
  margin-top: 0;
}

.video-chip:hover {
  background: var(--vhs-text);
  color: var(--vhs-blue);
}

/* The videos list drops down from the button over the write-up, right-aligned with it and wider than
   the picture column (history.js videosChip). */
.video-menu {
  position: relative;
}

.video-list {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 1;
  min-width: 360px;
  padding: 6px 8px;
  /* The panel color over a solid base: the popup's text mustn't show through it. */
  background: linear-gradient(var(--panel-bg, rgba(16, 16, 120, 0.97)), var(--panel-bg, rgba(16, 16, 120, 0.97))), #0b0f1a;
  border: var(--line, 1px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  text-align: left;
}

.video-list[hidden] {
  display: none;
}

/* A tornado's videos list's rows are links, laid out like the volcano eruptions list's buttons. */
a.hazard-pick-row {
  box-sizing: border-box;
  text-decoration: none;
}

.video-pick-icon {
  color: var(--vhs-green);
  font-size: 0.8em;
}

/* Atmospheric Data (atmosphere.js): its button bottom left, level with the control bar (right of the
   zoom buttons), and its panel above it, styled like the User button and panel. */
/* The Tornadoes view's day tools (Atmospheric Data, SPC Outlook): a row at the bottom left. */
#history-tools {
  position: absolute;
  left: 56px;
  bottom: 30px;
  z-index: 1001;
  display: flex;
  gap: 6px;
}

#atmos-button,
#outlook-button {
  padding: 3px 8px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
  line-height: 1;
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.06em);
  text-shadow: var(--vhs-fringe);
  cursor: pointer;
  transition: opacity 0.4s ease;
}

#atmos-button[hidden],
#outlook-button[hidden] {
  display: none;
}

#atmos-button:hover,
#atmos-button[aria-pressed="true"],
#outlook-button:hover,
#outlook-button[aria-pressed="true"] {
  background: var(--vhs-blue-light);
}

#atmos-panel,
#outlook-panel {
  position: absolute;
  left: 12px;
  bottom: 84px;
  z-index: 1002;
  width: 380px;
  max-width: calc(100% - 24px);
  box-sizing: border-box;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--panel-bg, rgba(16, 16, 120, 0.95));
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  box-shadow: var(--panel-shadow, 4px 4px 0 rgba(0, 0, 0, 0.7));
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(15px * var(--text-scale, 1));
  text-transform: var(--case, uppercase);
  letter-spacing: var(--tracking, 0.04em);
}

/* The value under the cursor while Atmospheric Data is shown (atmosphere.js showReadout). */
.atmos-readout {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1001;
  padding: 2px 6px;
  pointer-events: none;
  white-space: nowrap;
  background: rgba(0, 0, 0, 0.8);
  border: 1px solid var(--vhs-text);
  color: var(--vhs-text);
  font-family: var(--vhs-font);
  font-size: calc(14px * var(--text-scale, 1));
}

.atmos-readout[hidden],
#atmos-panel[hidden],
#outlook-panel[hidden],
#atmos-player[hidden],
#atmos-animate[hidden],
#atmos-status[hidden] {
  display: none;
}

#atmos-animate {
  margin-top: 6px;
}

#atmos-close,
#outlook-close {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

#atmos-layers {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

#atmos-status {
  font-size: 0.85em;
  text-transform: none;
  color: #c8c8ff;
}

#atmos-player {
  display: flex;
  align-items: center;
  gap: 8px;
}

#atmos-play {
  flex: none;
  width: 36px;
  padding: 4px 0;
  background: var(--vhs-blue-light);
  border: var(--line, 2px solid var(--vhs-text));
  border-radius: var(--radius, 0);
  color: inherit;
  font: inherit;
  cursor: pointer;
}

#atmos-time {
  flex: 1;
  min-width: 0;
}

#atmos-clock {
  flex: none;
  min-width: 11em;
  font-size: 0.85em;
}

.atmos-legend-title {
  font-size: 0.8em;
}

.atmos-legend-bar {
  height: 12px;
  margin: 4px 0 2px;
  border: 1px solid rgba(255, 255, 255, 0.5);
}

.atmos-legend-ticks {
  display: flex;
  justify-content: space-between;
  font-size: 0.8em;
}

/* The layer's canvas lies over the map; clicks go through it to the tracks. */
.atmos-canvas {
  pointer-events: none;
}

body.buttons-hidden #atmos-button,
body.buttons-hidden #atmos-panel {
  opacity: 0;
  pointer-events: none;
}

/* The SPC Outlook panel sits bottom left, in Atmosphere's place (only one of them is open at a time). */
#outlook-panel {
  width: 300px;
}

/* Tornado intensity hatching (spc-history.js): the SVG patterns in index.html, over the probabilities.
   CSS fill beats the fill Leaflet sets on the path. */
#outlook-hatches {
  position: absolute;
}

.hatch-solid {
  fill: url(#hatch-solid);
}

.hatch-dashed {
  fill: url(#hatch-dashed);
}

.hatch-cross {
  fill: url(#hatch-cross);
}

/* A categorical risk's label (TSTM ... HIGH) inside its area, in its outline color. */
.outlook-label > span {
  position: absolute;
  transform: translate(-50%, -50%);
  font-family: var(--vhs-font);
  font-size: calc(22px * var(--text-scale, 1));
  font-weight: bold;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
