/*
 * UK AI Compass Executive Summary - page-specific styles
 * Rebuild (v5+) implements: docs/uk-compass-exec-summary-copy-flow.md (11-beat brief)
 * House motion/a11y conventions: docs/superpowers/specs/2026-04-25-uk-compass-component-specs.md (Part 1 + cross-cutting only)
 *
 * Structure of this file:
 *   1. Tokens (palette, temperature, type roles, motion)
 *   2. Page shell overrides
 *   3. Hero
 *   4. Section system (header pattern, base, temperature, stub scaffold)
 *   5. Scroll progress
 *   6. Reduced-motion + mobile base
 * Per-beat styles are appended by their build chunk.
 */

/* ====== 1. Tokens ====== */
:root {
  /* Palette (inherits the site's --color-* / --seg-* but keeps page-local aliases) */
  --cs-paper:        #FFFFFF;
  --cs-ink:          #1C273B;
  --cs-ink-soft:     #3A4A61;
  --cs-gold:         #FDC100;
  --cs-brand-blue:   #1436BC;
  --cs-green:        #86A624;
  --cs-red:          #A71712;
  --cs-muted:        #999999;
  --cs-muted-soft:   #cfcfcf;
  --cs-teal:         #0E9C92;  /* "gains reach ordinary people" 10% segment (Beats 3-4) */
  --cs-rule:         rgba(28, 39, 59, 0.12);

  /* Temperature arc - DISCREET. The page warms a couple of percent at the turn
     ("This isn't a country that wants to switch AI off"). Felt, not seen. */
  --cs-paper-cool:   #FBFCFE;  /* beats 1-5: grievance, faint cool cast */
  --cs-paper-warm:   #FDFBF7;  /* beats 6-11: agency, faint warm cast */

  /* Type roles - three voices.
     verdict  = the country's settled view (Helvetica Black on Mac, Inter Black
                via webfont everywhere else - the page loads Inter so any
                visitor without local Helvetica Neue gets real Inter Black
                instead of falling all the way through to Arial Black)
     narrate  = editorial narration (Work Sans)
     evidence = the data speaking: stat units, credibility, attributions (DM Mono) */
  --cs-font-display:  "Helvetica Neue", "Helvetica", "Inter", "Arial Black", sans-serif;
  --cs-font-body:     "Work Sans", system-ui, sans-serif;
  --cs-font-mono:     "DM Mono", "Courier New", monospace;
  --cs-font-verdict:  var(--cs-font-display);
  --cs-font-narrate:  var(--cs-font-body);
  --cs-font-evidence: var(--cs-font-mono);

  /* Semantic colour - gold means "us" (ordinary people / agency), ink means power. */
  --cs-us:   var(--cs-gold);
  --cs-them: var(--cs-ink);

  /* Motion (house easings/durations from the component spec) */
  --cs-ease-standard:   cubic-bezier(0.4, 0, 0.2, 1);
  --cs-ease-out:        cubic-bezier(0.0, 0, 0.2, 1);
  --cs-ease-spring:     cubic-bezier(0.34, 1.2, 0.5, 1);
  /* "wipe": a strong decelerate (~GSAP power4.out) - quick to start, long
     gentle settle. Used by the Beat 5 photo reveal and the Beat 8/9 build-ins
     to match the Seismic block-scroll feel. */
  --cs-ease-wipe:       cubic-bezier(0.16, 1, 0.3, 1);

  --cs-dur-quick:    200ms;
  --cs-dur-standard: 400ms;
  --cs-dur-medium:   600ms;
  --cs-dur-long:     900ms;
}

/* ====== 1b. Lenis smooth scroll ======
   Required by the vendored Lenis instance (js/components/scroll-machinery.js).
   Lenis toggles .lenis / .lenis-smooth / .lenis-stopped on <html>. The
   scroll-behavior:auto override is essential: reset.css sets
   html{scroll-behavior:smooth} site-wide, which fights Lenis' own lerp. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }

/* ====== 2. Page shell overrides ======
   layout.css defaults body / #main-content to the navy chrome colour.
   This page is paper. */
html, body { background: var(--cs-paper); color: var(--cs-ink); }
#main-content { background: var(--cs-paper); }

.cs-page-nav { background: var(--color-blue); position: relative; z-index: 10; }
.cs-page-nav .hero-nav {
  padding-top: clamp(12px, 1.4vw, 22px);
  padding-bottom: clamp(12px, 1.4vw, 22px);
}

/* ====== 3. Hero ====== */
.cs-hero {
  background: var(--cs-paper);
  padding: 0 0 4em;
}
.cs-hero__inner {
  max-width: 1040px;
  margin: 0 auto;
  padding: clamp(3.5em, 7vw, 6em) 2em 3em;
  text-align: center;
  position: relative;
}
.cs-hero__kicker {
  font-family: var(--cs-font-evidence);
  font-size: 0.72em;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--cs-brand-blue);
  font-weight: 500;
  display: inline-block;
  margin-bottom: 1.4em;
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 0.2em;
}
.cs-hero__title {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(2.3em, 5vw, 4.4em);
  line-height: 1.04;
  letter-spacing: -0.025em;
  color: var(--cs-ink);
  margin: 0 auto 0.7em;
  max-width: 18ch;
  text-wrap: balance;
}
/* Two beats: each sentence is its own block so it balances on its own line(s)
   rather than running on; a small gap marks the beat between them. */
.cs-hero__title-line { display: block; }
.cs-hero__title-line--two { margin-top: 0.18em; }
.cs-hero__orient {
  font-family: var(--cs-font-narrate);
  font-size: clamp(1em, 1.4vw, 1.12em);
  color: var(--cs-ink-soft);
  font-weight: 400;
  max-width: 56ch;
  margin: 0 auto;
  line-height: 1.6;
}
.cs-hero__credstrip {
  font-family: var(--cs-font-evidence);
  font-size: 0.78em;
  letter-spacing: 0.1em;
  color: var(--cs-ink-soft);
  text-transform: uppercase;
  margin: 2em auto 0;
  font-weight: 500;
  line-height: 1.8;
  max-width: 60ch;
}

/* Hero fade-up. The animate class is added by JS ONLY when motion is allowed, so
   reduced-motion users never get the hidden initial state. */
.cs-hero--animate .cs-hero__kicker,
.cs-hero--animate .cs-hero__title,
.cs-hero--animate .cs-hero__orient,
.cs-hero--animate .cs-hero__credstrip {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--cs-dur-medium) var(--cs-ease-out),
              transform var(--cs-dur-medium) var(--cs-ease-out);
}
.cs-hero--animate.is-ready .cs-hero__kicker    { opacity: 1; transform: none; transition-delay: 0ms; }
.cs-hero--animate.is-ready .cs-hero__title     { opacity: 1; transform: none; transition-delay: 120ms; }
.cs-hero--animate.is-ready .cs-hero__orient    { opacity: 1; transform: none; transition-delay: 320ms; }
.cs-hero--animate.is-ready .cs-hero__credstrip { opacity: 1; transform: none; transition-delay: 480ms; }

/* ====== 3b. Ribbed-glass hero ======
   The hero background is a photograph refracted through reeded glass:
   js/components/ribbed-glass-hero.js builds a sine displacement map and the
   #cs-ribbed-glass SVG filter applies it (three passes = chromatic dispersion)
   plus a bloom (halation). The filter renders at reduced resolution (the .glass
   box is sized small and scaled back up) so it is cheap; the flutes slow-drift
   only while the hero is on screen, and stay static on mobile / reduced-motion.
   All glass layers sit BEHIND .cs-hero__inner, whose text is recoloured white. */
.cs-hero.cs-hero--glass{
  --csg-rib:54px;       /* on-screen flute width (drives the sheen period) */
  --csg-bleed:200px;    /* glass bled past the hero so the fringe is clipped */
  --csg-flow:0px;       /* sideways flute travel (set by JS for motion) */
  position:relative;
  min-height:clamp(560px, 82vh, 860px);
  display:grid;
  place-items:center;
  overflow:hidden;
  isolation:isolate;
  padding:0;
  background:#0b1026 url('../Images/exec-hero-countryside.webp') center/cover no-repeat;
}
/* Fixed, bled-out wrap that clips the refraction fringe */
.cs-hero__gwrap{
  position:absolute;inset:0 calc(-1 * var(--csg-bleed));
  overflow:hidden;pointer-events:none;
}
/* The displacement-filtered glass, rendered small then scaled up (cheap) */
.cs-hero__glass{
  position:absolute;top:0;left:0;width:60%;height:60%;
  transform-origin:top left;transform:scale(1.6667);
  overflow:hidden;
  filter:url(#cs-ribbed-glass);
  will-change:transform;
}
.cs-hero__gbg{
  position:absolute;inset:-4% -4%;
  background:url('../Images/exec-hero-countryside.webp') center/cover no-repeat;
  transform:scale(1.06);
}
/* Rib crest + recessed groove shading (hue-neutral, travels with the flutes) */
.cs-hero__gsheen{
  position:absolute;inset:0;pointer-events:none;
  background-image:linear-gradient(90deg,
    rgba(255,255,255,0.45) 0%,
    rgba(255,255,255,0.18) 9%,
    rgba(255,255,255,0)    22%,
    rgba(0,0,0,0.20)       38%,
    rgba(0,0,0,0.36)       50%,
    rgba(0,0,0,0.20)       62%,
    rgba(255,255,255,0)    78%,
    rgba(255,255,255,0.18) 91%,
    rgba(255,255,255,0.45) 100%);
  background-size:var(--csg-rib) 100%;
  background-position:calc(-1 * var(--csg-bleed) - var(--csg-flow)) 0;
  mix-blend-mode:soft-light;
}
/* Frosted/dirty surface grit (static SVG noise tile) */
.cs-hero__ggrain{
  position:absolute;inset:0;pointer-events:none;opacity:0.22;
  mix-blend-mode:soft-light;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:180px 180px;
}
/* Legibility scrim, heavier behind the text */
.cs-hero__gscrim{
  position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(125% 95% at 50% 52%,
      rgba(6,10,28,0.32) 0%, rgba(6,10,28,0.17) 42%, rgba(6,10,28,0) 78%),
    linear-gradient(180deg,
      rgba(6,10,28,.14) 0%, rgba(6,10,28,0) 22%,
      rgba(6,10,28,0) 68%, rgba(6,10,28,.20) 100%);
}
/* Content sits above the glass; recoloured white for the dark backdrop */
.cs-hero--glass .cs-hero__inner{position:relative;z-index:2;}
.cs-hero--glass .cs-hero__kicker{
  color:#fff;border-bottom-color:rgba(255,255,255,.7);
  text-shadow:0 1px 10px rgba(6,10,28,.45);
}
.cs-hero--glass .cs-hero__title{
  color:#fff;text-shadow:0 2px 30px rgba(6,10,28,.45), 0 1px 4px rgba(6,10,28,.35);
}
.cs-hero--glass .cs-hero__orient{
  color:rgba(255,255,255,.94);text-shadow:0 1px 14px rgba(6,10,28,.5);
}
.cs-hero--glass .cs-hero__credstrip{
  color:rgba(255,255,255,.86);text-shadow:0 1px 10px rgba(6,10,28,.5);
}

/* ====== 4. Section system ====== */

/* Header pattern. Optional kicker (evidence voice), headline (verdict voice),
   optional lead (narrate voice). No forced numerals - beats are not numbered
   on the page. */
.cs-section-header { margin-bottom: 2.5em; max-width: 60ch; }
.cs-kicker {
  font-family: var(--cs-font-evidence);
  font-weight: 500;
  font-size: 0.72em;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cs-brand-blue);
  display: inline-block;
  margin-bottom: 1em;
}
.cs-headline {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(1.8em, 3.6vw, 2.6em);
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  margin: 0 0 0.6em;
  line-height: 1.1;
  text-wrap: balance;
}
.cs-lead {
  font-family: var(--cs-font-narrate);
  font-size: 1.05em;
  line-height: 1.65;
  color: var(--cs-ink);
  margin: 0;
  max-width: 56ch;
}

/* Section base + temperature. The temperature seam falls once, at the turn. */
.cs-beat { padding: clamp(3em, 7vw, 5em) clamp(1.5em, 4vw, 3em); position: relative; }
.cs-beat--cool { background: var(--cs-paper-cool); }
.cs-beat--warm { background: var(--cs-paper-warm); }
.cs-beat__inner { max-width: var(--site-max-width, 1500px); margin: 0 auto; }

/* Scaffold stub - replaced beat-by-beat. Looks intentional while in development. */
.cs-stub { min-height: 60vh; display: grid; place-content: center; text-align: center; }
.cs-stub__eyebrow {
  font-family: var(--cs-font-evidence);
  font-size: 0.7em;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--cs-muted);
  margin: 0 0 0.8em;
}
.cs-stub__headline {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(1.5em, 3vw, 2.2em);
  letter-spacing: -0.02em;
  color: var(--cs-muted-soft);
  margin: 0;
  max-width: 20ch;
}

/* ====== 5. Scroll progress ====== */
.scroll-progress {
  position: fixed;
  top: 50%;
  right: 1.5em;
  transform: translateY(-50%);
  z-index: 50;
}
.scroll-progress ol { list-style: none; margin: 0; padding: 0; }
.scroll-progress li a {
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--cs-ink);
  opacity: 0.22;
  transition: opacity var(--cs-dur-quick) var(--cs-ease-standard);
  margin: 9px 0;
}
.scroll-progress li[aria-current] a { opacity: 1; }
.scroll-progress li a:focus-visible { outline: 2px solid var(--cs-brand-blue); outline-offset: 3px; }

@media (max-width: 759px) {
  .scroll-progress {
    top: auto;
    bottom: 1em;
    right: 50%;
    transform: translateX(50%);
  }
  .scroll-progress ol { display: flex; }
  .scroll-progress li a { margin: 0 6px; }
}

/* Screen-reader-only helper (used for chart data summaries and progress labels).
   Defined here because this page is the only consumer; not in the global CSS. */
.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;
}

/* ====== 6. Reduced-motion base ====== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

/* ============================================================
   BEAT 1 - "It's already in your life"
   Header on the left; the lived examples build into a compact grid of
   small, square-ish rounded boxes on the right. The boxes cascade in on
   entry (staggered) and hold. The closing line lands last, full width.
   ============================================================ */
.cs-b1 { position: relative; }

.cs-b1__inner {
  max-width: 1180px;
  padding-block: clamp(2.5em, 5vw, 4.5em);
  display: grid;
  grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
  column-gap: clamp(2em, 5vw, 5em);
  align-items: center;
}
/* Large opening claim in the left column; the evidence tiles stack on the right
   (two-column, matching the rest of the page). */
