/* ============================================================
   Redesign preview — "Organic" restyle layer.
   Loads AFTER styles.css and re-themes the existing production
   markup/JS (app.js, preseason-map.js, map-core.js) in place —
   no DOM structure or class names it depends on were changed.
   Only used by redesign-preview.html (orphaned, not linked from
   nav or sitemap). Tokens ported from
   design_handoff_sportsmaps_redesign/design/organic-styles.css.
   ============================================================ */

:root {
  /* Reuse the site's existing variable names so every component
     that already reads them re-themes automatically. */
  --color-bg: #f5ead8;
  --color-surface: #ebddc5;
  --color-surface-2: #e3d5b8;
  --color-border: rgba(32,30,29,.14);
  --color-primary: #c67139;      /* terracotta — was brick red */
  --color-primary-dim: rgba(198,113,57,.14);
  --color-accent: #7a8a5e;       /* sage — second voice, used sparingly */
  --color-text: #201e1d;
  --color-text-muted: rgba(32,30,29,.62);
  --color-white: #201e1d;        /* site's "heading ink" token — was navy */
  --font-main: 'Figtree', system-ui, sans-serif;
  --font-heading: 'Caprasimo', system-ui, sans-serif;
  --radius-sm: 10px;
  --radius-md: 16px;
  --radius-lg: 28px;
  --shadow-card: 0 3px 10px rgba(46,43,37,.16);
  --shadow-map: 0 12px 32px rgba(46,43,37,.22);

  /* Extra ramp steps the design system defines that the production
     tokens didn't have a slot for. */
  --color-accent-100: #fff2eb;
  --color-accent-400: #f6a06b;
  --color-accent-600: #b2622d;
  --color-accent-700: #8c491a;
  --color-accent-2-100: #f0fae1;
  --color-accent-2-700: #56633f;
}

body { font-family: var(--font-main); }

/* Headings switch to the display face everywhere the site currently
   just bumps Figtree to weight 900. This list is meant to be a superset
   of styles.css's own big heading selector (the one that sets Playfair
   Display) — any class covered there but missing here silently falls
   back to that old serif face instead of picking up Caprasimo, which is
   exactly what happened to .matchup-caption-title (used on every map
   section caption sitewide, on already-shipped home/listing/team pages)
   before this list was extended to include it. */
.hero-title, .section-title, .logo-text, .footer-brand .logo-text,
.stat-number, .step-number, .map-block-label, .faq-item > summary,
.listing-header-title, .card-title, .about h2, #featuredHeader h1,
#featuredHeader h2, .page-hero-title, .listing-title, .pagination-title,
.archive-strip-title, .article-card-title, .article-prose h2,
.broadcast-explainer-title, .broadcast-explainer-item-title,
.matchup-caption-title, .schedule-section-title, .team-hub-division-title,
.map-block-label-inline, .archive-season > summary,
.embed-title-logo .logo-text {
  font-family: var(--font-heading);
  font-weight: 400;
  letter-spacing: 0;
}
.hero-highlight {
  background: linear-gradient(135deg, var(--color-primary), var(--color-accent-400));
  -webkit-background-clip: text; background-clip: text;
}

/* ===== Buttons + pill controls ===== */
.btn, .county-search-box, .county-search-input, .page-jump-nav-select,
.filter-btn, .nav-search-trigger {
  border-radius: 999px !important;
}
.btn-primary { box-shadow: 0 4px 16px rgba(198,113,57,.35); }
.btn-primary:hover { background: var(--color-accent-600); box-shadow: 0 6px 22px rgba(198,113,57,.4); }
.btn-secondary { border: 1px solid var(--color-border); background: transparent; }
.btn-secondary:hover { background: rgba(32,30,29,.06); }

/* ===== Floating header ===== */
/* .site-header and .page-jump-nav each carry their own position:sticky from
   the base stylesheet (top:0 and top:65px respectively). Two adjacent sticky
   elements whose tops line up back-to-back (0 and this element's own
   height) hit a Chromium rendering quirk: the second one renders a few px
   below its true flush position even with zero margin/padding — confirmed
   with a headless-browser measurement, not guessed. Fix: only ONE ancestor
   (.sticky-chrome, wrapping both in the HTML) is actually sticky now; these
   two are demoted to static so there's no second sticky boundary to hit. */
.sticky-chrome { position: sticky; top: 0; z-index: 1200; }
.site-header, .page-jump-nav { position: static; }
.site-header {
  /* Was top:14px, floating just below the removed preview banner — with
     that banner gone there's nothing above it to float below anymore, so
     this sits flush at the actual top of the screen instead. */
  margin: 0 20px;
  border: none;
  border-radius: 999px;
  background: rgba(249,244,237,.93);
  box-shadow: var(--shadow-card);
  padding-top: 0;
}
.header-inner { height: 58px; }
/* Tried recoloring the favicon into a terracotta-circle mark to match the
   design system's stand-in logo — the filter trick didn't render cleanly
   against the actual favicon asset. Reverted: plain image, same as every
   other page on the site. */
.nav-link, .logo, .footer-nav a { font-family: var(--font-main); }
.nav-social a:hover, .nav-link:hover { color: var(--color-primary); }

/* ===== Nav dropdown — desktop hover menu only. The mobile version (below,
   768px) is a completely different treatment: an always-open flat list in
   the slide-down mobile nav, not a floating hover popover, so none of this
   should apply there. Previously unscoped, which is why the mobile list
   was picking up a boxed/shadowed card look it was never meant to have. ===== */
@media (min-width: 769px) {
  .nav-dropdown-menu { border-radius: var(--radius-md); overflow: hidden; box-shadow: var(--shadow-card); }
  /* .nav-dropdown-menu sits 10px below its trigger (top:calc(100% + 10px) in
     the base stylesheet) with an invisible ::before "bridge" over that gap to
     keep :hover continuous — evidently not enough here, since the menu was
     closing while the cursor crossed it before reaching the links. Removing
     the gap and pushing the content down with padding instead makes the
     hoverable box itself flush against the trigger, so there's no dead zone
     to cross in the first place. */
  .nav-dropdown-menu { top: 100% !important; padding-top: 10px !important; }
}

