/* ============================================
   2026 Fall Foliage Forecast — structural CSS only.
   Type, color and spacing live in ultralight Tailwind classes in the components.
   This file covers: theme pin, page rhythm, hero grid, table -> card reflow,
   the camp-picks snap rail, the road-trip layout, and the scrolly slot.
   Every rule is scoped under `.story-fall-foliage`.
   ============================================ */

/* Pin light theme — this is an editorial page with a data-viz color ramp that
   only reads correctly on a light ground. Mirrors superbloom.css. */
.story-fall-foliage {
  --surface: var(--white);
  --raised: var(--neutral-100);
  --emphasis: var(--neutral-500);
  --divider: var(--neutral-100);
  --border: var(--neutral-100);
  --focus: var(--neutral-700);
  --content: var(--neutral-700);
  --muted: var(--neutral-400);
  --ff-max: 1120px;
  color-scheme: light;
  background: var(--surface);
  color: var(--content);
}

/* Visible focus ring for the story's bespoke interactive elements. Ultralight's own
   `Button`/`Link` components already ship one, so this only covers the custom targets. */
.story-fall-foliage .ff-pick-card-link:focus-visible,
.story-fall-foliage .ff-place-link:focus-visible,
.story-fall-foliage .ff-destination-link:focus-visible,
.story-fall-foliage .ff-report-link:focus-visible,
.story-fall-foliage .ff-timeline-point:focus-visible,
.story-fall-foliage .ff-route-toggle:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: 8px;
}

/* ============================================
   PAGE RHYTHM
   ============================================ */

.story-fall-foliage .ff-container {
  max-width: var(--ff-max);
  margin: 0 auto;
  padding: 0 20px;
}

.story-fall-foliage .ff-section {
  padding: 56px 0;
}

.story-fall-foliage .ff-section-heading {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 68ch;
  margin-bottom: 28px;
}

@media (min-width: 768px) {
  .story-fall-foliage .ff-container {
    padding: 0 32px;
  }

  .story-fall-foliage .ff-section {
    padding: 88px 0;
  }

  .story-fall-foliage .ff-section-heading {
    margin-bottom: 40px;
  }
}

/* ============================================
   HERO — copy left, photo right on desktop; stacked on mobile.
   ============================================ */

.story-fall-foliage .ff-hero {
  padding: 40px 0 56px;
}

.story-fall-foliage .ff-hero-inner {
  max-width: var(--ff-max);
  margin: 0 auto;
  padding: 0 20px;
  display: grid;
  gap: 32px;
  align-items: center;
}

.story-fall-foliage .ff-hero-copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.story-fall-foliage .ff-hero-copy p {
  max-width: 56ch;
}

.story-fall-foliage .ff-hero-media {
  aspect-ratio: 8 / 5;
  overflow: hidden;
  border-radius: 24px;
  background: var(--raised);
}

@media (min-width: 900px) {
  .story-fall-foliage .ff-hero {
    padding: 64px 0 88px;
  }

  .story-fall-foliage .ff-hero-inner {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 56px;
    padding: 0 32px;
  }

  .story-fall-foliage .ff-hero-media {
    aspect-ratio: 4 / 5;
    max-height: 640px;
  }
}

/* ============================================
   DESTINATIONS TABLE — one table per group; a real table on desktop, cards below 768px.
   ============================================ */

.story-fall-foliage .ff-table-group + .ff-table-group {
  margin-top: 40px;
}

.story-fall-foliage .ff-table-group > h3 {
  margin: 0 0 12px;
}

.story-fall-foliage .ff-table-wrap {
  overflow-x: auto;
}