.cs-b1__statement {
  font-size: clamp(1.8em, 3.3vw, 3em);
  line-height: 1.1;
  margin: 0;
}
.cs-b1__head { max-width: 24ch; align-self: center; }
.cs-b1__lead { margin-top: 0.8em; color: var(--cs-ink-soft); }

/* Right column: grid of small, square-ish boxes, sitting to the right. */
.cs-b1__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: clamp(0.55em, 1vw, 0.85em);
}
.cs-b1__line {
  margin: 0;
  background: rgba(28, 39, 59, 0.05);
  border-radius: 12px;
  padding: clamp(0.8em, 1.2vw, 1.1em) clamp(1em, 1.5vw, 1.3em);
  display: flex;
  flex-direction: column;
  gap: 0.35em;
  transition: background-color 240ms var(--cs-ease-standard),
              box-shadow 240ms var(--cs-ease-standard);
}
.cs-b1__line-tag {
  font-family: var(--cs-font-evidence);
  font-weight: 500;
  font-size: 0.7em;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cs-ink-soft);
  transition: color 240ms var(--cs-ease-standard);
}
.cs-b1__line-text {
  font-family: var(--cs-font-narrate);
  font-weight: 500;
  font-size: clamp(0.95em, 1.05vw, 1.1em);
  line-height: 1.32;
  letter-spacing: -0.005em;
  color: var(--cs-ink);
}
/* Hover: deepen + a soft lift via box-shadow (not transform, so it never clashes
   with the reveal transform), and the tag picks up brand blue. */
.cs-b1__line:hover {
  background: rgba(28, 39, 59, 0.09);
  box-shadow: 0 8px 22px rgba(28, 39, 59, 0.12);
}
.cs-b1__line:hover .cs-b1__line-tag { color: var(--cs-brand-blue); }
/* Light grid-break: each tile indented a different amount so the stack reads as
   organic accumulation rather than a rigid list. */
.cs-b1__line:nth-child(2) { margin-left: clamp(0.5em, 1.4vw, 1.4em); }
.cs-b1__line:nth-child(3) { margin-left: clamp(0.2em, 0.6vw, 0.6em); }
.cs-b1__line:nth-child(4) { margin-left: clamp(0.8em, 2.2vw, 2.2em); }
.cs-b1__line:nth-child(5) { margin-left: clamp(0.35em, 0.9vw, 0.9em); }
.cs-b1__line:nth-child(6) { margin-left: clamp(0.6em, 1.7vw, 1.7em); }
.cs-b1__line:nth-child(7) { margin-left: clamp(0.25em, 0.7vw, 0.7em); }
.cs-b1__line:nth-child(8) { margin-left: clamp(0.45em, 1.2vw, 1.2em); }

/* Closing line - the punch, full width beneath both columns. */
.cs-b1__close {
  grid-column: 1 / -1;
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(1.5em, 3.2vw, 2.4em);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  max-width: 30ch;
  margin: clamp(0.4em, 1.2vw, 1.2em) 0 0;
}
.cs-b1__close::before {
  content: "";
  display: block;
  width: 2.5em;
  height: 3px;
  background: var(--cs-gold);
  margin-bottom: 0.6em;
}

/* Reveal states - applied ONLY when JS adds .is-animated (motion allowed).
   Reduced-motion and no-JS render everything visible by default. */
/* Reveal (motion only): the claim fades up first, then the evidence tiles slide
   in from the right in compounding order, accumulating down the stack. */
.cs-b1.is-animated .cs-b1__statement,
.cs-b1.is-animated .cs-b1__line {
  opacity: 0;
  transition: opacity var(--cs-dur-medium) var(--cs-ease-out),
              transform var(--cs-dur-medium) var(--cs-ease-out);
}
.cs-b1.is-animated .cs-b1__statement { transform: translateY(12px); }
.cs-b1.is-animated .cs-b1__line { transform: translateX(28px); }
.cs-b1.is-animated .cs-b1__statement.is-in,
.cs-b1.is-animated .cs-b1__line.is-in { opacity: 1; transform: none; }

.cs-b1.is-animated .cs-b1__line:nth-child(1).is-in { transition-delay: 120ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(2).is-in { transition-delay: 230ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(3).is-in { transition-delay: 340ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(4).is-in { transition-delay: 450ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(5).is-in { transition-delay: 560ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(6).is-in { transition-delay: 670ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(7).is-in { transition-delay: 780ms; }
.cs-b1.is-animated .cs-b1__line:nth-child(8).is-in { transition-delay: 890ms; }

@media (max-width: 759px) {
  .cs-b1__inner { grid-template-columns: 1fr; row-gap: clamp(1.6em, 5vw, 2.4em); }
  .cs-b1__head { align-self: start; max-width: none; }
  .cs-b1__line { margin-left: 0; }
}

/* ============================================================
   BEAT 2 - "The public has decided"  (layout follows the wireframe)
   Three-zone pinned row: refrain top-left (bold headline + smaller line),
   the big stat centred, the UK dot map on the right. The map recolours into
   a three-colour band that FILLS FROM THE TOP as the reader scrubs the three
   stats. Majority = gold ("us"), second view = ink, undecided = grey.
   All panel text is Helvetica Neue bold; only the legend is DM Mono.
   Reduced-motion / mobile / no-GSAP fall back to a stacked layout, one map
   per stat.
   ============================================================ */
/* The stage is the full-width pinned area; it just centres the composition so
   nothing stretches to the screen edges or clips under the nav at wide widths. */
.cs-b2__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1.5em, 4vw, 3em);
}

/* --- Sticky hold (motion desktop only; JS adds .cs-b2--scrub) ---
   The beat holds via CSS position:sticky, NOT a GSAP pin. There is no
   position:fixed swap, so the engage/release snap the pin produced cannot
   happen (see the pin-snap diagnosis). Structure:
     .cs-b2 (.cs-b2--scrub)  = tall "driver"; its extra height IS the scroll
                               distance the three stats scrub over.
     .cs-b2__sticky          = sticks under the banner for the driver's length.
     .cs-b2__stage           = the unchanged composition, filling the held box.
   --cs-hold is the scrub distance, written by createStickyObserver (was the
   pin's endScroll +=240%). --cs-banner is published by scroll-machinery.js
   (0 at launch, no edit). */
.cs-b2--scrub {
  position: relative;
  height: calc(100vh - var(--cs-banner, 0px) + var(--cs-hold, 240vh));
  padding: 0;   /* the .cs-beat padding would offset the sticky + inflate height */
}
.cs-b2--scrub .cs-b2__sticky {
  position: sticky;
  top: var(--cs-banner, 0px);
  height: calc(100vh - var(--cs-banner, 0px));
}
.cs-b2--scrub .cs-b2__stage { height: 100%; }
/* The composition itself is a bounded block (like the wireframe slide):
   col1 left text | col2 stat | col3 map. row1 headline | row2 sub-line + stat. */
.cs-b2__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  grid-template-rows: auto 1fr;
  column-gap: clamp(1em, 2vw, 2em);
  row-gap: clamp(1.5em, 4vw, 3em);
  width: 100%;
  max-width: 1120px;
  /* Height is driven by the map (which spans both rows), giving a contained,
     wireframe-like aspect rather than stretching to the full pinned height. */
}
/* Headline: top-left, the first thing read. */
.cs-b2__refrain {
  grid-column: 1;
  grid-row: 1;
  align-self: start;
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(2.6em, 5vw, 4.2em);   /* matches the b34 headline */
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  max-width: 15ch;
  margin: 0;
}
/* Sub-line: drops to the middle band on the left, level with the stat. */
.cs-b2__subrefrain {
  grid-column: 1;
  grid-row: 2;
  align-self: center;
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.3em, 2vw, 1.7em);
  line-height: 1.25;
  color: var(--cs-ink-soft);
  max-width: 18ch;
  margin: 0;
}

/* Stat + legend: a cluster anchored against the map's left edge (col2), sitting
   around its lower-middle (Northern Ireland down to Cornwall), legend underneath. */
.cs-b2__stat-col {
  grid-column: 2;
  grid-row: 2;
  align-self: center;
  max-width: 22ch;
}
.cs-b2__stats { display: grid; }
.cs-b2__num {
  font-family: var(--cs-font-verdict);
  font-weight: 800;
  font-size: clamp(3em, 6vw, 5em);
  line-height: 0.95;
  letter-spacing: -0.03em;
  color: var(--cs-us);   /* gold = the public's verdict */
  margin: 0;
}
.cs-b2__pct { font-size: 0.45em; vertical-align: 0.5em; margin-left: 0.05em; }
.cs-b2__stat-label {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.05em, 1.5vw, 1.35em);
  line-height: 1.3;
  color: var(--cs-ink);
  max-width: 22ch;
  margin: 0.45em 0 0;
}
.cs-b2__read {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.1em);
  line-height: 1.45;
  color: var(--cs-ink-soft);
  max-width: 30ch;
  margin: clamp(1.2em, 2.5vw, 2em) 0 0;
}

/* Map: right side (col3), spanning both rows so the stat anchors to its middle. */
.cs-b2__map { grid-column: 3; grid-row: 1 / 3; align-self: center; margin: 0; }
.cs-b2__map-mount { width: clamp(280px, 30vw, 400px); aspect-ratio: 620 / 841; }

/* Legend sits under the strap, left-aligned, as part of the stat cluster. */
.cs-b2__legend {
  display: flex;
  gap: clamp(0.6em, 1.4vw, 1.2em);
  flex-wrap: wrap;
  justify-content: flex-start;
  font-family: var(--cs-font-evidence);
  font-size: 0.74em;
  letter-spacing: 0.04em;
  color: var(--cs-ink-soft);
  margin: 1.1em 0 0;
}
.cs-b2__legend-item { display: inline-flex; align-items: center; gap: 0.5em; }
.cs-b2__legend-swatch { width: 0.8em; height: 0.8em; border-radius: 2px; flex: none; }

/* Sub-progress tick: tells the reader they are advancing through 3 stats while
   the panel itself holds still (the dead-zone affordance). Beat 2 only. Anchored
   bottom-left of the left column, beneath the sub-line. */
.cs-b2__tick {
  grid-column: 1;
  grid-row: 2;
  align-self: end;
  justify-self: start;
  display: flex;
  gap: 0.5em;
  width: clamp(7em, 14vw, 11em);
  margin: 0;
}
.cs-b2__tick-pill {
  flex: 1; height: 0.5em; border-radius: 0.4em;
  background: var(--cs-muted-soft);
  transition: background var(--cs-dur-medium) var(--cs-ease-out);
}
.cs-b2__tick-pill.is-on { background: var(--cs-ink); }
/* Stacked fallback has no single scrubbed sequence, so the tick is meaningless there. */
.cs-b2--stacked .cs-b2__tick { display: none; }

/* --- Scrub (motion desktop): stats overlap, only the active one shows. --- */
.cs-b2--scrub .cs-b2__stat {
  grid-area: 1 / 1;
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--cs-dur-medium) var(--cs-ease-out),
              transform var(--cs-dur-medium) var(--cs-ease-out);
  pointer-events: none;
}
.cs-b2--scrub .cs-b2__stat.is-active { opacity: 1; transform: none; pointer-events: auto; }
.cs-b2--scrub .cs-b2__read { opacity: 0; transition: opacity var(--cs-dur-medium) var(--cs-ease-out); }
.cs-b2--scrub[data-active-state="2"] .cs-b2__read { opacity: 1; }

/* --- Stacked fallback (reduced-motion / mobile / no-GSAP): one map per stat. --- */
.cs-b2--stacked .cs-b2__stage { display: block; height: auto !important; padding: 0; }
.cs-b2--stacked .cs-b2__grid { display: block; max-width: none; }
.cs-b2--stacked .cs-b2__subrefrain { margin: 0.8em 0 0; }
.cs-b2--stacked .cs-b2__map { display: none; }      /* the single pinned map */
.cs-b2--stacked .cs-b2__stats { display: block; margin-top: clamp(1.5em, 4vw, 3em); }
.cs-b2__panel {
  display: grid;
  grid-template-columns: clamp(130px, 26vw, 200px) 1fr;
  gap: clamp(1.2em, 3vw, 2.4em);
  align-items: center;
  margin-bottom: clamp(2em, 5vw, 3.5em);
}
.cs-b2__minimap { aspect-ratio: 620 / 841; width: 100%; }

@media (max-width: 759px) {
  .cs-b2__grid { grid-template-columns: 1fr; grid-template-rows: none; }
  .cs-b2__refrain, .cs-b2__subrefrain, .cs-b2__stat-col, .cs-b2__map {
    grid-column: 1; grid-row: auto; align-self: start; max-width: none;
  }
  .cs-b2__subrefrain { margin: 0.8em 0 0; }
  /* Each stat panel reads as one centred unit: the map sits directly above its
     number + label, tight, so the country and the figure clearly belong
     together (was left-aligned with a loose gap, which read as messy). */
  .cs-b2__panel {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    gap: clamp(0.5em, 2.5vw, 1em);
  }
  .cs-b2__minimap { max-width: 200px; margin: 0 auto; }
  .cs-b2__stat { justify-items: center; }
  .cs-b2__stat-label { margin-left: auto; margin-right: auto; }
}

/* ============================================================
   BEATS 3+4 - "And it's not for you"  (one pinned sequence)
   Phases (data-phase on the section): bar -> expand -> diane -> niamh -> cp.
   The 68/10 bar (red 68 to billionaires / grey / gold 10 to ordinary people)
   expands to full-height columns; the colour clears into the portraits (Diane
   focus, then Niamh focus); then it contracts to reveal the cross-party
   "bipartisan view". CSS transitions do the tweening; JS only sets data-phase
   from scroll progress. Reduced motion / mobile / no-GSAP: --static stacks it.
   ============================================================ */
.cs-b34 { padding: 0; background: var(--cs-paper); }
.cs-b34__pin { position: relative; height: 100vh; overflow: hidden; background: var(--cs-paper); }

/* --- Sticky hold (motion desktop; JS adds .cs-b34--scrub). The section is a
   tall driver; .cs-b34__pin holds via position:sticky (no GSAP pin, no
   position:fixed swap, no engage/release snap). The pin keeps its own
   overflow:hidden + absolute children - overflow on the sticky element itself
   is fine; only an ancestor's overflow would break sticky. --cs-hold is the
   scrub distance (was the pin endScroll +=440%); --cs-banner is published by
   scroll-machinery.js (0 at launch). --- */
