@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/cormorant-garamond.woff2") format("woff2");
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}

@font-face {
  font-family: "Alegreya Sans";
  src: url("../fonts/alegreya-sans-regular.ttf") format("truetype");
  font-style: normal;
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Alegreya Sans";
  src: url("../fonts/alegreya-sans-bold.ttf") format("truetype");
  font-style: normal;
  font-weight: 700;
  font-display: swap;
}

:root {
  --text: #000;
  --accent: #d6432c;
  --muted: rgba(0, 0, 0, 0.6);
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  padding: 0;
  font-family: "Alegreya Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  color: var(--text);
  background: #111;
  /* Any accidental horizontal overflow (even from an off-screen fixed
     element, like .scroll-anchor below) lets iOS Safari rubber-band the
     whole viewport sideways — fixed elements then visibly drift since they
     move with that bounce. Belt-and-suspenders on top of fixing the actual
     source. */
  overflow-x: hidden;
}

/* Fixed, faded map that sits behind everything. White background shows
   through the (semi-transparent) tile layer below — see .leaflet-tile-pane. */
#map-bg {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  background: #fff;
  background: rgb(240,240,240);
}

#map {
  width: 100%;
  height: 100%;
  background: transparent; /* override Leaflet's default #ddd container background */
}

/* Fade only the base tiles — not the route line or markers, which live in
   Leaflet's separate overlay/marker panes and should stay fully vivid so
   they stand out clearly above the muted map underneath.
   Real alpha blending (opacity revealing #map-bg's white behind it) rather
   than a white ::after overlay: .leaflet-tile-pane has no real box of its
   own (Leaflet only positions the individual tile images inside it), so an
   overlay element sized off that pane collapses to 0x0 and silently renders
   nothing. opacity/filter apply to the painted pixels regardless of box
   size, so they don't hit that problem — and unlike brightness(), opacity
   blends linearly toward white instead of multiplying (which clips
   already-light tiles straight to solid white).
   0.45 opacity here == the original rgba(255,255,255,0.55) overlay math. */
#map .leaflet-tile-pane {
  filter: saturate(1.8) contrast(.75);
  opacity: 0.7;
}

/* Scrolling content sits above the map */
#content {
  position: relative;
  z-index: 1;
  width: 100%;
}

.hero {
  min-height: 60vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  text-align: left;
  padding: 4vh 6vw;
  color: var(--text);
}

.hero h1 {
  font-family: "Cormorant Garamond", Georgia, serif;
  font-weight: 500;
  font-size: clamp(2.875rem, 8vw, 4.75rem);
  line-height: 0.95;
  margin: 0 0 1rem;
  letter-spacing: -0.03em;
  color: var(--text);
}

/* Cormorant Garamond's arrow glyph reads thin/awkward at this size —
   borrow Alegreya Sans's for just the arrow, rest of the headline stays
   serif. */
.hero h1 .arrow {
  font-family: "Alegreya Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
}

.hero .subtitle {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
  margin: 0;
}

/* "See the whole trip" — appended as a real DOM node right after the
   subtitle's text (js/app.js), not baked into the text string, so it
   stays a real clickable element rather than an emoji/glyph. Sized/
   colored to sit inline with the subtitle text it follows. */
#fit-bounds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  height: 1.1em;
  margin-left: 0.4em;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  cursor: pointer;
  vertical-align: middle;
}

#fit-bounds-btn svg {
  width: 100%;
  height: 100%;
}

/* Same icon/button, scoped to one day's stops instead of the whole trip —
   see .day-fit-bounds-btn's click handler in js/app.js. Styled to match
   #fit-bounds-btn exactly, just inline within .day-summary-line instead
   of the hero subtitle. */
.day-fit-bounds-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.1em;
  height: 1.1em;
  margin-left: 0.2em;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  cursor: pointer;
  vertical-align: middle;
}

.day-fit-bounds-btn svg {
  width: 100%;
  height: 100%;
}