.story-fall-foliage .ff-table {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

.story-fall-foliage .ff-table th,
.story-fall-foliage .ff-table td {
  padding: 14px 16px;
  vertical-align: top;
  border-bottom: 1px solid var(--divider);
}

.story-fall-foliage .ff-table thead th {
  white-space: nowrap;
  border-bottom-width: 2px;
}

/* Peak window is a small mono chip (ultralight `.pill`). The band color is tinted
   toward white so plain content-colored text clears contrast on every band, dark
   purple through pale gold, while the hue still matches the map. */
.story-fall-foliage .ff-peak-pill {
  background: color-mix(in srgb, var(--ff-band, var(--raised)) 45%, var(--white));
  line-height: 1.4;
}

.story-fall-foliage .ff-explore {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
  white-space: nowrap;
}

/* The whole row is the click target — every cell, not just the name. */
.story-fall-foliage .ff-row {
  cursor: pointer;
  transition: background-color 0.18s ease-out;
}

.story-fall-foliage .ff-row:hover {
  background: var(--raised);
}

.story-fall-foliage .ff-destination-link {
  color: inherit;
  text-decoration: none;
}

/* Below `md` the table reads as a guide index: one hairline card per destination, with the name
   and its peak pill on the first line, the species underneath, and a chevron trailing both. The
   column headers stay in the accessibility tree but leave the page. */
@media (max-width: 767px) {
  .story-fall-foliage .ff-table,
  .story-fall-foliage .ff-table tbody {
    display: block;
    width: 100%;
  }

  .story-fall-foliage .ff-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .story-fall-foliage .ff-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 16px;
    align-items: center;
    column-gap: 12px;
    row-gap: 4px;
    padding: 16px;
    border: 1px solid var(--divider);
    border-radius: 1rem;
    background: var(--surface);
  }

  .story-fall-foliage .ff-row + .ff-row {
    margin-top: 8px;
  }

  .story-fall-foliage .ff-row:active {
    background: var(--raised);
  }

  /* Grid items carry their own placement, so the table cell padding and rules come off. */
  .story-fall-foliage .ff-row th,
  .story-fall-foliage .ff-row td {
    padding: 0;
    border-bottom: none;
  }

  .story-fall-foliage .ff-cell-name {
    grid-area: 1 / 1;
  }

  .story-fall-foliage .ff-cell-peak {
    grid-area: 1 / 2;
  }

  .story-fall-foliage .ff-cell-species {
    grid-area: 2 / 1 / 3 / 3;
  }

  /* The chevron spans both lines: one "tap into this" affordance for the whole card. */
  .story-fall-foliage .ff-cell-explore {
    grid-area: 1 / 3 / 3 / 4;
  }

  .story-fall-foliage .ff-cell-explore .ff-explore {
    color: var(--muted);
  }

  .story-fall-foliage .ff-explore-label {
    display: none;
  }
}

/* ============================================
   CAMP PICKS — horizontal snap rail.
   ============================================ */

/* The rail bleeds out of the container, so the section clips it: nothing but the
   rail itself may scroll sideways. `clip` — not `hidden` — so no scroll container
   is created and the page's sticky elements keep working. */
.story-fall-foliage .ff-picks {
  overflow-x: clip;
}

/* Below the rail, right-aligned to the container. `hidden md:flex` on the element
   keeps it out of the layout entirely on touch viewports. */
.story-fall-foliage .ff-picks-controls {
  justify-content: flex-end;
  gap: 8px;
  margin-top: 4px;
}

/* The picks rail already carries its own air; pull the sections either side of it in. */
.story-fall-foliage .ff-picks {
  padding-bottom: 24px;
}

.story-fall-foliage .ff-picks + .ff-section {
  padding-top: 40px;
}

/* The rail is a child of `.ff-container`, so its first card starts on the heading's
   left edge by construction. From there it bleeds to the right viewport edge: at every
   width `50% + gutter == 50vw`, so one pair of values covers mobile and desktop. The
   matching `padding-right` puts the last card back on the container's right edge.
   The 8px left inset is scroll padding for the hover lift's shadow; the negative
   left margin cancels it so the card itself stays flush. */
.story-fall-foliage .ff-picks-rail {
  display: flex;
  gap: 16px;
  list-style: none;
  margin: 0 calc(50% - 50vw) 0 -8px;
  padding: 8px calc(50vw - 50%) 8px 8px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 8px;
  -webkit-overflow-scrolling: touch;
  /* Horizontal only: the rail never swallows a vertical wheel or swipe meant for the page. */
  overscroll-behavior-x: contain;
  touch-action: pan-x pan-y;
  scrollbar-width: none;
}

.story-fall-foliage .ff-picks-rail::-webkit-scrollbar {
  display: none;
}

.story-fall-foliage .ff-pick-card {
  flex: 0 0 auto;
  width: 280px;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  transition:
    transform 0.18s ease-out,
    box-shadow 0.18s ease-out;
}

/* Whole-card link — mirrors the `.fav-grid-card` lift in the 50-favorites story. */
.story-fall-foliage .ff-pick-card-link {
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  color: inherit;
  text-decoration: none;
}