@media (max-width: 768px) {
  /* MLB/NFL read as small section headings above their indented children,
     not just another link in the list — matches how the rest of the design
     system treats a label sitting above a group (e.g. .map-block-label).
     Terracotta instead of the plain text color ties it to the same accent
     the logo and active states use elsewhere, instead of reading flat. */
  .nav-dropdown > a.nav-link {
    font-weight: 700; color: var(--color-primary); font-size: 1.05rem;
  }
  /* Sub-items as small rounded pills (same pill-hover language as
     .page-jump-nav-link elsewhere in this redesign) instead of the base
     stylesheet's plain indented text list — and even right padding, which
     the base treatment (padding:6px 0 0 14px, zero on the right) didn't
     have, so long labels like "Most-Shown Team" sat flush against the
     list's right edge with no breathing room. Row + wrap instead of the
     base's one-per-line column: five short labels don't need five lines,
     and letting them flow lets the whole group sit in far less vertical
     space — smaller pill padding and a tighter gap compress it further. */
  .nav-dropdown-menu {
    padding: 4px 4px 2px; flex-direction: row; flex-wrap: wrap;
    row-gap: 4px; column-gap: 6px;
  }
  .nav-dropdown-menu a {
    padding: 5px 11px; border-radius: 12px;
    color: rgba(32,30,29,.72); font-weight: 600;
    transition: background var(--transition), color var(--transition);
  }
  .nav-dropdown-menu a:hover, .nav-dropdown-menu a:active {
    background: rgba(32,30,29,.08); color: var(--color-text);
  }
}

/* ===== In-page jump nav — same floating-pill language as the site header,
   just a different fill so the two read as related but distinct bars. ===== */
.page-jump-nav {
  /* No top/sticky here anymore — .sticky-chrome (wrapping this + the
     header) is the only sticky element, so this just sits flush below the
     header in normal flow, always exactly touching it. */
  max-width: var(--container-max); margin: 0 auto; /* same width as the map's container, not viewport-edge like the header */
  padding: 5px 10px;
  background: var(--color-surface);
  border-bottom: none;
  border-radius: 999px;
  box-shadow: var(--shadow-card);
}
.page-jump-nav-inner { gap: 2px; max-width: none; }
.page-jump-nav-link {
  border-radius: 999px !important;
  border: none !important;
  margin-bottom: 0;
  background: transparent;
  color: rgba(32,30,29,.72);
  font-weight: 600;
  padding: 9px 16px;
}
.page-jump-nav-link:hover { background: rgba(32,30,29,.08); color: var(--color-text); }
.page-jump-nav-link.is-active, .page-jump-nav-link[aria-current="true"] {
  background: var(--color-primary); color: var(--color-bg) !important;
}
.page-jump-nav-link + .page-jump-nav-link { border-left: none !important; }

/* The teams hub, archive, broadcast-history, and most-shown-team pages
   all open with .archive-section as (or just inside) the first thing
   after .sticky-chrome — its base 64px top padding was tuned for sitting
   below a plain static header, and reads as a large gap now that the
   header (plus, on 3 of these 4 page types, a jump-nav) floats as a
   compact pill directly above it instead. Two selector forms since the
   DOM varies: archive.html has no <main> wrapper (.archive-section is a
   direct sibling of the header), the other three do. */
.sticky-chrome + main > .archive-section:first-child,
.sticky-chrome + .archive-section { padding-top: 28px; }

/* ===== Hero — compact card, no full-bleed background map this pass ===== */
.hero {
  background: none;
  padding: 16px 0 12px;
}
.hero-inner {
  /* Same width as the map/content container below (var(--container-max),
     already set by the .container class this element also carries) rather
     than a narrower fixed card — a wider box wraps the intro paragraph
     into fewer lines, so the hero takes less vertical space. */
  margin: 0 auto;
  background: rgba(249,244,237,.95);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 14px 40px 12px;
}
.hero-subtitle-toggle { font-family: var(--font-main); font-weight: 600; color: var(--color-primary); }

/* ===== Page hero — same compact-card treatment as .hero above, for the
   NFL/MLB sport home pages, which use .page-hero/.page-hero-inner instead
   (a different template than the main homepage's .hero/.hero-inner, though
   visually it should read as the same design language). Structurally
   .page-hero-inner sits inside its own .container (unlike .hero-inner,
   which *is* the .container), so it's already inset by that parent's own
   padding — no separate mobile width override needed here. ===== */
.page-hero {
  background: none;
  padding: 16px 0 12px;
  border-bottom: none;
}
/* .page-hero-inner sits inside its own .container (unlike the main
   homepage's .hero-inner, which *is* the .container — see that rule's own
   comment) — that container still had the base stylesheet's default
   padding:0 24px, while .map-section > .container's got zeroed out below,
   so the hero card sat 24px narrower than the map/legend row beneath it on
   both sides. Zeroing it here too lines both up on the same outer edges. */
.page-hero > .container { padding-left: 0; padding-right: 0; }
.page-hero-inner {
  background: rgba(249,244,237,.95);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  padding: 14px 40px 12px;
  gap: 6px;
}
.page-hero-title { font-size: clamp(1.4rem, 3.2vw, 2rem); }
.page-hero-subtitle { font-size: .92rem; }
@media (max-width: 768px) {
  .page-hero-inner { padding: 16px 22px 14px; }
}

/* ===== Real Leaflet maps — rounded, contained, slightly shorter so the
   hero + featured map settle inside roughly one viewport and the next
   map (and the ad rail) stay visible as an obvious "keep scrolling" cue. ===== */
.map-wrapper { border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-map); }
.listing-map-canvas { height: 460px !important; }
/* app.js's fullscreen toggle (map-fs-close/.map-fullscreen-active) moves the
   canvas into a position:fixed;inset:0 panel and sets height:100% on it
   inline — but a *plain* inline style loses to an !important rule in a
   stylesheet regardless of specificity, so the height:460/345/315px
   !important rules here (needed everywhere else on the page) were pinning
   the canvas to its normal short height even inside that full-viewport
   panel, leaving the rest of it blank. This is scoped to
   body.map-fullscreen-active specifically (added/removed by the same
   toggle) and has higher specificity than the plain .listing-map-canvas
   rules above/below, so it wins only while actually in fullscreen. */