#stops {
  display: flex;
  flex-direction: column;
  /* Trailing scroll room so the last card can actually reach the reading
     anchor (.scroll-anchor, fixed at 45% down the viewport) — without
     this, scrolling runs out before the last stop can be centered/read.
     The old .outro footer used to provide this as a side effect of its
     own min-height: 50vh; now that a route can have no footer at all
     (see sf-slo), this needs to exist independently of whether one does. */
  padding-bottom: 50vh;
}

.stop {
  min-height: 45vh;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 4vh 6vw;
}

/* Town and minor stops now share one uniform baseline — no more
   "clustering" (tight spacing for anything after the most recent town):
   that was a document-order heuristic that broke whenever a stop was
   entered *before* its town in the sheet. A tight fixed baseline
   (0.15rem, both sides) plus --extra-gap — set per-node in js/app.js,
   scaled directly from the real mile gap since the previous stop, 0 up
   to a 6vh cap — replaces it: two stops that are actually close together
   read as close together regardless of document order, and a real gap in
   the road reads as a real gap on the page. Bonus only applies to
   padding-top ("space since the last one") — padding-bottom stays fixed
   so the same distance isn't counted twice across two adjacent nodes.
   Fixed rem for the baseline (predictable regardless of viewport
   height), vh for the distance-scaled part (matches how "spacious"
   values are expressed elsewhere on this page). Two class-level
   selectors gives this enough specificity to beat the mobile media
   query's plain ".stop" padding shorthand below — see the
   .stop.day-marker fix elsewhere in this file for the bug this pattern
   avoids repeating. Font-size is the one remaining town/minor
   distinction (below) — spacing itself no longer differs between them. */
.stop.town,
.stop.minor {
  min-height: 0;
  padding-top: calc(0.15rem + var(--extra-gap, 0vh));
  padding-bottom: 0.15rem;
}

.stop.minor .stop-card h3 {
  font-size: 1.1rem;
}

/* Equal horizontal padding gives the active-state background panel some
   breathing room around the text. No compensating negative margin here
   (an earlier version had one, meant to keep text pinned to its old
   pixel position) — that shifted the whole box left without an equal
   adjustment on the right, so the card's outer edges no longer matched
   .stop's own symmetric left/right padding. Text now sits 0.6rem further
   right than it historically did, in exchange for the card's outer box
   genuinely lining up with .stop's padding on both sides. Padding is
   present in both states so nothing about the box's geometry changes
   when a card becomes active — only background-color animates.
   width: fit-content (not 100%) — matches how day markers already hug
   their own content (a side effect of their column-flex layout, not a
   deliberate choice at the time) rather than always extending to the
   420px cap regardless of how short the text is: a short title like
   "Belfair, WA" hugs tightly, while a long note grows the panel toward
   the 420px cap as needed, capped there like every other panel on the
   page. margin-right: auto pins it to the left edge on mobile — .stop's
   own justify-content:center is invisible on a near-full-width card but
   very obvious on a hugging one, so the auto margin absorbs the leftover
   space instead of letting justify-content center it. This used to be a
   special case scoped to standalone photo rows only
   (.stop-card-photo-only); now that every card hugs by default, that
   class/rule is gone — a photo-only card just naturally hugs its photo
   through this same base rule, no special-casing needed. */
.stop-card {
  max-width: 420px;
  width: fit-content;
  margin-right: auto;
  padding: 1rem 0.6rem;
  border-radius: 8px;
  transition: opacity 0.3s ease, background-color 0.3s ease;
  opacity: 0.7;
}

/* Any card ending in a photo (photoHtml always renders last — mile →
   title → notes → photo, see js/app.js), not just photo-only cards: base
   .stop-card padding is 1rem top/bottom vs 0.6rem sides, which reads fine
   as "space above the mile marker" but doubles up at the bottom once a
   photo's own margin-bottom (0.5rem, .stop-photo-thumb below) stacks on
   top of it — bottom ends up ~2.5x deeper than the sides. Both knocked
   down here so a photo's edge sits the same distance from the panel on
   every side, whether it's the only content or trailing a title/notes. */
.stop-card:has(> .stop-photo-thumb) {
  padding-bottom: 0.6rem;
}