.story-fall-foliage .ff-pick-card:hover,
.story-fall-foliage .ff-pick-card:focus-within {
  transform: translateY(-3px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}

.story-fall-foliage .ff-pick-card:hover .ff-pick-image img,
.story-fall-foliage .ff-pick-card:focus-within .ff-pick-image img {
  transform: scale(1.04);
}

.story-fall-foliage .ff-pick-image {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--surface);
}

.story-fall-foliage .ff-pick-image img {
  transition: transform 0.18s ease-out;
}

.story-fall-foliage .ff-pick-copy {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px;
  flex: 1;
}

.story-fall-foliage .ff-pick-copy blockquote,
.story-fall-foliage .ff-pick-copy h3 {
  margin: 0;
}

/* Room under the cards for the hover lift's shadow — a pointer-only effect, so
   mobile doesn't pay for it with empty space below the rail. */
@media (min-width: 768px) {
  .story-fall-foliage .ff-picks-rail {
    padding-bottom: 16px;
  }

  .story-fall-foliage .ff-pick-card {
    width: 320px;
  }
}

/* ============================================
   PHENOLOGY
   ============================================ */

/* Closing section: no raised ground any more, so a hairline carries the break and
   the head room tightens to keep that rule attached to the copy it introduces. */
.story-fall-foliage .ff-phenology-section {
  padding-top: 40px;
}

@media (min-width: 768px) {
  .story-fall-foliage .ff-phenology-section {
    padding-top: 56px;
  }
}

.story-fall-foliage .ff-phenology-copy {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 68ch;
}

/* ============================================
   ROAD TRIPS — cards left, map right on desktop; list then map on mobile.
   ============================================ */

/* `start`, never `stretch`: expanding a card must not change the map column's height. */
.story-fall-foliage .ff-route-layout {
  display: grid;
  gap: 24px;
  align-items: start;
}

/* The slot is exactly as tall as the map it holds, so the CTA pinned to the slot's
   bottom-left sits on the map rather than floating below it. */
.story-fall-foliage .ff-route-map-slot,
.story-fall-foliage .ff-route-map {
  height: 360px;
}

.story-fall-foliage .ff-route-map-slot {
  position: relative;
  border-radius: 1rem;
  background: var(--raised);
}

/* One CTA for the section, pinned over the map and following the active route. Centered on the
   map's bottom edge so it clears the Mapbox logo and attribution in the two bottom corners. */
.story-fall-foliage .ff-route-map-cta {
  position: absolute;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 2;
}

.story-fall-foliage .ff-route-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: none;
}

.story-fall-foliage .ff-route-card {
  padding: 0;
  transition:
    background-color 0.2s ease,
    border-color 0.2s ease;
}

.story-fall-foliage .ff-route-card:hover {
  background: var(--raised);
}

/* Fixed header height so five collapsed cards always add up to the map's height.
   Border-box: 82px here + the card's 1px top and bottom border = 84px per collapsed card.
   The 82px leaves 50px of content for the 28px title line and the 20px date line. */
.story-fall-foliage .ff-route-card-top {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 12px;
  box-sizing: border-box;
  min-height: 82px;
  padding: 16px 20px;
}

.story-fall-foliage .ff-route-number {
  flex: none;
}

.story-fall-foliage .ff-route-marker {
  flex: none;
  margin-left: auto;
  align-self: center;
}

.story-fall-foliage .ff-route-toggle {
  padding: 0;
  border: none;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

/* One button per card: its hit area stretches over the whole header row, padding included. */
.story-fall-foliage .ff-route-toggle::after {
  content: '';
  position: absolute;
  inset: 0;
}

/* A normal block, so the inline `<a>`s inside the body copy flow inline with the prose
   instead of becoming flex items stacked one per line. */
.story-fall-foliage .ff-route-copy {
  display: block;
  margin: 0;
  padding: 0 20px 20px;
}

/* The explicit `display: block` above would otherwise beat the `hidden` attribute. */
.story-fall-foliage .ff-route-copy[hidden] {
  display: none;
}

.story-fall-foliage .ff-route-copy p {
  margin: 0;
}

/* Editorial links: same ink as the prose, distinguished by the underline, not by color. */
.story-fall-foliage .ff-route-copy a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

.story-fall-foliage .ff-route-copy a:hover {
  text-decoration-thickness: 2px;
}

@media (min-width: 900px) {
  .story-fall-foliage .ff-route-layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 32px;
  }

  /* Five collapsed 84px cards plus four 12px gaps: the map column ends level with the
     list when every card is closed, and never moves when one opens. */
  .story-fall-foliage .ff-route-map-slot,
  .story-fall-foliage .ff-route-map {
    height: 468px;
  }

  .story-fall-foliage .ff-route-map-slot {
    position: sticky;
    top: calc(var(--header-h) + 16px);
  }
}