.cs-b34--scrub { height: calc(100vh - var(--cs-banner, 0px) + var(--cs-hold, 440vh)); }
.cs-b34--scrub .cs-b34__pin {
  position: sticky;
  top: var(--cs-banner, 0px);
  height: calc(100vh - var(--cs-banner, 0px));
}

.cs-b34__blocks,
.cs-b34__block,
.cs-b34__intro,
.cs-b34__photo,
.cs-b34__quote,
.cs-b34__cp {
  transition: clip-path 900ms var(--cs-ease-standard),
              width 800ms var(--cs-ease-standard),
              opacity 700ms var(--cs-ease-standard),
              transform 800ms var(--cs-ease-standard);
}

/* --- The three graph columns ARE the layout. Each is a full-height column.
   Their colour fills are replaced by full-bleed images in the portrait phases:
   red 68% -> Diane image, grey 22% -> Niamh image, gold 10% stays. The focus
   shift swaps the major/mid widths. --- */
.cs-b34__blocks {
  position: absolute; inset: 0;
  display: flex;
  clip-path: inset(58% 6% 22% 6% round 8px);   /* bar phase: a chunky band (~20vh) in the lower third, per the wireframe */
}
.cs-b34__block { position: relative; height: 100%; flex: 0 0 auto; overflow: hidden; }
.cs-b34__block--major { width: 68%; background: var(--cs-red); }
.cs-b34__block--mid   { width: 22%; background: var(--cs-muted-soft); }
.cs-b34__block--minor { width: 10%; background: var(--cs-gold); }

/* --- Intro: the conventional bar reading --- */
.cs-b34__intro { position: absolute; inset: 0; }
.cs-b34__head { position: absolute; top: 13%; left: 6%; width: min(46ch, 58%); }
/* Headline reads large here (it was rendering small and unbalancing the panel) -
   matches the wireframe weight. */
.cs-b34__head .cs-headline { margin: 0 0 0.5em; font-size: clamp(2.6em, 5vw, 4.2em); line-height: 1.02; }
.cs-b34__head .cs-headline em { font-style: italic; }
.cs-b34__lead {
  font-family: var(--cs-font-verdict); font-weight: 700;
  font-size: clamp(1.05em, 1.6vw, 1.45em); line-height: 1.3;
  color: var(--cs-ink-soft); margin: 0; max-width: 26ch;
}
.cs-b34__barlabel { position: absolute; top: 68%; transform: translateY(-50%); font-family: var(--cs-font-verdict); font-weight: 700; }
/* Major (per wireframe): a giant 68% on the LEFT that nearly fills the bar
   height, with the descriptor set small to its right. */
/* left MUST be >= the bar's clip inset (6%) or the number renders past the red
   bar's left edge onto the page (the "breaking the edge" bug). 9% = the 6% clip
   plus a comfortable inset, matching the wireframe. */
.cs-b34__barlabel--major {
  left: 9%; color: #fff;
  display: flex; align-items: center; gap: clamp(0.6em, 1.4vw, 1.2em);
  max-width: 58%; line-height: 1.2;
}
.cs-b34__barlabel--major strong {
  font-size: clamp(3rem, 12.5vh, 8rem); font-weight: 800;
  letter-spacing: -0.04em; line-height: 0.85;
}
/* Descriptor scaled up so its two lines read as a co-equal label (not a
   caption), roughly matching the 68%'s height. Width-based so it always fits
   two lines beside the number without spilling past the red. */
.cs-b34__barlabel-text {
  font-size: clamp(1.4rem, 2.7vw, 2.4rem); font-weight: 700;
  line-height: 1.12; text-align: left;
}
/* Mid: a very subtle "22% / not sure" centred on the grey 22% segment (DOM
   68-90%, so its centre sits at 79%). 22% matches the 10% type size; "not sure"
   sits tight beneath it. */
.cs-b34__barlabel--mid {
  left: 79%; right: auto; transform: translate(-50%, -50%);
  color: #efefef; text-align: center;
  display: flex; flex-direction: column; align-items: center;
  line-height: 1.06; font-size: clamp(0.95em, 1.5vw, 1.3em);
}
.cs-b34__barlabel--mid strong { font-weight: 800; }
.cs-b34__mid-sub { font-weight: 600; }
/* Minor: centred within the visible gold column (clip cuts it at ~94%, so its
   visible centre sits near 92%). */
.cs-b34__barlabel--minor { left: 92%; right: auto; transform: translate(-50%, -50%); color: var(--cs-ink); font-size: clamp(0.95em, 1.5vw, 1.3em); font-weight: 800; text-align: center; }
.cs-b34__annotation { position: absolute; top: 26%; right: 6%; width: clamp(190px, 22vw, 260px); color: var(--cs-ink); text-align: right; }
.cs-b34__annotation-text { font-family: "Caveat", cursive; font-weight: 700; font-size: clamp(1.3em, 2.2vw, 1.9em); line-height: 1.05; margin: 0 0 0.2em; }
/* Tall curved arrow that bridges from the note down onto the gold 10% block. */
.cs-b34__arrow { display: block; width: auto; height: clamp(170px, 27vh, 280px); margin-left: auto; color: var(--cs-ink); }

/* --- Short-viewport guard (motion/desktop path only) ---------------------
   The intro is anchored to the TOP of the pin (.cs-b34__head at top:13%) while
   the bar band is pinned to 58% of the viewport HEIGHT (the .cs-b34__blocks
   clip). But the headline/lead are sized by WIDTH (vw/em), so they don't shrink
   as the window gets short - below ~700px tall the subheading grows down into
   the bar band. Reported on Edge/Windows at 1280x672 (it also reproduces in
   Chrome at the same window height); the heavier "Arial Black" fallback on
   Windows makes the subheading wrap taller, so the collision starts at a taller
   window there than on a Mac. Compress + lift the head block so the lead always
   clears the band, with a generous gap to absorb the wider Windows metrics.
   The --static path (mobile <=759px / reduced motion) already re-flows the beat
   in normal document order, so it is excluded here. ----------------------- */
@media (min-width: 760px) and (max-height: 760px) {
  /* Widen the headline column at short heights so the longer "We've decided it
     isn't built for us." line wraps to 2 tidy lines (not 4) and the lead clears
     the bar band - inc. the wider Windows "Inter"/"Arial Black" metrics. Tall
     viewports keep the base 46ch column (wireframe weight). */
  .cs-b34:not(.cs-b34--static) .cs-b34__head { top: 16%; width: min(54ch, 60%); }
  .cs-b34:not(.cs-b34--static) .cs-b34__head .cs-headline {
    /* Caps at 60px and scales with height on shorter windows. Smaller type
       wraps to two tidy lines and shrinks the block enough to clear the band
       even with the heavier Windows "Arial Black" fallback. */
    font-size: clamp(2.4rem, 8.9vh, 3.75rem);
    margin-bottom: 0.3em;
  }
  .cs-b34:not(.cs-b34--static) .cs-b34__lead {
    font-size: clamp(1.1rem, 3vh, 1.45em);   /* near-full at 672, gentle shrink below */
    max-width: 30ch;                          /* a touch wider so it stays to fewer lines */
  }
}

/* Photo fills its column edge-to-edge, full height; opacity 0 until the
   portrait phases, when it replaces the column's colour. */
.cs-b34__photo {
  position: absolute; inset: 0;
  background-size: cover; background-position: center;
  filter: grayscale(1) contrast(1.03);
  opacity: 0;
}

/* Quote sits in the open space to the lower-left of the subject's gaze (NO
   background layer - per the wireframe). A text-shadow alone carries legibility
   over the portrait. Hidden by default; the focused column's quote shows in its
   phase. */
.cs-b34__quote {
  position: absolute; top: 46%; left: 5%; right: auto; bottom: auto;
  margin: 0; padding: 0;
  width: min(40%, 20em);
  background: none;
  opacity: 0;
}
/* The quote is the key statement of the section (it only shows when its column
   is in the wide, open state), so it reads large - not a caption. */
.cs-b34__quote p {
  font-family: var(--cs-font-verdict); font-weight: 700;
  font-size: clamp(1.5em, 2.6vw, 2.6em); line-height: 1.2; color: #fff; margin: 0 0 0.55em;
  text-shadow: 0 2px 14px rgba(8, 12, 20, 0.85), 0 1px 3px rgba(8, 12, 20, 0.9);
}
.cs-b34__quote--signature p { font-size: clamp(1.05em, 1.7vw, 1.7em); }
.cs-b34__quote cite { font-family: var(--cs-font-evidence); font-style: normal; font-size: 0.95em; letter-spacing: 0.03em; color: rgba(255, 255, 255, 0.92); text-shadow: 0 1px 8px rgba(8, 12, 20, 0.9), 0 1px 3px rgba(8, 12, 20, 0.9); }

/* --- Cross-party "bipartisan view" --- */
/* Sits left of centre (the contracted portrait columns occupy ~40% on the
   left) with room to breathe, rather than crammed against the right edge.
   Whole block is Helvetica Neue (--cs-font-verdict), including the party rows
   and the CTA. */
.cs-b34__cp {
  position: absolute; top: 50%; left: 46%; right: 6%;
  font-family: var(--cs-font-verdict);
  transform: translateY(-50%) translateX(40px);
  opacity: 0;
  /* Snap in fast so the panel "loads" early in the cp hold, leaving the tail as
     real friction instead of the slow 700/900ms build eating it. */
  transition: opacity 420ms var(--cs-ease-out), transform 480ms var(--cs-ease-out);
}
.cs-b34__cp-title { font-family: var(--cs-font-verdict); font-weight: 800; font-size: clamp(1.7em, 2.7vw, 2.5em); line-height: 1.12; color: var(--cs-ink); margin: 0 0 0.7em; }
.cs-b34__cp-stat { font-family: var(--cs-font-verdict); font-weight: 700; font-size: clamp(1.15em, 1.5vw, 1.45em); line-height: 1.35; color: var(--cs-ink); margin: 0 0 1.2em; max-width: 34ch; }
.cs-b34__cp-stat strong { color: var(--cs-gold); }
.cs-b34__cp-bars { list-style: none; margin: 0 0 1.2em; padding: 0; display: grid; gap: 0.55em; max-width: 34em; }
.cs-b34__cp-row { display: grid; grid-template-columns: 8em 1fr auto; align-items: center; gap: 0.7em; font-family: var(--cs-font-verdict); font-weight: 500; font-size: 0.98em; color: var(--cs-ink-soft); }
.cs-b34__cp-val { font-weight: 700; color: var(--cs-ink); }
.cs-b34__cp-bar { height: 0.9em; width: 0; background: var(--cp-color); border-radius: 2px; transition: width 480ms var(--cs-ease-out); }
.cs-b34__foreign { font-family: var(--cs-font-verdict); font-weight: 700; font-size: clamp(1.05em, 1.3vw, 1.3em); line-height: 1.35; color: var(--cs-ink-soft); margin: 0 0 1.2em; max-width: 36ch; }
/* Ghost button: outlined, fills on hover/focus. */
.cs-cta--inline {
  display: inline-block;
  font-family: var(--cs-font-verdict);
  font-weight: 600;
  font-size: clamp(0.8em, 0.95vw, 0.95em);
  letter-spacing: 0.01em;
  line-height: 1.3;
  white-space: nowrap;   /* keep the label + trailing arrow on one line (no orphaned arrow) */
  color: var(--cs-brand-blue);
  text-decoration: none;
  border: 1.5px solid var(--cs-brand-blue);
  border-radius: 4px;
  padding: 0.7em 1.1em;
  transition: background-color 200ms var(--cs-ease-standard), color 200ms var(--cs-ease-standard);
}
.cs-cta--inline:hover,
.cs-cta--inline:focus-visible {
  background: var(--cs-brand-blue);
  color: #fff;
}
/* Phones can't fit the longest CTA (the bipartisan one) on a single line, so it
   overflowed the panel. On mobile let it wrap cleanly (text-wrap: pretty avoids
   an orphaned arrow) and tighten the padding so the button stays compact.
   Desktop keeps the single-line ghost button. */
@media (max-width: 759px) {
  .cs-cta--inline {
    white-space: normal;
    text-wrap: pretty;
    padding: 0.6em 0.9em;
  }
}

/* ============ PHASE STATES ============ */
/* bar (default): blocks clipped to a band, intro visible, portraits + cp hidden. */

/* expand: the bar grows to full-height columns; the bar reading fades out. The
   portraits come in WITH the expand (not a beat later) so the columns never sit
   full-screen as flat colour blocks waiting for the images. */
.cs-b34[data-phase="expand"] .cs-b34__blocks { clip-path: inset(0% 0% 0% 0% round 0); }
.cs-b34[data-phase="expand"] .cs-b34__intro { opacity: 0; }
.cs-b34[data-phase="expand"] .cs-b34__photo { opacity: 1; }
/* Diane's quote is present from the moment her panel emerges (the expand phase),
   not a phase later - so it lands like Niamh's, which arrives with her focus. */
.cs-b34[data-phase="expand"] .cs-b34__quote--diane { opacity: 1; }

/* diane / niamh: colour cleared to white, portraits in. */
/* diane: the colours disappear, replaced by full-height images filling their
   columns. Diane's column stays wide (68%); Niamh's column stays narrow (22%);
   gold sliver (10%) persists. Diane's quote overlays. */
.cs-b34[data-phase="diane"] .cs-b34__blocks { clip-path: inset(0% 0% 0% 0% round 0); }
.cs-b34[data-phase="diane"] .cs-b34__intro { opacity: 0; }
.cs-b34[data-phase="diane"] .cs-b34__photo { opacity: 1; }
.cs-b34[data-phase="diane"] .cs-b34__quote--diane { opacity: 1; }

/* niamh: focus shifts. Diane's column CONTRACTS (major -> 22%), Niamh's column
   EXPANDS (mid -> 68%). Gold stays 10%. Niamh's quote takes over. */
.cs-b34[data-phase="niamh"] .cs-b34__blocks { clip-path: inset(0% 0% 0% 0% round 0); }
.cs-b34[data-phase="niamh"] .cs-b34__intro { opacity: 0; }
.cs-b34[data-phase="niamh"] .cs-b34__photo { opacity: 1; }
.cs-b34[data-phase="niamh"] .cs-b34__block--major { width: 22%; }
.cs-b34[data-phase="niamh"] .cs-b34__block--mid   { width: 68%; }
.cs-b34[data-phase="niamh"] .cs-b34__quote--niamh { opacity: 1; }

/* cp: image columns contract to leave room for the bipartisan view on the
   right; gold sliver collapses. */