body.map-fullscreen-active .listing-map-canvas { height: 100% !important; }
/* Base .map-section has padding:0 0 96px (bottom) — sized for the original,
   much airier layout. Way too much once everything else here is tightened
   up, so this cuts it down for both this section (before "NFL Preseason")
   and the preseason maps section (before "How it works") that reuses the
   same class. */
.map-section { background: var(--color-bg); border-top: none; border-bottom: none; padding-bottom: 24px; }
/* .hero-inner's card spans the full container-max width edge to edge (its
   padding is internal to the card, not a reduction of the card's own box),
   but .container's base rule (padding:0 24px) insets everything inside
   this section by 24px from that same edge — the title/map/legend were
   sitting narrower than the hero card above them because of that. Zeroing
   it out here lines both up on the same edges; restored on mobile below so
   content doesn't run flush to the screen there. */
.map-section > .container { padding: 8px 0 0; }
/* The listing title (built by app.js into #featuredHeader) should read as
   attached to the map/legend below it, not evenly spaced between the hero
   card above and the map below — tighter than the hero's own padding
   (.hero's padding-bottom + this container's padding-top, ~20px). */
#featuredHeader .section-header { margin-bottom: 6px !important; }
#featuredHeader .section-title { margin-bottom: 0 !important; }
/* Second (and any further) listing shown on the home page — through an
   MLB/NFL overlap month the root page carries both sports' latest listings,
   and each needs the same title above its own maps. #featuredHeader is the
   static slot the leading listing renders into; app.js builds an identically
   shaped .featured-listing-header into #featuredMaps for the rest, so the
   two match here. The rule above can't just be extended to cover it: that one
   is an id selector and this is a class, so they'd need different specificity
   for the same !important declarations anyway. */
.featured-listing-header .section-header { margin-bottom: 6px !important; }
.featured-listing-header .section-title { margin-bottom: 0 !important; }
/* #featuredMaps's flat 10px gap is tuned for map → description → image row
   within one listing; crossing from one listing's last image row into the
   next listing's title needs to read as a real break instead. Same
   space/line/space treatment the multi-map NFL home page uses between days
   (#latest-map > .container > .map-block + .map-block, below). */
.featured-listing-header {
  margin-top: 26px; padding-top: 30px;
  border-top: 1px solid rgba(32,30,29,.12);
}
.map-block-label { margin-bottom: 10px; }
.map-hint { color: var(--color-text-muted); }
.map-game-pill.is-active { border-radius: 999px; }
/* "NFL Preseason Week 3 — TV Coverage Maps" was using the default
   .section-title size (clamp(1.6rem,3vw,2.2rem), from the base stylesheet)
   while "FOX MLB Saturday..." gets a smaller, specific override
   (#featuredHeader .section-title, above) — matching that here so the two
   read as the same weight of heading. */
/* #latest-map added alongside #preseason-maps so the same treatment applies
   on NFL's own home page (nfl-redesign-preview.html), which reuses this
   same preseason-map markup under a different section id. Doesn't collide
   with MLB's home page, which also uses #latest-map but never has a
   .section-title/.archive-intro directly in it — these selectors just
   don't match anything there. */
#preseason-maps .section-title, #latest-map .section-title { font-size: clamp(1.28rem, 2.4vw, 1.76rem); margin-bottom: 0 !important; }
#preseason-maps .section-header, #latest-map .section-header { margin-bottom: 6px !important; }
/* "Grey counties have no locally broadcast game..." — redundant with the
   legend panel's own swatches/labels and the "hover or tap" copy already
   removed from below the map; not needed. */
#preseason-maps .archive-intro, #latest-map .archive-intro { display: none; }

/* scroll-margin-top on an anchor target reduces how far the browser
   actually scrolls (target's scrollY = its position in the document minus
   this value) — needs to closely match .sticky-chrome's real rendered
   height (measured with a headless browser: ~107px desktop, ~105px mobile)
   so the target lands flush just below it. Too small and the target is
   clipped under the chrome; too large (124px, the previous value here) and
   it leaves a visible floating gap instead of sitting flush. 110px was
   measured (clicking every jump-nav link, headless) to land each target
   within ~2-6px of the chrome's bottom edge on both breakpoints. */
[id^="map-section-"], #preseason-thu, #preseason-fri, #preseason-sat, #featuredHeader, #schedule {
  scroll-margin-top: 110px;
}
/* Reverted: the 90px added here for the #preseason-sat scroll-anchor issue,
   stacked on top of .how-it-works's own 96px top padding, produced the
   ~185px empty gap flagged in review — worse than the problem it was
   trying to fix, and speculative to begin with (How It Works/About/FAQ/the
   footer already provide plenty of trailing content). Back to the shared
   24px from .map-section. If the Saturday jump-nav link still stops short,
   that needs a real look rather than another padding guess — most likely
   fix would be a smaller scroll-margin-top specifically on that one
   target, not more trailing space. */
/* The three preseason map blocks came with an inline margin-bottom:3rem
   each (redesign-preview.js strips it) — replaced with a slightly airier
   gap plus a hairline divider (space/line/space) to visually separate one
   day's map from the next, rather than just relying on whitespace alone.
   #latest-map > .container > .map-block is NFL's own home page's version
   of this same three-map layout — the child combinators (not just a
   descendant selector) matter here: NFL's blocks sit directly in
   #latest-map's .container, one level shallower than MLB's home page,
   whose map-blocks are nested inside #featuredMaps instead. That
   difference is what keeps this scoped to NFL's multi-map days without
   also adding a big divider between MLB's — which already gets its own,
   smaller #featuredMaps{gap:10px} spacing for the rare doubleheader. */
#preseason-maps .map-block + .map-block,
#latest-map > .container > .map-block + .map-block {
  margin-top: 36px; padding-top: 34px;
  border-top: 1px solid rgba(32,30,29,.12);
}

