.coastal-storymap {
  overflow-x: hidden;
}

.coastal-storymap *,
.coastal-storymap *::before,
.coastal-storymap *::after {
  box-sizing: border-box;
}

.coastal-storymap img {
  display: block;
}

.coastal-storymap {
  --coastal-title-font: var(--font-sans);
  --coastal-section-title-size: clamp(1.6rem, 4vw, 2.8rem);
  --coastal-section-lead-size: clamp(0.95rem, 1.3vw, 1.08rem);
  --coastal-display-title-size: clamp(2.8rem, 6vw, 5rem);
  --coastal-subsection-title-size: clamp(1.3rem, 2vw, 1.8rem);
  --coastal-card-title-size: 1.05rem;
  --coastal-small-title-size: 0.95rem;
  --coastal-card-body-size: 0.85rem;
  --ca-icon-size: 28px;
}

/* Progress */
.coastal-storymap #reading-progress {
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--z-flyout);
  width: 100%;
  height: 2px;
  background: var(--escap-blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 80ms linear;
}

/* Click-to-enlarge lightbox for content images and videos, opened via
   showModal() so it stacks in the top layer above the slide-deck dialogs. */
.coastal-storymap .lightbox-overlay {
  margin: auto;
  border: none;
  padding: 0;
  box-sizing: border-box;
  max-width: 100vw;
  max-height: none;
  background: transparent;
  cursor: zoom-out;
}

/* The flex layout is gated on [open]: an ungated display: flex would outrank
   the UA dialog:not([open]) rule and keep the closed dialog on screen. */
.coastal-storymap .lightbox-overlay[open] {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-8);
}

.coastal-storymap .lightbox-overlay::backdrop {
  background: var(--modal-backdrop);
}

.coastal-storymap .lightbox-overlay img,
.coastal-storymap .lightbox-overlay video {
  box-sizing: border-box;
  max-width: min(100%, 1600px); /* raw: lightbox media cap, no matching token */
  max-height: 88vh;
  cursor: default;
}

.coastal-storymap .lightbox-overlay img {
  background: var(--white);
  padding: var(--space-6);
}

.coastal-storymap .lightbox-close {
  position: absolute;
  top: var(--space-6);
  inset-inline-end: var(--space-7);
  width: var(--space-9);
  height: var(--space-9);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--escap-blue-deep);
  font-size: var(--text-3xl);
  line-height: 1;
  box-shadow: var(--shadow-lg);
  cursor: pointer;
}

.coastal-storymap .lightbox-close:hover {
  color: var(--escap-blue);
}

.coastal-storymap [data-lightbox] {
  cursor: zoom-in;
}

.coastal-storymap [data-lightbox]:focus-visible {
  outline: 3px solid var(--escap-blue);
  outline-offset: 2px;
}

.coastal-storymap .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.coastal-storymap .component-error {
  display: grid;
  place-items: center;
  align-content: center;
  gap: var(--space-3);
  min-height: 320px;
  padding: var(--space-6);
  border: 1px solid var(--border);
  background: var(--off-white);
  color: var(--fg-muted);
  text-align: center;
}

.coastal-storymap .component-error p {
  max-width: 60ch;
  margin: 0;
}

.coastal-storymap .component-error button {
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--escap-blue);
  border-radius: var(--radius-1);
  background: var(--escap-blue);
  color: var(--white);
  font: inherit;
  cursor: pointer;
}

.coastal-storymap .skip-link {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: var(--z-modal);
  padding: 8px 14px;
  background: var(--escap-blue);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: 0.7rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform 0.2s var(--ease-standard);
}

.coastal-storymap .skip-link:focus {
  transform: translateY(0);
}

/* First-paint loading veil: duplicated in coastal-critical.css so incomplete
   layout never flashes before deferred styles and scripts have settled. */
.coastal-storymap .ca-page-loader {
  position: fixed;
  inset: 0;
  z-index: var(--z-toast, 400);
  display: grid;
  place-items: center;
  background: var(--escap-blue-deep, #17354e);
  color: var(--white, #ffffff);
  opacity: 1;
  visibility: visible;
  transition: opacity var(--t-slow, 280ms) var(--ease-standard, ease), visibility var(--t-slow, 280ms) var(--ease-standard, ease);
}
.coastal-storymap .ca-page-loader.is-loaded {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.coastal-storymap .ca-page-loader[hidden] {
  display: none;
}
.coastal-storymap .ca-page-loader-inner {
  display: flex;
  width: min(240px, calc(100vw - 48px));
  flex-direction: column;
  align-items: center;
  gap: var(--space-4, 16px);
}
.coastal-storymap .ca-page-loader-brand {
  color: var(--white, #ffffff);
  font-family: var(--font-condensed, 'Arial Narrow', sans-serif);
  font-size: var(--text-5xl, 36px);
  font-weight: var(--weight-bold, 700);
  letter-spacing: var(--tracking-wide, 0.04em);
}
.coastal-storymap .ca-page-loader-track {
  position: relative;
  width: 100%;
  height: 2px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.18);
}
.coastal-storymap .ca-page-loader-track span {
  position: absolute;
  inset: 0;
  background: var(--escap-gold, #f4be18);
  transform: translateX(-72%);
  animation: ca-page-loading 1.2s var(--ease-standard, ease) infinite;
}
.coastal-storymap .ca-page-loader-label {
  color: rgba(255, 255, 255, 0.82);
  font-family: var(--font-sans, Arial, sans-serif);
  font-size: var(--text-sm, 14px);
}
@keyframes ca-page-loading {
  50% { transform: translateX(72%); }
  100% { transform: translateX(172%); }
}
@media (prefers-reduced-motion: reduce) {
  .coastal-storymap .ca-page-loader-track span {
    animation: none;
    transform: none;
  }
}

/* Nav */
.coastal-storymap .site-nav {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-dropdown);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 0.9rem clamp(1rem, 3vw, 2.5rem);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-bottom: 1px solid var(--escap-blue-wash);
  box-shadow: var(--shadow-sm);
}

.coastal-storymap .nav-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--escap-blue);
  font-family: var(--font-condensed);
  font-size: 1.1rem;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wider);
  text-decoration: none;
  text-transform: uppercase;
}

.coastal-storymap .nav-brand::before {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: var(--radius-1);
  background: var(--escap-blue);
}

.coastal-storymap .nav-links {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  padding: 0;
  margin: 0;
  list-style: none;
}

.coastal-storymap .nav-links li {
  margin: 0;
}

.coastal-storymap .nav-links a {
  padding: 0.4rem 0.85rem;
  border: 1px solid transparent;
  border-radius: var(--radius-1);
  color: var(--fg-muted);
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wide);
  text-decoration: none;
  text-transform: uppercase;
  transition: background var(--t-fast) var(--ease-standard), border-color var(--t-fast) var(--ease-standard), color var(--t-fast) var(--ease-standard);
}

.coastal-storymap .nav-links a:hover {
  border-color: var(--escap-blue);
  background: var(--escap-blue-wash);
  color: var(--escap-blue);
}

/* Side dots */
.coastal-storymap .side-nav {
  position: fixed;
  right: 22px;
  top: 50%;
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 0;
  transform: translateY(-50%);
}

/* CS-002 (#events) and CS-004 (#climate-explore) stack above .side-nav (90) so
   its dots stop floating over the map canvas and swallowing clicks, but stay
   below the sticky .site-nav (--z-dropdown, 100). */
.coastal-storymap #events,
.coastal-storymap #climate-explore {
  position: relative;
  z-index: 95;
}

.coastal-storymap .side-dot {
  position: relative;
  display: grid;
  width: 24px;
  height: 24px;
  place-items: center;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.coastal-storymap .side-dot::before {
  position: relative;
  z-index: 1;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--line-200);
  content: "";
  transition: background var(--t-fast) var(--ease-standard), transform var(--t-fast) var(--ease-standard);
}

/* Progress rail joining each dot to the next. Reads the side-nav as an ordered
   stepper rather than a cluster of loose circles, which is what made it
   resemble the hazard pins on the events map. Segment height == dot pitch
   (24px box, gap: 0 on .side-nav); the last dot has nothing to join to. */
.coastal-storymap .side-dot::after {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2px;
  height: 24px;
  translate: -50% 0;
  background: var(--line-200);
  content: "";
  transition: background var(--t-fast) var(--ease-standard);
}

.coastal-storymap .side-dot:last-child::after {
  display: none;
}

.coastal-storymap .side-dot.completed::before {
  background: var(--escap-gold);
}

.coastal-storymap .side-dot.completed::after {
  background: var(--escap-gold);
}

.coastal-storymap .side-dot.active::before {
  background: var(--escap-blue);
  transform: scale(1.6);
  animation: dot-pulse 2s ease-in-out 3; /* finite: WCAG 2.2.2, no pause control */
}

@keyframes dot-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(0, 104, 184, 0.6); }
  70%  { box-shadow: 0 0 0 8px rgba(0, 104, 184, 0); }
  100% { box-shadow: 0 0 0 0 rgba(0, 104, 184, 0); }
}

.coastal-storymap .side-dot:focus-visible {
  outline: 2px solid var(--escap-blue);
  outline-offset: 3px;
}

/* Sections */
.coastal-storymap section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100svh;
  padding: 96px 32px;
  scroll-margin-top: 86px;
}

.coastal-storymap main > section:not(#hero) {
  content-visibility: auto;
  contain-intrinsic-size: auto 100svh;
}

/* Tabbing to a control scrolls it clear of the fixed nav instead of behind it. */
.coastal-storymap a[href],
.coastal-storymap button,
.coastal-storymap video,
.coastal-storymap input,
.coastal-storymap select,
.coastal-storymap textarea,
.coastal-storymap [tabindex] {
  scroll-margin-top: 96px;
}

.coastal-storymap .wrap {
  width: 100%;
  max-width: var(--container-lg);
  margin: 0 auto;
}

.coastal-storymap .ca-eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 16px;
  color: var(--escap-blue);
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: var(--weight-regular);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
}

.coastal-storymap .ca-eyebrow::before {
  content: '';
  display: block;
  flex-shrink: 0;
  width: 24px;
  height: 1px;
  background: currentColor;
}

.coastal-storymap .ca-title {
  max-width: 22ch;
  margin-bottom: 20px;
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-section-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}

.coastal-storymap .ca-subtitle {
  max-width: 62ch;
  color: var(--fg-muted);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-section-lead-size);
  line-height: var(--lh-base);
}

/* Reveal */
.coastal-storymap .rv {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.45s var(--ease-standard), transform 0.45s var(--ease-standard);
}

.coastal-storymap .rv.in {
  opacity: 1;
  transform: none;
}

.coastal-storymap .rv.d1 { transition-delay: 0.08s; }
.coastal-storymap .rv.d2 { transition-delay: 0.16s; }
.coastal-storymap .rv.d3 { transition-delay: 0.24s; }

/* The hero is useful content, not a deferred interaction. Keep it readable
   while the below-fold application waits for user intent. */
.coastal-storymap #hero .rv {
  opacity: 1;
  transform: none;
  transition: none;
}

/* 1. Hero */
.coastal-storymap #hero {
  position: relative;
  overflow: hidden;
  padding-top: 128px;
  background-color: var(--escap-blue-deep);
  background-image: url('images/hero/BG-1.webp');
  background-position: center 46%;
  background-size: cover;
  color: var(--white);
}

@media (max-width: 640px) {
  .coastal-storymap #hero {
    background-image: url('images/hero/BG-1-mobile.webp');
    background-position: center;
  }
}

.coastal-storymap #hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  background:
    linear-gradient(90deg, rgba(0, 56, 102, 0.86) 0%, rgba(0, 56, 102, 0.70) 38%, rgba(23, 53, 78, 0.14) 68%, transparent 100%),
    linear-gradient(0deg, rgba(0, 56, 102, 0.42) 0%, transparent 46%);
  pointer-events: none;
}

.coastal-storymap #hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
  background:
    radial-gradient(ellipse at 82% 24%, rgba(244, 190, 24, 0.14), transparent 38%),
    linear-gradient(90deg, transparent 58%, rgba(13, 154, 215, 0.12));
  pointer-events: none;
}

.coastal-storymap #hero .wrap {
  position: relative;
  z-index: 1;
}

@media (max-width: 640px) {
  .coastal-storymap #hero::before {
    background:
      linear-gradient(180deg, rgba(0, 56, 102, 0.76) 0%, rgba(0, 56, 102, 0.64) 64%, rgba(0, 56, 102, 0.56) 100%),
      linear-gradient(90deg, rgba(23, 53, 78, 0.14), transparent 72%);
  }

  .coastal-storymap #hero::after {
    background: radial-gradient(ellipse at 70% 18%, rgba(244, 190, 24, 0.12), transparent 36%);
  }
}

.coastal-storymap .hero-kicker {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 24px;
  color: var(--escap-gold);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-widest);
  text-transform: uppercase;
  text-shadow: 0 var(--space-1) var(--space-3) rgba(0, 0, 0, 0.42);
}

.coastal-storymap .hero-kicker::before {
  content: '';
  display: block;
  width: 24px;
  height: 1px;
  background: var(--escap-gold);
}

.coastal-storymap .hero-h1 {
  /* 14ch in Roboto Light; em, because ch follows the fallback font until Roboto loads and re-wrapped the title. */
  max-width: 7.77em;
  margin-bottom: 28px;
  color: var(--white);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-display-title-size);
  font-weight: var(--weight-light);
  line-height: var(--lh-tight);
  text-shadow: 0 var(--space-1) var(--space-3) rgba(0, 0, 0, 0.42);
}

.coastal-storymap .hero-h1 i {
  color: var(--escap-gold);
  font-style: normal;
  font-weight: var(--weight-medium);
}

.coastal-storymap .hero-sub {
  max-width: 60ch;
  margin-bottom: 40px;
  color: rgba(255, 255, 255, 0.92);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-section-lead-size);
  line-height: var(--lh-base);
  text-shadow: 0 var(--space-1) var(--space-3) rgba(0, 0, 0, 0.42);
}

.coastal-storymap .hero-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.coastal-storymap .chip {
  padding: 8px 18px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--radius-1);
  background: rgba(255, 255, 255, 0.10);
  backdrop-filter: blur(8px);
  color: var(--white);
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}

.coastal-storymap .hero-credit {
  position: absolute;
  right: var(--space-7, 32px);
  bottom: var(--space-4, 16px);
  z-index: 1;
  margin: 0;
  color: rgba(255, 255, 255, 0.82);
  font-family: var(--font-sans);
  font-size: var(--text-xs, 12px);
  line-height: var(--lh-base, 1.5);
  text-shadow: 0 var(--space-1, 4px) var(--space-3, 12px) rgba(0, 0, 0, 0.56);
}

/* 2. Threat */
.coastal-storymap #threat {
  background: var(--escap-blue-deep);
}

.coastal-storymap #threat .ca-eyebrow,
.coastal-storymap #climate .ca-eyebrow,
.coastal-storymap #pilots .ca-eyebrow,
.coastal-storymap #resources .ca-eyebrow {
  color: var(--escap-gold);
}

.coastal-storymap #threat .ca-eyebrow::before,
.coastal-storymap #climate .ca-eyebrow::before,
.coastal-storymap #pilots .ca-eyebrow::before,
.coastal-storymap #resources .ca-eyebrow::before {
  background: var(--escap-gold);
}

.coastal-storymap #threat .ca-title,
.coastal-storymap #pilots .ca-title,
.coastal-storymap #resources .ca-title {
  color: var(--white);
}

.coastal-storymap #threat .ca-subtitle,
.coastal-storymap #pilots .ca-subtitle,
.coastal-storymap #resources .ca-subtitle {
  color: var(--escap-blue-wash);
}

/* Risk to Resilience */
.coastal-storymap #risk-to-resilience {
  align-items: center;
  text-align: center;
}

.coastal-storymap #risk-to-resilience .wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.coastal-storymap #risk-to-resilience .ca-eyebrow {
  justify-content: center;
}

.coastal-storymap .stat-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
  margin-top: 64px;
  background: transparent;
}

.coastal-storymap .stat-cell {
  padding: 40px 24px;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: rgba(255, 255, 255, 0.06);
  /* Figure and label rows are shared across the row (subgrid), so a figure that
     wraps to two lines no longer pushes only its own label down. */
  display: grid;
  grid-row: span 2;
  grid-template-rows: subgrid;
  row-gap: 0;
}
.coastal-storymap .stat-cell .stat-n {
  align-self: end; /* one-line figures sit on the label, like the wrapped one */
}

.coastal-storymap .stat-n {
  margin-bottom: 10px;
  color: var(--escap-gold);
  font-family: var(--font-condensed);
  font-size: clamp(2.4rem, 3.5vw, 3.6rem);
  font-variant-numeric: tabular-nums;
  font-weight: var(--weight-bold);
  line-height: 1;
}

.coastal-storymap .stat-lbl {
  color: rgba(255, 255, 255, 0.6);
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  line-height: 1.45;
  text-transform: uppercase;
}
/* Narrow cells: the forced <br> between the two label halves left single
   words stranded ('BY', 'EXPOSED'); let the halves flow as one sentence. */
@media (max-width: 900px) {
  .coastal-storymap .stat-lbl br { display: none; }
  .coastal-storymap .stat-lbl br + span::before { content: ' '; }
}

/* min-width (reversed from this file's other max-width desktop-first overrides):
   compensates for .wrap's max-width: var(--container-lg) freezing .stat-cell
   width while .stat-n's 3.5vw clamp component keeps growing, so stat text
   wraps to 3 lines instead of 2 across ≈1204–1646px. Applies to all stat
   cells uniformly (not just specific positions). */
@media (min-width: 1200px) {
  .coastal-storymap .stat-cell .stat-n {
    font-size: clamp(2.4rem, 2.6vw, 2.8rem);
  }
}

/* paper bg — historic disasters, coastal values, tools */
.coastal-storymap #historic-disasters,
.coastal-storymap #why-coastal,
.coastal-storymap #tools {
  background: var(--paper);
}
/* white bg — events, funding */
.coastal-storymap #events,
.coastal-storymap #funding {
  background: var(--white);
}
/* light-blue wash — global-initiatives */
.coastal-storymap #global-initiatives {
  background: var(--escap-blue-wash);
}
/* dark closing section */
.coastal-storymap #resources {
  background: var(--escap-blue-deep);
}

/* Full Width Map Layout override */
.coastal-storymap #events {
  padding-left: 0 !important;
  padding-right: 0 !important;
}
.coastal-storymap #events .wrap {
  /* The section's padding is 0 for the full-bleed map, so the gutter lives on
     .wrap; widen it by that gutter so the text column still matches the
     other sections' 1140px (it started 32px in at 1440). */
  max-width: calc(var(--container-lg) + 2 * var(--space-7));
  padding-left: var(--space-7);
  padding-right: var(--space-7);
  margin-bottom: var(--space-7);
}
@media (max-width: 640px) {
  .coastal-storymap #events .wrap {
    padding-left: var(--space-4);
    padding-right: var(--space-4);
  }
}

/* Leaflet Map & Cooperative Gesture Overlay */
/* Full-bleed: top/bottom rules only, no side borders, no radius — index.html used
   to set exactly this inline, which shadowed a conflicting 520px rule here. The
   inline style is gone; this is now the only place the map's box is defined. */