.cs-b34[data-phase="cp"] .cs-b34__blocks { clip-path: inset(0% 0% 0% 0% round 0); }
.cs-b34[data-phase="cp"] .cs-b34__intro { opacity: 0; }
.cs-b34[data-phase="cp"] .cs-b34__photo { opacity: 1; }
.cs-b34[data-phase="cp"] .cs-b34__block--major { width: 20%; }
.cs-b34[data-phase="cp"] .cs-b34__block--mid   { width: 20%; }
.cs-b34[data-phase="cp"] .cs-b34__block--minor { width: 0%; }
.cs-b34[data-phase="cp"] .cs-b34__quote { opacity: 0; }
.cs-b34[data-phase="cp"] .cs-b34__cp { opacity: 1; transform: translateY(-50%) translateX(0); }
.cs-b34[data-phase="cp"] .cs-b34__cp-bar { width: var(--cp); }

/* --- Static/mobile stacked bar for the gains split ---
   Desktop renders the gains split as the full-height .cs-b34__blocks band, so
   this is hidden there. In the static fallback that band is repurposed as the
   stacked portrait images, leaving the gains figure with no graph - so this
   compact stacked bar stands in for it (68 red / 22 grey / 10 gold), keeping
   the chart in the sequence rather than reducing it to bare text. */
.cs-b34__minibar { display: none; }
.cs-b34--static .cs-b34__minibar { display: block; margin: 0 0 0.85em; max-width: 38ch; }
.cs-b34__minibar-track {
  display: flex; width: 100%; height: 2.7em;
  border-radius: 5px; overflow: hidden;
}
.cs-b34__minibar-seg {
  flex: var(--w) 0 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--cs-font-verdict); font-weight: 800;
  font-size: clamp(0.85em, 3.6vw, 1.05em); line-height: 1;
  color: #fff;
}
.cs-b34__minibar-seg--major { background: var(--cs-red); }
.cs-b34__minibar-seg--mid   { background: var(--cs-muted-soft); color: var(--cs-ink); }
.cs-b34__minibar-seg--minor { background: var(--cs-gold); color: var(--cs-ink); font-size: clamp(0.6em, 2.4vw, 0.78em); }

/* ============ STATIC FALLBACK (reduced motion / mobile / no-GSAP) ============ */
/* Reorder to match the desktop narrative sequence: the gains statement + its
   bar lead, then the two portraits, then the bipartisan view last. (In source
   order the portrait band sits first because it doubles as the desktop bar; the
   flex order below restores reading order so the gains panel no longer collides
   with the bipartisan one beneath it.) */
.cs-b34--static .cs-b34__pin {
  height: auto; overflow: visible;
  padding: clamp(3em, 7vw, 5em) clamp(1.5em, 4vw, 3em);
  display: flex; flex-direction: column;
}
.cs-b34--static .cs-b34__intro  { order: 1; }
.cs-b34--static .cs-b34__blocks { order: 2; }
.cs-b34--static .cs-b34__cp     { order: 3; }
.cs-b34--static .cs-b34__intro { position: relative; inset: auto; }
.cs-b34--static .cs-b34__head { position: relative; top: auto; left: auto; width: auto; margin-bottom: 1.25em; }
/* Surface the 68% reading as flowing text beneath the bar (it lives on the red
   bar in the pinned phase). Hide the bare 10% / 22% labels (the bar segments and
   the annotation carry that) and drop the hand-drawn arrow. */
.cs-b34--static .cs-b34__barlabel--major {
  position: static; transform: none; left: auto; top: auto;
  display: block; width: auto; max-width: 40ch;
  color: var(--cs-ink); font-size: clamp(0.95em, 1.3vw, 1.15em);
  margin: 0 0 0.5em;
}
.cs-b34--static .cs-b34__barlabel--major strong { color: var(--cs-red); font-size: 1.6em; line-height: 1; margin-right: 0.3em; }
.cs-b34--static .cs-b34__barlabel-text { max-width: none; text-align: left; }
.cs-b34--static .cs-b34__barlabel--minor,
.cs-b34--static .cs-b34__barlabel--mid { display: none; }
.cs-b34--static .cs-b34__annotation {
  position: static; transform: none; top: auto; right: auto;
  width: auto; max-width: 40ch; text-align: left;
  margin: 0 0 2.25em;
}
.cs-b34--static .cs-b34__annotation-text {
  font-family: var(--cs-font-verdict); font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.1em); color: var(--cs-ink);
  line-height: 1.3;
}
.cs-b34--static .cs-b34__arrow { display: none; }
/* Static stacks the columns as image panels. The photo keeps its 4:3 frame and
   the quote flows BELOW it (was an absolute overlay sized for the desktop pin,
   which overflowed the small mobile frame and clipped - the "text falling off"
   bug). Block background cleared so the quote reads as ink on paper. */
/* Extra top buffer so the portraits sit clearly apart from the gains chart +
   its reading above them on mobile (was crowding the Diane image). */
.cs-b34--static .cs-b34__blocks { position: relative; clip-path: none; display: block; height: auto; margin: 1.75em 0 0.5em; }
.cs-b34--static .cs-b34__block { width: 100% !important; height: auto; background: transparent !important; overflow: visible; }
.cs-b34--static .cs-b34__block--major,
.cs-b34--static .cs-b34__block--mid {
  aspect-ratio: auto;
  display: flex; flex-direction: column;
  margin-bottom: 2em;
}
.cs-b34--static .cs-b34__block--minor { display: none; }
.cs-b34--static .cs-b34__photo {
  opacity: 1 !important;
  position: relative; inset: auto;
  width: 100%; aspect-ratio: 4 / 3;
  border-radius: 4px;
}
.cs-b34--static .cs-b34__quote {
  opacity: 1 !important;
  position: relative; top: auto; left: auto; right: auto; bottom: auto;
  width: auto; margin: 0.85em 0 0;
}
.cs-b34--static .cs-b34__quote p {
  color: var(--cs-ink); text-shadow: none;
  font-size: clamp(1.15em, 4.6vw, 1.5em);
}
.cs-b34--static .cs-b34__quote--signature p { font-size: clamp(1em, 4vw, 1.25em); }
.cs-b34--static .cs-b34__quote cite { color: var(--cs-muted); text-shadow: none; }
/* Bipartisan view: its own panel last, set off from the portraits with a rule. */
.cs-b34--static .cs-b34__cp {
  position: relative; top: auto; left: auto; right: auto; width: auto; max-width: 480px;
  transform: none; opacity: 1;
  margin-top: 0.5em; padding-top: 1.75em; border-top: 1px solid var(--cs-rule);
}
.cs-b34--static .cs-b34__cp-bar { width: var(--cp); }


/* ============================================================
   BEAT 5 - "The worries, with a face and a number"
   Five pinned profiles that swap on scroll. A single fixed top-left tag
   updates per active profile. Standard profile: italic quote (Work Sans
   bold italic) + attribution + stat (Helvetica Neue, larger); image (right)
   that slides DOWN from above over the previous one, with a soft zoom while
   on hold. The Women profile is a variant: lead (left) + four bars in two
   pairs (centre) + closing text (right).
   Order: child safety -> copyright -> jobs -> regulator -> women.
   ============================================================ */
.cs-b5 { padding: 0; background: var(--cs-paper); }
.cs-b5__pin { position: relative; height: 100vh; overflow: hidden; background: var(--cs-paper); }

/* --- Sticky hold (motion desktop; JS adds .cs-b5--scrub). See b34 note.
   --cs-hold was the pin endScroll +=(N*100)% (five profiles -> 500vh). --- */
.cs-b5--scrub { height: calc(100vh - var(--cs-banner, 0px) + var(--cs-hold, 500vh)); }
.cs-b5--scrub .cs-b5__pin {
  position: sticky;
  top: var(--cs-banner, 0px);
  height: calc(100vh - var(--cs-banner, 0px));
}

/* The fixed tag in the top-left corner; stays in place across transitions. */
.cs-b5__tag-fixed {
  position: absolute;
  top: clamp(2em, 5vh, 3.6em);
  left: clamp(2em, 5vw, 5em);
  margin: 0;
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.05em);
  letter-spacing: 0.05em;
  color: var(--cs-ink);
  z-index: 5;
  transition: opacity 250ms var(--cs-ease-standard);
}

/* Per-profile tags live inline for the static fallback / SR; hidden in motion. */
.cs-b5__tag {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.05em);
  letter-spacing: 0.05em;
  color: var(--cs-ink);
  margin: 0 0 clamp(2em, 4vh, 3em);
}
.cs-b5:not(.cs-b5--static) .cs-b5__tag { position: absolute; clip: rect(0,0,0,0); width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; }

/* Profile container: text-left + image-right. is-active shows text; is-prev
   keeps the previous photo visible underneath so the new one can slide over. */
.cs-b5__profile {
  position: absolute; inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(2em, 5vw, 5em);
  padding: clamp(6em, 12vh, 9em) clamp(2em, 5vw, 5em) clamp(3em, 7vh, 6em);
  align-items: center;
  box-sizing: border-box;
  opacity: 0;
  pointer-events: none;
  transition: opacity 500ms var(--cs-ease-standard);
  background: var(--cs-paper);   /* opaque so prior profile never bleeds through */
}
.cs-b5__profile.is-active { opacity: 1; pointer-events: auto; }
.cs-b5__text { max-width: 38ch; }

/* Quote: Work Sans Italic Bold (the user's explicit override for this beat).
   Now the SUPPORTING voice in grey, under the blue stat - so the topic reads first. */
.cs-b5__quote { margin: 0; }
.cs-b5__quote p {
  font-family: var(--cs-font-narrate);
  font-weight: 700;
  font-style: italic;
  font-size: clamp(1.3em, 2vw, 1.7em);
  line-height: 1.25;
  color: var(--cs-ink-soft);
  margin: 0 0 0.7em;
  max-width: 22ch;
}
.cs-b5__quote cite {
  font-family: var(--cs-font-verdict);
  font-style: normal;
  font-weight: 700;
  font-size: 0.85em;
  letter-spacing: 0.02em;
  color: var(--cs-muted);
}

/* Stat: the lead now - sits at the TOP of the profile in brand blue so the topic
   is unmistakable before the quote. Helvetica Neue. */
.cs-b5__stat {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.35em, 2.4vw, 2em);
  line-height: 1.3;
  color: var(--cs-brand-blue);
  margin: 0 0 clamp(1.4em, 3vw, 2.2em);
  max-width: 22ch;
}

/* Media column: each photo eases out of a slight zoom as its profile becomes
   active, while the whole profile cross-fades over the previous one. We do NOT
   clip-wipe the frame: a clip reveal exposes the profile's paper background
   behind it, which read as a white flash between images. The photo is always
   scaled >1 so it fills the frame at every moment (no uncovered edge), the frame
   carries a dark fallback as a final safety net, and the cross-fade does the
   image-to-image transition. */
.cs-b5__media {
  position: relative; height: 100%; max-height: 78vh;
  overflow: hidden; border-radius: 4px;
  background: var(--cs-ink);
}
.cs-b5__photo {
  position: absolute; inset: 0;
  /* --photo (portrait crop) is set per profile inline; the static/mobile
     fallback swaps in --photo-wide (a wider crop) below. */
  background-image: var(--photo);
  background-size: cover; background-position: center;
  filter: grayscale(1) contrast(1.03);
  transform: scale(1.12);
  transform-origin: center;
  transition: transform 1400ms var(--cs-ease-wipe);
}
.cs-b5__photo--placeholder {
  background: repeating-linear-gradient(135deg, rgba(28,39,59,0.06) 0 12px, rgba(28,39,59,0.10) 12px 24px);
}
.cs-b5__profile.is-active .cs-b5__photo { transform: scale(1); }