/* #featuredMaps is flex column with a 3rem (48px) gap between its children
   in the base stylesheet — way too airy now that the map/description/image
   row all sit close together. .map-block, .broadcast-description-section
   and .map-fullres-details (below) are its direct children, so this one
   rule controls all the spacing between them. */
#featuredMaps { gap: 10px; }

/* Coverage map description — native <details> so it stays crawlable
   regardless of open/closed state (same approach as the FAQ). No margin of
   its own — spacing between it, the map, and the image row below all comes
   from #featuredMaps's gap above, so it stays consistent instead of adding
   up with it. */
.broadcast-description-section {
  margin-top: 0 !important;
  border: none; border-left: none;
  border-radius: var(--radius-md);
  background: #f9f4ed;
}
.broadcast-description-section > .broadcast-description-header {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-family: var(--font-heading); font-weight: 400;
  font-size: 15px; text-transform: none; letter-spacing: 0;
  color: var(--color-text); margin-bottom: 0 !important;
}
/* "Coverage Map Description"'s static markup wraps its text in <strong>;
   "Full-resolution map images" (built via textContent in the *-redesign-
   preview.js scripts) doesn't. Browsers bold <strong> by default regardless
   of the font-weight:400 above (a real UA rule on the tag itself beats
   simple inheritance from its parent), so the two headers rendered at
   different weights even though both target this same class. */
.broadcast-description-section > .broadcast-description-header strong { font-weight: inherit; }
.broadcast-description-section > .broadcast-description-header::-webkit-details-marker { display: none; }
.broadcast-description-section > .broadcast-description-header::after {
  content: '▾'; flex: none; font-size: 22px; line-height: 1; color: var(--color-primary);
}
.broadcast-description-section[open] > .broadcast-description-header::after { content: '▴'; }
.broadcast-description-section > .broadcast-description-list { margin-top: 12px; }

/* Team page "What's on this page?" explainer — was a row of tab buttons
   plus one shared description box below (all three tools' worth of chrome
   visible even though only one panel showed at a time), consolidated into
   a row of native <details>, all collapsed by default. All descriptions
   stay in the page source regardless of open/closed state, same as
   .broadcast-description-section above, so nothing is lost for SEO.
   Each item's body is positioned absolutely against .team-tool-accordion
   itself (not its own <details>, which has no positioning context of its
   own) so the opened dropdown spans the full row width — edge to edge
   with the map/legend below, per the design — instead of staying
   confined to its own ~1/3-width column. Only one item is meant to be
   open at a time (team-redesign-preview.js enforces that and reserves
   the extra space below the row so it doesn't overlap the next
   section), since two open dropdowns would render on top of each other
   at this shared position otherwise. */
.team-tool-accordion { display: flex; align-items: flex-start; gap: 8px; margin-top: 14px; position: relative; }
.team-tool-item {
  flex: 1; min-width: 0;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface);
}
.team-tool-item > summary {
  cursor: pointer; list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 18px;
  font-family: var(--font-heading); font-weight: 400;
  font-size: 15px; color: var(--color-text);
}
.team-tool-item > summary::-webkit-details-marker { display: none; }
.team-tool-item > summary::after {
  content: '▾'; flex: none; font-size: 18px; line-height: 1; color: var(--color-primary);
}
.team-tool-item[open] > summary::after { content: '▴'; }
.team-tool-item[open] > summary { border-color: var(--color-primary); }
.team-tool-item > p {
  position: absolute; left: 0; right: 0; top: 100%;
  margin: 8px 0 0; padding: 14px 18px;
  border: 1px solid var(--color-border); border-radius: var(--radius-md);
  background: var(--color-surface);
  font-size: .9rem; color: var(--color-text-muted); line-height: 1.7;
}
.team-tool-item > p a { color: var(--color-primary); font-weight: 600; }
/* Mobile used to stack these as three full-width cards (~250px+ of
   vertical space before anything was even opened). Now it keeps the
   same row layout as desktop — three compact tabs, label over the
   arrow, answer still positioned absolutely below the whole row (see
   base rule above) so opening one doesn't push the others around.
   team-redesign-preview.js's updateSpacing() now runs at every width
   (not just >700px) to reserve room for that absolutely-positioned
   panel here too. */
@media (max-width: 700px) {
  /* stretch so all three items share the tallest one's natural
     height, instead of each sizing to its own (shorter) label */
  .team-tool-accordion { gap: 6px; align-items: stretch; }
  .team-tool-item { display: flex; }
  .team-tool-item > summary {
    flex: 1;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    padding: 8px 6px;
    font-size: .78rem;
    line-height: 1.15;
    text-align: center;
  }
  .team-tool-item > summary::after { font-size: 14px; }
  .team-tool-item > p { font-size: .85rem; padding: 12px 14px; }
}

/* Mobile hero-listing banner — a 320x100 ad slot placed just below the
   hero on mobile only (<768px). Originally homepage-only (inline
   <style> there still carries its own copy of this same rule, loaded
   later in that page's cascade so it keeps winning there); defined
   here too so the identical unit can be reused on the team pages
   without duplicating markup+CSS into three template files. */
.mobile-listing-ad-wrap { display: none; }
@media (max-width: 767px) {
  .mobile-listing-ad-wrap { display: flex; justify-content: center; width: 320px; max-width: calc(100% - 32px); margin: 12px auto; padding: 0; overflow: hidden; max-height: 200px; }
}

/* ===== How it works / About / FAQ ===== */
.step-card { border: none; background: var(--color-surface); }
.step-card:hover { border-color: transparent; box-shadow: var(--shadow-card); }
.stat-card, .stat-card:first-child { border: none; background: var(--color-surface); }
/* margin:0 24px made this section only 48px narrower than the full
   viewport — at wide viewports that's much wider than the map/legend/hero
   (all capped at var(--container-max)), so it visually ran into the
   side-rail ad zones sitting just outside that container. Matching the
   same max-width/centering as everything else keeps it contained. */
.about { max-width: var(--container-max); margin: 0 auto; background: var(--color-surface); border-radius: var(--radius-lg); padding: 32px 40px; }
.about .container { max-width: none; padding: 0; }
/* The left column (two paragraphs + a 4-item checklist) is naturally taller
   than the right (three short stat lines), and .about-inner centers the
   shorter column within that height — leaving a big block of empty space
   under the stats specifically (see review screenshot). Spreading the two
   stat rows further apart uses more of that height productively instead of
   just leaving it blank. */