.coastal-storymap #leaflet-map {
  width: 100%;
  height: clamp(560px, 72vh, 820px);
  border-radius: 0;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  position: relative;
  overflow: hidden;
  background: var(--bg-soft);
  z-index: 1;
}

.coastal-storymap .map-container-relative {
  position: relative;
  width: 100%;
}

/* Fullscreen map (the ⤢ control under Leaflet's zoom buttons). The panel is the
   whole .map-container-relative, so the filter pills, year slider and WMS legend
   travel with the map; the pills stay absolutely positioned against it exactly as
   they are inline. Only .map-frame is in flow, so flex:1 hands it the full height
   — under 640px, where the pills return to flow, flex splits the box for them. */
.coastal-storymap .map-container-relative:popover-open {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--bg-soft);
  display: flex;
  flex-direction: column;
}

.coastal-storymap .map-container-relative:popover-open::backdrop {
  background: rgba(17, 24, 39, 0.7);
}

.coastal-storymap .map-container-relative:popover-open .map-frame {
  flex: 1;
  min-height: 0;
}

/* Beats the clamp(560px, 72vh, 820px) on #leaflet-map: same id, three classes. */
.coastal-storymap .map-container-relative:popover-open #leaflet-map {
  height: 100%;
  border-top: 0;
  border-bottom: 0;
}

/* Icon only — the .leaflet-bar box, borders and 44px touch sizing come from
   Leaflet's own control CSS and the .leaflet-touch rule further down. 15px
   matches .trend-card .expand-btn svg, whose glyph this reuses. */
.coastal-storymap .map-fullscreen-ctl a {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Both icons scoped under .map-fullscreen-ctl so these names can't collide with
   .trend-card .expand-btn, which is a real <button>, not an icon. */
.coastal-storymap .map-fullscreen-ctl .expand-btn,
.coastal-storymap .map-fullscreen-ctl .compress-btn {
  width: 15px;
  height: 15px;
}

/* Corners point out to enter, in to leave. */
.coastal-storymap .map-fullscreen-ctl .compress-btn,
.coastal-storymap .map-container-relative:popover-open .map-fullscreen-ctl .expand-btn {
  display: none;
}

.coastal-storymap .map-container-relative:popover-open .map-fullscreen-ctl .compress-btn {
  display: block;
}

/* escap-design-system-scoped.css:394 underlines every `a:hover` under
   .coastal-storymap, which catches Leaflet's control buttons — the zoom +/− as
   much as the fullscreen toggle. Killed here for the whole .leaflet-bar rather
   than per-control; the attribution links outside it stay underlined, as real
   links should. */
.coastal-storymap .leaflet-bar a,
.coastal-storymap .leaflet-bar a:hover,
.coastal-storymap .leaflet-bar a:focus {
  text-decoration: none;
}

/* Containing block for the two map-anchored overlays (gesture hint, WMS legend).
   Always exactly the map's box — unlike .map-container-relative, which also
   holds the filter pills and grows under 640px when those return to flow. */
.coastal-storymap .map-frame {
  position: relative;
  width: 100%;
}

.coastal-storymap .map-gesture-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(17, 24, 39, 0.75);
  backdrop-filter: blur(3px);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  z-index: 1000;
}

.coastal-storymap .map-gesture-overlay.active {
  opacity: 1;
  pointer-events: none;
}

.coastal-storymap .map-gesture-overlay p {
  font-size: 1.1rem;
  font-family: var(--font-sans);
  font-weight: var(--weight-medium);
  text-align: center;
  padding: var(--space-4) 28px;
  background: rgba(23, 37, 84, 0.9);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-lg);
  margin: 0;
  color: var(--white);
}

.coastal-storymap .map-gesture-overlay b {
  color: var(--escap-gold);
}

/* Leaflet Pulse Custom Markers */
.coastal-storymap .custom-map-marker {
  background: transparent;
  border: none;
}

.coastal-storymap .map-pin-div {
  position: relative;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: transform 0.2s ease;
}

.coastal-storymap .map-pin-div:hover {
  transform: scale(1.15);
}

.coastal-storymap .pin-ripple {
  position: absolute;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  animation: pin-pulse 2s 3 ease-out forwards; /* finite (WCAG 2.2.2), ends faded out */
  pointer-events: none;
}

.coastal-storymap .pin-core {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: currentColor;
  border: 2px solid var(--white);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
  z-index: 2;
  transition: transform 0.2s ease;
}

.coastal-storymap .map-pin-div:hover .pin-core {
  transform: scale(1.2);
}

/* Pulse Color Classes matching UN Accent palette tags */
.coastal-storymap .map-pin-div.tag-ts { color: var(--escap-blue); }
.coastal-storymap .map-pin-div.tag-ts .pin-ripple { background: rgba(0, 104, 184, 0.45); }

.coastal-storymap .map-pin-div.tag-cy { color: var(--un-yellow-shade); }
.coastal-storymap .map-pin-div.tag-cy .pin-ripple { background: rgba(177, 109, 3, 0.5); }
/* Cyclones never pulse. With a track they show only the line; the two without
   one (Winnie 2004, Ulysses 2020) keep a static dot so they stay visible. */
.coastal-storymap .map-pin-div.tag-cy .pin-ripple { display: none; }
.coastal-storymap .map-pin-div.tag-cy.has-track .pin-core { display: none; }

/* Direction-of-travel arrowheads along cyclone track polylines — colored to
   match the track's tag-cy token. Plain CSS triangle, no image asset.

   The glyph's 10x8 border-triangle box must be centred in the 14x14 divIcon,
   otherwise it sits at the icon's top-left and every arrow renders 3.6px up
   and left of the track (measured constant (-2,-3)px across all rotations —
   transform-origin pivots the glyph around its own off-centre midpoint, so
   rotating never corrects it). The bearing math is fine: applied rotation
   tracks the true on-screen segment angle to within 0.1 degrees. */
.coastal-storymap .cyclone-track-arrow-inner {
  position: relative;
  display: none;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* An ancestor's display: none suppresses a position: absolute descendant
   regardless of the descendant's own display value, so hiding this wrapper
   alone also hides .cyclone-track-arrow-wind — no separate display rule
   needed on that descendant. */
.coastal-storymap .cyclone-track-arrow.cyclone-track-arrow--active .cyclone-track-arrow-inner {
  display: flex;
}

.coastal-storymap .cyclone-track-arrow-glyph {
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 8px solid var(--un-yellow-shade);
  transform-origin: center;
}

/* Positioned absolutely so it sits outside the 14x14 divIcon box without
   disturbing the glyph's flex-centered position or its rotation transform. */
.coastal-storymap .cyclone-track-arrow-wind {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  white-space: nowrap;
  font-size: 10px;
  font-weight: 600;
  line-height: 1;
  color: var(--un-yellow-shade);
  background: rgba(255, 255, 255, 0.85);
  padding: 1px 4px;
  border-radius: 3px;
  pointer-events: none;
}

/* Marching-ants dash-flow animation on the cyclone track polyline itself,
   applied via Leaflet's Path `className` option in showCyclonePath(). */
.coastal-storymap .cyclone-track-line-animated {
  animation: cyclone-dash-flow 1s linear 3; /* finite: WCAG 2.2.2 */
}

@keyframes cyclone-dash-flow {
  0% { stroke-dashoffset: 0; }
  100% { stroke-dashoffset: -8; }
}

.coastal-storymap .map-pin-div.tag-fl { color: var(--un-orange-aa); }
.coastal-storymap .map-pin-div.tag-fl .pin-ripple { background: rgba(207, 63, 11, 0.5); }

@keyframes pin-pulse {
  0% {
    transform: scale(0.5);
    opacity: 0.95;
  }
  100% {
    transform: scale(2.8);
    opacity: 0;
  }
}

@keyframes tif-spin {
  to { transform: rotate(360deg); }
}

.coastal-storymap .map-pin-div.tif-loading .pin-ripple {
  animation: tif-spin 0.7s linear infinite;
  border: 2px solid currentColor;
  border-color: currentColor transparent transparent transparent;
  background: transparent;
  opacity: 0.85;
  transform-origin: center;
}

/* Premium Leaflet Tooltips & Popups */
/* Tooltip structure */
.coastal-storymap .tooltip-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
  border-bottom: 1px solid var(--border);
  padding-bottom: 6px;
}

.coastal-storymap .tooltip-year {
  font-family: var(--font-condensed);
  font-weight: var(--weight-bold);
  color: var(--escap-blue);
  font-size: 1.05rem;
}

/* Sheet date (full date on tsunami rows, month-year elsewhere) and the row's
   country/location share the header's left side; they wrap onto a second line
   in a 360px popup rather than squeezing the hazard chip. */
.coastal-storymap .tooltip-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--space-2);
  min-width: 0;
}

.coastal-storymap .tooltip-place {
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: var(--weight-semibold);
  color: var(--fg-muted);
}

/* Tsunami and cyclone bodies open with a prose lead above the facts table. */
.coastal-storymap .tooltip-desc + .tooltip-facts {
  margin-top: var(--space-2);
}

.coastal-storymap .tooltip-tag {
  font-size: 0.62rem;
  font-family: var(--font-sans);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
  padding: 3px var(--space-2);
  border-radius: var(--radius-1);
}

.coastal-storymap .tooltip-tag.tag-ts { background: var(--un-blue-tint-50); color: var(--un-blue-aaa); border: 1px solid var(--un-blue-tint); }
.coastal-storymap .tooltip-tag.tag-cy { background: var(--un-yellow-tint-50); color: var(--un-yellow-shade); border: 1px solid var(--un-yellow-tint); }
.coastal-storymap .tooltip-tag.tag-fl { background: var(--un-orange-tint-50); color: var(--un-orange-aa); border: 1px solid var(--un-orange-tint); }

.coastal-storymap .tooltip-title {
  font-family: var(--coastal-title-font);
  font-weight: var(--weight-bold);
  color: var(--escap-blue-dark);
  margin: 0 0 6px;
  font-size: var(--coastal-card-title-size);
  line-height: var(--lh-tight);
}

.coastal-storymap .tooltip-desc {
  color: var(--fg-muted);
  font-size: 0.8rem;
  line-height: var(--lh-base);
  margin: 0;
}

/* Cyclone popups render the sheet's labelled fields as a two-column table;
   prose bodies (tsunami, storm surge) stay in .tooltip-desc. The label column
   is capped rather than max-content so a long label ("Impacted countries")
   wraps instead of squeezing the values in a 360px popup. Grid flips on its
   own under [dir="rtl"] — no separate rule needed. */
.coastal-storymap .tooltip-facts {
  display: grid;
  grid-template-columns: minmax(0, 7rem) minmax(0, 1fr);
  gap: 4px var(--space-3);
  margin: 0;
  font-size: 0.8rem;
  line-height: var(--lh-base);
}

.coastal-storymap .tooltip-facts dt {
  color: var(--fg-muted);
  font-weight: var(--weight-semibold);
}

.coastal-storymap .tooltip-facts dd {
  color: var(--fg);
  margin: 0;
}

/* 4. Climate */
.coastal-storymap #climate {
  background: var(--escap-blue-deep);
  padding-top: 64px;
  padding-bottom: 64px;
}

.coastal-storymap #climate .ca-title {
  color: var(--white);
}

.coastal-storymap #climate .ca-subtitle {
  color: var(--escap-blue-wash);
}

.coastal-storymap .glacier-split-layout {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 48px;
  margin-top: 32px;
}

@media (max-width: 900px) {
  .coastal-storymap .glacier-split-layout {
    flex-direction: column;
    gap: 32px;
  }
}

.coastal-storymap .glacier-chart-container {
  flex: 1 1 360px;
  max-width: 420px;
  display: flex;
  justify-content: center;
}

.coastal-storymap .glacier-donut-svg {
  width: 100%;
  height: auto;
  max-width: 360px;
  overflow: visible;
}

.coastal-storymap .glacier-segment {
  cursor: pointer;
  transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), filter 0.3s ease, opacity 0.3s ease;
  transform-origin: 150px 150px;
  stroke: var(--escap-blue-deep);
  stroke-width: 2px;
}

.coastal-storymap .segment-cyclone { fill: #2d5b73; }
.coastal-storymap .segment-communities { fill: #733f3d; }
.coastal-storymap .segment-glacier { fill: #3d633e; }
.coastal-storymap .segment-fisheries { fill: #8c5225; }

.coastal-storymap .glacier-segment:hover,
.coastal-storymap .glacier-segment:focus-visible,
.coastal-storymap .glacier-segment.active-segment {
  transform: scale(1.05);
  filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.4));
  opacity: 1 !important;
  stroke-width: 0;
}

.coastal-storymap .glacier-donut-svg:hover .glacier-segment:not(:hover),
.coastal-storymap .glacier-donut-svg.has-active .glacier-segment:not(.active-segment) {
  opacity: 0.45;
}

.coastal-storymap .donut-hole {
  fill: var(--escap-blue-deep);
}

.coastal-storymap .donut-hole-text {
  font-family: var(--font-sans);
  text-anchor: middle;
  fill: var(--white);
  pointer-events: none;
}

.coastal-storymap .donut-hole-text.main-word {
  font-size: 15px;
  font-weight: 700;
}

.coastal-storymap .donut-hole-text.sub-word {
  font-size: 13px;
  font-weight: 500;
  opacity: 0.95;
}

.coastal-storymap .segment-label {
  font-family: var(--font-sans);
  font-size: 10px;
  font-weight: 500;
  fill: var(--white);
  text-anchor: middle;
  pointer-events: none;
  opacity: 0.95;
  transition: opacity 0.3s ease;
}

.coastal-storymap .glacier-donut-svg:hover .segment-label,
.coastal-storymap .glacier-donut-svg.has-active .segment-label {
  opacity: 0.3;
}

.coastal-storymap .glacier-donut-svg:hover .glacier-segment:hover + .segment-label,
.coastal-storymap .glacier-donut-svg:hover .glacier-segment:hover + * + .segment-label,
.coastal-storymap .glacier-segment.active-segment + .segment-label,
.coastal-storymap .glacier-segment.active-segment + * + .segment-label {
  opacity: 1 !important;
}

.coastal-storymap .glacier-info-panel {
  flex: 1 2 460px;
  background: #fcfaf2; /* Soft cream card background */
  border-radius: var(--radius-3);
  padding: 20px;
  box-shadow: var(--shadow-lg), 0 20px 40px rgba(0,0,0,0.25);
  border: 1px solid rgba(255, 255, 255, 0.1);
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.coastal-storymap .glacier-info-item {
  display: flex;
  gap: 16px;
  padding: 12px 16px;
  border-radius: var(--radius-2);
  background: transparent;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.3s var(--ease-standard), border-color 0.3s var(--ease-standard), box-shadow 0.3s var(--ease-standard), transform 0.3s var(--ease-standard);
}

.coastal-storymap .ca-info-title {
  margin: 0 0 6px 0;
  color: var(--gray-900);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-card-title-size);
  font-weight: 700;
}

.coastal-storymap .glacier-info-item p {
  margin: 0;
  color: var(--gray-700);
  font-size: 0.88rem;
  line-height: 1.45;
}

.coastal-storymap .glacier-info-item:hover,
.coastal-storymap .glacier-info-item.active-item {
  background: var(--white) !important;
  border-color: rgba(0, 0, 0, 0.08) !important;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08) !important;
  transform: translateX(6px);
}

.coastal-storymap .glacier-indicator-box {
  width: 14px;
  height: 14px;
  border-radius: var(--radius-1);
  flex-shrink: 0;
  margin-top: 4px;
}

.coastal-storymap .box-cyclone { background: #2d5b73; }
.coastal-storymap .box-communities { background: #733f3d; }
.coastal-storymap .box-glacier { background: #3d633e; }
.coastal-storymap .box-fisheries { background: #8c5225; }

.coastal-storymap .tool-name {
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}

.coastal-storymap .tool-body {
  color: var(--fg-muted);
  font-size: var(--coastal-card-body-size);
  line-height: var(--lh-base);
}

/* bg-soft — explore-climawise */
.coastal-storymap #explore-climawise {
  background: var(--bg-soft);
}
/* climacoast white, so it alternates with explore-climawise (bg-soft) and the
   dark #pilots above it, and funding (white) stays distinct after bg-soft */
.coastal-storymap #climacoast {
  background: var(--white);
}
/* forecasting gets blue-wash to break up the near-white run with data/objectives */
.coastal-storymap #forecasting {
  background: var(--escap-blue-wash);
}


/* 6. Objectives */
.coastal-storymap .tool-card {
  border: 1px solid var(--border);
  background: var(--white);
  transition: border-color var(--t-base) var(--ease-standard), box-shadow var(--t-base) var(--ease-standard);
}

.coastal-storymap .split-wrap {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(320px, 1.1fr);
  gap: 56px;
  align-items: center;
}

.coastal-storymap .resource-grid,
.coastal-storymap .partner-grid {
  display: grid;
  gap: 16px;
  margin-top: 64px;
}

.coastal-storymap .resource-card {
  padding: 28px;
  border: 1px solid var(--border);
  background: var(--white);
}

.coastal-storymap .resource-card span {
  display: inline-block;
  margin-bottom: 16px;
  color: var(--escap-blue);
  font-family: var(--font-condensed);
  font-size: 2.4rem;
  font-weight: var(--weight-bold);
  line-height: 1;
}

/* Global Frameworks diagram (#global-initiatives): one client-supplied image,
   a plain-text hub under it, and the four tinted descriptions below. The intro
   lead paragraphs sit full-width above the diagram, not in a side column. */
.coastal-storymap .gi-diagram {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: var(--space-6);
}

/* The diagram is one client-supplied image (arrows, labels and logos baked in),
   so the section keeps no per-logo or per-category styling. Click-to-enlarge is
   the story's existing [data-lightbox] overlay. */
.coastal-storymap .gi-diagram-img {
  width: 100%;
  max-width: 1200px;
  height: auto;
}

.coastal-storymap .gi-hub {
  font-weight: var(--weight-bold);
  /* Scales down so it never outweighs the section's h2 on phones. */
  font-size: clamp(1.1rem, 1.5vw + 0.6rem, 1.7rem);
  color: var(--fg);
  text-align: center;
  margin: 0;
  line-height: 1.25;
  padding: var(--space-1);
  border-radius: var(--radius-1);
}

.coastal-storymap .gi-descriptions {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  width: 100%;
  margin-top: var(--space-4);
}

.coastal-storymap .gi-descriptions p {
  margin: 0;
  font-size: 0.9rem;
  color: var(--fg-muted);
  text-align: center;
  line-height: var(--lh-base);
  padding: var(--space-2);
  border-radius: var(--radius-1);
  box-sizing: border-box;
}


/* Tinted description boxes: each framework group's hue at low opacity, matching
   its arrow in the diagram image. */
.coastal-storymap .gi-descriptions p[data-cat="disaster"] { background: rgba(28, 109, 191, 0.1); }
.coastal-storymap .gi-descriptions p[data-cat="ocean"]    { background: rgba(74, 143, 60, 0.1); }
.coastal-storymap .gi-descriptions p[data-cat="climate"]  { background: rgba(232, 137, 46, 0.1); }
.coastal-storymap .gi-descriptions p[data-cat="sdg"]      { background: rgba(41, 168, 216, 0.1); }

@media (max-width: 900px) {
  .coastal-storymap .gi-hub {
    margin-top: var(--space-4);
  }

  .coastal-storymap .gi-descriptions {
    grid-template-columns: 1fr;
  }
}

.coastal-storymap .logos {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 40px;
  flex-wrap: wrap;
  margin-top: 48px;
}
.coastal-storymap .logo {
  max-height: 120px;
  max-width: 300px;
  object-fit: contain;
}
.coastal-storymap .partner-grid {
  grid-template-columns: repeat(4, 1fr);
}

/* Consolidated funding + partners section — tighten spacing to help fit one screen.
   Only the second heading gets the gap; "Funded by" keeps the usual 8px under its eyebrow. */
.coastal-storymap #funding .partners-title {
  margin-top: 48px;
}

.coastal-storymap #funding .partner-grid {
  margin-top: 32px;
}