.stop-card:has(> .stop-photo-thumb) .stop-photo-thumb {
  margin-bottom: 0;
}

/* Translucent panel behind the in-focus card's text, separating it from
   the map showing through behind it — replaces the old plain-opacity-only
   active state. An earlier version added a red left border here (folding
   in the separate "stronger in-focus indicator" idea, backlog item 10) —
   removed per direct feedback, it read as too busy against the panel. */
.stop.active .stop-card {
  opacity: 1;
  background: rgba(240, 240, 230, 0.55);
}

/* Same treatment for a day marker's notes, which live outside .stop-card
   entirely (day rows use .day-card + a bare .stop-notes, no card
   wrapper) — without this, a day's notes never got the active-state
   legibility panel other stops do. Geometry (padding/radius) lives on
   .day-notes-wrap above; only background animates here. Same color as
   .stop.active .stop-card above — keep these two in sync by hand, they're
   separate rules (one on .stop-card, one on .day-notes-wrap) rather than
   a shared class, since a day marker has no card wrapper to share one
   with. */
.stop.day-marker.active .day-notes-wrap {
  background: rgba(240, 240, 230, 0.55);
}

.stop-mile {
  font-size: 1.2rem;
  letter-spacing: 0.02em;
  color: var(--accent);
  font-weight: 600;
  margin-bottom: 0.1rem;
}

.mile-total {
  font-size: 0.8em;
  font-weight: 500;
}

.gpx-badge {
  color: #2a8a4a;
  font-size: 0.9em;
  margin-left: 0.25em;
  vertical-align: middle;
}

.stop-card h3 {
  margin: 0 0 0.25rem;
  font-size: 1.5rem;
  color: var(--text);
}

.stop-notes {
  font-size: 0.95rem;
  color: var(--text);
  line-height: 1.4;
}

/* Applied by default in app.js; removed on tap to reveal the full note.
   -webkit-line-clamp works in every current browser (not just WebKit
   despite the prefix — Chrome/Firefox/Edge all ship it), which is why
   this and not a JS height-measuring trick. */
.stop-notes.clamped {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  overflow: hidden;
}

.notes-toggle {
  display: block;
  margin-top: 0.2rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  text-decoration: underline;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
}

/* Capped on both dimensions but no fixed box/object-fit — a portrait photo
   stays portrait, a landscape one stays landscape, each scaled down to fit
   within the cap rather than cropped to match a fixed shape. */
.stop-photo-thumb {
  display: block;
  max-width: 140px;
  max-height: 180px;
  width: auto;
  height: auto;
  border-radius: 4px;
  margin: 0.5rem 0;
  cursor: pointer;
}

/* Single overlay reused for whichever photo was tapped — see app.js. Full
   viewport dark backdrop, image centered and capped so it never spills
   past the screen either dimension. Hidden via opacity/pointer-events
   (not display:none) so it can fade, same reasoning as #day-nav. */
#photo-overlay {
  position: fixed;
  inset: 0;
  z-index: 10;
  background: rgba(0, 0, 0, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
  cursor: pointer;
}

#photo-overlay.visible {
  opacity: 1;
  pointer-events: auto;
}

#photo-overlay img {
  max-width: 92vw;
  max-height: 92vh;
  object-fit: contain;
}

.website-icon {
  text-decoration: none;
  color: inherit;
  font-size: 0.8em;
  vertical-align: middle;
}

/* Lives inside .stop-mile now (first item, ahead of the mile numbers),
   not the title — red to match .stop-mile's own --accent color instead
   of inheriting the title's black, so it reads as part of the mile
   marker rather than a title decoration. */
.maps-icon {
  text-decoration: none;
  color: var(--accent);
  font-size: 0.8em;
  vertical-align: middle;
  margin-right: 0.35em;
}

/* Line-art category/link icons — inherit color from surrounding text via
   currentColor, so they adapt automatically instead of needing separate
   light/dark handling like emoji glyphs would. */
.icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
}