/* ============================================
   CONDITIONS
   ============================================ */

.story-fall-foliage .ff-report-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.story-fall-foliage .ff-report-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px;
  text-decoration: none;
  transition:
    transform 0.18s ease-out,
    box-shadow 0.18s ease-out;
}

.story-fall-foliage .ff-report-link:hover {
  transform: translateY(-3px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.1);
}

.story-fall-foliage .ff-report-link:active {
  transform: translateY(0);
}

/* ============================================
   REDUCED MOTION
   ============================================ */

@media (prefers-reduced-motion: reduce) {
  .story-fall-foliage .ff-picks-rail {
    scroll-behavior: auto;
  }

  .story-fall-foliage .ff-route-card,
  .story-fall-foliage .ff-report-link,
  .story-fall-foliage .ff-pick-card,
  .story-fall-foliage .ff-pick-image img,
  .story-fall-foliage .ff-place-link,
  .story-fall-foliage .ff-row {
    transition: none;
  }

  /* Keep the color and shadow feedback, drop the movement. */
  .story-fall-foliage .ff-pick-card:hover,
  .story-fall-foliage .ff-report-link:hover,
  .story-fall-foliage .ff-pick-card:hover .ff-pick-image img,
  .story-fall-foliage .ff-pick-card:focus-within .ff-pick-image img {
    transform: none;
  }
}

/* ============================================
   SCROLLYTELLING + MAPS (structure only)
   ============================================ */
.story-fall-foliage {
  --header-h: var(--nav-header-height, 76px);
}

/* ============================================
   STICKY MAP
   ============================================ */

.story-fall-foliage #forecast-map {
  position: relative;
}

.story-fall-foliage .ff-map-sticky {
  position: sticky;
  top: var(--header-h);
  width: 100%;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  z-index: 1;
  background: var(--surface);
}

/* When the page supplies the wrapper, the wrapper is the sticky viewport. */
.story-fall-foliage .ff-map-sticky > #scrolly-map {
  position: relative;
  top: auto;
  height: 100%;
  z-index: auto;
}

/* react-map-gl's container is the map div's only child. */
.story-fall-foliage #scrolly-map > div:first-child {
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.5s ease-out;
}

.story-fall-foliage #scrolly-map.is-loaded > div:first-child {
  opacity: 1;
}

/* Loading skeleton behind the fading-in map. */
.story-fall-foliage #scrolly-map::before {
  content: '';
  position: absolute;
  inset: 0;
  background: #f0efeb;
  animation: ff-skeleton-pulse 1.5s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}

.story-fall-foliage #scrolly-map.is-loaded::before {
  display: none;
}

@keyframes ff-skeleton-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.6;
  }
}

@media (min-width: 769px) {
  .story-fall-foliage #scrolly-map {
    padding: 24px;
  }

  .story-fall-foliage #scrolly-map > div:first-child {
    border-radius: 24px;
    overflow: hidden;
  }

  .story-fall-foliage #scrolly-map::before {
    inset: 24px;
    border-radius: 24px;
  }
}

/* ============================================
   TEXT COLUMN — pulled back over the map
   ============================================ */

.story-fall-foliage #scrolly-text {
  position: relative;
  z-index: 2;
  width: 500px;
  margin-top: calc(-100vh + var(--header-h));
  margin-top: calc(-100dvh + var(--header-h));
  pointer-events: none;
}

.story-fall-foliage .step {
  min-height: 80vh;
  display: flex;
  /* Desktop cards mount top-left so they never cover the middle of the country. */
  align-items: flex-start;
  padding: 60px 48px;
  pointer-events: none;
}

/* Lead-in on the intro so the map is readable before the first card lands. */
.story-fall-foliage .step:first-of-type {
  min-height: calc(130vh - var(--header-h));
  padding-bottom: 40vh;
}

.story-fall-foliage .step:first-of-type .step-card {
  scroll-margin-top: calc(var(--header-h) + 48px);
}