/* The grid's gap spaces the stacked logos; a top margin doubled it (104px at 768). */
.coastal-storymap .split-wrap > .logos {
  margin-top: 0;
}

/* Direct children only: as a descendant selector it also hit .partner-logo-container
   and its min-height/padding made every logo a different size. */
.coastal-storymap .partner-grid > div {
  min-height: 140px;
  display: flex;
  align-items: center;
  padding: 20px;
  background: var(--white);
  color: var(--escap-blue);
  font-size: 0.72rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}

/* 7. Tools — CS-013 workbench. Full-bleed two-pane layout: a sticky
   numbered stepper (.tools-steps, the four .flow-card rows) beside a 3-col
   grid of .tool-card. Opening a step spotlights its linked tools and dims
   the rest (.is-filtering, set by the flow-card JS). Same pattern as
   .coastal-area-shell for the bleed: width from the viewport, margin pulls
   it out of .wrap's 1140px column. */
.coastal-storymap .tools-workbench {
  /* Never narrower than the heading column: below ~1204px the bleed width was
     inside the 32px section gutter and the steps started 8px right of the h2. */
  width: max(100%, calc(100vw - 2 * var(--space-8)));
  margin-left: min(0px, calc(50% - 50vw + var(--space-8)));
  margin-top: var(--space-8);
  display: grid;
  grid-template-columns: minmax(300px, 420px) minmax(0, 1fr);
  gap: var(--space-8);
  align-items: start;
}
.coastal-storymap .tools-steps {
  position: sticky;
  top: 96px; /* raw: clears the fixed site nav */
}
.coastal-storymap .tools-deck {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}
.coastal-storymap .tools-deck.is-filtering .tool-card:not(.is-linked) {
  opacity: 0.35;
  filter: saturate(0.4);
  transform: none;
  box-shadow: var(--shadow-sm);
}

/* card chrome matches the CS-005 .coasts-card recipe */
.coastal-storymap .tool-card {
  position: relative;
  padding: 36px 28px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  border-top: 4px solid var(--escap-blue);
  box-shadow: var(--shadow-sm);
  transition: transform var(--t-base) var(--ease-standard), box-shadow var(--t-base) var(--ease-standard),
    opacity var(--t-base) var(--ease-standard), filter var(--t-base) var(--ease-standard);
}

.coastal-storymap .tool-card:hover,
.coastal-storymap .tool-card.is-linked {
  transform: translateY(-6px);
  box-shadow: var(--shadow-md);
}

.coastal-storymap .tool-card.is-linked {
  background: var(--escap-blue);
  border-top-color: var(--white);
}

.coastal-storymap .tool-card.is-linked .tool-name {
  color: var(--white);
}

.coastal-storymap .tool-card.is-linked .tool-body {
  color: var(--white);
}

.coastal-storymap .tool-name {
  margin-bottom: 12px;
  font-size: var(--coastal-card-title-size);
}

.coastal-storymap .country-deck .tool-body {
  margin-bottom: 16px;
  color: var(--fg-muted);
}

/* provenance badge, flush into the card's bottom-right corner */
.coastal-storymap .tool-badge {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 100%;
  padding: 5px 12px;
  border-radius: var(--radius-1) 0 0 0;
  background: var(--escap-gold);
  color: var(--escap-blue-deep);
  font-family: var(--font-sans);
  font-size: 0.64rem;
  font-weight: var(--weight-bold);
  line-height: 1.35;
  text-align: center;
}

.coastal-storymap .tool-learn-more {
  display: inline-block;
  text-decoration: none;
  margin-top: auto;
  padding: 6px 14px;
  border: 1px solid var(--escap-blue);
  background: var(--escap-blue-wash);
  color: var(--escap-blue-deep);
  font-family: var(--font-sans);
  font-size: 0.72rem;
  font-weight: var(--weight-medium);
}

/* 8. Pilots */
.coastal-storymap #pilots {
  background: var(--escap-blue-deep);
}

.coastal-storymap .tool-preview {
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--white);
  box-shadow: var(--shadow-md);
}

/* Slide 26 ClimaWise: the recording fills the preview frame under its chrome
   bar. `display:block` kills the inline-baseline gap; the aspect-ratio holds
   the box before metadata loads, so `preload="none"` costs no layout shift. */
/* Tool sections (CS-018/CS-019): copy on the inline-start side, the Explore
   CTA pinned to the inline-end edge of the same row. `margin-inline-start`
   (not `margin-left`) so RTL/Dhivehi flips it to the correct edge, and the
   420px flex-basis is what drops the CTA onto its own line before the copy
   gets too narrow to read. */
.coastal-storymap .tool-intro {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  /* Breathing room before .tool-preview below. */
  margin-bottom: var(--space-7);
}
.coastal-storymap .tool-intro-copy {
  flex: 1 1 420px;
  min-width: 0;
}
.coastal-storymap .tool-intro-cta {
  flex: 0 0 auto;
  /* .escap-btn carries `margin-top: 16px` for its stacked use in #funding;
     in this row that pushes the CTA below the copy's last baseline. Reset it
     and lift the button clear of that baseline instead. */
  margin-top: 0;
  margin-bottom: var(--space-5);
}

.coastal-storymap .cw-video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--border);
  border-top: none;
  border-bottom-left-radius: var(--radius-2);
  border-bottom-right-radius: var(--radius-2);
  background: var(--bg-card);
}

/* Pause/play toggle over each looping video (WCAG 2.2.2), added by coastal-story.js. */
.coastal-storymap .has-media-toggle {
  position: relative;
}
.coastal-storymap .media-toggle {
  position: absolute;
  right: var(--space-2);
  bottom: var(--space-2);
  z-index: var(--z-raised);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--space-7);
  height: var(--space-7);
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: var(--escap-blue-dark);
  color: var(--white);
  font-size: var(--text-xs);
  line-height: 1;
  cursor: pointer;
  opacity: 0.85;
}
.coastal-storymap .media-toggle:hover {
  opacity: 1;
}
.coastal-storymap .media-toggle:focus-visible {
  opacity: 1;
  outline: 3px solid var(--escap-blue);
  outline-offset: 2px;
}
@media (hover: none) {
  .coastal-storymap .media-toggle {
    width: 44px; /* raw: 44px touch target, between --space-8 and --space-9 */
    height: 44px;
  }
}

.coastal-storymap .preview-bar {
  height: 42px;
  background: var(--escap-blue-dark);
  display: flex;
  align-items: center;
  padding: 0 16px;
}

/* Restored: ebd2fdc dropped these with the slide 39/40 CSS sweep while the
   markup stayed in index.html, leaving the dots as zero-width spans and the
   title as near-black body text on the dark bar. */
.coastal-storymap .preview-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.3);
  margin-right: 4px;
}

.coastal-storymap .preview-title {
  font-size: 0.65rem;
  color: rgba(255, 255, 255, 0.5);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  margin-left: 8px;
}

.coastal-storymap .resource-grid {
  grid-template-columns: repeat(2, 1fr);
  margin-top: 0;
}

.coastal-storymap .resource-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 220px;
}

/* 9. Data */
/* 10. Outputs */
/* Footer */
.coastal-storymap .site-footer {
  padding: 56px 32px;
  background: var(--escap-blue-dark);
  color: rgba(255, 255, 255, 0.68);
}

.coastal-storymap .footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: start;
  justify-content: space-between;
  gap: 32px;
  max-width: var(--container-lg);
  margin: 0 auto;
}

.coastal-storymap .footer-brand {
  color: var(--white);
  font-family: var(--font-condensed);
  font-size: 0.82rem;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}

.coastal-storymap .footer-org {
  margin-top: 6px;
  color: var(--escap-gold);
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}

.coastal-storymap .footer-p {
  max-width: 50ch;
  color: inherit;
  font-size: 0.78rem;
  line-height: var(--lh-base);
}

.coastal-storymap .footer-meta {
  color: rgba(255, 255, 255, 0.78);
  font-family: var(--font-sans);
  font-size: 0.6rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  line-height: 2;
  text-align: right;
  text-transform: uppercase;
}

.coastal-storymap .footer-note {
  margin-top: 6px;
  color: rgba(255, 255, 255, 0.78);
  font-size: 0.58rem;
}

/* Premium Buttons & Controls */
.coastal-storymap .escap-btn {
  /* inline-flex + min-height, not inline-block: the Explore CTAs in CS-018/019
     are primary controls and inline-block leaves them ~39px tall, under the
     44px touch target interaction-contracts.test.js enforces. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 20px;
  background: var(--escap-blue);
  color: var(--white);
  text-decoration: none;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  font-weight: var(--weight-bold);
  border-radius: var(--radius-1);
  transition: background var(--t-fast) var(--ease-standard);
  margin-top: 16px;
  text-align: center;
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
}
/* Dark, not pale: white on --escap-blue-pale is 2.4:1. */
.coastal-storymap .escap-btn:hover {
  background: var(--escap-blue-dark);
  color: var(--white);
}

/* Slide 3 Map Styles */
/* ── Controls floated over the events map ──────────────────────────────────
   Frosted pill: low-alpha white + blur, so the basemap still reads through.
   z-index 500 puts them above #leaflet-map (z-index 1) and everything inside it
   — Leaflet's own zoom/attribution controls included — but deliberately BELOW
   .map-gesture-overlay (1000): that overlay is a transient, pointer-events:none
   hint whose whole job is to dim the map area, so it should dim these too rather
   than be occluded by them. Each pill is positioned clear of Leaflet's chrome
   (zoom control top-left, attribution bottom-right); only the pills take pointer
   events, nothing else is laid over the map, so drag/zoom stay live everywhere
   else. */
.coastal-storymap .map-overlay-ctl {
  position: absolute;
  z-index: 500;
  background: rgba(255, 255, 255, 0.62);
  -webkit-backdrop-filter: blur(10px) saturate(1.5);
  backdrop-filter: blur(10px) saturate(1.5);
  border: 1px solid var(--border);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-sm);
}
/* No blur available (older Firefox, blur disabled): fall back to a near-opaque
   pill rather than leaving text over a live map at 62% white. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .coastal-storymap .map-overlay-ctl {
    background: rgba(255, 255, 255, 0.94);
  }
}

.coastal-storymap .map-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  justify-content: center;
  top: 14px;
  /* Centred with auto margins against both edges, NOT `left: 50%` + a shift:
     for an absolutely positioned box, `left: 50%` alone also caps shrink-to-fit
     at half the container, which silently wrapped the four buttons onto two rows
     at 768px. This also sidesteps `.rv.in { transform: none }` entirely, and
     mirrors for free under RTL. The max-width keeps the pill out of Leaflet's
     ~54px zoom-control gutter at either end. */
  inset-inline: 0;
  width: fit-content;
  margin-inline: auto;
  max-width: calc(100% - 140px);
  padding: 4px;
}
.coastal-storymap .map-filter-btn {
  padding: 8px 16px;
  border: 1px solid transparent;
  border-radius: calc(var(--radius-2) - 2px);
  background: transparent;
  color: var(--fg-muted);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: var(--weight-medium);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
  transition: all var(--t-fast) var(--ease-standard);
}
.coastal-storymap .map-filter-btn:hover:not(:disabled), .coastal-storymap .map-filter-btn.active {
  background: var(--escap-blue);
  color: var(--white);
  border-color: var(--escap-blue);
}
/* A hazard with no events inside the selected year span (see .map-year-filter). */
.coastal-storymap .map-filter-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* Year-range filter, floated over the bottom of the map. Wordless by design —
   the two numeric readouts are the only visible text, so the control adds
   nothing translatable. One line: start year, track, end year. Under RTL the
   flex row reverses, which puts the earliest year on the same side the native
   range puts it. */
.coastal-storymap .map-year-filter {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 12px;
  /* 30px, not 14px: Leaflet's attribution strip owns the bottom ~17px of the
     map and the two overlap horizontally once the viewport drops to ~768px.
     Same auto-margin centring as .map-filters above. */
  bottom: 30px;
  inset-inline: 0;
  width: fit-content;
  margin-inline: auto;
  padding: 8px 16px;
  max-width: calc(100% - 32px);
}
.coastal-storymap .year-readout {
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  color: var(--fg-muted);
  /* Fixed slot so the track doesn't jitter sideways as digits change. */
  font-variant-numeric: tabular-nums;
  min-width: 4ch;
  text-align: center;
  white-space: nowrap;
}
.coastal-storymap .year-range {
  position: relative;
  display: grid;
  width: clamp(150px, 40vw, 380px);
  min-height: 24px;
}
/* Rail (::before) and selected-span fill (::after), both centred on the same
   3px line. No `transform` for the centring — .rv.in wipes transforms, and this
   sits inside a .rv element. */
.coastal-storymap .year-range::before,
.coastal-storymap .year-range::after {
  content: '';
  position: absolute;
  top: 50%;
  margin-top: -1.5px;
  height: 3px;
  border-radius: 2px;
  pointer-events: none;
}
.coastal-storymap .year-range::before {
  left: 0;
  right: 0;
  background: var(--border);
}
/* `inset-inline-start`, not `left`: the native range reverses under RTL (1992
   lands on the right), so the fill has to be measured from the same end the
   browser measures the thumbs from. One logical property mirrors it; the JS
   keeps emitting plain left-to-right percentages. */
.coastal-storymap .year-range::after {
  inset-inline-start: var(--year-from, 0%);
  width: var(--year-span, 100%);
  background: var(--escap-blue);
}
/* Both inputs occupy the same grid cell. The track is invisible and
   pointer-transparent so the lower input's thumb stays grabbable where the two
   overlap; only the thumbs take pointer events. */
.coastal-storymap .year-slider {
  grid-area: 1 / 1;
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 100%;
  margin: 0;
  background: none;
  pointer-events: none;
}
.coastal-storymap .year-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--white);
  background: var(--escap-blue);
  cursor: pointer;
}
.coastal-storymap .year-slider::-moz-range-thumb {
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid var(--white);
  background: var(--escap-blue);
  cursor: pointer;
}
.coastal-storymap .year-slider::-moz-range-track {
  background: none;
}
.coastal-storymap .year-slider:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--escap-blue);
  outline-offset: 2px;
}
.coastal-storymap .year-slider:focus-visible::-moz-range-thumb {
  outline: 2px solid var(--escap-blue);
  outline-offset: 2px;
}

/* WMS colour-bar legend for the tsunami rasters. `inset-inline-start`, not
   `left`: "bottom-left" becomes bottom-right in the RTL (dv) build, same
   treatment the year-range fill already uses. Leaflet's attribution sits
   bottom-right by default, so this corner is free in LTR; in RTL the two swap
   sides, which is why the bottom offset clears the attribution strip. */
.coastal-storymap .map-wms-legend {
  display: flex;
  align-items: stretch;
  gap: 8px;
  inset-inline-start: 14px;
  bottom: 30px;
  padding: 8px 10px;
}
/* .map-overlay-ctl sets display:flex, which outranks the UA's [hidden] rule. */
.coastal-storymap .map-wms-legend[hidden] {
  display: none;
}
.coastal-storymap .wms-legend-bar {
  display: block;
  width: 14px;
  height: 104px;
  border: 1px solid var(--border);
  border-radius: 2px;
}
/* Three ticks spread over the bar's full height. The values match the ncWMS
   scale exactly (max at top, 0.51 is the server's own midpoint tick for a
   0.02–1 linear range) — nothing here is estimated from the gradient. */
.coastal-storymap .wms-legend-ticks {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  font-family: var(--font-sans);
  font-size: 0.62rem;
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-wider);
  color: var(--fg-muted);
  font-variant-numeric: tabular-nums;
}

/* Under 640px (where .side-nav also drops out) the two big pills would swallow
   the map, so they fall back to static flow — filters above, year range below —
   and lose the frosting they no longer need. The small legend stays overlaid. */
@media (max-width: 639px) {
  .coastal-storymap .map-filters,
  .coastal-storymap .map-year-filter {
    position: static;
    width: auto;
    max-width: none;
    margin: 12px 16px;
    background: var(--white);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .coastal-storymap .year-range {
    width: clamp(120px, 44vw, 380px);
  }
}
@keyframes pulse-ring {
  0% { transform: scale(0.6); opacity: 0.8; }
  100% { transform: scale(1.6); opacity: 0; }
}
.coastal-storymap .tooltip-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.coastal-storymap .tooltip-tag {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 2px;
  font-size: 0.58rem;
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: var(--tracking-wider);
}
.coastal-storymap .tooltip-year {
  font-size: 0.65rem;
  font-weight: var(--weight-bold);
  color: var(--escap-blue);
}
.coastal-storymap .tooltip-title {
  margin: 0 0 6px;
  color: var(--escap-blue);
  font-size: var(--coastal-small-title-size);
  font-weight: var(--weight-medium);
}
/* Slide 5 Historic Disaster Spotlights */
/* CS-003 slide deck: the modal behind a card's "Learn more". Native <dialog>,
   so the backdrop, Esc and focus trapping come from the platform; one slide is
   visible at a time and the prev/next buttons step through them. */
.coastal-storymap .slide-deck {
  width: min(92vw, var(--container-lg));
  max-width: calc(100vw - var(--space-6));
  height: 88vh;
  max-height: calc(100svh - var(--space-6));
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-4);
  background: var(--white);
  color: var(--fg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  margin: auto;
}

.coastal-storymap .slide-deck::backdrop {
  background: rgba(10, 20, 30, 0.78);
}

.coastal-storymap .slide-deck-shell {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

/* One toolbar carries prev | counter | next | close, and stays put while a long
   slide scrolls under it. */
.coastal-storymap .slide-deck-toolbar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-5);
  border-bottom: 1px solid var(--border);
  background: var(--off-white);
}

.coastal-storymap .slide-deck-close {
  /* 44px keeps the tap target at the contract-test minimum, same as .escap-btn */
  width: 44px;
  height: 44px;
  margin-inline-start: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--fg-muted);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.coastal-storymap .slide-deck-close:hover {
  border-color: var(--escap-blue-pale);
  background: var(--escap-blue-wash);
  color: var(--escap-blue);
}

.coastal-storymap .slide-deck-title {
  margin: 0;
  color: var(--escap-blue-dark);
  font-family: var(--coastal-title-font);
  font-size: clamp(var(--text-2xl), 2.4vw, var(--text-4xl));
  font-weight: var(--weight-bold);
  line-height: var(--lh-tight);
  text-wrap: balance;
}

.coastal-storymap .slide-deck-deck {
  max-width: 62ch;
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--text-lg);
  line-height: var(--lh-base);
}

.coastal-storymap .slide-deck-slide {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  min-height: 0;
  padding: clamp(var(--space-6), 5vw, var(--space-10));
  overflow-y: auto;
  scrollbar-gutter: stable;
}

.coastal-storymap .slide-deck-slide > * {
  width: 100%;
  max-width: var(--container-md);
  margin-inline: auto;
}