/* --- Women variant: lead | 2x2 bars | closing --- */
.cs-b5__profile--women {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1fr);
  /* Shared label-box height + the gap between a label box and its bar fill.
     The longest label ("Women without degrees 50>") wraps to ~3 lines; every
     label box is this tall and bottom-aligned, so all bar fills start on the
     same line and the baseline sits exactly there.
     These MUST be in rem, not em: the values are read in two different
     font-size contexts - the label box (font-size 0.78em) and the baseline
     pseudo-element on .cs-b5__pair (full font-size). em would resolve to
     different pixels in each, dropping the baseline a few px into the bars
     (the overlap this fixes). rem is font-size-independent, so the line lands
     exactly on the bar tops at every viewport. */
  --cs-b5-label-h: clamp(3.8rem, 6.5vh, 4.8rem);
  --cs-b5-label-gap: 0.4rem;
}
.cs-b5__lead {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.15em, 1.6vw, 1.4em);
  line-height: 1.3;
  color: var(--cs-ink);
  margin: 0;
  max-width: 22ch;
}
.cs-b5__bars {
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(2em, 5vw, 4em);
}
.cs-b5__pair {
  display: flex;
  align-items: flex-start;
  gap: clamp(0.6em, 1.2vw, 1em);
  position: relative;
}
.cs-b5__pair::before {
  /* Baseline (zero line). It sits at the bottom of the label row, which is
     exactly where every bar fill starts. Both the label box and this line key
     off the same --cs-b5-label-h, so a wrapped label can never push a fill
     below the line (the old hardcoded top let that happen and the line cut
     through the bars). */
  content: "";
  position: absolute;
  top: calc(var(--cs-b5-label-h, 3.4rem) + var(--cs-b5-label-gap, 0.4rem));
  left: 0; right: 0;
  height: 1px;
  background: var(--cs-ink);
}
.cs-b5__bar { display: flex; flex-direction: column; align-items: center; width: clamp(68px, 8vw, 105px); }
.cs-b5__bar-label {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: 0.92em;
  line-height: 1.15;
  color: var(--cs-ink);
  text-align: center;
  height: var(--cs-b5-label-h, 3.4rem);
  display: flex; align-items: flex-end; justify-content: center;
  margin-bottom: var(--cs-b5-label-gap, 0.4rem);
}
.cs-b5__bar-fill {
  width: 100%;
  height: calc(var(--mag) * 1px * 4);  /* scaled in @media for fluid sizing */
  display: flex; align-items: flex-end; justify-content: center;
  padding-bottom: 0.4em;
  box-sizing: border-box;
}
.cs-b5__bar--men   .cs-b5__bar-fill { background: #D87B79; }
.cs-b5__bar--women .cs-b5__bar-fill { background: var(--cs-red); }
.cs-b5__bar--women-deep .cs-b5__bar-fill { background: #7C1812; }
.cs-b5__bar-value {
  font-family: var(--cs-font-verdict);
  font-weight: 800;
  font-size: clamp(1.05em, 1.6vw, 1.4em);
  color: #fff;
}
.cs-b5__text-right p {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.15em, 1.6vw, 1.4em);   /* match the lead on the other side */
  line-height: 1.3;
  color: var(--cs-ink);
  margin: 0;
  max-width: 22ch;
}
.cs-b5__text-right strong { color: var(--cs-brand-blue); font-weight: 700; }

/* Bar magnitude scaling: --mag (e.g. 19, 41, 79). Use viewport-relative so
   it scales but doesn't blow out the layout. */
.cs-b5__bar-fill { height: calc(var(--mag) * 0.55vh); max-height: 50vh; }
@media (min-height: 900px) { .cs-b5__bar-fill { height: calc(var(--mag) * 0.65vh); } }

/* --- Women's two-beat build-in (motion only; .cs-b5--static shows it whole).
   Beat 1 (.is-built-1): the lead line and the left pair (Men <50 / Women <50)
   fade in and their bars drop from the zero line. Beat 2 (.is-built-2), about a
   second later: the right pair (the education/age cohorts, with the long
   Women-without-degrees drop) and the "two realities" closing line. JS in
   setupBeat5 adds the classes when the women profile becomes active. --- */
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women .cs-b5__lead,
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women .cs-b5__text-right {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 600ms var(--cs-ease-out), transform 600ms var(--cs-ease-out);
}
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women .cs-b5__pair {
  opacity: 0;
  transition: opacity 600ms var(--cs-ease-out);
}
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women .cs-b5__bar-fill {
  height: 0;
  transition: height 950ms var(--cs-ease-wipe);
}
/* Beat 1. The lead/text-right reveals carry the full .cs-b5:not(.cs-b5--static)
   prefix so they out-specify the hide rule above (which has the same prefix). */
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women.is-built-1 .cs-b5__lead { opacity: 1; transform: translateY(0); }
.cs-b5__profile--women.is-built-1 .cs-b5__pair:first-child { opacity: 1; }
.cs-b5__profile--women.is-built-1 .cs-b5__pair:first-child .cs-b5__bar-fill { height: calc(var(--mag) * 0.55vh); }
/* Beat 2 */
.cs-b5:not(.cs-b5--static) .cs-b5__profile--women.is-built-2 .cs-b5__text-right { opacity: 1; transform: translateY(0); }
.cs-b5__profile--women.is-built-2 .cs-b5__pair:last-child { opacity: 1; }
.cs-b5__profile--women.is-built-2 .cs-b5__pair:last-child .cs-b5__bar-fill { height: calc(var(--mag) * 0.55vh); }
@media (min-height: 900px) {
  .cs-b5__profile--women.is-built-1 .cs-b5__pair:first-child .cs-b5__bar-fill,
  .cs-b5__profile--women.is-built-2 .cs-b5__pair:last-child .cs-b5__bar-fill { height: calc(var(--mag) * 0.65vh); }
}

/* --- Static fallback (reduced motion / mobile / no-GSAP) --- */
.cs-b5--static .cs-b5__pin { height: auto; overflow: visible; padding: 0; }
.cs-b5--static .cs-b5__tag-fixed { display: none; }
.cs-b5--static .cs-b5__profile { position: relative; opacity: 1 !important; pointer-events: auto; padding: clamp(3em, 6vw, 4em) clamp(1.5em, 4vw, 3em); border-top: 1px solid var(--cs-rule); }
.cs-b5--static .cs-b5__profile:first-child { border-top: none; }
.cs-b5--static .cs-b5__text { opacity: 1 !important; }
.cs-b5--static .cs-b5__media { height: clamp(280px, 50vw, 460px); clip-path: none !important; }
/* The static media box is wide/landscape, so use the wider crop (falls back to
   --photo if a profile has no wide variant). */
.cs-b5--static .cs-b5__photo { transform: none !important; animation: none !important; background-image: var(--photo-wide, var(--photo)); }
.cs-b5--static .cs-b5__profile--women { grid-template-columns: 1fr; }

@media (max-width: 759px) {
  .cs-b5--static .cs-b5__profile { grid-template-columns: 1fr; }

  /* Women variant: the WOMEN tag is a full-width header, then the lead and the
     closing line sit side-by-side in one row beneath it (so their top lines are
     parallel, not jagged), with the bars spanning full width below. display:
     contents dissolves .cs-b5__text so its tag + lead become direct grid items
     and can be placed individually. Text shrinks so two columns sit comfortably
     at phone width. The doubled .cs-b5__profile--women selector out-specifies
     the single-column rule above. */
  .cs-b5--static .cs-b5__profile.cs-b5__profile--women {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "tag   tag"
      "intro closing"
      "bars  bars";
    column-gap: clamp(1em, 4vw, 1.6em);
    row-gap: clamp(1.1em, 4vw, 1.8em);
    align-items: start;
  }
  .cs-b5--static .cs-b5__profile--women .cs-b5__text       { display: contents; }
  .cs-b5--static .cs-b5__profile--women .cs-b5__tag        { grid-area: tag; margin: 0; }
  .cs-b5--static .cs-b5__profile--women .cs-b5__lead       { grid-area: intro; }
  .cs-b5--static .cs-b5__profile--women .cs-b5__text-right { grid-area: closing; }
  .cs-b5--static .cs-b5__profile--women .cs-b5__bars       { grid-area: bars; }
  .cs-b5--static .cs-b5__profile--women .cs-b5__lead,
  .cs-b5--static .cs-b5__profile--women .cs-b5__text-right p {
    font-size: clamp(0.9em, 3.5vw, 1.05em);
    line-height: 1.3;
    max-width: none;
  }
}

/* ============================================================
   BEAT 6 - "This isn't a country that wants to switch AI off"
   The turn / hope beat. Two optimist voices open at the top, then the
   title + body + tie-back land beneath them. Generous negative space.
   The page warms here (--cs-paper-warm via .cs-beat--warm); this is the
   moment of breath after the grievance beats.
   ============================================================ */
.cs-b6__inner {
  max-width: 980px;
  margin: 0 auto;
  padding: clamp(8em, 18vh, 14em) clamp(1.5em, 5vw, 3em);
}

.cs-b6__voices {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2em, 5vw, 4em);
  margin-bottom: 0;   /* voices are last now; section padding handles the base */
}
.cs-b6__voice { margin: 0; }
.cs-b6__voice p {
  font-family: var(--cs-font-narrate);
  font-style: italic;
  font-weight: 700;
  font-size: clamp(1.1em, 1.7vw, 1.4em);
  line-height: 1.3;
  color: var(--cs-ink);
  margin: 0 0 0.5em;
  max-width: 26ch;
}
.cs-b6__voice cite {
  font-family: var(--cs-font-evidence);
  font-style: normal;
  font-size: 0.74em;
  letter-spacing: 0.04em;
  color: var(--cs-muted);
  text-transform: uppercase;
}

/* Turn block: two columns. Big title on the left, the more substantive body
   + tie-back on the right. It now leads the beat, so it carries the spacing
   down to the voices that follow. */
.cs-b6__turn {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(2em, 5vw, 5em);
  align-items: start;
  margin-bottom: clamp(5em, 12vh, 9em);
}
.cs-b6__title {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(2.2em, 4.5vw, 3.6em);
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--cs-brand-blue);   /* the hopeful "turn" beat lifts to brand blue */
  margin: 0;
  max-width: 14ch;
  text-wrap: balance;
}
.cs-b6__body, .cs-b6__tieback {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.1em, 1.6vw, 1.35em);
  line-height: 1.45;
  color: var(--cs-ink);
  margin: 0 0 clamp(1em, 2vw, 1.4em);
  max-width: 44ch;
}
.cs-b6__tieback { color: var(--cs-ink-soft); margin-bottom: 0; }

/* Reveal: the turn block fades in first; the voices follow beneath it. */
.cs-b6 [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 700ms var(--cs-ease-out), transform 700ms var(--cs-ease-out);
}
.cs-b6.is-animated [data-reveal].is-in { opacity: 1; transform: none; }
.cs-b6:not(.is-animated) [data-reveal] { opacity: 1; transform: none; }

@media (max-width: 759px) {
  .cs-b6__voices { grid-template-columns: 1fr; gap: 1.5em; }
  .cs-b6__turn { grid-template-columns: 1fr; gap: 1.5em; margin-bottom: clamp(2.5em, 8vw, 3.5em); }
  /* The desktop vh-based inner padding stacked on top of .cs-beat's own ~48px
     section padding, leaving a huge void between sections on mobile. Zero the
     inner vertical padding so .cs-beat alone sets the section rhythm. */
  .cs-b6__inner { padding-top: 0; padding-bottom: 0; }
}

/* ============================================================
   BEAT 7 - "So we built a Compass" (six-segment donut)
   Intro text on the left (lead -> name -> body -> tease); the donut on
   the right, centre stage. Each segment is a hover-active link into its
   mindset profile in the full report.
   ============================================================ */
.cs-b7__inner {
  max-width: 1180px;
  margin: 0 auto;
  padding: clamp(5em, 12vh, 9em) clamp(1.5em, 5vw, 3em);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  gap: clamp(2em, 5vw, 5em);
  align-items: center;
}
.cs-b7__intro { max-width: 38ch; }
.cs-b7__lead {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1em, 1.3vw, 1.2em);
  line-height: 1.45;
  color: var(--cs-ink-soft);
  margin: 0 0 clamp(1.4em, 3vw, 2.2em);
  max-width: 32ch;
}
.cs-b7__name {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(2em, 4vw, 3.2em);
  line-height: 1.05;
  letter-spacing: -0.025em;
  color: var(--cs-ink);
  margin: 0 0 clamp(0.9em, 2vw, 1.4em);
  max-width: 14ch;
  text-wrap: balance;
}
.cs-b7__body {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1em, 1.25vw, 1.15em);
  line-height: 1.45;
  color: var(--cs-ink);
  margin: 0 0 clamp(1.6em, 3.5vw, 2.4em);
  max-width: 36ch;
}
.cs-b7__tease {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.05em, 1.4vw, 1.25em);
  color: var(--cs-ink);
  margin: 0;
}
.cs-b7__tease strong { color: var(--cs-brand-blue); font-weight: 800; }
/* Ghost link to the Compass section of the full report (matches the bipartisan
   view CTA). Sits under the intro copy with room to breathe. */
.cs-b7__cta { margin-top: clamp(1.6em, 3vw, 2.4em); }
.cs-b8__cta { margin-top: clamp(1.6em, 3vw, 2.4em); }

.cs-b7__donut {
  position: relative;
  margin: 0;
  aspect-ratio: 1;
  max-width: 520px;
  justify-self: center;
  width: 100%;
}
.cs-b7__svg-wrap { width: 100%; height: 100%; }
.cs-b7__svg-wrap svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* Segment: a stroked circle, with dasharray controlling its arc length.
   On hover/focus the segment is nudged outward and brightened. */
.cs-b7__seg {
  fill: none;
  stroke-width: 70;
  transform-origin: 200px 200px;
  transition: opacity 280ms var(--cs-ease-standard), filter 280ms var(--cs-ease-standard);
  cursor: pointer;
  outline: none;
}
/* Focus treatment: hovering/focusing one segment dims the other five and lifts
   the active one. No movement, so segments never collide. */
.cs-b7__donut.is-hover .cs-b7__seg:not(:hover):not(:focus-visible) {
  opacity: 0.28;
  filter: saturate(0.5);
}
.cs-b7__seg:hover, .cs-b7__seg:focus-visible {
  filter: brightness(1.05) drop-shadow(0 3px 12px rgba(28, 39, 59, 0.32));
}

/* Centre text. Updates on hover to show the segment's name + share. */
.cs-b7__centre {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
  font-family: var(--cs-font-verdict);
  font-weight: 800;
}
.cs-b7__centre-prompt {
  font-size: clamp(1.05em, 1.6vw, 1.4em);
  line-height: 1.1;
  color: var(--cs-ink);
}
.cs-b7__centre-name {
  display: none;
  font-size: clamp(1em, 1.5vw, 1.3em);
  line-height: 1.15;
  color: var(--cs-ink);
  max-width: 12ch;
}
.cs-b7__centre-share {
  display: none;
  font-family: var(--cs-font-evidence);
  font-weight: 500;
  font-size: 0.78em;
  letter-spacing: 0.04em;
  margin-top: 0.4em;
  color: var(--cs-ink-soft);
}
.cs-b7__donut.is-hover .cs-b7__centre-prompt { display: none; }
.cs-b7__donut.is-hover .cs-b7__centre-name,
.cs-b7__donut.is-hover .cs-b7__centre-share { display: block; }

/* Segment labels positioned around the donut (set inline by JS). */
.cs-b7__label {
  position: absolute;
  transform: translate(-50%, -50%);
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.78em, 0.95vw, 0.92em);
  line-height: 1.15;
  color: var(--cs-ink);
  max-width: 13ch;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 600ms var(--cs-ease-out),
              transform 240ms var(--cs-ease-standard),
              color 240ms var(--cs-ease-standard);
}
.cs-b7__donut.is-revealed .cs-b7__label { opacity: 1; }
/* The label for the hovered/focused segment lifts to full emphasis. */
.cs-b7__label.is-active { transform: translate(-50%, -50%) scale(1.1); font-weight: 800; }
.cs-b7__label-share {
  display: block;
  font-family: var(--cs-font-evidence);
  font-weight: 500;
  font-size: 0.78em;
  letter-spacing: 0.04em;
  color: var(--cs-ink-soft);
  margin-top: 0.15em;
}

/* Mobile-only legend beneath the donut (built in JS). Desktop uses the around-
   ring labels, so it's hidden there. */
.cs-b7__legend { display: none; }
.cs-b7__legend-item {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: 0.5em;
  font-family: var(--cs-font-verdict);
  font-size: 0.8rem;
  line-height: 1.2;
  color: var(--cs-ink);
}
.cs-b7__legend-swatch { width: 0.7em; height: 0.7em; border-radius: 2px; align-self: center; }
.cs-b7__legend-name { font-weight: 700; }
.cs-b7__legend-share { font-family: var(--cs-font-evidence); font-weight: 500; color: var(--cs-ink-soft); }