.story-fall-foliage #destinations,
.story-fall-foliage #best-hipcamps,
.story-fall-foliage #forecast-map {
  scroll-margin-top: calc(var(--header-h) + 16px);
}

/* Scroll-out buffer so the last chapter can hold the map while the reader keeps scrolling. */
.story-fall-foliage .step:last-of-type {
  padding-bottom: calc(100vh - var(--header-h));
}

.story-fall-foliage .step-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Park at the top-left while the chapter is active; the step scrolls it away.
     The map tile is inset 24px inside #scrolly-map, so +48px keeps the card 24px
     inside the tile, matching its 24px left inset. */
  position: sticky;
  top: calc(var(--header-h) + 48px);
  scroll-margin-top: calc(var(--header-h) + 48px);
  border-radius: 1rem;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
  padding: 28px 28px 24px;
  max-width: 440px;
  width: 100%;
  pointer-events: auto;
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);
}

.story-fall-foliage .step.is-active .step-card {
  opacity: 1;
  transform: translateY(0);
}

/* Hold the cards hidden until the map has reported ready. */
.story-fall-foliage:not(.map-ready) .step.is-active .step-card {
  opacity: 0;
}

/* ============================================
   STEP CONTENTS — legend, destination rows, actions
   ============================================ */

.story-fall-foliage .ff-legend {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.story-fall-foliage .ff-legend ul {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.story-fall-foliage .ff-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
}

.story-fall-foliage .ff-legend-swatch {
  width: 12px;
  height: 12px;
  border-radius: 3px;
  flex-shrink: 0;
}

.story-fall-foliage .ff-step-places {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.story-fall-foliage .ff-step-places li {
  display: flex;
}

/* The whole row is one link: dot, name and species share a single hover target. */
.story-fall-foliage .ff-place-link {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  flex: 1;
  min-width: 0;
  margin: 0 -12px;
  padding: 8px 12px;
  color: inherit;
  text-decoration: none;
  transition: background-color 0.18s ease-out;
}

.story-fall-foliage .ff-place-link:hover {
  background: var(--raised);
}

.story-fall-foliage .ff-place-dot {
  width: 10px;
  height: 10px;
  border-radius: 9999px;
  margin-top: 6px;
  flex-shrink: 0;
}

.story-fall-foliage .ff-place-copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.story-fall-foliage .ff-step-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}

/* ============================================
   TIMELINE + RETURN PILL — overlaid inside the map.

   Copied one-to-one from superbloom (`.superbloom-timeline*`, `.superbloom-return-pill`).
   Both are children of `#scrolly-map`, so they ride the sticky map tile: the timeline pinned
   24px inside its bottom-right corner, the pills bottom-center. They paint under `#scrolly-text`
   (z-index 2) but that column is `pointer-events: none` everywhere except its cards, so both
   stay clickable.
   ============================================ */

.story-fall-foliage .ff-timeline {
  position: absolute;
  bottom: 48px;
  right: 48px;
  z-index: 5;
  opacity: 0;
  transition: opacity 0.5s ease-out;
  display: flex;
  align-items: flex-start;
  background: rgba(255, 255, 255, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-radius: 9999px;
  padding: 12px 20px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
  pointer-events: auto;
}

.story-fall-foliage .ff-timeline.is-visible {
  opacity: 1;
}

/* Each item: optional line segment + dot/label */
.story-fall-foliage .ff-timeline-item {
  display: flex;
  align-items: flex-start;
}

/* Line segment between dots — sits in the flex flow */
.story-fall-foliage .ff-timeline-seg {
  width: 24px;
  height: 2px;
  background: var(--neutral-200);
  margin-top: 5px;
  flex-shrink: 0;
  transition: background 0.3s;
}

/* A filled segment takes the colour of the chapter it leads into: `--ff-band` is set on the
   item that owns both the segment and the dot after it. */
.story-fall-foliage .ff-timeline-seg.is-filled {
  background: var(--ff-band, var(--content));
  opacity: 0.6;
}

.story-fall-foliage .ff-timeline-point {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
}

.story-fall-foliage .ff-timeline-point:hover .ff-timeline-dot {
  transform: scale(1.3);
}

.story-fall-foliage .ff-timeline-point:hover .ff-timeline-label {
  transform: scale(1.05);
}

/* Every dot carries its chapter's forecast-band colour, so the timeline reads as the same ramp
   as the map. Progress is expressed with opacity and size, not hue. */
.story-fall-foliage .ff-timeline-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ff-band, var(--content));
  border: 2px solid var(--ff-band, var(--content));
  opacity: 0.4;
  transition: all 0.3s;
  flex-shrink: 0;
}