/* The first slide is an editorial opener, not a document page. Keeping its
   short copy centred gives it deliberate scale instead of leaving a blank
   lower two-thirds of the dialog. */
.coastal-storymap .slide-deck-slide[data-slide-index="0"] {
  justify-content: safe center;
}

.coastal-storymap .slide-deck-slide[data-slide-index="0"] > * {
  max-width: var(--container-sm);
}

.coastal-storymap .slide-deck-slide[data-slide-index="0"] > .slide-deck-split {
  max-width: var(--container-md);
}

.coastal-storymap .slide-deck-slide[data-slide-index="0"] .slide-deck-title {
  padding-inline-start: var(--space-5);
  border-inline-start: var(--space-1) solid var(--un-yellow);
}

.coastal-storymap .slide-deck-slide:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: -2px;
}

.coastal-storymap .slide-deck-slide[hidden] {
  display: none;
}

.coastal-storymap .slide-deck-split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--space-8);
  align-items: start;
}

/* Every deck image and the YouTube embed fit within one screen: a slide never
   needs to scroll past its own media to reach the rest of its content. */
.coastal-storymap .slide-deck-slide img,
.coastal-storymap .slide-deck-embed {
  width: 100%;
  max-height: 56vh;
  object-fit: contain;
}

.coastal-storymap .slide-deck-embed {
  aspect-ratio: 16 / 9;
  border: 0;
}

.coastal-storymap .slide-deck-media {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-3);
  background: var(--off-white);
}

.coastal-storymap .slide-deck-video-fallback {
  align-self: flex-start;
  color: var(--escap-blue);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}

.coastal-storymap .slide-deck-map {
  margin: 0;
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-3);
  background: var(--off-white);
}

/* The deck figure already frames its media; the tool-preview border on
   .cw-video (open top edge for .preview-bar) would double it. */
.coastal-storymap .slide-deck-map .cw-video {
  border: 0;
  border-radius: 0;
}

.coastal-storymap .slide-deck-map figcaption {
  margin-top: var(--space-2);
  color: var(--fg-muted);
  font-size: var(--text-sm);
  line-height: var(--lh-base);
}

.coastal-storymap .slide-deck-copy p {
  max-width: 62ch;
  margin: 0 0 var(--space-4);
  font-size: var(--text-base);
  line-height: var(--lh-base);
}

/* Provisional: the client's slide leaves the image and the animation as boxes,
   so these stay dashed until the real assets arrive. */
.coastal-storymap .slide-deck-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 260px;
  margin: 0;
  border: 2px dashed var(--border);
  border-radius: var(--radius-1);
  background: var(--off-white);
  color: var(--fg-muted);
  font-size: var(--text-sm);
}

.coastal-storymap .slide-deck-cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}

.coastal-storymap .slide-deck-card {
  padding: var(--space-5);
  border: 1px solid var(--escap-blue-pale);
  border-radius: var(--radius-3);
  background: var(--escap-blue-wash);
}

.coastal-storymap .slide-deck-card h4 {
  margin: 0 0 var(--space-2);
  font-family: var(--coastal-title-font);
  color: var(--escap-blue);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-bold);
}

.coastal-storymap .slide-deck-card ul {
  margin: 0;
  padding-inline-start: var(--space-4);
  display: grid;
  gap: 6px;
  font-size: var(--text-base);
  line-height: var(--lh-base);
}

.coastal-storymap .slide-deck-phases {
  margin-block: 0; /* block only: inline auto margins centre it under the title */
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-4);
}

.coastal-storymap .slide-deck-phase {
  min-width: 0;
  padding: var(--space-5);
  border: 1px solid var(--escap-blue-pale);
  border-radius: var(--radius-3);
  background: var(--escap-blue-wash);
}

.coastal-storymap .slide-deck-closing-center {
  margin-top: var(--space-2);
  padding: var(--space-4) var(--space-5);
  border-block: 1px solid var(--escap-blue-pale);
  color: var(--escap-blue-dark);
  font-weight: var(--weight-medium);
  text-align: center;
}

.coastal-storymap .slide-deck-phases dt {
  color: var(--escap-blue);
  font-weight: var(--weight-bold);
  font-size: var(--text-lg);
}

.coastal-storymap .slide-deck-phases dd {
  margin: var(--space-2) 0 0;
  color: var(--fg-muted);
  font-size: var(--text-base);
  line-height: var(--lh-base);
}

.coastal-storymap .slide-deck-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}

.coastal-storymap .slide-deck-stat {
  display: grid;
  align-content: center;
  padding: var(--space-5);
  border: 1px solid var(--escap-blue-pale);
  border-radius: var(--radius-3);
  background: var(--escap-blue-wash);
  text-align: center;
}

.coastal-storymap .slide-deck-stat b {
  display: block;
  color: var(--escap-blue);
  font-family: var(--font-condensed);
  font-size: 2.2rem;
  font-weight: var(--weight-bold);
  line-height: 1.1;
}

.coastal-storymap .slide-deck-stat span {
  color: var(--fg-muted);
  font-size: var(--text-sm);
  line-height: var(--lh-base);
}

/* CS-003 slide 6 timeline: single-rail vertical timeline replacing the old
   centre-trunk flowmap. One card per reform stops the long sentences being
   squeezed into narrow side columns, and the top-to-bottom rail reads as
   progress from 1999 to today. Logical properties keep it RTL-safe;
   step numbers come from a CSS counter so no new i18n strings are needed. */
.coastal-storymap .slide-deck-timeline {
  counter-reset: timeline-step;
  list-style: none;
  margin-block: 0;
  padding: 0;
  padding-inline-start: 8px;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.coastal-storymap .slide-deck-timeline-item {
  counter-increment: timeline-step;
  position: relative;
  padding-inline-start: 44px;
  padding-bottom: var(--space-1);
}

/* The rail runs the full height of the list on the inline-start side. */
.coastal-storymap .slide-deck-timeline-item::before {
  content: '';
  position: absolute;
  inset-inline-start: 21px;
  top: 34px;
  bottom: calc(-1 * var(--space-4));
  width: 2px;
  background: var(--escap-blue);
  opacity: 0.35;
}

/* The last item keeps its rail segment: it now runs on into the closing stop
   below the list. */
.coastal-storymap .slide-deck-timeline-item:last-child::before {
  bottom: calc(-1 * var(--space-4));
}

/* Numbered node: step number sits on the rail, opaque so the rail stops
   visually at each stop. */
.coastal-storymap .slide-deck-timeline-item::after {
  content: counter(timeline-step, decimal-leading-zero);
  position: absolute;
  inset-inline-start: 8px;
  top: 2px;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--escap-blue);
  color: var(--white);
  font-family: var(--font-condensed);
  font-size: 0.75rem;
  font-weight: var(--weight-bold);
  line-height: 1;
}

/* CS-003 tsunami deck: a translated year cannot come from a CSS counter, so
   this modifier swaps the numbered-step node for a real i18n year pill. */
.coastal-storymap .slide-deck-timeline--years .slide-deck-timeline-item {
  padding-inline-start: 92px;
}

.coastal-storymap .slide-deck-timeline--years .slide-deck-timeline-item::before {
  inset-inline-start: 38px;
}

.coastal-storymap .slide-deck-timeline--years .slide-deck-timeline-item::after {
  content: none;
}

.coastal-storymap .slide-deck-timeline-year {
  position: absolute;
  inset-inline-start: 0;
  top: 2px;
  min-width: 76px;
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--escap-blue);
  color: var(--white);
  font-family: var(--font-condensed);
  font-size: var(--text-xs);
  font-weight: var(--weight-bold);
  line-height: 1.4;
  text-align: center;
  white-space: nowrap;
}

.coastal-storymap .slide-deck-timeline-card {
  padding: var(--space-4);
  border-radius: var(--radius-2);
  border-inline-start: 3px solid var(--escap-blue);
  background: var(--escap-blue-wash);
}

.coastal-storymap .slide-deck-timeline-card h4 {
  margin: 0 0 var(--space-2);
  font-family: var(--coastal-title-font);
  color: var(--escap-blue);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-bold);
  line-height: var(--lh-tight);
}

.coastal-storymap .slide-deck-timeline-card ul {
  margin: 0;
  padding-inline-start: var(--space-4);
  display: grid;
  gap: 6px;
  font-size: var(--text-base);
  line-height: var(--lh-base);
}

/* First and last stop on the rail. Both sit outside the <ol>, so they repeat
   its node/rail geometry offset by the list's own 8px inline padding: node
   centre 30px, text at 52px, which is where a card's text starts. Neither is a
   filled pill — that read as a button. */
.coastal-storymap .slide-deck-timeline-start,
.coastal-storymap .slide-deck-timeline-closing {
  position: relative;
  margin-block: 0;
  padding-inline-start: 52px;
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-weight: var(--weight-bold);
  line-height: var(--lh-tight);
}

.coastal-storymap .slide-deck-timeline-start {
  padding-bottom: var(--space-4);
  font-size: var(--text-lg);
}

.coastal-storymap .slide-deck-timeline-closing {
  padding-top: var(--space-4);
  font-size: var(--text-lg);
}

.coastal-storymap .slide-deck-timeline-start::before,
.coastal-storymap .slide-deck-timeline-closing::before {
  content: '';
  position: absolute;
  inset-inline-start: 29px;
  width: 2px;
  background: var(--escap-blue);
  opacity: 0.35;
}

.coastal-storymap .slide-deck-timeline-start::before {
  top: 20px;
  bottom: 0;
}

.coastal-storymap .slide-deck-timeline-closing::before {
  top: 0;
  height: calc(var(--space-4) + 6px);
}

.coastal-storymap .slide-deck-timeline-start::after,
.coastal-storymap .slide-deck-timeline-closing::after {
  content: '';
  position: absolute;
  inset-inline-start: 22px;
  top: 4px;
  width: 16px;
  height: 16px;
  border-radius: var(--radius-pill);
  background: var(--escap-blue);
  /* the ring masks the rail so it reads as a stop, not a line passing through */
  box-shadow: 0 0 0 4px var(--white);
}

.coastal-storymap .slide-deck-timeline-closing::after {
  top: calc(var(--space-4) + 4px);
}

/* CS-003 tsunami deck: the start line sits outside the <ol>, so its rail/dot
   must be given the --years timeline's own rail position rather than the
   numbered-step one, and its text must line up with the year items' cards. */
.coastal-storymap .slide-deck-timeline-start--years {
  padding-inline-start: 100px; /* raw: item 92px + list 8px, aligns with card text */
}

.coastal-storymap .slide-deck-timeline-start--years::before {
  inset-inline-start: 46px;
}

.coastal-storymap .slide-deck-timeline-start--years::after {
  inset-inline-start: 39px;
}

.coastal-storymap .slide-deck-lessons {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.coastal-storymap .slide-deck-lessons-row-label {
  margin: 0;
  color: var(--escap-blue);
  font-weight: var(--weight-bold);
  font-size: var(--text-base);
}

.coastal-storymap .slide-deck-lessons-row {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4);
}

/* Hover/focus reveal only, same pattern as .glacier-segment:hover (#climate) —
   no JS toggling of state. */
.coastal-storymap .slide-deck-lessons-card {
  position: relative;
  min-height: 320px;
  padding: var(--space-4);
  border-radius: var(--radius-2);
  background: var(--escap-blue-wash);
  cursor: default;
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px solid var(--escap-blue-pale);
}

.coastal-storymap .slide-deck-lessons-card-title {
  margin: 0;
  color: var(--escap-blue);
  font-weight: var(--weight-bold);
  font-size: var(--coastal-card-title-size);
  line-height: var(--lh-tight);
  text-align: center;
}

.coastal-storymap .slide-deck-lessons-reveal {
  position: absolute;
  inset: 0;
  padding: var(--space-4);
  border-radius: var(--radius-2);
  background: var(--escap-blue-deep);
  color: var(--white);
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.3s ease, transform 0.3s ease;
  pointer-events: none;
}

.coastal-storymap .slide-deck-lessons-card:hover .slide-deck-lessons-reveal,
.coastal-storymap .slide-deck-lessons-card:focus-visible .slide-deck-lessons-reveal {
  opacity: 1;
  transform: translateY(0);
}

.coastal-storymap .slide-deck-lessons-reveal-list {
  margin: 0;
  display: grid;
  gap: var(--space-2);
  font-size: var(--text-base);
  line-height: var(--lh-base);
}

.coastal-storymap .slide-deck-lessons-closing {
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--text-base);
  line-height: var(--lh-base);
  text-align: center;
}

.coastal-storymap .slide-deck-prev,
.coastal-storymap .slide-deck-next {
  width: 44px;
  height: 44px;
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--escap-blue);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.coastal-storymap .slide-deck-prev:hover:not(:disabled),
.coastal-storymap .slide-deck-next:hover:not(:disabled) {
  border-color: var(--escap-blue-pale);
  background: var(--escap-blue-wash);
}

.coastal-storymap .slide-deck-prev:focus-visible,
.coastal-storymap .slide-deck-next:focus-visible,
.coastal-storymap .slide-deck-close:focus-visible,
.coastal-storymap .slide-deck-lessons-card:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
}

.coastal-storymap .slide-deck-prev:disabled,
.coastal-storymap .slide-deck-next:disabled {
  opacity: 0.4;
  cursor: default;
}

.coastal-storymap .slide-deck-count {
  min-width: var(--space-9);
  margin: 0;
  color: var(--fg-muted);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  text-align: center;
  direction: ltr;
}

@media (max-width: 900px) {
  .coastal-storymap .slide-deck {
    width: calc(100vw - var(--space-4));
    max-width: calc(100vw - var(--space-4));
    height: calc(100svh - var(--space-4));
    max-height: calc(100svh - var(--space-4));
  }

  .coastal-storymap .slide-deck-toolbar {
    padding: var(--space-2) var(--space-3);
  }

  .coastal-storymap .slide-deck-slide {
    gap: var(--space-5);
    padding: var(--space-6);
  }

  .coastal-storymap .slide-deck-split,
  .coastal-storymap .slide-deck-cards,
  .coastal-storymap .slide-deck-lessons-row,
  .coastal-storymap .slide-deck-phases {
    grid-template-columns: 1fr;
  }

  .coastal-storymap .slide-deck-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .coastal-storymap .slide-deck-timeline-item {
    padding-inline-start: 40px;
  }

  .coastal-storymap .slide-deck-timeline--years .slide-deck-timeline-item {
    padding-inline-start: 84px;
  }

  .coastal-storymap .slide-deck-timeline-start--years {
    padding-inline-start: 92px; /* raw: item 84px + list 8px, aligns with card text */
  }

  .coastal-storymap .slide-deck-lessons-card {
    min-height: 0;
  }

  .coastal-storymap .slide-deck-lessons-reveal {
    position: static;
    opacity: 1;
    transform: none;
    pointer-events: auto;
    margin-top: var(--space-2);
    background: transparent;
    color: var(--fg-muted);
    padding: 0;
  }
}

@media (max-width: 480px) {
  .coastal-storymap .slide-deck {
    width: 100vw;
    max-width: none;
    height: 100svh;
    max-height: none;
    border: 0;
    border-radius: var(--radius-0);
  }

  .coastal-storymap .slide-deck-slide {
    padding: var(--space-5);
    scrollbar-gutter: auto;
  }

  .coastal-storymap .slide-deck-slide[data-slide-index="0"] .slide-deck-title {
    padding-inline-start: var(--space-4);
  }

  .coastal-storymap .slide-deck-title {
    font-size: var(--text-2xl);
  }

  .coastal-storymap .slide-deck-deck {
    font-size: var(--text-base);
  }

  .coastal-storymap .slide-deck-stats {
    grid-template-columns: 1fr;
  }
}

.coastal-storymap .disaster-spotlight-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 24px;
  margin-top: 64px;
}

.coastal-storymap .disaster-spotlight {
  padding: 32px;
  background: var(--escap-blue-wash);
  /* Summary stretches so both cards' buttons line up when one text wraps longer. */
  display: flex;
  flex-direction: column;
}

.coastal-storymap .disaster-spotlight h3 {
  margin: 0 0 20px;
  color: var(--fg);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-bold);
  text-align: center;
}

.coastal-storymap .disaster-summary {
  flex: 1;
  margin: 0 0 20px;
  padding: 24px;
  background: var(--white);
  border: 1px solid var(--border);
  color: var(--fg-muted);
  font-size: var(--coastal-card-body-size);
  line-height: var(--lh-base);
  text-align: center;
}

.coastal-storymap .disaster-learn-more {
  /* Look comes from .escap-btn, like every other CTA on the page; this rule
     only centres the button in its card and clears the UA <button> border
     that .escap-btn (written for <a>) never needed to reset. */
  display: flex;
  width: fit-content;
  margin: 0 auto;
  border: 0;
  cursor: pointer;
}

@media (max-width: 768px) {
  .coastal-storymap .disaster-spotlight-grid {
    grid-template-columns: 1fr;
  }
}

/* Slide 11 NDC card note */
/* Slide 12 Forecasting Infographic */
/* Slide 16 Partner Cards */
.coastal-storymap .partner-card-new {
  padding: 24px;
  border: 1px solid var(--border);
  background: var(--white);
  display: flex;
  flex-direction: column;
  /* Top-aligned so logo, title and text line up across the row; the link is pushed down. */
  justify-content: flex-start;
  align-items: center;
  text-align: center;
  min-height: 150px;
  box-shadow: var(--shadow-sm);
}
/* One fixed logo box per card; the cap keeps wide wordmarks (Met Office) from
   outgrowing the square marks. */
.coastal-storymap .partner-logo-container {
  height: var(--space-10);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-3);
}
.coastal-storymap .partner-logo-container img {
  max-height: 100%;
  max-width: min(100%, 180px); /* raw: logo cap */
  object-fit: contain;
}
.coastal-storymap .ca-partner-title {
  margin: 0 0 8px;
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-small-title-size);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wider);
  text-transform: uppercase;
}
.coastal-storymap .partner-card-new p {
  margin: 0 0 16px;
  color: var(--escap-blue);
  font-family: var(--font-sans);
  font-size: 0.85rem;
  font-weight: var(--weight-medium);
}
.coastal-storymap .partner-card-new a {
  margin-top: auto;
  font-size: 0.7rem;
  font-weight: var(--weight-bold);
  color: var(--escap-blue);
  text-decoration: none;
  text-transform: uppercase;
  transition: color 0.2s;
  /* 24px hit area (WCAG 2.5.8); Drupal gets only this file, not the critical copy */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
.coastal-storymap .partner-card-new a:hover {
  color: var(--escap-blue-dark);
}

/* Slide 18 Flip Cards */
.coastal-storymap .flip-card {
  background-color: transparent;
  height: 220px;
  perspective: 1000px;
}
.coastal-storymap .flip-card-inner {
  position: relative;
  width: 100%;
  height: 100%;
  text-align: left;
  transition: transform 0.6s;
  transform-style: preserve-3d;
  box-shadow: var(--shadow-sm);
  border: 1px solid var(--border);
}
.coastal-storymap .flip-card:hover .flip-card-inner,
.coastal-storymap .flip-card:focus-within .flip-card-inner {
  transform: rotateY(180deg);
  border-color: var(--escap-blue-pale);
}

.coastal-storymap .flip-card:focus-visible {
  outline: 2px solid var(--escap-blue);
  outline-offset: 2px;
}
.coastal-storymap .flip-card-front, .coastal-storymap .flip-card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  padding: 28px;
  display: flex;
  flex-direction: column;
}
.coastal-storymap .flip-card-front {
  background-color: var(--white);
  color: var(--fg);
  justify-content: flex-start;
}
.coastal-storymap .flip-card-back {
  background-color: var(--escap-blue-wash);
  transform: rotateY(180deg);
  justify-content: space-between;
}
/* match the standard card recipe (.output-title / .output-body): sans, 1rem/0.85rem */
.coastal-storymap .flip-card-back h4 {
  margin: 0 0 8px;
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
}
.coastal-storymap .flip-card-front p,
.coastal-storymap .flip-card-back p {
  margin: 0 0 12px;
  font-size: 0.85rem;
  line-height: var(--lh-base);
  color: var(--fg-muted);
}
.coastal-storymap .flip-card-front p {
  margin: 0;
}