/* Persistent header bar — updated in js/app.js whenever the active stop
   changes, pinned regardless of scroll position. Hidden (opacity/pointer-
   events) until the hero's been scrolled past, rather than display:none,
   so it can fade in instead of popping in abruptly. Two-step reveal: the
   shell (this element) fades in first, on leaving the hero; the day line
   inside it fades in separately, later, once a day marker actually crosses
   the bar's own trigger line — see the two IntersectionObservers in
   app.js. */
#day-nav {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 3;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 48px;
  background: #000;
  color: #fff;
  padding: 0.4rem 3vw;
  opacity: 0;
  transition: opacity 0.2s ease;
  pointer-events: none;
}

#day-nav.visible {
  opacity: 1;
  pointer-events: auto;
}

.day-nav-btn {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  cursor: pointer;
  text-decoration: none;
}

.day-nav-icon {
  width: 1.1em;
  height: 1.1em;
  display: block;
}

.day-nav-text {
  flex: 1 1 auto;
  min-width: 0;
}

/* Fades in on its own, later than the shell around it — see the
   route-visible class added once the hero fully clears, app.js. */
.day-nav-route {
  font-size: 0.7rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.6);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transition: opacity 0.2s ease;
}

#day-nav.route-visible .day-nav-route {
  opacity: 1;
}

/* Fades in on its own, after the shell above is already visible — see the
   day-visible class added in updateDayNav(), app.js. */
.day-nav-day {
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  opacity: 0;
  transition: opacity 0.2s ease;
}

#day-nav.day-visible .day-nav-day {
  opacity: 1;
}

/* "Jump to a day" bottom sheet — built and populated in js/app.js (day
   markers only, not every stop), same reasoning as #photo-overlay: a
   single shared element, shown/hidden via opacity+pointer-events rather
   than display:none so it can transition in/out. Bottom-sheet rather than
   a small anchored dropdown because a full route can have 20+ days —
   comfortable to scroll as a sheet, cramped as a tiny popover. */
#day-jump-overlay {
  position: fixed;
  inset: 0;
  z-index: 5;
  background: rgba(0, 0, 0, 0.75);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

#day-jump-overlay.visible {
  opacity: 1;
  pointer-events: auto;
}

.day-jump-panel {
  width: 100%;
  max-width: 480px;
  max-height: 75vh;
  background: #000;
  color: #fff;
  border-radius: 16px 16px 0 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transform: translateY(16px);
  transition: transform 0.2s ease;
}

#day-jump-overlay.visible .day-jump-panel {
  transform: translateY(0);
}

.day-jump-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 1rem 0.7rem 1.2rem;
  font-size: 0.9rem;
  font-weight: 600;
  border-bottom: 1px solid rgba(255, 255, 255, 0.15);
  flex: 0 0 auto;
}