.story-fall-foliage .ff-timeline-point.is-past .ff-timeline-dot {
  opacity: 0.75;
}

.story-fall-foliage .ff-timeline-point.is-active .ff-timeline-dot {
  opacity: 1;
  width: 14px;
  height: 14px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--ff-band, var(--content)) 28%, transparent);
}

/* Labels stay in the text palette — the colour is carried by the dots alone. */
.story-fall-foliage .ff-timeline-label {
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: all 0.3s;
}

.story-fall-foliage .ff-timeline-point.is-active .ff-timeline-label {
  color: var(--content);
}

/* ============================================
   MAP LOCK — story mode

   The map is inert until the reader opts in. `.ff-map-lock` covers the canvas so wheel and
   touch events stay with the page (`touch-action: pan-y` keeps vertical swipes scrolling),
   and its click is forwarded to the pins in JS. It paints under the timeline (z-index 5) and
   the popup, so both stay reachable while the map is locked. It carries no visible affordance:
   the return pill is the only mode control the reader ever sees.
   ============================================ */

.story-fall-foliage .ff-map-lock {
  position: absolute;
  inset: 0;
  z-index: 4;
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  touch-action: pan-y;
}

.story-fall-foliage .ff-map-lock:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: -4px;
  border-radius: 24px;
}

/* Popups outrank the lock so a pin opened in story mode stays clickable. */
.story-fall-foliage #scrolly-map .ff-map-popup {
  z-index: 5;
}

/* Return-to-timeline pill — only while the reader has taken the map off the story.
   It is positioned against `#scrolly-map`, whose padding box includes the 24px desktop inset,
   so the offset is that inset plus 24px of clearance from the rounded tile's bottom edge.
   Centred horizontally, which also keeps it clear of the mapbox attribution bottom-left. */
.story-fall-foliage .ff-return-pill {
  position: absolute;
  bottom: 48px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  background: rgba(28, 28, 25, 0.9);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: none;
  border-radius: 9999px;
  padding: 10px 20px;
  font-size: 0.82rem;
  font-weight: 600;
  color: #faf9f6;
  /* Matches the `shadow-md` token. */
  box-shadow:
    0 4px 6px -1px rgba(0, 0, 0, 0.1),
    0 2px 4px -2px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease-out;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.story-fall-foliage .ff-return-pill.is-visible {
  opacity: 1;
  pointer-events: auto;
}

.story-fall-foliage .ff-return-pill:hover {
  background: rgba(28, 28, 25, 0.97);
}

/* While exploring, the story gets out of the way. */
.story-fall-foliage.user-exploring .step.is-active .step-card {
  opacity: 0 !important;
  pointer-events: none !important;
}

.story-fall-foliage.user-exploring .ff-timeline {
  opacity: 0 !important;
  pointer-events: none !important;
}

@media (max-width: 768px) {
  /* Mobile puts the timeline at the TOP of the map, centred and shrunk. The bottom of the map
     belongs to the step cards (which are bottom-mounted) and to the return pill; the mapbox
     logo and attribution also sit along the bottom edge. Nothing of ours is up here. */
  .story-fall-foliage .ff-timeline {
    padding: 7px 10px;
    bottom: auto;
    top: 16px;
    right: auto;
    left: 50%;
    transform: translateX(-50%);
  }

  .story-fall-foliage .ff-timeline-seg {
    width: 10px;
    margin-top: 4px;
  }

  .story-fall-foliage .ff-timeline-dot {
    width: 10px;
    height: 10px;
    border-width: 1.5px;
  }

  .story-fall-foliage .ff-timeline-point.is-active .ff-timeline-dot {
    width: 12px;
    height: 12px;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--ff-band, var(--content)) 28%, transparent);
  }

  .story-fall-foliage .ff-timeline-point {
    gap: 4px;
  }

  .story-fall-foliage .ff-timeline-label {
    font-size: 0.55rem;
  }

  /* No tile inset on mobile — the map is full-bleed — so 24px off the map edge is the gap.
     Exploring hides the cards, so the pill keeps the bottom of the map to itself. */
  .story-fall-foliage .ff-return-pill {
    bottom: 24px;
  }
}