.about-visual { row-gap: 40px; column-gap: 16px; } /* only the vertical gap grows — the two side-by-side stats keep their original spacing */
/* .about-inner is normally a 2-column grid (text + a .about-visual
   companion like stat cards or an embedded map), but several sections
   across the site (how-it-works.html's "Why It Goes Down to the County
   Level", about.html's "How Maps Are Made", plus contact/terms/
   privacy-policy) reuse the same .about-content markup with no
   .about-visual at all — some still wrapped in .about-inner, some just a
   plain .container. Either way .about-content was left capped by its own
   inline max-width:680px (and, when .about-inner was present, additionally
   confined to the grid's first column with the second column sitting
   empty) — narrow text taking up far more vertical space than it needed
   to. Sibling-detected via :has() rather than a page-specific class so any
   future single-column .about section gets this automatically regardless
   of which of the two wrapper patterns it uses. */
.about-inner:has(> .about-content:only-child) { grid-template-columns: 1fr; }
.about-content:not(:has(~ .about-visual)) { max-width: none !important; }
.faq-item { border: none; background: #f9f4ed; }

/* ===== Footer — dark chrome to match the design system ===== */
.site-footer {
  background: #2e2b25;
  color: rgba(245,234,216,.7);
  border-top: none;
  margin-top: 48px;
}
.site-footer .footer-brand .logo-text,
.site-footer .footer-nav a,
.site-footer .footer-social-label,
.site-footer .footer-legal a {
  color: rgba(245,234,216,.85);
}
.site-footer .logo-text strong { color: var(--color-accent-400); }
.site-footer .footer-tagline,
.site-footer .footer-bottom p { color: rgba(245,234,216,.55); }
/* The OpenStreetMap attribution link inside .footer-bottom p isn't
   covered by that rule above — color doesn't cascade from a parent's
   rule to a child's own more-specific one, and styles.css sets
   `.footer-bottom a { color: var(--color-text-muted) }` directly on it,
   a dark color meant for the light page background, nearly invisible on
   this dark footer. Same story for its :hover (styles.css's
   `--color-white` is a dark navy, not literally white). */
.site-footer .footer-bottom a { color: rgba(245,234,216,.7); }
.site-footer .footer-nav a:hover,
.site-footer .footer-legal a:hover,
.site-footer .footer-bottom a:hover { color: var(--color-accent-400); }
.site-footer .nav-social a, .site-footer .footer-social-icons a { color: rgba(245,234,216,.7); }
.site-footer .footer-social-icons a:hover { color: var(--color-accent-400); }
.site-footer .footer-bottom { border-top: 1px solid rgba(245,234,216,.12); }

@media (max-width: 768px) {
  /* Previously flush/square (margin:0, border-radius:0) on both, as a
     workaround for the header/jump-nav gap — that gap turned out to be a
     sticky-positioning rendering quirk (fixed above via .sticky-chrome),
     not something needing square edges to hide. Both keep their rounded
     floating-pill look on mobile too now, just with a tighter side margin. */
  /* Less rounded than desktop's full 999px pill — a floating pill that
     narrow reads oddly at full-width mobile scale, but still visibly
     rounded rather than square. */
  .site-header, .page-jump-nav { border-radius: 16px; }
  .site-header { margin: 0 10px; }
  .page-jump-nav { padding: 4px 8px; margin: 0 auto; max-width: calc(100% - 20px); }
  .page-jump-nav-link { padding: 7px 12px; font-size: 13px; }
  /* margin:0 16px *should* center this symmetrically, but width:calc()+
     margin:auto is the more robust way to get a centered box at a fixed
     inset — used here instead since the fixed-margin version was reported
     as visibly off-center. */
  .hero-inner { width: calc(100% - 32px); margin: 0 auto; padding: 16px 22px 14px; }
  .map-section > .container { padding: 8px 16px 0; } /* matches .hero-inner's 16px mobile inset */
  /* .page-hero > .container was zeroed out above (desktop) to match
     .map-section > .container's own zeroed padding — but .map-section's
     container regains 16px horizontal padding here on mobile, so this
     needs to match that back, or .page-hero-inner would span edge-to-edge
     while the map/legend row sits inset by 16px. */
  .page-hero > .container { padding-left: 16px; padding-right: 16px; }
  /* .listing-map-canvas and .map-overlay-panel heights are set below, in
     the max-width:900px block — that condition is a superset of this one
     (768px implies 900px), so those rules win here too; no point repeating
     different numbers in both places. */
  .about { margin: 0; border-radius: 0; padding: 32px 20px; }
}

@media (max-width: 600px) {
  /* Below this the base stylesheet swaps .page-jump-nav-inner's link row
     for a single native <select> (.page-jump-nav-inner{display:none},
     .page-jump-nav-select-wrap{display:block}). Overridden below: on
     mobile the links should stay a single horizontal row instead, since
     .page-jump-nav-inner already comes with overflow-x:auto + nowrap
     links from the base stylesheet (built for exactly this), and
     jump-nav-active.js already toggles .is-active on these same <a> elements
     regardless of whether they're visible — so keeping them shown is all
     that's needed to get scroll-highlighting on mobile for free. */
  .page-jump-nav-inner { display: flex !important; }
  .page-jump-nav-select-wrap { display: none !important; }
  .page-jump-nav-inner { padding: 2px 4px; }
  .page-jump-nav-link { padding: 7px 11px; font-size: 12.5px; }
}

/* ===== Hero map legend panel =====
   Built by js/redesign-preview.js, which relocates the already-wired
   .county-search-wrap and .map-game-pills nodes app.js built for the hero
   map into this panel — no app.js logic duplicated or touched.
   Sits BESIDE the map (not overlapping it) as a same-height flex sibling —
   .map-wrapper.has-map-overlay becomes the row, .map-canvas-col (wrapping
   the real canvas + its loading spinner) is the other side. The built-in
   bottom-left Leaflet legend is redundant once the panel exists (its
   matchup rows do the same job with a search bar and locate button added),
   so it's hidden only on the wrapper the panel was attached to. */
.map-wrapper.has-map-overlay {
  display: flex; align-items: stretch; gap: 14px;
  /* The base .map-wrapper rule above rounds/clips/shadows the whole row as
     one card — here the panel and the map are each their own rounded card
     instead (so the panel's right side, facing the map, is rounded too,
     not just its outer left edge), so the wrapper itself goes flat. */
  border-radius: 0; overflow: visible; box-shadow: none; border: none;
}
.map-wrapper.has-map-overlay .leaflet-bottom.leaflet-left { display: none; }
.map-canvas-col {
  position: relative; z-index: 1; flex: 1 1 auto; min-width: 0;
  border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-map);
}
/* .listing-map-canvas keeps its fixed height from the rule above — that
   height becomes .map-canvas-col's auto height, and flexbox's default
   align-items:stretch then matches .map-overlay-panel to it, which is what
   makes the panel "the same height as the map" without any % trickery. */