/* CS-017 Country Applications: two evidence dossiers. The desktop mosaic lets
   readers compare all five themes without horizontal scrolling; compact
   screens return to the existing touch-friendly deck interaction. */
.coastal-storymap #pilots .wrap {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  column-gap: var(--space-7);
}
.coastal-storymap #pilots .ca-eyebrow {
  grid-column: 1 / -1;
}
.coastal-storymap #pilots .ca-title {
  grid-column: 1 / 8;
  max-width: 16ch;
  margin-bottom: 0;
  text-wrap: balance;
}
.coastal-storymap #pilots .ca-subtitle {
  grid-column: 8 / -1;
  align-self: end;
  max-width: 42ch;
  margin-bottom: var(--space-1);
  color: rgba(255, 255, 255, 0.78);
  text-wrap: pretty;
}
.coastal-storymap .country-section {
  grid-column: 1 / -1;
  display: block;
  min-width: 0;
  margin-top: var(--space-10);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(255, 255, 255, 0.03);
}
.coastal-storymap .country-section + .country-section {
  margin-top: var(--space-7);
}
.coastal-storymap .country-header {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  min-width: 0;
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(0, 0, 0, 0.12);
}
/* Flag sits outside the h3: data-i18n rewrites the heading's innerHTML.
   Sized off the title so the pair scales together. flags/*.svg are flag-icons
   (MIT), 4:3. */
.coastal-storymap .country-name {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
}
.coastal-storymap .country-flag {
  flex: none;
  width: auto;
  height: calc(var(--coastal-subsection-title-size) * 0.85);
  border-radius: var(--radius-1);
  box-shadow: var(--shadow-sm);
}
.coastal-storymap .country-title {
  margin: 0;
  color: var(--white);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-subsection-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
  text-wrap: balance;
}
.coastal-storymap .deck-controls {
  display: flex;
  gap: var(--space-2);
}
.coastal-storymap .deck-btn {
  width: var(--space-8);
  height: var(--space-8);
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.15);
  color: var(--white);
  border-radius: 50%;
  cursor: pointer;
  font-size: var(--text-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: background 0.2s, border-color 0.2s;
  user-select: none;
}
.coastal-storymap .deck-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: var(--white);
}
.coastal-storymap .country-deck {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  width: 100%;
  min-width: 0;
  max-width: 100%;
  gap: 1px;
  overflow: visible;
  background: rgba(255, 255, 255, 0.14);
  scrollbar-width: none;
}
.coastal-storymap .country-deck::-webkit-scrollbar {
  display: none;
}
.coastal-storymap .country-deck .deck-card {
  grid-column: span 4;
  min-height: 0;
  padding: var(--space-8) var(--space-6) var(--space-7);
  border: 0;
  background: var(--escap-blue-deep);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  transition: background var(--t-base), box-shadow var(--t-base), translate var(--t-base);
}
.coastal-storymap .country-deck .deck-card[data-card="4"] {
  grid-column: span 5;
}
.coastal-storymap .country-deck .deck-card[data-card="5"] {
  grid-column: span 7;
}
.coastal-storymap .country-deck .deck-card::before {
  content: "0" attr(data-card);
  margin-bottom: var(--space-6);
  color: var(--escap-gold);
  font-family: var(--font-condensed);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-wide);
}
.coastal-storymap .country-deck .deck-card:hover:not(.active) {
  z-index: var(--z-raised);
  background: var(--escap-blue-dark);
  box-shadow: var(--shadow-lg);
  translate: 0 calc(-1 * var(--space-1));
}
.coastal-storymap .country-deck h4 {
  margin: 0 0 var(--space-4);
  color: var(--white);
  font-family: var(--coastal-title-font);
  font-size: var(--text-2xl);
  font-weight: var(--weight-medium);
  line-height: var(--lh-snug);
  text-wrap: balance;
}
.coastal-storymap .country-deck p {
  margin: 0;
  max-width: 42ch;
  color: rgba(255, 255, 255, 0.76);
  font-size: var(--text-base);
  line-height: var(--lh-base);
  text-wrap: pretty;
}
/* Workshop cards carry two paragraphs; margin:0 above ran them together. */
.coastal-storymap .country-deck .deck-card > p + p {
  margin-top: var(--space-3);
}
.coastal-storymap .country-deck .deck-card {
  cursor: pointer;
}
.coastal-storymap .country-deck .deck-card.active {
  background: var(--escap-blue-dark);
}
.coastal-storymap .country-deck .deck-card:focus-visible {
  z-index: var(--z-raised);
  outline: 2px solid var(--escap-gold);
  outline-offset: var(--space-1);
}
.coastal-storymap .country-header > .deck-controls {
  display: none;
}

@media (max-width: 900px) {
  .coastal-storymap #pilots .wrap {
    grid-template-columns: 1fr;
  }
  .coastal-storymap #pilots .ca-eyebrow,
  .coastal-storymap #pilots .ca-title,
  .coastal-storymap #pilots .ca-subtitle,
  .coastal-storymap .country-section {
    grid-column: 1;
  }
  .coastal-storymap #pilots .ca-title {
    margin-bottom: var(--space-5);
  }
  .coastal-storymap #pilots .ca-subtitle {
    max-width: 62ch;
    margin-bottom: 0;
  }
  .coastal-storymap .country-section {
    display: block;
    width: 100%;
    margin-top: var(--space-9);
    overflow: hidden;
  }
  .coastal-storymap .country-header {
    padding: var(--space-5);
  }
  .coastal-storymap .country-header > .deck-controls {
    display: flex;
  }
  .coastal-storymap .country-deck {
    grid-template-columns: none;
    grid-auto-columns: minmax(240px, 78vw);
    grid-auto-flow: column;
    align-items: stretch;
    gap: 1px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
  }
  .coastal-storymap .country-deck .deck-card,
  .coastal-storymap .country-deck .deck-card[data-card="4"],
  .coastal-storymap .country-deck .deck-card[data-card="5"] {
    grid-column: auto;
    min-height: 100%;
    scroll-snap-align: start;
  }
}

/* #pilots click-expand card morph (SM: pilots-card-morph-fullwidth-expand).
   Scoped to `.country-section .country-deck`/`.country-section .deck-card`
   only — never bare `.country-deck`/`.deck-card`, which would also match
   #tools' unrelated `.tools-deck`/`.tool-card` (CS-013). */
.coastal-storymap .country-section.pilot-expanded .country-header .deck-controls {
  /* visibility, not display: the header keeps its height so the deck doesn't jump 10px. */
  visibility: hidden;
}
.coastal-storymap .country-section .country-deck {
  position: relative;
}
/* While a card is active the deck must show an overlay that can extend
   beyond its resting row height. The deck's resting `overflow-x: auto`
   (coastal-story.css ~L2741) has no `overflow-y` declared, which computes
   to `overflow-y: auto` per the CSS overflow spec (a non-`visible` value on
   one axis forces the other off its `visible` initial value) — without this
   override a taller overlay would be scrolled/clipped inside the deck's box
   instead of rendering full-bleed. */
.coastal-storymap .country-section .country-deck.deck-has-expanded {
  /* Clip sideways so the dimmed, scrolled siblings don't paint into the gutter. */
  overflow-x: clip;
  overflow-y: visible;
}
.coastal-storymap .country-section .deck-card {
  position: relative;
  min-width: 0;
  overflow: hidden;
  transition: opacity var(--t-slow) var(--ease-standard);
}
/* Scoped to .deck-has-expanded, not the base .deck-card rule above, so this
   doesn't win the equal-specificity/later-source-order tiebreak against the
   compact deck's own `min-height: 180px` (coastal-story.css ~L2754) at rest.
   Needed only while expanded: without it, the grid's auto row-height still
   considers each item's content-based minimum (the same fr/auto-minimum
   gotcha `min-width: 0` guards against on the column axis). */
.coastal-storymap .country-section .country-deck.deck-has-expanded .deck-card {
  min-height: 0;
}
/* Siblings stay in their existing grid tracks, dimmed only — no more
   height/padding collapse (SM: pilots-card-morph-fullwidth-expand,
   background-overlay delta). The active card breaks out of grid flow below
   to render as a full-bleed overlay on top of them. */
.coastal-storymap .country-section .country-deck.deck-has-expanded .deck-card:not(.active) {
  opacity: 0.35;
  pointer-events: none;
}
/* × close: the collapsing card has already dropped .active, so without this
   it would snap to the dimmed sibling opacity and fall behind them mid-shrink.
   ‹ › switch: swap the overlay instantly instead of cross-fading through the
   dimmed grid; .pilot-panel-body's own reveal animation carries the change. */
.coastal-storymap .country-section .country-deck.deck-has-expanded .deck-card.pilot-closing {
  z-index: 5;
  opacity: 1;
}
.coastal-storymap .country-section .country-deck.pilot-switching .deck-card {
  transition: none;
}
/* The active card breaks out of grid flow to overlay the full deck: it's
   absolutely positioned against `.country-deck` (position:relative above),
   filling its width/height via `inset: 0`, elevated above the dimmed
   siblings via z-index + box-shadow. Its actual open/close size animation
   is a JS-driven FLIP (see animateCardExpand/animateCardCollapse in
   coastal-story.js), which pins explicit top/left/width/height inline
   styles during the transition and clears them once settled, letting this
   `inset: 0` take back over at rest. The solid dark background fully
   occludes the dimmed siblings sitting in the same box and keeps long-form
   panel copy legible. */
.coastal-storymap .country-section .deck-card.active {
  position: absolute;
  inset: 0;
  z-index: 5;
  cursor: default;
  overflow: visible;
  background: var(--escap-blue-dark);
  box-shadow: var(--shadow-lg);
}
.coastal-storymap .country-section .deck-card .pilot-panel-controls {
  position: absolute;
  top: var(--space-4);
  right: var(--space-4);
  z-index: 1;
  display: none;
  gap: var(--space-2);
}
.coastal-storymap .country-section .deck-card.active .pilot-panel-controls {
  display: flex;
}
.coastal-storymap .country-section .deck-card .pilot-panel-close,
.coastal-storymap .country-section .deck-card .pilot-panel-nav-btn {
  position: static;
  width: var(--space-7);
  height: var(--space-7);
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.15);
  background: rgba(255, 255, 255, 0.08);
  color: var(--white);
  font-size: var(--text-xl);
  line-height: 1;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
}
.coastal-storymap .country-section .deck-card.active .pilot-panel-close,
.coastal-storymap .country-section .deck-card.active .pilot-panel-nav-btn {
  display: flex;
}
.coastal-storymap .country-section .deck-card .pilot-panel-close:hover,
.coastal-storymap .country-section .deck-card .pilot-panel-nav-btn:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: var(--white);
}
.coastal-storymap .country-section .deck-card .pilot-panel-close:focus-visible,
.coastal-storymap .country-section .deck-card .pilot-panel-nav-btn:focus-visible {
  outline: 2px solid var(--escap-gold);
  outline-offset: var(--space-1);
}
@media (max-width: 640px) {
  .coastal-storymap .country-section .deck-card.active {
    scroll-margin-top: calc(var(--space-11) + var(--space-4));
  }
  .coastal-storymap .country-section .deck-card .pilot-panel-close,
  .coastal-storymap .country-section .deck-card .pilot-panel-nav-btn {
    width: var(--space-9);
    height: var(--space-9);
  }
}
.coastal-storymap .country-section .deck-card.active > h4,
.coastal-storymap .country-section .deck-card.active > p {
  display: none;
}
.coastal-storymap .country-section .deck-card .pilot-panel-body {
  display: none;
}
.coastal-storymap .country-section .deck-card.active .pilot-panel-body {
  display: block;
  padding-top: var(--space-7);
  animation: pilotBodyReveal var(--t-slow) var(--ease-standard);
}
@keyframes pilotBodyReveal {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.coastal-storymap .pilot-panel-title {
  margin: 0 0 var(--space-4);
  color: var(--white);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-medium);
}
.coastal-storymap .pilot-panel-body p {
  margin: 0 0 var(--space-3);
  color: rgba(255, 255, 255, 0.72);
  font-size: var(--text-base);
  line-height: var(--lh-base);
}
.coastal-storymap .pilot-panel-body p:last-child {
  margin-bottom: 0;
}
.coastal-storymap .pilot-panel-body strong {
  color: var(--white);
  font-weight: var(--weight-bold);
}
.coastal-storymap .pilot-panel-columns {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: var(--space-7);
  align-items: start;
}
.coastal-storymap .pilot-panel-stats {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.coastal-storymap .pilot-panel-stat {
  padding: var(--space-4);
  border: 1px solid var(--escap-blue-wash);
  border-radius: var(--radius-2);
  background: var(--escap-blue-wash);
}
.coastal-storymap .pilot-panel-stat-value {
  color: var(--escap-blue);
  font-family: var(--font-condensed);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  line-height: 1.1;
}
.coastal-storymap .pilot-panel-stat-label {
  margin-top: var(--space-1);
  color: var(--escap-blue-deep);
  font-size: var(--text-base);
  line-height: var(--lh-base);
}
.coastal-storymap .pilot-panel-bullets {
  margin: 0 0 var(--space-5);
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.coastal-storymap .pilot-panel-bullets li {
  padding-left: var(--space-5);
  position: relative;
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--text-sm);
  line-height: var(--lh-base);
}
.coastal-storymap .pilot-panel-bullets li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.5em;
  width: var(--space-2);
  height: var(--space-2);
  border-radius: 50%;
  background: var(--escap-blue-pale);
}
.coastal-storymap .pilot-panel-logos {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}
/* width:auto + the <img> width/height attributes: the box takes the logo's ratio
   before the lazy image loads, so the open card's measured height already includes
   it (it overflowed the card on phones). */
.coastal-storymap .pilot-panel-logo {
  width: auto;
  height: 72px;
  max-width: 140px;
  object-fit: contain;
  background: var(--white);
  border: 1px solid var(--escap-blue-wash);
  border-radius: var(--radius-2);
  padding: var(--space-2) var(--space-3);
}
.coastal-storymap .pilot-panel-carousel {
  position: relative;
}
.coastal-storymap .pilot-panel-carousel-img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-2);
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(0, 0, 0, 0.25);
  display: block;
}
.coastal-storymap .pilot-panel-carousel-controls {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-3);
}
.coastal-storymap .pilot-panel-carousel-controls .deck-btn {
  background: rgba(0, 0, 0, 0.55);
  border-color: rgba(255, 255, 255, 0.35);
  backdrop-filter: blur(4px);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
}
.coastal-storymap .pilot-panel-carousel-controls .deck-btn:hover {
  background: rgba(0, 0, 0, 0.75);
  border-color: var(--white);
}

@media (max-width: 900px) {
  .coastal-storymap .pilot-panel-columns {
    grid-template-columns: 1fr;
  }
}

/* Header */
.coastal-storymap .ca-header {
  margin-bottom: clamp(var(--space-6), 4vw, var(--space-8));
}
.coastal-storymap .ca-header-left {
  max-width: 760px;
}
.coastal-storymap .ca-eyebrow {
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--escap-blue);
  margin: 0 0 var(--space-2);
}
.coastal-storymap .ca-title {
  max-width: 22ch;
  margin: 0 0 var(--space-5);
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-section-title-size);
  font-weight: var(--weight-medium);
  line-height: var(--lh-tight);
}
.coastal-storymap .ca-subtitle {
  max-width: 62ch;
  color: var(--fg-muted);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-section-lead-size);
  margin: 0;
  line-height: var(--lh-base);
}

/* Body */
.coastal-storymap .ca-body {
  display: grid;
  grid-template-columns: 1fr;
  margin-bottom: clamp(var(--space-6), 4vw, var(--space-8));
}