.day-jump-close {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  border: none;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.day-jump-close .day-nav-icon {
  width: 0.9em;
  height: 0.9em;
}

.day-jump-list {
  overflow-y: auto;
  padding: 0.4rem;
}

.day-jump-item {
  display: block;
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  color: #fff;
  font-size: 0.95rem;
  font-family: inherit;
  padding: 0.9rem 0.8rem;
  border-radius: 8px;
  cursor: pointer;
}

.day-jump-item:hover,
.day-jump-item:active {
  background: rgba(255, 255, 255, 0.1);
}

/* Fixed reference line: whichever stop's text is crossing this triangle is
   the one currently synced with the map. Used to match the map's active-
   marker red-ring/white-center motif, but that pairing is being
   deliberately loosened — a future focus-legibility treatment (see backlog
   item 14) is planned to become the stronger visual tie to the active
   marker instead, freeing this one up to just be whatever reads best on
   its own. Must stay at 45% to match the IntersectionObserver rootMargin
   in js/app.js — see that file if this ever moves (e.g. to 40%, floated
   but not yet decided as of this note).
   Pure border-triangle, no clip-window trick needed here (unlike the old
   half-circle version): the box itself never leaves x:0, so there's
   nothing to trigger the iOS Safari horizontal-drift bug documented
   elsewhere in this file. */
.scroll-anchor {
  position: fixed;
  left: 0;
  top: 45%;
  transform: translateY(-50%);
  width: 0;
  height: 0;
  border-top: 10px solid transparent;
  border-bottom: 10px solid transparent;
  border-left: 14px solid var(--accent);
  z-index: 2;
  pointer-events: none;
}

/* "Scroll to Wander" loading text — sits next to .scroll-anchor (the left
   triangle), same anchor line, entirely independent of the hero's own
   .subtitle (which just gets the real "N Days · Xm · Yft" text directly
   once data loads, no animation of its own anymore). Typed in once by
   js/app.js on page load regardless of fetch speed, holds with a blinking
   cursor, then is removed from the DOM outright — not faded, not
   swapped — the instant the user starts scrolling. Its lifecycle has
   nothing to do with whether the sheet/GPX fetch has actually finished by
   then: if it's still loading, there's simply nothing on screen saying so
   anymore, same as before this feature existed. */
.hero-loading {
  position: fixed;
  left: 6vw; /* matches .hero/.stop's own left padding, same left edge as the hero title and every stop card's text */
  top: 45%;
  transform: translateY(-50%);
  z-index: 2;
  max-width: 55vw;
  font-size: 1.1rem;
  color: var(--text); /* solid black, per direct request — was var(--muted) */
  pointer-events: none;
}

/* A day boundary reads as a real chapter/milestone moment now, not a
   small flag — revised 2026-08-18 per direct feedback that the old
   compact version was too easy to miss while scrolling. Deliberately no
   longer sized/tucked to minimize its presence; still left-aligned and
   still part of the town cluster's flow (not a hard section break), just
   visually heavier. */
/* .stop.day-marker (not just .day-marker) specifically so this reliably
   beats the mobile media query's plain ".stop { padding: 4vh 5vw }" below
   — same specificity as a bare ".day-marker" would have, so on a narrow
   viewport (confirmed live at 528px) the media query silently won by
   source order and reset padding-bottom back to 4vh, nearly doubling the
   gap above whatever followed a day marker (measured 79px vs. the
   intended ~51px) — the exact inconsistency that read as "towns have
   more space above" when a town happened to follow a day marker. .stop
   .town (and .stop.minor) were already two-class selectors and never had
   this problem. */
.stop.day-marker {
  min-height: 0;
  padding-top: 4vh; /* matches .stop.town's own padding-top, per direct request */
  padding-bottom: 0.75rem;
  /* .stop's base display:flex defaults to flex-direction:row — fine when
     a day marker only ever had one child (the flag), but with notes now
     rendering alongside it, row placement put them side by side instead
     of stacked. Column + left-align here, scoped to day markers only, so
     regular stops (which rely on the row behavior via their single
     .stop-card child) aren't affected. */
  flex-direction: column;
  align-items: flex-start;
}

/* Shared width for .day-card + .day-notes-wrap together — without this,
   each hugged its *own* content independently (the title line vs. the
   note text are rarely the same length), so the two connected panels
   ended up different widths, undermining the "one block" effect from the
   flat-corner/no-gap treatment below. .day-block is the one thing that
   actually hugs/caps at 420px now (the same fit-content-with-a-cap
   principle as .stop-card); .day-card and .day-notes-wrap both go
   width:100% to fill whatever width .day-block settles on — the wider of
   the two contents, not each one's own. */
.day-block {
  width: fit-content;
  max-width: 420px;
}

/* The day marker's own mile line (js/app.js) — the last child of whichever
   panel is actually last (.day-notes-wrap when notes exist, .day-card
   otherwise), so it sits inside that panel's own padding/focus-mode
   background instead of needing its own positioning. Just needs a bit of
   separation from whatever's above it inside that same panel. */
.day-card .stop-mile,
.day-notes-wrap .stop-mile {
  margin-top: 0.5rem;
}

/* Padding on all sides (not just left) so it doubles as its own
   focus-mode panel, matching .stop-card and .day-notes-wrap — .day-number
   /.day-summary-line get the same active-state background as the notes
   below them, not just the notes alone. Left padding specifically still
   serves its original purpose too: matches .stop-card's own inset so
   "Day 1" lines up with regular stop titles/notes, not flush with
   .day-marker's outer edge. */
.day-card {
  display: block;
  width: 100%;
  padding: 0.6rem;
  border-radius: 8px;
  margin-bottom: 0.5rem;
  transition: background-color 0.3s ease;
}

.stop.day-marker.active .day-card {
  background: rgba(240, 240, 230, 0.55);
}

/* Matches the hero's own h1-to-subtitle gap (16px) — scoped to only the
   case where notes actually follow (:has(+ .day-notes-wrap)), via a
   negative margin trimming the combined day-card padding-bottom +
   day-notes-wrap padding-top (19.2px together) down to 16px. Doesn't
   touch the no-notes case, where .day-card's own 0.6rem bottom padding
   stays the untouched, symmetric panel edge. */
.day-card:has(+ .day-notes-wrap) .day-summary-line {
  margin-bottom: -3.2px;
}

/* When notes follow, treat .day-card + .day-notes-wrap as one continuous
   panel instead of two separate rounded boxes with a gap between them —
   no margin between them, and the touching corners go flat so only the
   outer corners of the combined block stay rounded. :has() rather than a
   JS-added class since "does this day have notes" is already knowable
   purely from markup structure (day-notes-wrap only renders at all when
   w.notes exists — see js/app.js). */
.day-card:has(+ .day-notes-wrap) {
  border-radius: 8px 8px 0 0;
  margin-bottom: 0;
}

.day-card + .day-notes-wrap {
  border-radius: 0 0 8px 8px;
}

/* "Day 1" — big and black. No font-family override (reverted per direct
   feedback — inherits the body's Alegreya Sans like everything else on
   the page, rather than borrowing the hero h1's serif display font). */
.day-number {
  font-size: 2.5rem;
  font-weight: 400;
  line-height: 1;
  color: var(--text);
}

/* "→ Santa Cruz · 51m · 1620ft" — the old .day-line content, now on its
   own line below .day-number instead of inline after it. */
.day-summary-line {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
  margin-top: 0.15rem;
}

/* Same 420px cap as .stop-card, so a day's notes read the same width as
   every other note instead of stretching full-bleed just because this
   section has no .stop-card wrapper of its own to inherit a width from.
   Padding/radius mirror .stop-card's own active-state treatment (present
   in both states, only background-color animates — see
   .stop.day-marker.active .day-notes-wrap below) so day notes get the
   same legibility panel as every other stop. Lives on the wrapper
   (js/app.js), not .stop-notes directly, specifically so it also
   contains the "more" toggle button — that's inserted as a *sibling* of
   .stop-notes after render, so a panel scoped to .stop-notes alone would
   leave the toggle sitting outside its background. */
.day-notes-wrap {
  width: 100%;
  /* Top matches the sides (0.6rem) — nothing stacked above the notes
     within this wrap to justify extra top padding, unlike .stop-card.
     Bottom stays at 1rem, matching a regular .stop-card's own
     padding-bottom exactly (verified live: 16px gap below "Pacific Blue
     Inn"'s "more" button, same card treatment the toggle already reads
     fine in) — gives the toggle room to breathe instead of crowding the
     panel's edge. */
  padding: 0.6rem 0.6rem 1rem;
  border-radius: 8px;
  transition: background-color 0.3s ease;
}

.outro {
  min-height: 50vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  color: #fff;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0.15));
  padding: 2rem;
}

@media (max-width: 640px) {
  .stop {
    justify-content: center !important;
    padding: 4vh 5vw;
  }
  /* .stop-card used to go full-bleed (max-width:100%) here — harmless
     when the card had no visible background, but once the active-state
     panel was added this made it stretch edge-to-edge on mobile instead
     of staying a symmetrically-inset, content-sized box. Letting it keep
     the base 420px cap (which is already wider than any phone, so this
     is a no-op for actual sizing) plus the centering above is what keeps
     left/right padding equal. */
  /* The day flag is sized to its content, not full-width like .stop-card —
     the centering above (meant for the old full-width day header) would
     visibly center it instead of just being a no-op. Keep it flush left. */
  .day-marker {
    justify-content: flex-start !important;
  }
}