/* ============================================
   ROAD TRIP MAP
   ============================================ */

/* Height is fixed alongside its slot in the ROAD TRIPS section, so opening a card
   never resizes the map or moves the CTA pinned over it. */
.story-fall-foliage .ff-route-map {
  position: relative;
  width: 100%;
  border-radius: 1rem;
  overflow: hidden;
  background: var(--surface);
}

.story-fall-foliage .ff-route-map > div:first-child {
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.5s ease-out;
}

.story-fall-foliage .ff-route-map.is-loaded > div:first-child {
  opacity: 1;
}

.story-fall-foliage .ff-route-map::before {
  content: '';
  position: absolute;
  inset: 0;
  background: #f0efeb;
  animation: ff-skeleton-pulse 1.5s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}

.story-fall-foliage .ff-route-map.is-loaded::before {
  display: none;
}

/* ============================================
   MAPBOX GL OVERRIDES
   ============================================ */

.story-fall-foliage .mapboxgl-canvas {
  background: var(--surface);
}

.story-fall-foliage .mapboxgl-ctrl-attrib {
  font-size: 10px !important;
  background: rgba(255, 255, 255, 0.7) !important;
}

/* Neither map renders zoom buttons — zoom is by wheel/pinch in explore mode only — so there
   is no `.mapboxgl-ctrl-group` on either map to style. */

.story-fall-foliage .ff-map-popup .mapboxgl-popup-content {
  padding: 14px 16px !important;
  border-radius: 8px !important;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important;
}

.story-fall-foliage .ff-map-popup .mapboxgl-popup-tip {
  border-top-color: #fff !important;
}

.story-fall-foliage .ff-map-popup-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 220px;
}

/* The CTA is the popup's only interactive element, so it gets room to breathe. */
.story-fall-foliage .ff-map-popup-cta {
  margin-top: 10px;
  align-self: flex-start;
}

/* Text links only — the CTA is a Button and keeps its own treatment. */
.story-fall-foliage .ff-map-popup-body a:not(.ff-map-popup-cta) {
  text-decoration: none;
}

.story-fall-foliage .ff-map-popup-body a:not(.ff-map-popup-cta):hover {
  text-decoration: underline;
}

/* ============================================
   MOBILE — bottom-mounted cards
   ============================================ */

@media (max-width: 768px) {
  .story-fall-foliage #scrolly-text {
    width: 100%;
    margin-top: calc(-100vh + var(--header-h));
    margin-top: calc(-100dvh + var(--header-h));
  }

  .story-fall-foliage .step {
    min-height: 100vh;
    min-height: 100svh;
    align-items: flex-end;
    padding: 0 12px 24px;
  }

  .story-fall-foliage .step:first-of-type {
    min-height: 100vh;
    min-height: 100svh;
    padding-bottom: 24px;
  }

  .story-fall-foliage .step:last-of-type {
    padding-bottom: calc(60vh - var(--header-h));
  }

  .story-fall-foliage .step-card {
    position: static;
    max-width: none;
    width: 100%;
    padding: 20px 16px 16px;
    border: none;
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    box-shadow: 0 4px 24px rgba(0, 0, 0, 0.14);
    transition:
      opacity 0.4s ease-out,
      transform 0.4s ease-out;
  }

  .story-fall-foliage .ff-legend ul {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .story-fall-foliage .ff-route-map-slot,
  .story-fall-foliage .ff-route-map {
    height: 360px;
  }
}

/* ============================================
   REDUCED MOTION
   ============================================ */

@media (prefers-reduced-motion: reduce) {
  .story-fall-foliage .step-card {
    transition: none;
  }

  .story-fall-foliage #scrolly-map > div:first-child,
  .story-fall-foliage .ff-route-map > div:first-child {
    transition: none;
  }

  .story-fall-foliage #scrolly-map::before,
  .story-fall-foliage .ff-route-map::before {
    animation: none;
  }

  .story-fall-foliage .ff-timeline,
  .story-fall-foliage .ff-timeline-seg,
  .story-fall-foliage .ff-timeline-dot,
  .story-fall-foliage .ff-timeline-label,
  .story-fall-foliage .ff-return-pill {
    transition: none;
  }

  .story-fall-foliage .ff-timeline-point:hover .ff-timeline-dot,
  .story-fall-foliage .ff-timeline-point:hover .ff-timeline-label {
    transform: none;
  }
}