/* Main column */
.coastal-storymap .ca-main {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* Zone axis */
.coastal-storymap .ca-zone-axis {
  display: flex;
  align-items: flex-start;
  /* Labels a picture with land on the left and ocean on the right, so it must
     not mirror under dir=rtl. */
  direction: ltr;
  gap: 0;
  position: relative;
  margin-bottom: var(--space-4);
  width: 100%;
}
.coastal-storymap .ca-zone {
  flex: 1;
  position: relative;
  padding: var(--space-1);
}
.coastal-storymap .ca-zone-line {
  position: absolute;
  top: -6px;
  left: 0;
  right: 0;
  height: 3px;
  border-radius: 2px;
  background: currentColor;
  opacity: 0.3;
}
.coastal-storymap .ca-zone.land  .ca-zone-line { color: #3d7a3d; }
.coastal-storymap .ca-zone.shore .ca-zone-line { color: #c8620a; }
.coastal-storymap .ca-zone.ocean .ca-zone-line { color: var(--escap-blue); }
.coastal-storymap .ca-zone-label {
  text-align: center;
  text-wrap: nowrap;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.coastal-storymap .ca-zone-label.land  { color: #3d7a3d; }
.coastal-storymap .ca-zone-label.shore { color: #c8620a; }
.coastal-storymap .ca-zone-label.ocean { color: var(--escap-blue); }
.coastal-storymap .ca-zone-sub {
  text-align: center;
  font-size: var(--text-xs);
  color: var(--fg-muted); /* blue-pale on the scrim was ~2.2:1 */
  margin-top: 0.15rem;
}

/* CS-020: the client's IBF animation (Canva export) beside the four takeaways,
   then the storyboard link. Replaced the interactive science-to-policy bridge
   (SM-085) — its panels, SVG span and step cards are gone, along with their
   step-switcher JS and the contract test that guarded it. */
.coastal-storymap .ibf-deck {
  color: var(--escap-blue);
  font-weight: var(--weight-medium);
  margin-bottom: var(--space-3);
}

.coastal-storymap .ibf-chain {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-5);
  align-items: center;
  margin-top: var(--space-5);
}

.coastal-storymap .ibf-chain-media {
  width: 100%;
  height: auto;
  max-width: 520px;
  /* Start edge, on the copy's gutter — auto centred it 20px in at 1440. */
  margin-inline: 0;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--border);
  border-radius: var(--radius-2);
  box-shadow: var(--shadow-md);
}

.coastal-storymap .ibf-chain-points {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

.coastal-storymap .ibf-chain-points li {
  position: relative;
  background: var(--escap-blue-wash);
  border-radius: var(--radius-1);
  padding: var(--space-3);
  padding-inline-start: var(--space-4);
  color: var(--fg);
  font-size: var(--coastal-card-body-size);
  line-height: var(--lh-base);
}

/* The accent bar sits on the inline-start edge, so it flips under [dir="rtl"]
   without a separate rule. */
.coastal-storymap .ibf-chain-points li::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 4px;
  background: var(--escap-blue);
  border-start-start-radius: var(--radius-1);
  border-end-start-radius: var(--radius-1);
}

.coastal-storymap .ibf-chain-cta {
  margin-top: var(--space-5);
  text-align: center;
}

/* Arrow in CSS, not in the string: it has to point the other way under RTL.
   On the label span, not the inline-flex button: as its own flex item the
   leading space collapsed and a wrapped label left the arrow stranded. The
   no-break space keeps it with the last word. */
.coastal-storymap .ibf-chain-cta .escap-btn span::after { content: '\00a0\2192'; }
.coastal-storymap[dir="rtl"] .ibf-chain-cta .escap-btn span::after { content: '\00a0\2190'; }

@media (max-width: 900px) {
  .coastal-storymap .ibf-chain {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .coastal-storymap .cyclone-track-line-animated { animation: none; }
}

/* Project Approach (CS-015): the drag-and-drop jigsaw over the CS-005 artwork
   (ApproachPuzzle in coastal-story.js) + Knowledge/Decisions/Action pillars. */
.coastal-storymap #project-approach { background: var(--white); padding-block: var(--space-7); } /* inline gutter comes from the shared section rule (16px on phones) */

/* Delta-3 re-pace: `.ca-title`/`.ca-subtitle` are shared sitewide, so a
   `#project-approach`-scoped override compacts just this section's title/lead
   instead of every section. Widening `.ca-title`'s max-width (default 22ch)
   lets the title wrap to 2 lines instead of 3 (saved ~49px measured at
   1440px), and `.ca-subtitle`'s widened max-width + smaller line-height
   drops it from 3 lines to 2 (saved ~26px) — verified via Playwright measurement,
   not assumed from character counts. */
.coastal-storymap #project-approach .ca-title {
  max-width: 40ch;
  font-size: clamp(1.5rem, 3vw, 2.15rem);
  line-height: 1.15;
  margin-bottom: 10px;
}
.coastal-storymap #project-approach .ca-subtitle {
  max-width: 78ch;
  line-height: 1.35;
  margin-bottom: 4px;
}

.coastal-storymap .approach-puzzle {
  padding: var(--space-3) 0 var(--space-6);
  margin-top: var(--space-6);
  border-top: 1px solid var(--escap-blue-wash);
  border-bottom: 1px solid var(--escap-blue-wash);
  margin-bottom: var(--space-5);
}
.coastal-storymap .approach-puzzle-hint {
  margin: 0 0 var(--space-3);
  font-size: var(--text-sm);
  color: var(--fg-muted);
}

/* Jigsaw (ApproachPuzzle, coastal-story.js). `isolation` keeps the piece and
   popup z-indices local to the widget. The stage's aspect-ratio is set inline
   from the same constants as the geometry. */
.coastal-storymap .ap-wrap { position: relative; isolation: isolate; }
.coastal-storymap .ap-stage {
  position: relative;
  user-select: none;
  -webkit-user-select: none;
}
.coastal-storymap .ap-board {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.coastal-storymap .ap-gap path {
  fill: var(--white);
  fill-opacity: 0.9;
  stroke: var(--escap-blue-pale);
  stroke-width: 3px;
}
/* Font size is in artwork px: it scales with the board. tspan listed too:
   Safari doesn't inherit dominant-baseline into it. */
.coastal-storymap .ap-gap text,
.coastal-storymap .ap-gap tspan {
  fill: var(--escap-blue-dark);
  font-family: var(--coastal-title-font);
  font-size: 26px;
  font-weight: var(--weight-bold);
  text-anchor: middle;
  dominant-baseline: central;
}
.coastal-storymap .ap-gap.filled { opacity: 0; }

/* The box is square and larger than the piece; only the outline path takes the
   pointer, so a press on the box's empty corners falls through to the board. */
.coastal-storymap .ap-piece {
  position: absolute;
  z-index: var(--z-raised);
  pointer-events: none;
  touch-action: none;
  outline: none;
  transition: left 0.35s ease, top 0.35s ease;
}
.coastal-storymap .ap-piece svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
  /* raw: filter drop-shadow can't take a --shadow-* token */
  filter: drop-shadow(0 6px 8px color-mix(in srgb, var(--black) 35%, transparent));
}
.coastal-storymap .ap-piece-edge {
  fill: transparent;
  stroke: var(--white);
  stroke-width: 4px;
  pointer-events: visiblePainted;
  cursor: grab;
}
.coastal-storymap .ap-piece.dragging { z-index: var(--z-dropdown); transition: none; }
.coastal-storymap .ap-piece.dragging .ap-piece-edge { cursor: grabbing; }
.coastal-storymap .ap-piece.placed { z-index: var(--z-base); touch-action: auto; }
.coastal-storymap .ap-piece.placed svg { filter: none; }
.coastal-storymap .ap-piece.placed .ap-piece-edge { stroke-opacity: 0.55; stroke-width: 2px; cursor: pointer; }
.coastal-storymap .ap-piece:hover .ap-piece-edge { stroke: var(--escap-gold); }
.coastal-storymap .ap-piece:focus-visible .ap-piece-edge { stroke: var(--escap-gold); stroke-width: 8px; stroke-opacity: 1; }

.coastal-storymap .ap-popup {
  position: absolute;
  z-index: var(--z-flyout);
  width: min(300px, 40%); /* raw: popup width, no size token */
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: var(--radius-4);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.coastal-storymap .ap-popup[hidden] { display: none; }
.coastal-storymap .ap-popup-header {
  padding: var(--space-2) var(--space-7) var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  font-weight: var(--weight-black);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--white);
  background: var(--escap-blue-dark);
}
.coastal-storymap .ap-popup-body {
  margin: 0;
  padding: var(--space-3);
  font-size: var(--text-sm);
  line-height: var(--lh-snug);
  color: var(--fg);
}
.coastal-storymap .ap-popup-close {
  position: absolute;
  top: 0;
  inset-inline-end: 0;
  width: var(--space-7);
  height: var(--space-7);
  border: 0;
  background: transparent;
  color: var(--white);
  font-size: var(--text-lg);
  line-height: 1;
  cursor: pointer;
}
.coastal-storymap .ap-popup-close:focus-visible { outline: 2px solid var(--escap-gold); outline-offset: -2px; }
.coastal-storymap[dir="rtl"] .ap-popup-header { padding: var(--space-2) var(--space-3) var(--space-2) var(--space-7); }

/* Subtitle + Reset share a row: the button sits at the column's end edge,
   level with the subtitle's last line, and wraps under it when space runs out. */
.coastal-storymap .approach-lead-row {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--space-3);
}
.coastal-storymap .ap-reset {
  flex: none;
  margin-inline-start: auto;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--escap-blue-dark);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--escap-blue-dark);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  cursor: pointer;
}
/* Always shown, so it's findable on a phone; disabled until a piece is placed. */
.coastal-storymap .ap-reset:disabled { opacity: 0.45; cursor: default; }
.coastal-storymap .ap-reset:not(:disabled):hover { background: var(--escap-blue-wash); }
.coastal-storymap .ap-reset:focus-visible { outline: 2px solid var(--escap-gold); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .coastal-storymap .ap-piece { transition: none; }
}

/* Narrow screens: no room beside a gap, so the popup stacks under the stage.
   Gap labels would be ~5px here; the popup header names each piece instead. */
@media (max-width: 640px) {
  .coastal-storymap .ap-popup { position: relative; width: auto; margin-top: var(--space-3); }
  .coastal-storymap .ap-gap text { display: none; }
}

/* Pillars: single grid, DOM order head1,body1,arrow1,head2,body2,arrow2,head3,body3
   so mobile auto-placement (media queries below) naturally stacks each pillar's head+body
   together, followed by its arrow — desktop uses grid-template-areas to recreate the
   header-row/content-row look without needing two separate grids. */
.coastal-storymap .approach-pillars {
  display: grid;
  grid-template-columns: 1fr 40px 1fr 40px 1fr;
  /* Chevrons sit in the body row only, so they centre on the cards, not on head+body. */
  grid-template-areas:
    "h1 . h2 . h3"
    "b1 a1 b2 a2 b3";
  row-gap: var(--space-3);
  margin-bottom: 0;
}
.coastal-storymap .approach-pillar-head {
  display: flex; align-items: center; gap: var(--space-3); position: relative; align-self: center;
}
.coastal-storymap .approach-pillar-head .badge {
  width: 40px; height: 40px; border-radius: var(--radius-pill); overflow: hidden; flex: none;
  background: var(--white); box-shadow: var(--shadow-sm); padding: 7px;
}
.coastal-storymap .approach-pillar-head .badge img { width: 100%; height: 100%; object-fit: contain; }
.coastal-storymap .ca-pillar-title {
  font-family: var(--coastal-title-font); font-size: var(--coastal-card-title-size); font-weight: var(--weight-bold, 700);
  letter-spacing: 0.01em; margin: 0;
}
.coastal-storymap .approach-pillar-head.p1 h3 { color: var(--escap-blue-dark); }
.coastal-storymap .approach-pillar-head.p2 h3 { color: var(--escap-blue); }
.coastal-storymap .approach-pillar-head.p3 h3 { color: var(--un-green-shade); }
.coastal-storymap .approach-pillar-head.p1 { grid-area: h1; }
.coastal-storymap .approach-pillar-head.p2 { grid-area: h2; }
.coastal-storymap .approach-pillar-head.p3 { grid-area: h3; }

.coastal-storymap .approach-pillars-arrow {
  display: flex; align-items: center; justify-content: center; opacity: 0.55;
}
.coastal-storymap .approach-pillars-arrow svg { width: 20px; height: 20px; }
.coastal-storymap .approach-pillars-arrow.a1 { grid-area: a1; }
.coastal-storymap .approach-pillars-arrow.a2 { grid-area: a2; }

.coastal-storymap .approach-pillar-body {
  /* flex centres the text on the absolutely centred badge instead of top-aligning it */
  display: flex; align-items: center;
  position: relative; background: var(--escap-blue-wash); border-radius: var(--radius-4);
  padding: var(--space-3) var(--space-4) var(--space-3) 100px; text-align: left; min-height: 68px;
  box-shadow: var(--shadow-sm);
  border-left: 3px solid var(--escap-blue-dark);
}
.coastal-storymap .approach-pillar-body.p2 { border-left-color: var(--escap-blue-bright); }
.coastal-storymap .approach-pillar-body.p3 { background: var(--un-green-tint-50); border-left-color: var(--un-green-shade); }
.coastal-storymap .approach-pillar-body.p1 { grid-area: b1; }
.coastal-storymap .approach-pillar-body.p2 { grid-area: b2; }
.coastal-storymap .approach-pillar-body.p3 { grid-area: b3; }
.coastal-storymap .approach-pillar-body .badge-lg {
  position: absolute; top: 50%; left: var(--space-4); transform: translateY(-50%); width: 68px; height: 68px; border-radius: var(--radius-pill);
  box-shadow: var(--shadow-md); overflow: hidden; background: var(--white); border: 2px solid var(--white);
}
.coastal-storymap .approach-pillar-body .badge-lg img { width: 100%; height: 100%; object-fit: contain; }
.coastal-storymap .approach-pillar-body p { font-size: var(--text-sm); line-height: var(--lh-base); color: var(--fg-muted); margin: 0; }

@media (max-width: 980px) {
  .coastal-storymap .approach-pillar-body { padding-left: 88px; }
  .coastal-storymap .approach-pillar-body .badge-lg { width: 58px; height: 58px; left: var(--space-3); }
}

/* 900px, not 720px: at 768 three columns left a ~101px text column. */
@media (max-width: 900px) {
  /* Drop the desktop grid-template-areas and per-item grid-area assignments so the
     grid falls back to auto-placement in DOM order: head1, body1, arrow1, head2,
     body2, arrow2, head3, body3 — each pillar's head sits directly above its own
     body, arrow between pillars, not a stack of all three heads then all three bodies. */
  .coastal-storymap .approach-pillars {
    grid-template-columns: 1fr;
    grid-template-areas: none;
    row-gap: var(--space-4);
  }
  .coastal-storymap .approach-pillar-head.p1, .coastal-storymap .approach-pillar-head.p2, .coastal-storymap .approach-pillar-head.p3,
  .coastal-storymap .approach-pillar-body.p1, .coastal-storymap .approach-pillar-body.p2, .coastal-storymap .approach-pillar-body.p3,
  .coastal-storymap .approach-pillars-arrow.a1, .coastal-storymap .approach-pillars-arrow.a2 {
    grid-area: auto;
  }

  /* Chevron-arrow reflow: rotate 90deg (pointing down) rather than hide, so it still
     reads as "flow continues to the next pillar" once stacked vertically. */
  .coastal-storymap .approach-pillars-arrow { transform: rotate(90deg); margin: var(--space-1) auto; }
}

/* Full-bleed: the CS-005 picture runs edge-to-edge like #climate-explore's
   .map-stage above it. Bleeds .ca-body, not .ca-image-wrap alone — above 901px
   .ca-zone-axis is positioned against .ca-main, so widening only the image
   would leave the LAND/SHORELINE/OCEAN band short. Same RTL-safe
   margin: calc(50% - 50vw) pattern as .map-stage. */
.coastal-storymap .ca-main {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* …but the facts carousel below the picture stays in the 1140px column, and
   keeps the 32px (16px on phones) section gutter where .ca-main is 100vw. */
.coastal-storymap .ca-facts-bar {
  width: min(var(--container-lg), 100% - 2 * var(--space-7));
  margin-inline: auto;
}

/* Image wrap */
.coastal-storymap .ca-image-wrap {
  width: 100%;
  aspect-ratio: 1981 / 793;
  position: relative;
  background: center / cover no-repeat;
  /* Top/bottom rules only, no radius — it now touches both viewport edges. */
  border-top: 1px solid color-mix(in oklab, var(--escap-blue-pale) 28%, transparent);
  border-bottom: 1px solid color-mix(in oklab, var(--escap-blue-pale) 28%, transparent);
  border-radius: 0;
  overflow: visible;
  box-shadow: var(--shadow-lg);
  /* Makes cqw available to .ca-panel so it can clamp itself to this box — see
     the .ca-panel rule. inline-size containment is safe here: the width comes
     from `width: 100%` + `aspect-ratio`, never from the contents, and layout
     containment does not clip, so panels can still hang below the image. */
  container-type: inline-size;
}
/* .is-near is set by coastal-story.js (whenNear) shortly before the section
   scrolls in, so the art isn't fetched while the reader is on the hero. */
.coastal-storymap .ca-image-wrap.is-near {
  background-image: url('images/why-coastal/coastal-area-matters.webp');
}
@media (max-width: 640px) {
  .coastal-storymap .ca-image-wrap.is-near {
    background-image: url('images/why-coastal/coastal-area-matters-1200.webp');
  }
}
.coastal-storymap .ca-image-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(180deg, transparent 52%, rgba(0, 56, 102, 0.18));
  pointer-events: none;
}

/* Hover regions — an invisible SVG hit layer over the artwork. `fill: none`
   would not hit-test, and a visible fill would tint the artwork, so the paths
   stay transparent and opt into hit-testing with `pointer-events: all`. The
   layer sits above the background but below .ca-hotspot (z-index 2) so the
   pins and their panels still take the pointer first. */