@media (max-width: 759px) {
  .cs-b7__inner { grid-template-columns: 1fr; padding-top: 0; padding-bottom: 0; row-gap: 0; }
  /* Dissolve the intro so the donut, the legend, and the "Find out more" CTA can
     each be ordered independently below the intro copy. The around-ring labels
     can't fit a phone (they hit the edges / overlap the ring), so they're hidden
     here and replaced by a colour-keyed legend beneath the donut. */
  .cs-b7__intro { display: contents; }
  .cs-b7__donut {
    order: 1;
    max-width: 220px;
    margin: 2em auto 0;
    justify-self: center;
  }
  .cs-b7__label { display: none; }
  .cs-b7__centre-prompt { font-size: 1rem; }
  .cs-b7__legend {
    order: 1;            /* sits with the donut group, after it in DOM order */
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.55em 1.25em;
    list-style: none;
    margin: 1.6em 0 0;
    padding: 0;
    width: 100%;
  }
  .cs-b7__cta { order: 2; margin: 1.75em 0 0; justify-self: start; }
  /* Section-break marker: a short gold rule centred on the seam delineates the
     new section without the old huge empty band. */
  .cs-b7 { position: relative; }
  .cs-b7::before {
    content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 56px; height: 2px; background: var(--cs-gold); border-radius: 2px;
  }
}

/* ============================================================
   BEAT 8 - "Britain wants its own way" (by-mindset sovereignty chart)
   Intro left; horizontal connected-dots chart right showing the share
   saying sovereignty is extremely important under three framings
   (Neutral, US frame, China frame), by mindset. Real data from
   js/charts/chart-sovereignty-segments.js.
   ============================================================ */
.cs-b8__inner {
  max-width: 1240px;
  margin: 0 auto;
  padding: clamp(5em, 12vh, 9em) clamp(1.5em, 5vw, 3em);
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(2em, 5vw, 5em);
  align-items: center;
}
/* 40ch caps the body text, but the CTA (no width of its own) inherited it and
   wrapped its arrow onto a second line at larger fonts. Title (22ch) and body
   (38ch) have their own caps, so widening the intro only frees the CTA. */
.cs-b8__intro { max-width: 48ch; }
.cs-b8__title {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(1.7em, 3vw, 2.6em);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  margin: 0 0 clamp(1em, 2vw, 1.5em);
  max-width: 22ch;
  text-wrap: balance;
}
.cs-b8__body {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.1em);
  line-height: 1.5;
  color: var(--cs-ink-soft);
  margin: 0;
  max-width: 38ch;
}

/* Chart layout */
.cs-b8__chart {
  margin: 0;
  position: relative;
  /* shared so the rows, the gridlines and the axis ticks all line up on the
     same left edge (the start of the value track). */
  --b8-label-w: clamp(8.5em, 14vw, 12em);
  --b8-col-gap: clamp(0.8em, 1.5vw, 1.4em);
}
.cs-b8__legend {
  display: flex;
  gap: clamp(0.8em, 2vw, 1.6em);
  flex-wrap: wrap;
  justify-content: flex-end;   /* sit on the right, not the top-left reading edge */
  font-family: var(--cs-font-evidence);
  font-size: 0.72em;
  letter-spacing: 0.04em;
  color: var(--cs-ink-soft);
  margin: 0 0 clamp(1.4em, 3vw, 2em);
  text-transform: uppercase;
}
.cs-b8__legend-item { display: inline-flex; align-items: center; gap: 0.5em; }
.cs-b8__legend-dot { width: 0.85em; height: 0.85em; border-radius: 50%; flex: none; }
.cs-b8__plot { position: relative; }
.cs-b8__rows { display: grid; gap: clamp(0.6em, 1.2vw, 1.1em); position: relative; }
.cs-b8__row {
  display: grid;
  grid-template-columns: var(--b8-label-w) 1fr;
  gap: var(--b8-col-gap);
  align-items: center;
  position: relative;   /* data dots/lines sit above the grid backdrop */
  opacity: 0;
  transform: translateX(-12px);
  transition: opacity 500ms var(--cs-ease-out), transform 500ms var(--cs-ease-out);
}
.cs-b8__chart.is-in .cs-b8__row { opacity: 1; transform: none; }

/* Quiet reference grid: faint vertical gridlines + an x-axis baseline, spanning
   exactly the value track. Static and present from the start - the chart's
   structure, not part of the choreography. */
.cs-b8__grid {
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--b8-label-w) + var(--b8-col-gap));
  right: 0;
  pointer-events: none;
}
.cs-b8__gridline {
  position: absolute;
  top: 0; bottom: 0;
  width: 1px;
  background: var(--cs-rule);
  transform: translateX(-0.5px);
}
.cs-b8__gridline--axis { background: rgba(28, 39, 59, 0.22); }   /* the 0 line = y-axis */
.cs-b8__axis-x {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: rgba(28, 39, 59, 0.22);
}
.cs-b8__axis {
  position: relative;
  margin-left: calc(var(--b8-label-w) + var(--b8-col-gap));
  height: 1.2em;
  margin-top: 0.55em;
}
.cs-b8__axis-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  font-family: var(--cs-font-evidence);
  font-size: 0.62em;
  letter-spacing: 0.03em;
  color: var(--cs-muted);
}
.cs-b8__row-label {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.85em, 1.05vw, 0.98em);
  line-height: 1.15;
  color: var(--cs-ink);
}
.cs-b8__row-track {
  position: relative;
  height: clamp(28px, 4vh, 36px);
}
/* The line spans from Neutral to the rightmost framed value. */
.cs-b8__row-line {
  position: absolute;
  top: 50%; transform: translateY(-50%);
  height: 1.5px;
  background: var(--cs-muted-soft);
  transition: opacity 500ms var(--cs-ease-out);
}
.cs-b8__dot {
  position: absolute;
  top: 50%;
  width: clamp(14px, 1.8vw, 18px);
  height: clamp(14px, 1.8vw, 18px);
  border-radius: 50%;
  transform: translate(-50%, -50%) scale(0);
  transition: transform 450ms var(--cs-ease-out);
}
.cs-b8__chart.is-in.is-built-1 .cs-b8__dot--neutral,
.cs-b8__chart.is-in.is-built-1 .cs-b8__dot--us { transform: translate(-50%, -50%) scale(1); }
.cs-b8__chart.is-in.is-built-2 .cs-b8__dot { transform: translate(-50%, -50%) scale(1); }
.cs-b8__dot--neutral { background: var(--cs-muted); }
.cs-b8__dot--us      { background: var(--cs-gold); }
.cs-b8__dot--china   { background: var(--cs-brand-blue); }
.cs-b8__dot-value {
  position: absolute;
  top: -1.55em;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--cs-font-evidence);
  font-weight: 500;
  font-size: 0.7em;
  color: var(--cs-ink-soft);
  white-space: nowrap;
  opacity: 0;
  transition: opacity 400ms var(--cs-ease-out);
}
.cs-b8__chart.is-in.is-built-1 .cs-b8__dot--us .cs-b8__dot-value,
.cs-b8__chart.is-in.is-built-1 .cs-b8__dot--neutral .cs-b8__dot-value { opacity: 1; }
.cs-b8__chart.is-in.is-built-2 .cs-b8__dot-value { opacity: 1; }

/* Stagger rows on entry */
.cs-b8__chart.is-in .cs-b8__row:nth-child(1) { transition-delay: 0ms; }
.cs-b8__chart.is-in .cs-b8__row:nth-child(2) { transition-delay: 90ms; }
.cs-b8__chart.is-in .cs-b8__row:nth-child(3) { transition-delay: 180ms; }
.cs-b8__chart.is-in .cs-b8__row:nth-child(4) { transition-delay: 270ms; }
.cs-b8__chart.is-in .cs-b8__row:nth-child(5) { transition-delay: 360ms; }
.cs-b8__chart.is-in .cs-b8__row:nth-child(6) { transition-delay: 450ms; }

@media (max-width: 759px) {
  .cs-b8__inner { grid-template-columns: 1fr; padding-top: 0; padding-bottom: 0; }
  .cs-b8 { position: relative; }
  .cs-b8::before {
    content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 56px; height: 2px; background: var(--cs-gold); border-radius: 2px;
  }
  .cs-b8__row { grid-template-columns: 1fr; gap: 0.3em; }
  /* The label column is dropped on mobile (label stacks above its track), so
     zero its reserved width: otherwise the gridlines + axis ticks stay offset by
     the old label width while the dots run full-track, and the two scales no
     longer line up (Market Optimists' dots landed back at "0"). */
  .cs-b8__chart { --b8-label-w: 0px; --b8-col-gap: 0px; }
  .cs-b8__grid { display: none; }   /* faint full-height gridlines would cut
     through the stacked row labels; the axis ticks below carry the scale */
  .cs-b8__axis { margin-left: 0; }
  /* At phone width the three dots in a row cluster so tightly that their value
     labels collided into an unreadable run ("11315"). Give the track height and
     stack each framing's value in its own colour-coded tier above the dots, so
     labels never overlap however close the dots sit. */
  .cs-b8__row-track { height: 4.6em; }
  .cs-b8__row-line,
  .cs-b8__dot { top: 84%; }
  .cs-b8__dot { width: 13px; height: 13px; }
  .cs-b8__dot-value { font-size: 0.72em; font-weight: 700; line-height: 1; }
  .cs-b8__dot--neutral .cs-b8__dot-value { top: -3.6em; color: var(--cs-muted); }
  .cs-b8__dot--us .cs-b8__dot-value      { top: -2.35em; color: #9C7400; }
  .cs-b8__dot--china .cs-b8__dot-value   { top: -1.1em; color: var(--cs-brand-blue); }
  .cs-b8__axis { margin-top: 0.2em; }
}

/* ============================================================
   BEAT 9 - "All this anger is going somewhere" (pinned, two text beats over one Sankey)
   Two text beats (9A cause / 9B effect) cross-fade over the same Labour Sankey;
   the "1 in 7" and "21 vs 12" stat blocks sit beneath as a two-up band.
   ============================================================ */
.cs-b9 { padding: 0; background: var(--cs-paper-warm); }
.cs-b9__pin { position: relative; height: 100vh; overflow: hidden; background: var(--cs-paper-warm); }

/* --- Sticky hold (motion desktop; JS adds .cs-b9--scrub). See b34 note.
   --cs-hold was the pin endScroll +=240%. --- */
.cs-b9--scrub { height: calc(100vh - var(--cs-banner, 0px) + var(--cs-hold, 240vh)); }
.cs-b9--scrub .cs-b9__pin {
  position: sticky;
  top: var(--cs-banner, 0px);
  height: calc(100vh - var(--cs-banner, 0px));
}
.cs-b9__stage {
  position: absolute; inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(2em, 5vw, 4em);
  padding: clamp(2em, 5vh, 4em) clamp(1.5em, 5vw, 3em);
  align-items: center;   /* vertically centre both columns in the held stage so
                            the content sits mid-page on tall monitors, not high */
  box-sizing: border-box;
}

/* Headline and stats stack tight at the top, read as one unit (was 1fr/auto,
   which pushed the stats to the floor and left a void in the middle). */
.cs-b9__text {
  position: relative;
  display: grid;
  grid-template-rows: auto auto;
  gap: clamp(1.5em, 3vw, 2.5em);
  height: auto;
}

/* Beats overlap; cross-fade per phase. */
.cs-b9__beat {
  grid-row: 1;
  grid-column: 1;
  opacity: 0;
  transition: opacity 600ms var(--cs-ease-standard);
  align-self: start;
  max-width: 38ch;
}
.cs-b9[data-phase="a"] .cs-b9__beat--a,
.cs-b9[data-phase="b"] .cs-b9__beat--b { opacity: 1; }

.cs-b9__title {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(1.7em, 3vw, 2.6em);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  margin: 0 0 clamp(0.8em, 2vw, 1.2em);
  max-width: 22ch;
  text-wrap: balance;
}
.cs-b9__body {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.95em, 1.2vw, 1.1em);
  line-height: 1.5;
  color: var(--cs-ink-soft);
  margin: 0;
  max-width: 36ch;
}

/* Stat blocks (two-up under the text). */
.cs-b9__stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1em, 2.5vw, 2em);
  padding-top: clamp(1.5em, 3vw, 2.4em);
  border-top: 1px solid var(--cs-rule);
}
.cs-b9__stat-eyebrow {
  font-family: var(--cs-font-evidence);
  font-size: 0.72em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cs-ink-soft);
  margin: 0 0 0.4em;
}
.cs-b9__stat-figure {
  font-family: var(--cs-font-verdict);
  font-weight: 900;
  font-size: clamp(2em, 3.5vw, 3em);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--cs-ink);
  margin: 0 0 0.4em;
}
.cs-b9__stat-read {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(0.85em, 1.05vw, 0.95em);
  line-height: 1.4;
  color: var(--cs-ink);
  margin: 0;
}

/* Sankey - rendered by js/chart-engine.js + js/charts/chart-vote-sankey.js,
   the same module used in the full report. Inside the exec-summary b9 stage
   we suppress the chart card chrome (title, subtitle, legend, methodology
   annotation, figure-number) so only the SVG itself shows; the section's own
   headline and text already supply the framing. */
.cs-b9__sankey {
  margin: 0;
  align-self: center;        /* don't stretch; the chart centres with the copy */
  display: flex;
  align-items: center;       /* the SVG rides at the stage's vertical centre */
  min-width: 0;
}
/* Build-in: the Sankey wipes in left-to-right, following its own flow direction
   (2024 vote -> tomorrow). Motion only; static/reduced-motion shows it whole. */
.cs-b9:not(.cs-b9--static) .cs-b9__sankey {
  clip-path: inset(0 100% 0 0);
  opacity: 0;
  transition: clip-path 1200ms var(--cs-ease-wipe), opacity 500ms var(--cs-ease-out);
}
.cs-b9:not(.cs-b9--static).is-sankey-in .cs-b9__sankey {
  clip-path: inset(0 0 0 0);
  opacity: 1;
}
.cs-b9__sankey .chart { margin: 0; padding: 0; background: transparent; box-shadow: none; width: 100%; }
.cs-b9__sankey .chart__header,
.cs-b9__sankey .chart__annotations,
.cs-b9__sankey .chart__annotations--above,
.cs-b9__sankey .chart__legend,
.cs-b9__sankey .chart__figure-number,
.cs-b9__sankey .chart__source { display: none; }
.cs-b9__sankey .chart__body { margin: 0; padding: 0; }
.cs-b9__sankey .chart__sankey-svg { width: 100%; height: auto; max-height: 70vh; }

/* --- Static fallback ---
   The Sankey is reordered to sit between the beat text and the stats: in source
   it is the last child (it underlays both text beats on desktop), but stacked it
   read better up in the gap above the "1 in 7" figure and its rule. display:
   contents dissolves .cs-b9__text so its beats + stats become direct, orderable
   children of the stage alongside the Sankey; flex order then slots the Sankey
   ahead of the stats (and so above the stats' top rule). */