/* app.js's geolocation banner and matchup search — both superseded by the
   panel's search box + "Use my location". !important because app.js sets
   #local-game-banner's display via inline style (higher specificity than a
   plain class/ID rule here) once geolocation kicks off. */
#topSearchRow { display: none !important; }
/* "View Full Listing" + archive-link box — superseded by the panel title
   itself linking to the listing page (see redesign-preview.js). !important
   for the same reason: app.js sets its display via inline style. */
#featuredFooter { display: none !important; }

.map-overlay-panel {
  /* Its own rounded card now (gap + independent radius/shadow instead of
     the wrapper's single clipped card + a divider line), so its right
     side — facing the map — is rounded too, not just the outer left edge. */
  flex: 0 0 232px; width: 232px;
  /* Flexbox stretch alone only grows a shorter panel up to the map's height
     — it doesn't stop a panel with more content (e.g. a preseason map with
     4+ matchups plus national-broadcast notes) from growing taller than
     the map and dragging the whole row down with it. Capping height to
     match .listing-map-canvas's 460px turns that overflow into an internal
     scroll on .map-overlay-body instead (overflow-y:auto, below). */
  max-height: 460px;
  display: flex; flex-direction: column;
  background: #f9f4ed; border-radius: var(--radius-lg); box-shadow: var(--shadow-card);
  overflow: hidden; font-family: var(--font-main);
  transition: flex-basis .2s ease, width .2s ease;
}
.map-overlay-header {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 16px 16px 0;
}
.map-overlay-kicker {
  /* Holds the real map window label (e.g. "FOX - 7:15 p.m. ET"), not a
     short eyebrow, so no uppercase/letter-spacing treatment here. Links to
     this map's individual listing page (see redesign-preview.js) in place
     of the separate "View Full Listing" button/box, so it needs its own
     hover affordance since nothing else marks it as clickable. */
  flex: 1; min-width: 0;
  font: 700 15px/1.25 var(--font-main); /* bigger than the rest of the panel's text (13px search/matchup) */
  color: var(--color-primary); overflow-wrap: break-word;
  text-decoration: none;
}
a.map-overlay-kicker:hover { text-decoration: underline; text-underline-offset: 2px; }
.map-overlay-toggle {
  flex: none; width: 26px; height: 26px; border-radius: 999px; border: none;
  background: rgba(32,30,29,.08); color: var(--color-text);
  display: grid; place-items: center; cursor: pointer; padding: 0;
}
.map-overlay-toggle:hover { background: rgba(32,30,29,.15); }
.map-overlay-toggle svg { display: block; transition: transform .2s ease; }
.map-overlay-panel.is-collapsed .map-overlay-toggle svg { transform: rotate(180deg); }

.map-overlay-body { flex: 1; display: flex; flex-direction: column; padding: 14px 16px 18px; overflow-y: auto; }
.map-overlay-panel.is-collapsed { flex-basis: 48px; width: 48px; }
.map-overlay-panel.is-collapsed .map-overlay-header { padding: 10px 0; justify-content: center; }
.map-overlay-panel.is-collapsed .map-overlay-kicker,
.map-overlay-panel.is-collapsed .map-overlay-body { display: none; }

.map-overlay-matchups { margin-top: 14px; }
.map-overlay-matchups .map-game-pills { display: flex; flex-direction: column; gap: 5px; margin: 10px 0 0; }
.map-overlay-matchups .map-game-pill {
  /* Centered now, not flex-start — that offset was there to keep the swatch
     pinned to the top when a two-line label sat over a count line below it.
     No count line anymore, so center reads better for the (usually) one-line
     case and still looks fine if a long matchup name wraps to two. */
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 6px 9px; margin: 0; border-radius: 11px;
  background: rgba(32,30,29,.05);
}
.map-overlay-matchups .map-game-pill:hover { background: rgba(32,30,29,.09); }
.map-overlay-matchups .map-game-pill-swatch { width: 10px; height: 10px; flex: none; }
.map-overlay-matchups .map-game-pill-content { display: flex; flex-direction: column; min-width: 0; }
.map-overlay-matchups .map-game-pill-label {
  font-size: 13px; line-height: 1.25; font-weight: 600;
  color: var(--color-text); /* base .map-game-pill sets the muted color; this reads too light at this size/weight */
}
.map-overlay-matchup-note {
  margin-top: 6px; font-size: 12px; line-height: 1.4; color: var(--color-text-muted);
  text-wrap: balance; /* spreads words evenly across lines instead of risking a lone word stranded on the last one */
}

/* Individual listing pages (listing.js) never build a .map-game-pills
   element — they only call SMMapCore.buildLegend(), so their matchup list
   only ever exists as Leaflet's own .map-legend corner control.
   listing-redesign-preview.js relocates that whole control into
   .map-overlay-matchups instead of a pills div (see its own comment for
   why moving the node, not rebuilding it, is what keeps its click-to-
   highlight behavior working) — restyled here to read as the same pill
   list as everywhere else, overriding the base stylesheet's corner-control
   look (small scaled-down card, float-based icon layout). */