.coastal-storymap .ca-regions {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.coastal-storymap .ca-regions path {
  fill: transparent;
  pointer-events: all;
  cursor: pointer;
}

/* Hotspot container */
.coastal-storymap .ca-hotspot {
  --ca-hotspot-size: 72px;
  position: absolute;
  /* Centring uses the `translate` PROPERTY, not `transform` — deliberately.
     Every hotspot also carries `.rv`, whose reveal animates `transform` and
     ends on `.rv.in { transform: none }`. As a `transform: translate(…)` this
     centring was silently wiped by that rule, leaving every pin half a button
     (22px) right of and below its coordinates — and because the offset is a
     constant 22px while left/top are percentages, the error grew as the
     viewport shrank, so the pins only aligned at one window width. As a
     separate property it coexists with the reveal instead of losing to it.
     Do not fold this back into `transform`. See SM-030. */
  translate: -50% -50%;
  /* --ca-x/--ca-y are the raw coordinates the JS hotspot data puts on the inline
     style; --ca-left/--ca-top are what actually positions the pin. They are kept
     separate on purpose: the artwork is 1535×1024 (1.499:1) behind
     `background: … cover`, which crops differently at each aspect-ratio, so the
     ≤640px block overrides --ca-left/--ca-top with a second set. An inline style
     would outrank that media query — routing through --ca-x/--ca-y lets the
     override win without !important. See SM-033. */
  --ca-left: var(--ca-x, 50);
  --ca-top: var(--ca-y, 50);
  left: calc(var(--ca-left) * 1%);
  top: calc(var(--ca-top) * 1%);
  z-index: 2;
  /* No-op standalone. On Drupal, iddtheme's Vue bundle injects a bare
     `.active { background-color: #717171 }` on every storymap route, which
     would otherwise fill this container grey when .active is added on
     hover/focus. */
  background-color: transparent;
}
.coastal-storymap .ca-hotspot.active {
  /* must stay > sibling .ca-hotspot (2) */
  z-index: 5;
}
/* 641-1279px: the side-nav rail sits in the 32px page gutter, and the picture
   is full-bleed, so a pin near the edge (Ports & Global at 768) reached under
   it. Keep each pin's button (and its ring) inside the gutter's edge. */
@media (min-width: 641px) and (max-width: 1279px) {
  .coastal-storymap .ca-hotspot {
    left: min(calc(var(--ca-left) * 1%), calc(100% - var(--space-7) - var(--ca-hotspot-size) / 2 - var(--space-2)));
  }
  .coastal-storymap[dir="rtl"] .ca-hotspot {
    left: max(calc(var(--ca-left) * 1%), calc(var(--space-7) + var(--ca-hotspot-size) / 2 + var(--space-2)));
  }
}

/* Hotspot button */
.coastal-storymap .ca-hotspot-btn {
  width: var(--ca-hotspot-size);
  height: var(--ca-hotspot-size);
  border-radius: 50%;
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  /* The icon's corners are transparent, so an unset colour lets the UA / Drupal
     theme button fill show through as a grey square behind the circle. */
  appearance: none;
  padding: 0;
  background-color: transparent;
  background-size: cover;
  background-position: center;
  transition: transform 180ms var(--ease-standard), box-shadow 180ms var(--ease-standard);
  position: relative;
  z-index: 3;
}
.coastal-storymap .ca-hotspot-btn::before {
  content: '';
  position: absolute;
  inset: calc(-1 * var(--space-2));
  border-radius: 50%;
  border: 2px solid currentColor;
  opacity: 0.35;
  animation: ca-pulse 2s ease-in-out 3; /* finite: WCAG 2.2.2 */
}
@keyframes ca-pulse {
  0%, 100% { transform: scale(1);    opacity: 0.35; }
  50%       { transform: scale(1.25); opacity: 0; }
}
.coastal-storymap .ca-hotspot-btn:hover,
.coastal-storymap .ca-hotspot-btn:focus-visible,
.coastal-storymap .ca-hotspot.active .ca-hotspot-btn {
  transform: scale(1.18);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
  outline: none;
}

/* Hotspot colour variants */
.coastal-storymap .ca-hotspot.cities      .ca-hotspot-btn { color: #3d7a3d; }
.coastal-storymap .ca-hotspot.economy     .ca-hotspot-btn { color: #c8620a; }
.coastal-storymap .ca-hotspot.people      .ca-hotspot-btn { color: #c8620a; }
.coastal-storymap .ca-hotspot.connections .ca-hotspot-btn { color: #2066a8; }
.coastal-storymap .ca-hotspot.nature      .ca-hotspot-btn { color: #c8620a; }
.coastal-storymap .ca-hotspot.coral       .ca-hotspot-btn { color: #2066a8; }

/* Connector line */
.coastal-storymap .ca-hotspot-connector {
  position: absolute;
  left: 50%;
  top: 100%; /* from the pin's bottom edge; from its centre the line hid under the pin */
  transform: translateX(-50%);
  width: 2px;
  opacity: 0.4;
  height: 0;
  transition: height 0.2s ease;
  z-index: 2;
}
.coastal-storymap .ca-hotspot.active .ca-hotspot-connector { height: var(--space-7); }
.coastal-storymap .ca-hotspot.cities      .ca-hotspot-connector { background: #3d7a3d; }
.coastal-storymap .ca-hotspot.economy     .ca-hotspot-connector { background: #c8620a; }
.coastal-storymap .ca-hotspot.people      .ca-hotspot-connector { background: #c8620a; }
.coastal-storymap .ca-hotspot.connections .ca-hotspot-connector { background: #2066a8; }
.coastal-storymap .ca-hotspot.nature      .ca-hotspot-connector { background: #1a7a6e; }
.coastal-storymap .ca-hotspot.coral       .ca-hotspot-connector { background: #d9704f; }

/* Info panel */
.coastal-storymap .ca-panel {
  position: absolute;
  top: calc(100% + var(--space-7));
  left: 50%;

  /* Horizontal clamp. The panel is centred on its hotspot, and a hotspot sits at
     an arbitrary --ca-left% across .ca-image-wrap, so on a narrow viewport an
     edge hotspot used to push the panel past the page (320px viewport → 350px
     scrollWidth, the SM-029 reflow failure). --ca-shift nudges it back inside:
     clamp() returns 0 while the panel fits, the lower bound when it hangs off
     the left, the upper bound when it hangs off the right. Never centred on the
     hotspot at the cost of leaving the image box. The connector is a separate
     element, so shifting the panel does not desync a pointer arrow. */
  --ca-panel-w: min(260px, 74vw);
  --ca-half: calc(var(--ca-panel-w) / 2);
  /* Hotspot centre measured from the image box's left edge. Since SM-030 fixed
     the centring, a pin's centre is exactly its left% of the image box. */
  --ca-center: calc(var(--ca-left, 50) * 1cqw);
  --ca-shift: clamp(
    calc(var(--ca-half) + var(--space-2) - var(--ca-center)),
    0px,
    calc(100cqw - 8px - var(--ca-half) - var(--ca-center))
  );
  transform: translateX(calc(-50% + var(--ca-shift))) translateY(-6px);
  width: var(--ca-panel-w);
  background: var(--white);
  border: 1px solid color-mix(in oklab, var(--escap-blue-pale) 28%, transparent);
  border-radius: var(--radius-4);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  z-index: 10;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease, transform 0.2s ease;
}
.coastal-storymap .ca-hotspot.active .ca-panel {
  opacity: 1;
  pointer-events: auto;
  /* Must carry --ca-shift too — this rule replaces the transform above, and
     dropping the shift here would let the open panel jump back off-screen. */
  transform: translateX(calc(-50% + var(--ca-shift))) translateY(0);
}

.coastal-storymap .ca-panel-header {
  padding: var(--space-2) var(--space-3);
  font-size: var(--text-xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
}
.coastal-storymap .ca-hotspot.cities      .ca-panel-header { background: #3d7a3d; }
.coastal-storymap .ca-hotspot.economy     .ca-panel-header { background: #c8620a; }
.coastal-storymap .ca-hotspot.people      .ca-panel-header { background: #c8620a; }
.coastal-storymap .ca-hotspot.connections .ca-panel-header { background: #2066a8; }
.coastal-storymap .ca-hotspot.nature      .ca-panel-header { background: #c8620a; }
.coastal-storymap .ca-hotspot.coral       .ca-panel-header { background: #2066a8; }
.coastal-storymap .ca-panel-body {
  padding: var(--space-3);
  font-size: var(--text-base);
}
.coastal-storymap .ca-panel-body ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.coastal-storymap .ca-panel-body li {
  color: #333;
  line-height: 1.35;
  padding-left: var(--space-4);
  position: relative;
}
.coastal-storymap .ca-panel-body li::before {
  content: '•';
  position: absolute;
  left: 0;
  color: #888;
}
.coastal-storymap .ca-panel-sdgs {
  display: flex;
  gap: 0.4rem;
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid color-mix(in oklab, var(--escap-blue-pale) 28%, transparent);
}
.coastal-storymap .ca-panel-sdg-icon {
  width: var(--ca-icon-size);
  height: var(--ca-icon-size);
  border-radius: var(--radius-2);
}


/* Facts bar */
.coastal-storymap .ca-facts-bar {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-items: stretch;
  gap: var(--space-2);
}
/* .ca-facts-header/.ca-facts-deck exist only so the >900px desktop overlay
   (below) can give the eyebrow+deck-controls their own row above a
   scroll-snap carousel row. Below that breakpoint they stay `display:
   contents` so they're invisible to layout — .ca-facts-eyebrow and the 5
   .ca-fact cards become direct grid items of .ca-facts-bar exactly as
   before the >900px overlay/carousel work, so the untouched tablet
   (max-width:900px) and mobile (max-width:640px) blocks below keep working
   unmodified against this markup. */
.coastal-storymap .ca-facts-header,
.coastal-storymap .ca-facts-deck {
  display: contents;
}
/* Carousel prev/next controls only make sense once .ca-facts-deck becomes an
   actual scroll track at >900px; hidden by default. */
.coastal-storymap .ca-facts-header .deck-controls {
  display: none;
}
.coastal-storymap .ca-facts-eyebrow {
  display: flex;
  align-items: center;
  grid-column: 1 / -1;
  width: fit-content;
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--white);
  padding: var(--space-3);
  border: 1px solid var(--escap-blue-dark);
  border-radius: var(--radius-3);
  background: var(--escap-blue-dark);
  white-space: nowrap;
}
.coastal-storymap .ca-fact {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  padding: var(--space-3);
  border: 1px solid var(--border);
  border-radius: var(--radius-3);
  background: var(--white);
  font-size: var(--text-xs);
  color: var(--escap-blue-deep);
  line-height: 1.4;
  transition: border-color 180ms var(--ease-standard), box-shadow 180ms var(--ease-standard), transform 180ms var(--ease-standard);
}
.coastal-storymap .ca-fact-icon {
  width: var(--ca-icon-size);
  height: var(--ca-icon-size);
  border-radius: var(--radius-3);
  /* No background: each icon image carries its own tinted tile, several of them
     semi-transparent, so a fill here showed through — and forced/auto dark
     modes repaint CSS fills (not images) grey, giving a grey square. */
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.coastal-storymap .ca-fact-icon img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.coastal-storymap .ca-fact-label {
  font-weight: 600;
  color: var(--escap-blue-dark);
}
.coastal-storymap .ca-fact-text {
  min-width: 0;
  flex: 1;
}

/* Tools stepper — the four .flow-card rows of the CS-013 workbench. Hover
   and focus only recolour (and spotlight linked tools); the bullet list
   opens on click/Enter via .is-open so the rail never jumps under the
   pointer. */
.coastal-storymap .flow-card {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-4);
  padding: var(--space-5) var(--space-5) var(--space-5) var(--space-4);
  border-inline-start: 3px solid var(--escap-blue-wash);
  background: var(--white);
  cursor: pointer;
  transition: background var(--t-base) var(--ease-standard), border-color var(--t-base) var(--ease-standard);
}
.coastal-storymap .flow-card + .flow-card {
  margin-top: 1px;
}
.coastal-storymap .flow-card:focus-visible {
  outline: 2px solid var(--escap-gold);
  outline-offset: -2px;
}
.coastal-storymap .flow-num {
  grid-row: 1 / span 3;
  align-self: start;
  font-family: var(--coastal-title-font);
  font-size: var(--text-4xl);
  font-weight: var(--weight-bold);
  line-height: 1;
  color: var(--escap-blue-pale);
  transition: color var(--t-base) var(--ease-standard);
}
.coastal-storymap .flow-card:hover,
.coastal-storymap .flow-card:focus-visible,
.coastal-storymap .flow-card.is-open {
  background: var(--escap-blue);
  border-inline-start-color: var(--escap-gold);
}
.coastal-storymap .flow-card h3 {
  margin: 0 0 var(--space-2);
  color: var(--escap-blue);
  font-family: var(--coastal-title-font);
  font-size: var(--coastal-card-title-size);
  font-weight: var(--weight-medium);
}
.coastal-storymap .flow-card p {
  margin: 0;
  color: var(--fg-muted);
  font-size: var(--coastal-card-body-size);
  line-height: var(--lh-base);
}
.coastal-storymap .flow-card:hover h3,
.coastal-storymap .flow-card:focus-visible h3,
.coastal-storymap .flow-card.is-open h3,
.coastal-storymap .flow-card:hover p,
.coastal-storymap .flow-card:focus-visible p,
.coastal-storymap .flow-card.is-open p,
.coastal-storymap .flow-card:hover .flow-num,
.coastal-storymap .flow-card:focus-visible .flow-num,
.coastal-storymap .flow-card.is-open .flow-num {
  color: var(--white);
}
.coastal-storymap .flow-card-detail {
  grid-column: 2;
  list-style: disc;
  margin: 0;
  padding: 0 0 0 var(--space-5);
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--t-base) var(--ease-standard), margin-top var(--t-base) var(--ease-standard);
}
.coastal-storymap .flow-card.is-open .flow-card-detail {
  max-height: 400px; /* raw: transition ceiling, tallest list is 4 wrapped bullets */
  margin-top: var(--space-4);
}
.coastal-storymap .flow-card-detail li {
  margin: 0 0 var(--space-2);
  color: var(--white);
  font-size: var(--coastal-card-body-size);
  line-height: var(--lh-base);
}
.coastal-storymap .flow-card-detail li:last-child {
  margin-bottom: 0;
}

/* Placed directly after the component's own block, ahead of the shared
   Responsive section below, so it isn't shadowed by later unconditional
   rules by source order. 1279px, not 1000px: at 1024 the 420px stepper left
   the 3-column deck ~93px text columns. */
@media (max-width: 1279px) {
  .coastal-storymap .tools-workbench {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
  .coastal-storymap .tools-steps {
    position: static;
  }
  .coastal-storymap .tools-deck {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 640px) {
  .coastal-storymap .tools-workbench {
    width: calc(100vw - 2 * var(--space-4));
    margin-left: calc(50% - 50vw + var(--space-4));
  }
  .coastal-storymap .tools-deck {
    grid-template-columns: 1fr;
  }
}

/* Responsive */
@media (max-width: 900px) {
  .coastal-storymap .partner-grid,
  .coastal-storymap .resource-grid {
    grid-template-columns: 1fr;
  }

  .coastal-storymap .split-wrap {
    grid-template-columns: 1fr;
  }

  .coastal-storymap .stat-row {
    grid-template-columns: repeat(2, 1fr);
  }

  .coastal-storymap .site-nav {
    flex-direction: column;
    align-items: flex-start;
  }

  .coastal-storymap .nav-links {
    justify-content: flex-start;
  }

  /* CoastalArea — tablet */
  .coastal-storymap .ca-facts-bar {
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--space-1);
  }
  .coastal-storymap .ca-facts-eyebrow,
  .coastal-storymap .ca-fact {
    padding: var(--space-2);
  }
  .coastal-storymap .ca-fact {
    font-size: var(--text-xs);
  }
  .coastal-storymap .ca-fact-icon {
    display: none;
  }
}

@media (max-width: 640px) {
  .coastal-storymap .site-nav .nav-links,
  .coastal-storymap .side-nav {
    display: none;
  }

  .coastal-storymap section {
    padding: 64px 16px;
  }

  .coastal-storymap .stat-row {
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  .coastal-storymap .stat-cell {
    min-width: 0;
    padding: 32px 12px;
  }

  /* CoastalArea — mobile */
  .coastal-storymap .coastal-area-shell { padding-block: var(--space-5); padding-inline: 0; }
  .coastal-storymap .ca-facts-bar { width: calc(100% - 2 * var(--space-4)); }
  .coastal-storymap .ca-zone-label { font-size: var(--text-xs); letter-spacing: 0.06em; }
  .coastal-storymap .ca-zone-sub { display: none; }
  .coastal-storymap .ca-image-wrap { background-position: center; }

  /* One coordinate set, not two. SM-033's second (mobile) set existed because
     the box cropped the artwork differently at each breakpoint; the box now
     carries the artwork's own 1981/793 ratio at every width, so `cover` crops
     nothing and a single set of percentages is correct everywhere. Pins are
     smaller here so they don't swamp a ~335px-wide frame. */
  .coastal-storymap .ca-hotspot { --ca-hotspot-size: 36px; }
  .coastal-storymap .ca-facts-bar { grid-template-columns: 1fr; }
  .coastal-storymap .ca-facts-eyebrow {
    width: 100%;
    box-sizing: border-box;
  }
  .coastal-storymap .ca-fact {
    padding: var(--space-4);
  }
}

/* CoastalArea — desktop overlay (>900px only). Overlays .ca-zone-axis across
   the top of .ca-image-wrap; .ca-facts-bar flows below the image on its own
   row. Tablet (641-900px) and mobile (<=640px) keep today's stacked layout
   untouched — see the two blocks above. */
@media (min-width: 901px) {
  .coastal-storymap .ca-main {
    position: relative;
  }

  /* Zone axis overlay: pulled out of .ca-main's flow (it's already a flow
     sibling of .ca-image-wrap there — see .ca-main), so .ca-image-wrap
     naturally expands to fill the vacated space and this lands correctly
     across its top edge. Needs a blur/scrim band underneath: plain text
     directly on the photo was confirmed illegible in the user's CSS
     prototype (unlike the facts bar, whose cards already carry their own
     opaque white background). */
  .coastal-storymap .ca-zone-axis {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 3;
    margin-bottom: 0;
    padding: var(--space-2);
    background: rgba(255, 255, 255, 0.55);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-radius: var(--radius-4) var(--radius-4) 0 0;
  }
  .coastal-storymap .ca-zone-axis .ca-zone {
    padding: var(--space-1);
  }
  .coastal-storymap .ca-zone-axis .ca-zone-label {
    font-size: var(--text-xs);
  }
  .coastal-storymap .ca-zone-axis .ca-zone-sub {
    font-size: var(--text-xs);
  }

  /* Facts bar sits below the artwork, not over it: it stays the third flow
     child of .ca-main that CoastalArea._render() reparents it into, so it
     lands under .ca-image-wrap on its own row. Only .ca-zone-axis still
     overlays. */
  .coastal-storymap .ca-facts-bar {
    display: flex;
    flex-direction: column;
    gap: var(--space-2);
    padding: var(--space-3) 0 0;
  }
  .coastal-storymap .ca-facts-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
  }
  .coastal-storymap .ca-facts-header .ca-facts-eyebrow {
    grid-column: auto;
  }
  .coastal-storymap .ca-facts-header .deck-controls {
    display: flex;
  }
  /* Deck buttons default to a translucent-white-on-dark treatment (built for
     #pilots' dark section background) — overridden here to read against the
     bright photo instead. */
  .coastal-storymap .ca-facts-header .deck-btn {
    background: rgba(255, 255, 255, 0.9);
    border-color: var(--border);
    color: var(--escap-blue-dark);
  }
  .coastal-storymap .ca-facts-header .deck-btn:hover {
    background: var(--white);
    border-color: var(--escap-blue-pale);
  }

  /* 5 facts become a horizontal scroll-snap carousel, mirroring
     .country-deck (Slide 20/21 country card decks) above. Fewer facts
     visible at once, so both the label and body run larger than the base
     (stacked, all-5-visible) rule. */
  .coastal-storymap .ca-facts-deck {
    display: grid;
    /* Fixed, not minmax(): the deck has room to fit all 5 cards at any
       minmax() minimum without overflowing, so a minmax() max is never
       actually invoked and every track sits at ~244px regardless of the
       max given — which is too narrow to wrap the longest fact
       description ("Global Trade Hub", 177 chars) into the fixed 100px
       card. Verified empirically (Playwright against the live page):
       380px is the true minimum width for that description to wrap and
       fit; 400px adds margin. A fixed width also makes the deck actually
       overflow and scroll as a real carousel, which minmax() was
       accidentally preventing since all 5 cards fit without scrolling. */
    grid-auto-columns: 400px;
    grid-auto-flow: column;
    gap: var(--space-3);
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }
  .coastal-storymap .ca-facts-deck::-webkit-scrollbar {
    display: none;
  }
  .coastal-storymap .ca-facts-deck .ca-fact {
    scroll-snap-align: start;
    font-size: var(--text-xs);
    height: 100px;
  }
  .coastal-storymap .ca-facts-deck .ca-fact-label {
    font-size: var(--text-sm);
  }
}
/* Where the picture is short, the sub-line made the band tall enough to cover
   the top-row pins. */
@media (min-width: 901px) and (max-width: 1199px) {
  .coastal-storymap .ca-zone-axis .ca-zone-sub { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .coastal-storymap .rv {
    opacity: 1;
    transform: none;
  }
}

@media (hover: none), (max-width: 768px) {
  .coastal-storymap .map-filter-btn {
    min-height: 44px;
  }

  .coastal-storymap .year-range {
    min-height: 44px;
  }

  .coastal-storymap .deck-btn {
    min-width: 44px;
    min-height: 44px;
  }



  .coastal-storymap .leaflet-touch .leaflet-bar a {
    width: 44px;
    height: 44px;
    line-height: 44px;
  }
}

/* Custom Leaflet Popup overrides to match premium theme */
.coastal-storymap .custom-leaflet-popup .leaflet-popup-content-wrapper {
  background: rgba(255, 255, 255, 0.96) !important;
  color: var(--fg) !important;
  border-radius: var(--radius-3) !important;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.12) !important;
  backdrop-filter: blur(8px) !important;
  border: 1px solid var(--border) !important;
}

.coastal-storymap .custom-leaflet-popup .leaflet-popup-content {
  margin: 0 !important;
  padding: 16px !important;
  font-family: var(--font-sans) !important;
  font-size: var(--text-sm) !important;
  max-width: 380px !important;
  width: min(360px, calc(100vw - 48px)) !important; /* fits a 390px phone map */
  line-height: var(--lh-base) !important;
}

.coastal-storymap .custom-leaflet-popup .leaflet-popup-tip {
  background: rgba(255, 255, 255, 0.96) !important;
  border: 1px solid var(--border) !important;
}

/* Flipped below the pin (coastal-story.js openPopup) — the tip would point the
   wrong way, so drop it. */
.coastal-storymap .custom-leaflet-popup.popup-below .leaflet-popup-tip-container {
  display: none;
}

/* ── Climate Scenario Widget ─────────────────────────────────────────────── */

.coastal-storymap climate-scenario {
  display: block;
}
/* Same subtitle-to-map gap as #events .wrap. */
.coastal-storymap #climate-explore .wrap {
  margin-bottom: var(--space-7);
}
/* Reserve the rendered height until the widget draws (it waits on two CSVs,
   ApexCharts and Leaflet), so its late render doesn't shift the page. :empty
   drops the reserve the moment the shell or the error UI is inserted.
   Desktop: .map-stage's height plus the caption; stacked: measured ≥1312px. */
.coastal-storymap climate-scenario:empty {
  min-height: calc(max(520px, min(78vh, 780px)) + var(--space-9)); /* raw: mirrors .map-stage */
}
@media (max-width: 1000px) {
  .coastal-storymap climate-scenario:empty {
    min-height: 1300px; /* raw: stacked widget renders 1312–1390px tall */
  }
}

.coastal-storymap .scenario-shell {
  min-width: 0;
}

/* The map IS the stage: edge-to-edge, tall, everything else floats above it.
   z-index 1001+ clears Leaflet panes (200–700) and controls (1000).
   Full-bleed out of section's 32px padding via the same RTL-safe
   margin: calc(50% - 50vw) pattern as .coastal-area-shell (see its note). */
.coastal-storymap .map-stage {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  height: min(78vh, 780px);
  min-height: 520px;
  overflow: hidden;
  background: #e8edf3;
}

.coastal-storymap .map-stage > [data-role="leaflet-container"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* ── Control dock (top-left): hazard accordion with nested levels ── */
.coastal-storymap .control-dock {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 1001;
  width: 340px; /* raw: fits "Sea Surface Temperature Change (°C)" on one line */
  max-width: calc(100% - 32px);
  max-height: calc(100% - 90px);
  overflow-y: auto;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(223, 230, 242, 0.9);
  border-radius: 14px;
  box-shadow: 0 16px 40px rgba(13, 40, 80, 0.16);
  padding: 1rem;
  display: grid;
  gap: 0.75rem;
  align-content: start;
}

/* Short laptop screens (1366×768, 1280×720): the flooding dock needs ~480px, so
   let it run to the bottom and move the zoom control out from under it. */
@media (min-width: 1001px) {
  .coastal-storymap .control-dock {
    max-height: calc(100% - 32px);
  }
  .coastal-storymap .map-stage .leaflet-bottom.leaflet-left {
    left: calc(340px + var(--space-4)); /* raw: the dock's width */
  }
}

.coastal-storymap .dock-title {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #5b667a;
}

.coastal-storymap .hazard-accordion {
  display: grid;
  gap: 0.4rem;
}

.coastal-storymap .hazard-item {
  border: 1px solid #dfe6f2;
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
}

.coastal-storymap .hazard-item.active {
  border-color: var(--escap-blue-wash);
  box-shadow: 0 6px 18px rgba(13, 40, 80, 0.1);
}

.coastal-storymap .hazard-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  width: 100%;
  padding: 0.65rem 0.8rem;
  background: transparent;
  border: none;
  cursor: pointer;
  font-weight: 600;
  font-size: 0.85rem;
  color: #5b667a;
  text-align: start;
}

/* .hazard-item's overflow:hidden clips the default outside focus ring. */
.coastal-storymap .hazard-head:focus-visible {
  outline-offset: -2px;
}

.coastal-storymap .hazard-item.active .hazard-head {
  color: var(--escap-blue);
}

.coastal-storymap .hazard-radio {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  border-radius: 50%;
  border: 2px solid #b9c6da;
  transition: all 0.2s ease;
}

.coastal-storymap .hazard-item.active .hazard-radio {
  border-color: var(--escap-blue);
  background: var(--escap-blue);
  box-shadow: inset 0 0 0 2.5px #fff;
}

.coastal-storymap .hazard-body {
  padding: 0.2rem 0.8rem 0.8rem;
  display: grid;
  gap: 0.7rem;
}

/* ── Level groups inside the dock ── */
.coastal-storymap .level-group {
  display: grid;
  gap: 0.35rem;
  min-width: 0;
}

.coastal-storymap .level-label {
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--fg-muted);
  white-space: nowrap;
}

.coastal-storymap .level-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}

.coastal-storymap .level-chip {
  border: 1px solid #dfe6f2;
  background: #f6f8fc;
  color: #5b667a;
  padding: 0.3rem 0.65rem;
  border-radius: 7px;
  font-size: 0.74rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s ease;
}

.coastal-storymap .level-chip.active {
  background: var(--escap-blue);
  border-color: var(--escap-blue);
  color: #fff;
}

.coastal-storymap .level-chip:hover:not(.active) {
  border-color: var(--escap-blue);
  color: var(--escap-blue);
}

/* ── Subregion pills (top-right, over the map) ── */
.coastal-storymap .region-pills {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 1001;
  display: flex;
  align-items: center;
  gap: 0.3rem;
  flex-wrap: wrap;
  justify-content: flex-end;
  max-width: calc(100% - 380px);
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(223, 230, 242, 0.9);
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(13, 40, 80, 0.14);
  padding: 0.45rem 0.6rem;
}

.coastal-storymap .region-pills .level-label {
  margin-right: 0.3rem;
}

.coastal-storymap .region-pill {
  border: 1px solid transparent;
  background: transparent;
  color: #5b667a;
  padding: 0.3rem 0.6rem;
  border-radius: 8px;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease;
}

.coastal-storymap .region-pill.active {
  background: var(--escap-blue);
  color: #fff;
}

.coastal-storymap .region-pill:hover:not(.active, [disabled]) {
  color: var(--escap-blue);
  background: rgba(32, 102, 168, 0.08);
}

/* ── Floating trend card (bottom-right) ── */
.coastal-storymap .trend-card {
  position: absolute;
  right: 16px;
  bottom: 16px;
  z-index: 1001;
  width: 460px;
  max-width: calc(100% - 32px);
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(223, 230, 242, 0.9);
  border-radius: 14px;
  box-shadow: 0 16px 40px rgba(13, 40, 80, 0.18);
  padding: 0.8rem 0.9rem 0.4rem;
}

.coastal-storymap .trend-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.2rem;
}

.coastal-storymap .scenario-readout {
  flex: 1 1 auto;
  font-size: 0.78rem;
  line-height: 1.45;
  color: #5b667a;
}

.coastal-storymap .scenario-readout .nw {
  white-space: nowrap;
}

.coastal-storymap .scenario-readout strong {
  color: var(--escap-blue);
}

.coastal-storymap .trend-card .expand-btn {
  position: static;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  border: 1px solid #dfe6f2;
  background: #f6f8fc;
  color: #5b667a;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s ease;
}

.coastal-storymap .trend-card .expand-btn:hover {
  background: var(--escap-blue);
  border-color: var(--escap-blue);
  color: #fff;
}

.coastal-storymap .trend-card .expand-btn svg {
  width: 15px;
  height: 15px;
}

.coastal-storymap .apex-chart {
  width: 100%;
  position: relative;
  cursor: default;
}

.coastal-storymap .apex-chart .apexcharts-canvas {
  width: 100% !important;
  position: relative;
  z-index: 2;
}

.coastal-storymap .apexcharts-tooltip {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
}

/* ── Trend card view tabs + exposure matrix ── */
.coastal-storymap .trend-tabs {
  display: inline-flex;
  gap: 0.2rem;
  background: #f1f4f9;
  border: 1px solid #dfe6f2;
  border-radius: 8px;
  padding: 0.18rem;
  flex: 0 0 auto;
}

.coastal-storymap .trend-tab {
  border: none;
  background: transparent;
  color: #5b667a;
  padding: 0.26rem 0.6rem;
  border-radius: 6px;
  font-size: 0.72rem;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease;
}

.coastal-storymap .trend-tab.active {
  background: var(--escap-blue);
  color: #fff;
}

.coastal-storymap .matrix-wrap {
  max-height: 340px;
  overflow: auto;
  padding-bottom: 0.5rem;
}

/* Small multiples: name column, then per period a spacer track + one track per
   class. grid-template-columns is set inline by _matrixHTML. */
.coastal-storymap .matrix-grid {
  display: grid;
  gap: 2px 1px;
  align-items: stretch;
  font-size: 0.68rem;
}

/* Corner and names stay pinned when the matrix scrolls sideways (mobile). */
.coastal-storymap .mx-corner {
  position: sticky;
  top: 0;
  left: 0;
  z-index: 2;
  background: rgba(255, 255, 255, 0.97);
}

.coastal-storymap .mx-panel {
  position: sticky;
  top: 0;
  z-index: 1;
  background: rgba(255, 255, 255, 0.97);
  padding: 0.2rem 0 0.25rem;
  font-weight: 700;
  color: #2b3448;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* The period (or return period) the menu has selected. The matrix shows every
   panel at once, so this marker is the only thing the period control changes
   here — without it the buttons look inert from the Exposure view. The accent
   goes on the label, never on the cells: dimming or tinting them would read as
   a different share. */
.coastal-storymap .mx-panel.active {
  color: #2066a8;
  box-shadow: inset 0 -2px 0 #2066a8;
}

/* Class initials repeated under each panel — the legend carries the full names. */
.coastal-storymap .mx-abbr {
  padding-top: 0.2rem;
  font-size: 0.6rem;
  font-weight: 600;
  color: var(--fg-muted);
  text-align: center;
  white-space: nowrap;
}

.coastal-storymap .mx-class-range {
  font-weight: 500;
  color: var(--fg-muted);
  font-size: 0.6rem;
}

.coastal-storymap .matrix-name {
  position: sticky;
  left: 0;
  z-index: 1;
  background: rgba(255, 255, 255, 0.97);
  color: #2b3448;
  font-weight: 600;
  padding-block: 0.14rem;
  padding-inline-end: 0.5rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: end;
}

.coastal-storymap .mx-cell {
  min-height: 16px;
  cursor: default;
}

.coastal-storymap .matrix-legend {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.3rem 0.8rem;
  margin-top: 0.5rem;
  font-size: 0.66rem;
  color: #5b667a;
}

.coastal-storymap .matrix-key {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.coastal-storymap .matrix-swatch {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex: 0 0 auto;
}

/* Class keys carry the cell ramp itself — white at 0%, full colour at 100% —
   so the legend reads as the scale the cells are painted with. */
.coastal-storymap .mx-ramp {
  width: 34px;
  height: 12px;
  border: 1px solid var(--border);
  background: linear-gradient(to right, #fff, var(--mx-ramp-to));
}

.coastal-storymap .matrix-key b {
  font-weight: 700;
  color: #2b3448;
}

/* A hazard with no data for the selected subregion (SM-063), and the reverse:
   a subregion with no data for the selected hazard. */
.coastal-storymap .hazard-item.empty,
.coastal-storymap .region-pill[disabled] {
  opacity: 0.45;
}

.coastal-storymap .hazard-head[disabled],
.coastal-storymap .region-pill[disabled] {
  cursor: not-allowed;
}

.coastal-storymap .mx-tip {
  position: fixed;
  z-index: 2000;
  pointer-events: none;
  white-space: pre-line;
  max-width: 260px;
  padding: 6px 9px;
  border-radius: 8px;
  background: #2d2d2d;
  color: #fff;
  font-size: 0.66rem;
  line-height: 1.35;
  box-shadow: 0 10px 20px rgba(15, 23, 42, 0.35);
}

.coastal-storymap .mx-cell:hover {
  outline: 1px solid #2b3448;
  outline-offset: -1px;
}

.coastal-storymap .matrix-status {
  padding: 2rem 0;
  text-align: center;
  color: var(--fg-muted);
  font-size: 0.8rem;
}

/* ── Legend (top-right, below the subregion pills) ── */
.coastal-storymap .map-stage .hazard-map-legend {
  position: absolute;
  left: auto;
  right: 16px;
  top: 76px;
  bottom: auto;
  z-index: 1001;
  max-width: 240px;
  max-height: 180px;
  overflow-y: auto;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(223, 230, 242, 0.9);
  border-radius: 10px;
  box-shadow: 0 12px 30px rgba(13, 40, 80, 0.14);
  padding: 0.5rem 0.65rem;
  font-size: 0.68rem;
  color: var(--fg-muted);
}

/* Restored: ebd2fdc dropped these three with the slide 39/40 CSS sweep, leaving
   the swatches as zero-width inline spans and the rows as plain blocks. */
.coastal-storymap .hazard-map-legend-title {
  font-weight: 700;
  font-size: 0.78rem;
  line-height: 1.25;
  color: var(--fg);
  padding-bottom: 5px;
}
.coastal-storymap .hazard-map-legend-row {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 0;
}
.coastal-storymap .hazard-map-legend-swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex-shrink: 0;
  /* Keeps near-white swatches (SST "< 0.5") visible on the white panel. */
  box-shadow: inset 0 0 0 1px var(--border);
}

/* dir=rtl would reverse numeric ranges ("0.3 - 0.0") and "2 yr" labels. */
.coastal-storymap .hazard-map-legend-label,
.coastal-storymap .mx-class-range,
.coastal-storymap .mx-panel,
.coastal-storymap .level-chip {
  unicode-bidi: plaintext;
}

.coastal-storymap .scenario-data-note {
  margin: 0;
  font-size: 0.74rem;
  color: #a04d4d;
}

.coastal-storymap .scenario-caption {
  margin-top: 0.8rem;
  font-size: 0.875rem;
  color: #524f47;
  line-height: 1.625;
}

/* Full screen: the stage covers the viewport without the map — dock on the
   left, subregion pills and a full-size trend card on the right.
   z-index > 1000 clears Leaflet panes (200–700) and controls (1000). */
.coastal-storymap .map-stage.is-full {
  position: fixed;
  inset: 0;
  z-index: 1100;
  width: auto;
  height: auto;
  min-height: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 340px minmax(0, 1fr); /* raw: matches the dock's own width */
  grid-template-rows: auto minmax(0, 1fr);
  gap: var(--space-4);
  padding: var(--space-4);
  overflow-y: auto;
  /* The <1000px column layout clears the stage background; full screen needs one. */
  background: var(--bg-soft);
  /* Panels size to their content instead of stretching into blank white. */
  align-items: start;
}

/* content-visibility:auto (main > section) would make the section the
   containing block for position:fixed — the full-screen stage and the matrix
   .mx-tip would be placed against the section, not the viewport. Selector
   matches that rule's specificity (the :not(#hero) counts as an id). */
.coastal-storymap main > section#climate-explore {
  content-visibility: visible;
}

/* Its z-index 95 would leave the sticky .site-nav (100) over full screen. */
.coastal-storymap #climate-explore:has(.map-stage.is-full) {
  z-index: 1100;
}

.coastal-storymap .map-stage.is-full > [data-role="leaflet-container"],
.coastal-storymap .map-stage.is-full .hazard-map-legend {
  display: none;
}

.coastal-storymap .map-stage.is-full .control-dock,
.coastal-storymap .map-stage.is-full .region-pills,
.coastal-storymap .map-stage.is-full .trend-card {
  position: static;
  width: auto;
  max-width: none;
  max-height: none;
}

.coastal-storymap .map-stage.is-full .control-dock { grid-row: 1 / 3; }
.coastal-storymap .map-stage.is-full .region-pills { justify-content: flex-start; }

.coastal-storymap .map-stage.is-full .matrix-wrap {
  max-height: none;
}

/* Short desktop viewports (1280×720): a 340px matrix pushes the bottom-anchored
   card up over the top-right map legend. */
@media (min-width: 1001px) and (max-height: 880px) {
  .coastal-storymap .map-stage:not(.is-full) .matrix-wrap {
    max-height: 180px; /* raw: card clears the legend on the 520px min stage */
  }
}

@media (max-width: 1000px) {
  .coastal-storymap .map-stage.is-full {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
    /* Auto rows let the scrolling dock collapse to a 34px strip under a tall chart. */
    grid-auto-rows: max-content;
  }
  .coastal-storymap .map-stage.is-full .control-dock { grid-row: auto; }
  /* The card that was expanded (and its exit button) comes first. */
  .coastal-storymap .map-stage.is-full .trend-card { order: 0; }
}

/* Climate Scenario widget responsive rules — below ~1000px the floating
   panels would bury the map, so the stage unstacks into a plain column:
   dock → region pills → trend card → map → legend. The card sits right under
   the controls that drive it. */
@media (max-width: 1000px) {
  .coastal-storymap .map-stage {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
    height: auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 0.9rem;
    overflow: visible;
    background: transparent;
    box-shadow: none;
    border-radius: 0;
  }
  .coastal-storymap .map-stage > [data-role="leaflet-container"] {
    position: relative;
    inset: auto;
    order: 3;
    height: 420px;
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow);
  }
  .coastal-storymap .control-dock,
  .coastal-storymap .region-pills,
  .coastal-storymap .map-stage .hazard-map-legend,
  .coastal-storymap .trend-card {
    position: static;
    width: auto;
    max-width: none;
    max-height: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .coastal-storymap .control-dock { order: 1; }
  .coastal-storymap .region-pills { order: 2; justify-content: flex-start; }
  .coastal-storymap .trend-card { order: 2; }
  .coastal-storymap .map-stage .hazard-map-legend { order: 4; }
  /* Legend rows wrap side by side instead of a tall, mostly empty box. */
  .coastal-storymap .map-stage .hazard-map-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--space-3);
  }
  .coastal-storymap .hazard-map-legend-title { flex-basis: 100%; }
  /* The page scrolls; a second nested vertical scroll hid the class axis and key. */
  .coastal-storymap .matrix-wrap { max-height: none; }
}

@media (max-width: 640px) {
  .coastal-storymap .map-stage > [data-role="leaflet-container"] {
    height: 320px;
  }
  /* Readout gets its own row; tabs and expand share the next one. */
  .coastal-storymap .trend-head { flex-wrap: wrap; }
  .coastal-storymap .scenario-readout { flex-basis: 100%; }
  .coastal-storymap .trend-card .expand-btn { margin-inline-start: auto; }
  /* The matrix already scrolls sideways here (names are sticky); wider cells
     keep the class initials (VL, L … VH, E) from running together. */
  .coastal-storymap .matrix-grid { --mx-cell: 16px; }
  .coastal-storymap .logos {
    gap: 24px;
    margin-top: 32px;
  }
}

/* Touch targets, matching the story's 44px touch block (placed after the
   widget's base rules so it wins on source order). */
@media (hover: none), (max-width: 768px) {
  .coastal-storymap .trend-tab {
    min-height: 44px;
  }
  .coastal-storymap .trend-card .expand-btn {
    width: 44px;
    height: 44px;
  }
}

/* RTL (dv) — layout-affecting overrides only. Widgets (Leaflet, donut chart,
   cascade flow) don't auto-mirror and need their own manual RTL review. */
.coastal-storymap[dir="rtl"] {
  direction: rtl;
}

.coastal-storymap[dir="rtl"] .side-nav {
  right: auto;
  left: 22px;
}

/* Below ~1232px the column reaches the 32px gutter, and at 22px the rail sat
   on the content's edge and took its clicks; up to 1279px the stacked #tools
   workbench also reaches it. 4px keeps it inside the gutter. */
@media (min-width: 641px) and (max-width: 1279px) {
  .coastal-storymap .side-nav { right: 4px; }
  .coastal-storymap[dir="rtl"] .side-nav { right: auto; left: 4px; }
}

.coastal-storymap[dir="rtl"] .ca-eyebrow {
  flex-direction: row-reverse;
}

.coastal-storymap[dir="rtl"] .custom-leaflet-popup .leaflet-popup-content-wrapper {
  text-align: right;
}

body.page-coastal-story .main-content__content {
  margin-bottom: 0;
}