.cs-b9--static .cs-b9__pin { height: auto; overflow: visible; }
.cs-b9--static .cs-b9__stage {
  position: relative;
  display: flex; flex-direction: column;
  gap: clamp(1.5em, 5vw, 2.4em);
  padding: clamp(3em, 6vw, 4em) clamp(1.5em, 4vw, 3em);
}
.cs-b9--static .cs-b9__text { display: contents; }
.cs-b9--static .cs-b9__beat { position: relative; opacity: 1 !important; margin: 0; max-width: 56ch; }
.cs-b9--static .cs-b9__sankey { order: 1; }
.cs-b9--static .cs-b9__stats { order: 2; }
.cs-b9--static .cs-b9__sankey path { fill-opacity: 0.55; }

@media (max-width: 759px) {
  .cs-b9__stats { grid-template-columns: 1fr; }
  /* Section-break marker, matching b7 / b8. */
  .cs-b9 { position: relative; }
  .cs-b9::before {
    content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 56px; height: 2px; background: var(--cs-gold); border-radius: 2px; z-index: 1;
  }
}

/* ============================================================
   BEAT 10 - "Dear Prime Minister"  (pinned No 10 facade + voice wall)
   Header sits in normal flow above a tall scroll driver whose inner
   .cs-b10__pinned is pinned by GSAP ScrollTrigger. The facade scales
   down from 1.55 to 1.0 (a camera pull-back off the door); the
   navy/purple wash and "Dear Prime Minister" signature fade in; the
   eight voices fade onto the brick in waves; Gary (slot 9) lands in
   the foreground strip. JS adds .is-* phase classes per scroll
   progress. Static fallback (.cs-b10.is-static): facade collapses to
   a banner, voices stack in reading order.
   ============================================================ */
.cs-b10 {
  background: var(--cs-ink);   /* stays dark behind the facade + static voice stack */
  color: var(--cs-paper);
  padding: 0;       /* no padding so the cream intro band sits flush, full-bleed */
  position: relative;
}
/* The intro statement sits on the cream paper we have used through the warm
   beats, large and centred in Helvetica Neue, above the dark No 10 facade
   panel. Full-bleed cream band; the generous bottom padding is the breathing
   room before the facade panel begins. */
.cs-b10__header {
  background: var(--cs-paper-warm);
  color: var(--cs-ink);
  max-width: none;
  margin: 0;
  padding: clamp(4.5em, 10vw, 8em) 1.5em clamp(5.5em, 12vw, 9.5em);
  text-align: center;
}
.cs-b10__headline {
  color: var(--cs-ink);
  max-width: 28ch;
  margin: 0 auto;
  line-height: 1.18;
}
/* Second beat on its own line, tight under the first (a small rhythm gap, not a
   paragraph break). */
.cs-b10__headline-beat { display: block; margin-top: 0.4em; }

.cs-b10__scroll { position: relative; }

/* --- Sticky hold (motion desktop; JS adds .cs-b10--scrub). The driver is the
   .cs-b10__scroll wrapper (header sits above it in the section); .cs-b10__pinned
   holds via position:sticky. No GSAP pin, no position:fixed swap, no snap. The
   facade scale transform stays on the .cs-b10__facade child, never on the sticky
   element. --cs-hold was the pin endScroll +=220%. --- */
.cs-b10--scrub .cs-b10__scroll { height: calc(100vh - var(--cs-banner, 0px) + var(--cs-hold, 220vh)); }
.cs-b10--scrub .cs-b10__pinned {
  position: sticky;
  top: var(--cs-banner, 0px);
  height: calc(100vh - var(--cs-banner, 0px));
}

/* Pinned stage: full-bleed; banner-aware height set in JS. */
.cs-b10__pinned {
  position: relative;
  height: 100vh;
  overflow: hidden;
}

/* Facade: full-bleed image scaled by JS from ~1.55 (tight on the door)
   down to 1.0 (whole building). transform-origin sits on the door. */
.cs-b10__facade {
  position: absolute;
  inset: 0;
  transform: scale(1.55);
  transform-origin: 50% 60%;
  will-change: transform;
}
.cs-b10__facade picture { display: block; width: 100%; height: 100%; }
.cs-b10__facade img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center 58%;
  filter: brightness(0.82) saturate(0.85);
}

/* Subtle navy/purple wash for legibility; bottom gradient also darkens
   the foreground strip where Gary lands. */
.cs-b10__wash {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(20,22,52,0) 52%, rgba(13,15,36,0.9) 100%),
    linear-gradient(0deg, rgba(33,27,66,0.22), rgba(27,25,57,0.22));
  transition: opacity var(--cs-dur-long) var(--cs-ease-standard);
}
.cs-b10__pinned.is-washed .cs-b10__wash { opacity: 1; }

/* Handwritten salutation, centered on the facade band. */
.cs-b10__signature {
  position: absolute;
  top: 39%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  margin: 0;
  font-family: "Caveat", "Brush Script MT", cursive;
  font-weight: 600;
  font-size: clamp(2.4rem, 5vw, 4.4rem);
  line-height: 1;
  white-space: nowrap;
  color: var(--cs-paper);
  text-shadow: 0 2px 18px rgba(0,0,0,0.6);
  opacity: 0;
  transition: opacity var(--cs-dur-long) var(--cs-ease-out);
}
.cs-b10__pinned.is-signed .cs-b10__signature { opacity: 1; }
.cs-b10__signature::after {
  content: "";
  display: block;
  width: 80%;
  height: 3px;
  margin: 0.06em auto 0;
  border-radius: 3px;
  background: var(--cs-paper);
  opacity: 0.9;
  transform: rotate(-1.2deg);
}

/* Voice wall: each quote absolutely placed on the brick. */
.cs-pm-wall {
  position: absolute;
  inset: 0;
  z-index: 2;
  list-style: none;
  margin: 0;
  padding: 0;
}
.cs-pm-quote {
  position: absolute;
  margin: 0;
  color: var(--cs-paper);
  font-family: var(--cs-font-display);
  font-weight: 700;
  text-transform: uppercase;
  line-height: 1.12;
  letter-spacing: 0.005em;
  font-size: clamp(0.95rem, 1.15vw, 1.35rem);
  text-shadow: 0 2px 14px rgba(0,0,0,0.65), 0 0 2px rgba(0,0,0,0.45);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--cs-dur-medium) var(--cs-ease-out),
              transform var(--cs-dur-medium) var(--cs-ease-out);
}
.cs-pm-quote.is-shown { opacity: 1; transform: none; }

.cs-pm-quote blockquote { margin: 0; quotes: none; }
.cs-pm-quote cite {
  display: block;
  margin-top: 0.55em;
  font-family: var(--cs-font-display);
  font-style: italic;
  font-size: 0.62em;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  line-height: 1.3;
  color: rgba(255,255,255,0.82);
  text-shadow: 0 1px 6px rgba(0,0,0,0.7);
}
.cs-pm-quote cite::before {
  content: "";
  display: inline-block;
  width: 1.6em;
  height: 2px;
  margin-right: 0.5em;
  vertical-align: middle;
  background: var(--cs-gold);
}
.cs-pm-quote cite strong { font-weight: 600; font-style: normal; color: var(--cs-paper); }
.cs-pm-quote__tag { color: rgba(255,255,255,0.7); }

/* Placement across the facade at settled scale. Slot 3 (the long marquee) sits
   top-center; short punchy lines flank the door; Gary closes in the foreground. */
.cs-pm-quote[data-slot="3"] {
  top: 6%; left: 50%; transform: translateX(-50%) translateY(10px);
  width: min(34ch, 40vw); text-align: center;
}
.cs-pm-quote[data-slot="3"].is-shown { transform: translateX(-50%); }
.cs-pm-quote[data-slot="1"] { top: 25%; left: 7%;  width: 20ch; text-align: left;  }
.cs-pm-quote[data-slot="6"] { top: 20%; right: 5%; width: 25ch; text-align: right; }
.cs-pm-quote[data-slot="7"] { top: 47%; right: 6%; width: 23ch; text-align: right; }
.cs-pm-quote[data-slot="8"] { top: 56%; left: 6%;  width: 19ch; text-align: left;  }
.cs-pm-quote[data-slot="4"] { top: 62%; left: 25%; width: 22ch; text-align: left;  }
.cs-pm-quote[data-slot="2"] { top: 58%; left: 60%; width: 16ch; text-align: left;  }
/* Leon sits below Nate (slot 7) in the right stack. top:65% (was 58%) so the long
   Nate quote no longer overlaps it; still clears Gary below on normal desktops. */
.cs-pm-quote[data-slot="5"] { top: 65%; right: 6%; width: 17ch; text-align: right; }

/* Gary: the closing line, set apart in the dark foreground strip. */
.cs-pm-quote--final {
  top: auto; bottom: 7%; left: 50%;
  transform: translateX(-50%) translateY(10px);
  z-index: 3;
  width: min(40ch, 60vw);
  text-align: center;
  font-size: clamp(1.45rem, 2.4vw, 2.5rem);
}
.cs-pm-quote--final.is-shown { transform: translateX(-50%); }
.cs-pm-quote--final cite { font-size: 0.5em; margin-top: 0.7em; }

/* Short-viewport guard (scrub/overlay desktop only). On short laptop screens the
   pinned facade is short, so quotes that sit low or stack three-deep on one side
   collide - reported on a ~1366x640 Windows laptop. Scoped to <=760px tall AND the
   overlay layout (.cs-b10--scrub) so taller screens (where it works) and the
   static/mobile stack are untouched:
     - slot 4 (Rory) grew down into Gary: lift it, and cap Gary's size by height.
     - the right stack (Adam/Nate/Leon) can't all fit, so move Leon (slot 5) out of
       it into the open band on the left, between Yasmin (slot 1) and Theo (slot 8).
       A small height-based size cap keeps it clear of both. */
@media (min-width: 760px) and (max-height: 760px) {
  .cs-b10--scrub .cs-pm-quote[data-slot="4"] { top: 48%; }
  .cs-b10--scrub .cs-pm-quote--final { font-size: clamp(1.3rem, min(2.4vw, 4.6vh), 2.5rem); }
  .cs-b10--scrub .cs-pm-quote[data-slot="5"] {
    top: 41%; left: 7%; right: auto; text-align: left;
    font-size: clamp(0.8rem, 2vh, 1.2rem);
  }
}

/* --- Static fallback (mobile / reduced-motion / no-GSAP) --- */
.cs-b10.is-static .cs-b10__pinned { height: auto; overflow: visible; }
.cs-b10.is-static .cs-b10__facade {
  position: relative;
  transform: none;
  height: clamp(220px, 42vw, 460px);
}
.cs-b10.is-static .cs-b10__wash {
  opacity: 1;
  height: clamp(220px, 42vw, 460px);
  inset: 0 0 auto 0;
}
.cs-b10.is-static .cs-b10__signature {
  position: static;
  transform: none;
  opacity: 1;
  text-align: center;
  white-space: normal;
  margin: 1.2em auto 0;
}
.cs-b10.is-static .cs-pm-wall {
  position: static;
  display: flex;
  flex-direction: column;
  gap: 1.8em;
  margin: 2em 3em 0;
}
.cs-b10.is-static .cs-pm-quote {
  position: static !important;
  opacity: 1 !important;
  transform: none !important;
  width: auto !important;
  max-width: 48ch;
  text-align: left !important;
}
.cs-b10.is-static .cs-pm-quote--final {
  bottom: auto;
  align-self: center;
  text-align: center !important;
}

@media (max-width: 759px) {
  /* No navy strip above the cream intro band: the section's dark background was
     showing through the top padding as an odd block after "21 vs 12". Sit the
     cream header flush and mark the hand-off with a soft grey rule instead.
     Keep generous padding at the BOTTOM so the last quote (Gary) has navy room
     beneath it and the hand-off to the cream close isn't a harsh cut. */
  .cs-b10 { padding: 0 0 clamp(3.5em, 10vw, 5em); }
  .cs-b10__header { position: relative; }
  .cs-b10__header::before {
    content: ""; position: absolute; top: 0; left: 50%; transform: translateX(-50%);
    width: 64px; height: 1px; background: var(--cs-muted-soft);
  }
  .cs-b10__pinned { height: auto; overflow: visible; }
  /* Without the scrollytelling pull-back, the whole-street image read as a tiny
     facade. Zoom the static banner in onto the No 10 door (the camera's start
     point on desktop). The .cs-b10.is-static selectors are doubled so these win
     over the earlier is-static block on mobile, where JS adds that class. */
  .cs-b10__facade,
  .cs-b10.is-static .cs-b10__facade {
    position: relative; transform: none;
    height: clamp(240px, 66vw, 400px);
    overflow: hidden;
  }
  .cs-b10__facade img,
  .cs-b10.is-static .cs-b10__facade img {
    transform: scale(2.5);
    transform-origin: 49% 60%;
  }
  /* No text sits over the facade on mobile (the quotes stack below it), so the
     dark wash overlay isn't needed - drop it. */
  .cs-b10__wash,
  .cs-b10.is-static .cs-b10__wash { display: none; }
  .cs-b10__signature {
    position: static; transform: none; opacity: 1;
    white-space: normal; text-align: center; margin: 1em auto 0; padding: 0 1em;
    font-size: clamp(2rem, 11vw, 3rem);
  }
  .cs-pm-wall {
    position: static; display: flex; flex-direction: column;
    gap: 1.6em; margin: 1.8em 1.5em 0;
  }
  .cs-pm-quote {
    position: static !important; opacity: 1 !important; transform: none !important;
    width: auto !important; max-width: 100%; text-align: left !important;
    font-size: 1.15rem;
  }
  .cs-pm-quote--final { bottom: auto; text-align: left !important; font-size: 1.4rem; }
}

@media (prefers-reduced-motion: reduce) {
  .cs-b10__pinned { height: auto; overflow: visible; }
  .cs-b10__facade { position: relative; transform: none !important; height: clamp(220px, 42vw, 460px); }
  .cs-b10__wash { opacity: 1; height: clamp(220px, 42vw, 460px); inset: 0 0 auto 0; }
  .cs-b10__signature {
    position: static; transform: none; opacity: 1;
    white-space: normal; text-align: center; margin: 1.2em auto 0;
  }
  .cs-pm-wall { position: static; display: flex; flex-direction: column; gap: 1.8em; margin: 2em 3em 0; }
  .cs-pm-quote {
    position: static !important; opacity: 1 !important; transform: none !important;
    width: auto !important; max-width: 48ch; text-align: left !important;
  }
  .cs-pm-quote--final { bottom: auto; align-self: center; text-align: center !important; }
}