.map-overlay-matchups .map-legend {
  transform: none !important; position: static !important;
  background: transparent !important; border: none !important;
  box-shadow: none !important; padding: 0 !important; border-radius: 0 !important;
  font-size: 13px !important;
}
.map-overlay-matchups .map-legend-header { display: none; } /* redundant with the panel's own title above */
.map-overlay-matchups .map-legend-body { max-height: none; overflow: visible; }
.map-overlay-matchups .map-legend-hint {
  display: block; margin: 0 0 8px; font-size: 12px; font-style: normal;
  text-transform: none; letter-spacing: 0; color: var(--color-text-muted); opacity: .8;
}
.map-overlay-matchups .map-legend-row {
  display: flex; align-items: center; gap: 7px; width: 100%;
  padding: 6px 9px; margin: 0; border-radius: 11px;
  background: rgba(32,30,29,.05); font-weight: 600; color: var(--color-text);
}
.map-overlay-matchups .map-legend-row + .map-legend-row { margin-top: 4px; }
.map-overlay-matchups .map-legend-row:hover { background: rgba(32,30,29,.09); }
.map-overlay-matchups .map-legend-row.is-active { background: var(--color-primary-dim); }
.map-overlay-matchups .map-legend-row.is-dimmed { opacity: .45; }
.map-overlay-matchups .map-legend-row i {
  float: none; width: 10px; height: 10px; margin: 0; flex: none; border-radius: 50%;
}

.map-overlay-search .county-search-wrap { width: 100%; margin-bottom: 10px; }
.map-overlay-search .county-search-box {
  background: var(--color-bg); height: 42px; padding: 0 12px; box-sizing: border-box;
}
.map-overlay-search .county-search-input { font-size: 13px; line-height: 1.3; }
/* Base search results put the county name and its game side by side on one
   line, both truncated with an ellipsis if they don't fit — fine at the
   search box's original width, but this panel is much narrower, so both
   were getting cut off (see review screenshot). Rather than widen or move
   the panel, stack each result: full county name on its own row (wrapping
   instead of truncating), game info on a second row below it. Trades
   unused vertical space in the dropdown for the horizontal space this
   panel doesn't have. */
.map-overlay-search .county-search-result {
  flex-direction: column; align-items: flex-start; gap: 4px;
  padding: 10px 14px;
}
.map-overlay-search .county-search-result-name {
  white-space: normal; overflow: visible; text-overflow: clip;
  flex: none; width: 100%; line-height: 1.3;
}
.map-overlay-search .county-search-result-game-wrap { max-width: 100%; width: 100%; }
.map-overlay-search .county-search-result-game {
  white-space: normal; overflow: visible; text-overflow: clip; line-height: 1.3;
}

.map-overlay-locate {
  width: 100%; justify-content: center; font-size: 13px; white-space: nowrap;
  height: 42px !important; padding: 0 16px; box-sizing: border-box; /* matches the search box's height */
  flex: 0 0 auto;
}
.map-overlay-locate:disabled { opacity: .55; cursor: default; }
.map-overlay-locate-status {
  margin-top: 8px; font-size: 11.5px; line-height: 1.5; color: var(--color-text-muted); min-height: 1px;
}

/* Side-by-side only makes sense once there's enough width for the map to
   still read as a map next to a fixed-width panel. Below that, the map
   takes the full width, and the legend goes back into normal document flow
   below it (column-reverse, since the panel is actually the first DOM
   child) instead of floating on top of it — just overlapping its very top
   edge by a few pixels (negative margin-top + a higher z-index than the
   map, so it paints over that sliver rather than under it) for a tucked-
   together look, not a large covering overlay. No more collapsibility
   here either — with so little of the map actually covered, there's much
   less reason to put the panel away. */