/* ============================================================
   BEAT 11 - "The country has done its part" (the close)
   ============================================================
   Normal flow. A two-column layout on wide screens: the dot map
   sits on the left in segment colours and sparkles softly; the
   headline, body, messaging tease, manifest, CTAs, and disclosure
   stack to its right. Sparkle is a slow opacity pulse on each dot
   with a per-dot animation-delay (set in JS). Mobile / reduced-
   motion: map sits above text, no sparkle.
   ============================================================ */
.cs-b11 {
  background: var(--cs-paper-warm);
  padding: clamp(3em, 6vw, 5em) clamp(1.5em, 4vw, 3em) clamp(3em, 6vw, 5em);
  /* Helvetica throughout this closing section: redefine the narrate token so
     every element that used Work Sans here resolves to Helvetica Neue. The
     verdict/display elements were already Helvetica. */
  --cs-font-narrate: var(--cs-font-display);
}
.cs-b11__inner {
  max-width: 560px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 1.5em;
}
/* Centre the whole column in the viewport while keeping the text left-aligned:
   the blocks fill the (snug, centred) column so they share one left edge on the
   page's centre line. Previously each block kept its own narrower max-width and
   hugged the left of a wider container, so the section read ~40px left of
   centre. Descendant selectors (specificity 0,2,0) so they win over each block's
   own max-width declared later in this file. */
.cs-b11__inner > .cs-b11__head,
.cs-b11__inner .cs-b11__body,
.cs-b11__inner > .cs-b11__tease,
.cs-b11__inner > .cs-b11__hook,
.cs-b11__inner > .cs-b11__manifest,
.cs-b11__inner > .cs-b11__disclosure { max-width: 100%; }

/* Map sits at the top, centred, in a constrained width so it reads as a
   symbolic close (a six-mindset population), not a geographic chart. */
.cs-b11__map { margin: 0 auto 1.5em; width: min(320px, 60%); }
.cs-b11__map-mount {
  width: 100%;
  aspect-ratio: 5 / 8;     /* matches the SVG viewBox */
  position: relative;
}
.cs-b11__map-mount svg { width: 100%; height: 100%; display: block; }
.cs-b11__map-mount circle {
  /* Fill set via JS. transition/transform on all dots; the pulse is class-gated. */
  transition: fill var(--cs-dur-long) var(--cs-ease-out);
  transform-box: fill-box;
  transform-origin: center;
}
/* Only the ~42% of dots JS tags with .cs-b11--spark actually pulse - the map
   still reads as a live sparkle at roughly half the continuous-animation cost. */
.cs-b11__map-mount circle.cs-b11--spark {
  animation: cs-b11-sparkle 4.2s ease-in-out infinite;
  animation-delay: var(--sparkle-delay, 0s);
}

@keyframes cs-b11-sparkle {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}

.cs-b11__head { }
.cs-b11__headline { margin: 0 0 0.5em; color: var(--cs-ink); }
.cs-b11__body {
  font-family: var(--cs-font-narrate);
  font-size: clamp(1.05em, 1.3vw, 1.2em);
  line-height: 1.55;
  color: var(--cs-ink);
  margin: 0;
  max-width: 50ch;
}

.cs-b11__tease {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1em, 1.2vw, 1.12em);
  line-height: 1.45;
  color: var(--cs-ink);
  margin: 0.5em 0 0;
  max-width: 50ch;
  padding-left: 1em;
  border-left: 3px solid var(--cs-gold);
}
.cs-b11__hook {
  font-family: var(--cs-font-narrate);
  font-size: 1em;
  line-height: 1.55;
  color: var(--cs-ink-soft);
  margin: 0;
  max-width: 50ch;
}

.cs-b11__manifest {
  list-style: none;
  padding: 0;
  margin: 1em 0 0;
  max-width: 60ch;
  counter-reset: cs-b11-manifest;
}
.cs-b11__manifest li {
  counter-increment: cs-b11-manifest;
  padding: 1em 0;
  border-bottom: 1px solid rgba(28,39,59,0.12);
  font-family: var(--cs-font-narrate);
  font-size: 1em;
  line-height: 1.55;
  color: var(--cs-ink);
  display: grid;
  grid-template-columns: 2.4em 1fr;
  gap: 1em;
  align-items: baseline;
}
.cs-b11__manifest li:first-child { border-top: 1px solid rgba(28,39,59,0.12); }
.cs-b11__manifest li::before {
  content: counter(cs-b11-manifest) ".";
  font-family: var(--cs-font-display);
  font-weight: 900;
  font-size: 1.4em;
  color: var(--cs-gold);
  letter-spacing: -0.02em;
}

.cs-b11__ctas {
  display: flex;
  gap: 1em;
  align-items: center;
  flex-wrap: wrap;
  margin: 1.5em 0 0;
}
.cs-b11__cta {
  font-family: var(--cs-font-narrate);
  font-size: 1em;
  text-decoration: none;
  transition: opacity var(--cs-dur-medium) var(--cs-ease-standard),
              background var(--cs-dur-medium) var(--cs-ease-standard),
              color var(--cs-dur-medium) var(--cs-ease-standard);
}
.cs-b11__cta--primary {
  background: var(--cs-brand-blue);
  color: var(--cs-paper);
  font-weight: 600;
  padding: 0.9em 1.8em;
  border-radius: 2px;
  border: none;
}
.cs-b11__cta--primary:hover { opacity: 0.9; }
.cs-b11__cta--secondary {
  background: transparent;
  color: var(--cs-ink);
  font-weight: 500;
  padding: 0.88em 1.5em;
  border-radius: 2px;
  border: 1.5px solid var(--cs-ink);
}
.cs-b11__cta--secondary:hover { background: var(--cs-ink); color: var(--cs-paper); }
.cs-b11__cta--tertiary {
  color: var(--cs-ink-soft);
  font-size: 0.92em;
  font-weight: 500;
  border-bottom: 1px solid var(--cs-ink-soft);
  padding-bottom: 0.15em;
}
.cs-b11__cta--tertiary:hover { color: var(--cs-ink); border-color: var(--cs-ink); }

.cs-b11__disclosure {
  font-family: var(--cs-font-narrate);
  font-size: 0.85em;
  color: var(--cs-ink-soft);
  max-width: 60ch;
  margin: 2em 0 0;
  line-height: 1.55;
}
.cs-b11__disclosure a {
  color: var(--cs-ink);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}
.cs-b11__disclosure a:hover { color: var(--cs-brand-blue); }

/* Coda: the country's last word. Lifted out of the functional footer (it used
   to sit below the legal fine print, easy to miss) into a centred, confident
   close in the verdict voice, set off by a gold end-mark - gold being the
   page's "us"/agency colour - with room above it and a deliberate fade-up. */
.cs-b11__closing {
  font-family: var(--cs-font-verdict);
  font-style: normal;
  font-weight: 500;
  font-size: clamp(1.6em, 2.8vw, 2.4em);
  line-height: 1.2;
  letter-spacing: -0.015em;
  color: var(--cs-ink);
  max-width: 26ch;
  text-wrap: balance;
  text-align: center;
  align-self: center;
  position: relative;
  margin: clamp(3.5em, 9vh, 6.5em) auto clamp(0.5em, 2vh, 1.5em);
  padding-top: clamp(2.4em, 5vh, 3.6em);
}
.cs-b11__closing::before {
  content: "";
  position: absolute;
  top: 0; left: 50%;
  width: 2.4em; height: 3px;
  transform: translateX(-50%);
  background: var(--cs-gold);
  border-radius: 2px;
}
/* Fade-up reveal, armed by JS only when motion is allowed (.cs-b11--coda);
   reduced motion shows it immediately. */
.cs-b11--coda .cs-b11__closing {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 900ms var(--cs-ease-out), transform 900ms var(--cs-ease-out);
}
.cs-b11--coda.is-coda-in .cs-b11__closing { opacity: 1; transform: translateY(0); }

/* Static fallback: kill the sparkle on reduced-motion. (Mobile keeps the
   pulse off too, via the @media block below.) */
.cs-b11.is-static .cs-b11__map-mount circle { animation: none; opacity: 1; }
/* Lite mode (weak hardware / ?lite=1 / FPS watchdog) drops the sparkle entirely;
   the recolour stays - it carries the data, not the motion. */
html.cs-lite .cs-b11__map-mount circle { animation: none !important; opacity: 1 !important; }

@media (prefers-reduced-motion: reduce) {
  .cs-b11__map-mount circle { animation: none; opacity: 1; }
}

@media (max-width: 759px) {
  .cs-b11__inner { gap: 1.2em; }
  .cs-b11__map { width: min(220px, 70%); }
  .cs-b11__map-mount circle { animation: none; opacity: 1; }
  .cs-b11__ctas { flex-direction: column; align-items: stretch; }
  .cs-b11__cta--primary, .cs-b11__cta--secondary { text-align: center; }
}

/* ============================================================
   BAND - "It's more than a fear of the unknown"
   A "window" interstitial between b5 and b6: the section is the warm
   cream paper (--cs-paper-warm), and the photo shows through a rounded
   inset hole with a 30px buffer of cream around it (Daniel). The image
   drifts inside the window (parallax, JS-scrubbed) and settles from a
   soft zoom; the three stats stack (number over label) so the numbers
   share one line and the columns read symmetrically. Motion is armed in
   setupStatband(); this file owns the rest states + static fallback.
   ============================================================ */
.cs-statband {
  /* The cream frame: 30px buffer L/R (and top/bottom) shows the warm paper
     around the window, restoring the cream of the surrounding warm beats. */
  background: var(--cs-paper-warm);
  padding: 30px;
}
.cs-statband__window {
  position: relative;
  isolation: isolate;
  overflow: hidden;                          /* the "hole": clips the photo + rounds it */
  border-radius: clamp(10px, 1.4vw, 18px);
  max-width: 85%;                            /* ~15% narrower box (Daniel), centred */
  margin-inline: auto;
  min-height: clamp(360px, 52vh, 540px);     /* ~half a page (Daniel: "shorter") */
  display: flex;
  align-items: center;
  color: #fff;
}
.cs-statband__mask { position: absolute; inset: 0; overflow: hidden; z-index: 0; }
.cs-statband__parallax {
  /* Sized well beyond the mask so the parallax drift never exposes an edge:
     20% slack top and bottom for the yPercent +-13 scrub in setupStatband. */
  position: absolute;
  top: -20%;
  left: 0;
  width: 100%;
  height: 140%;
  will-change: transform;
}
.cs-statband__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
  transform: scale(1.18);
  transition: transform 1600ms var(--cs-ease-wipe);
}
.cs-statband.is-revealed .cs-statband__img { transform: scale(1); }
.cs-statband:not(.is-animated) .cs-statband__img { transform: none; transition: none; }
.cs-statband__scrim {
  position: absolute;
  inset: 0;
  /* Halved from the original (Daniel: "much less gradient") so the autumn colour
     and saturation come through. Type stays legible via the text-shadow below. */
  background:
    linear-gradient(100deg,
      rgba(15, 21, 33, 0.46) 0%,
      rgba(15, 21, 33, 0.39) 34%,
      rgba(15, 21, 33, 0.17) 64%,
      rgba(15, 21, 33, 0.06) 100%),
    linear-gradient(0deg, rgba(15, 21, 33, 0.22) 0%, rgba(15, 21, 33, 0) 42%);
}
.cs-statband__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--site-max-width, 1500px);
  margin: 0 auto;
  padding: clamp(2.2em, 6vh, 3.8em) clamp(1.6em, 4vw, 3em);
  /* Soft halo carries legibility now that the scrim is light (inherited by all text). */
  text-shadow: 0 1px 16px rgba(8, 12, 20, 0.55), 0 1px 4px rgba(8, 12, 20, 0.4);
}
.cs-statband__header {
  font-family: var(--cs-font-verdict);
  font-weight: 700;
  font-size: clamp(1.2em, 2.1vw, 1.65em);
  line-height: 1.32;
  letter-spacing: -0.01em;
  max-width: 46ch;
  margin: 0 0 clamp(1.4em, 3.2vw, 2.2em);
  text-wrap: balance;
}
/* Stats stack (number over label) in three equal columns, so the numbers all sit
   on one line and the columns read symmetrically (Daniel). */
.cs-statband__stats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.1em, 2.4vw, 2.2em);
  /* Wide enough that the longest label (NHS) wraps to ~3 lines instead of 5, so
     the three stacked columns stay close to a uniform height (Daniel). */
  max-width: clamp(30ch, 80vw, 660px);
}
.cs-statband__stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3em;
}
.cs-statband__num {
  font-family: var(--cs-font-verdict);
  font-weight: 800;
  font-size: clamp(2.3em, 4vw, 3.3em);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--cs-gold);
  font-variant-numeric: tabular-nums;
}
.cs-statband__pct { font-size: 0.46em; font-weight: 700; margin-left: 0.05em; }
.cs-statband__label {
  font-family: var(--cs-font-narrate);
  font-weight: 500;
  font-size: clamp(0.95em, 1.25vw, 1.12em);
  line-height: 1.25;
  color: rgba(255, 255, 255, 0.94);
}

/* Content reveal: staggered fade-up (mirrors Seismic's data-reveal-delay). The
   .is-in flips are added together by JS; CSS transition-delay does the cascade. */
.cs-statband [data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 900ms var(--cs-ease-wipe), transform 900ms var(--cs-ease-wipe);
}
.cs-statband.is-animated [data-reveal].is-in { opacity: 1; transform: none; }
.cs-statband:not(.is-animated) [data-reveal] { opacity: 1; transform: none; }
.cs-statband__header { transition-delay: 0ms; }
.cs-statband__stat:nth-child(1) { transition-delay: 140ms; }
.cs-statband__stat:nth-child(2) { transition-delay: 260ms; }
.cs-statband__stat:nth-child(3) { transition-delay: 380ms; }

@media (max-width: 759px) {
  .cs-statband { padding: 16px; }            /* slimmer buffer on small screens */
  .cs-statband__window { min-height: clamp(420px, 76vh, 620px); max-width: none; }
  /* one stat per row when there is no width for three columns */
  .cs-statband__stats { grid-template-columns: 1fr; gap: clamp(0.9em, 3vw, 1.4em); max-width: none; }
  .cs-statband__scrim {
    background:
      linear-gradient(180deg,
        rgba(15, 21, 33, 0.34) 0%,
        rgba(15, 21, 33, 0.22) 45%,
        rgba(15, 21, 33, 0.42) 100%);
  }
}