@media (max-width: 900px) {
  .listing-map-canvas { height: 345px !important; } /* ~25% shorter than the 460px this started at */
  .map-wrapper.has-map-overlay { display: flex; flex-direction: column-reverse; }
  .map-canvas-col { width: 100%; }
  .map-overlay-panel {
    /* -46px (see prior note: -26px plus ~10% of the panel's own rendered
       height) plus another 5% pushed further up top and, via
       .map-overlay-body's padding-bottom below, another 5% added at the
       bottom too — both estimated off the same ~180-190px typical
       content-driven height (content-driven, so no fixed value to measure
       against; ~9-10px per 5% step). */
    position: relative; z-index: 10; margin-top: -56px; /* clearly above .map-canvas-col's z-index:1 */
    width: auto; flex: none;
    /* Was content-driven with no cap (max-height:none) — heights ranged
       from ~192px (2 matchups) to ~440px (10 matchups) across the four
       maps, measured with a headless browser. A flat fixed height fixed
       the inconsistency but left dead empty space under short matchup
       lists — capping instead lets each panel shrink to fit its own
       content while sharing the same ceiling: search row + padding
       (~130px) + 4.5 pill rows (27px each + 4px gap = 31px/row) ≈ 270px.
       Panels under that show exactly their content, no more; panels over
       it cap at 270px and scroll inside .map-overlay-body
       (overflow-y:auto, already in place) — the partial 5th row there is
       a deliberate "there's more, keep scrolling" cue. */
    max-height: 270px;
    border-radius: var(--radius-lg);
  }

  /* Title + toggle both live in here — title's redundant with the heading
     already sitting above the map (#featuredHeader / .map-block-label,
     never hidden), and collapsibility is gone on mobile entirely (desktop
     keeps both, see redesign.css's non-mobile rules). Removing this frees
     up real vertical space (not just visually — the panel is a flex
     column, so a display:none header doesn't leave a gap behind it). */
  .map-overlay-header { display: none; }
  .map-overlay-body { padding-top: 12px; padding-bottom: 28px; } /* base is 18px — +10px extends the card's bottom edge to match the extra pushed in at the top */

  /* Search bar + locate button docked beside it instead of stacked — the
     wrapping div is added in redesign-preview.js and does nothing on
     desktop (plain block, same as before); this is what turns it into a
     row here. Locate button loses its label and becomes an icon-only
     circle to make room, same height as the compressed search box. */
  .map-overlay-search-row { display: flex; align-items: center; gap: 8px; }
  .map-overlay-search-row .map-overlay-search { flex: 1; min-width: 0; margin-bottom: 0; }
  .map-overlay-search-row .county-search-wrap { margin-bottom: 0; }
  /* iOS/Android zoom the whole page in on focus when a text input's
     computed font-size is under 16px — true of the 13px set above, sized
     for the desktop panel's tighter width. Bumping just this input back to
     the 16px floor on mobile stops that zoom from happening at all, rather
     than trying to zoom it back out afterward. */
  .map-overlay-search .county-search-input { font-size: 16px; }
  .map-overlay-locate {
    flex: none; width: 42px; height: 42px !important; padding: 0; border-radius: 999px;
  }
  .map-overlay-locate span { display: none; }

  /* Matchups on one line each — the manual <br> (inserted in
     redesign-preview.js, useful in the ~230px desktop sidebar) is
     suppressed by hiding the <br> itself; white-space:nowrap stops the
     browser picking its own wrap point instead, and the smaller font plus
     an ellipsis fallback cover names that still don't fit even at full map
     width. Freed-up row height also tightens the gap between rows. */
  .map-overlay-matchups { margin-top: 10px; }
  .map-overlay-matchups .map-game-pills { gap: 4px; }
  .map-overlay-matchups .map-game-pill-label br { display: none; }
  .map-overlay-matchups .map-game-pill-label {
    font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }

  /* The map's own "embed this map" button (bottom-right Leaflet control) —
     not something worth the tap target on a phone-sized map. Scoped to
     .map-canvas-col (the main-site overlay-map layout) so it doesn't also
     hide the button inside embed.html's own iframe, which reuses this same
     control class but has no .map-canvas-col ancestor — that collateral hit
     was killing the embed button on every real-world embed under 900px wide. */
  .map-canvas-col .leaflet-control-embed { display: none !important; }
  /* Leaflet's own attribution control lives inside .map-canvas-col, which
     as a whole paints *under* .map-overlay-panel (z-index:2 above) — a
     child's own z-index can't escape its parent's stacking level, so
     bumping the attribution's z-index alone wouldn't help while it's still
     nested in there. redesign-preview.js physically moves it out to be a
     sibling of the panel instead; this just positions it where it
     visually was and keeps it above the panel in their small overlap. */
  .leaflet-control-attribution.map-overlay-attribution {
    /* bottom:0 — .map-overlay-panel is the last thing in the (column-
       reverse) flex column, so the wrapper's own bottom edge is exactly
       the panel's bottom edge; flush against that lines this up with the
       legend's bottom line instead of floating above it. */
    position: absolute; z-index: 20; bottom: 0; left: 50%; transform: translateX(-50%); /* above .map-overlay-panel's z-index:10 */
    background: rgba(255,255,255,.7) !important; font-size: 10px !important; padding: 0 4px !important;
    white-space: nowrap;
  }

  /* Reverted the force-to-one-line treatment (clamp + nowrap + ellipsis) —
     wrapping to two lines is fine; these just run a bit smaller than their
     normal size on mobile. */
  #featuredHeader .section-title,
  .featured-listing-header .section-title,
  #preseason-maps .section-title {
    font-size: 19px !important;
  }
  .map-block-label {
    font-size: 16px;
  }
}

@media (max-width: 480px) {
  .listing-map-canvas { height: 315px !important; } /* ~25% shorter than the 420px this started at */
}

/* ===== Individual listing pages =====
   .listing-games-list (a plain bulleted list of the same matchups, right
   under the title) is redundant now that every map's own legend panel
   shows the same games with the same color swatches — hidden via CSS
   rather than removed in JS since listing.js rebuilds .listingHeader's
   entire innerHTML (including this list) whenever it re-renders, so a JS
   removal would just get overwritten. */
.listing-games-list { display: none; }
/* Breadcrumb ("‹ MLB Home") is redundant now that the jump-nav carries the
   same sport-home link (plus Previous/Next/Archive); the badges + separate
   date row is redundant too, since listing-redesign-preview.js folds the
   date directly into .listing-title's own text instead. Both stay in the
   static/JSON-LD markup (breadcrumb structured data, badge semantics) —
   only the visual presentation is hidden here. */
.listing-breadcrumb, .listing-title-row { display: none; }
.listing-title { margin-bottom: 20px; } /* was margin-bottom:0 on .listing-header + margin-bottom:14/20px on the title itself, tuned for the badges/date row sitting right above it — a bit more breathing room now that it's the first thing in the card */
/* Previous/Next cards and the "More Maps" related grid are both redundant
   now that the jump-nav carries Previous/Next/Archive links itself (see
   listing-redesign-preview.js's ensureJumpNav()). */
.listing-pagination, .related-maps-section { display: none; }
/* .listing-maps carries the base .container class directly (like
   .hero-inner does — <div class="listing-maps container">, not a separate
   nested container the way .map-section's is) — so it kept the base
   stylesheet's default padding:0 24px, 48px narrower than the home pages'
   map area (whose .map-section > .container padding was zeroed out
   earlier). Confirmed by measuring the actual rendered map container:
   754px here vs. 802px on the MLB home page at the same viewport. That
   width feeds directly into getBoundsZoom() and the pixel-space
   CONTROL_CLEARANCE_PX/zoom-boost shift in listing-redesign-preview.js —
   both tuned against the home pages' 802px width — so the narrower
   container was computing a different fit and shifting by the same
   absolute pixel amount against a smaller frame, throwing off zoom and
   centering even though the underlying lat/lng math was identical. */
/* .listing-header (wraps .listing-title) has the exact same
   class="... container" pattern and was sitting 24px right of .listing-maps'
   now-zeroed left edge — title reading as misaligned from the map/legend
   below it. Same fix, same element pair. */
.listing-maps.container, .listing-header.container { padding-left: 0; padding-right: 0; }
@media (max-width: 768px) {
  /* .map-section > .container keeps 16px horizontal padding on mobile
     (not zeroed like desktop) to match .hero-inner's own mobile inset —
     same treatment here for the same reason. */
  .listing-maps.container, .listing-header.container { padding-left: 16px; padding-right: 16px; }
}
