/* ==========================================================================
   British Built Power — microsite styles
   Page-level layout for index.html. Consumes tokens.css + components.css;
   no raw hex or px values beyond what tokens provide.
   ========================================================================== */

/* --------------------------------------------------------------------
   Page width — the campaign page runs full width, edge to edge, with
   only the gutters holding content off the viewport. The gutter grows
   with the screen: 24px on phones, ~5.5% of the width in between, up
   to 80px on large desktops — so copy, logo and captions sit in from
   the edges while photos, the map and the bars stay full-bleed.
   (Scoped here on purpose: design-system.html doesn't load site.css,
   so the style guide keeps the documented --container-max frame and
   its fixed gutter.)
   -------------------------------------------------------------------- */

:root {
  --container-gutter: clamp(1.5rem, 5.5vw, 5rem);
}

.container {
  max-width: none;
}

/* --------------------------------------------------------------------
   Hero — brand teal field (per the VI identity page): white display
   text and the lock-up in a translucent stamp container, over a
   full-bleed photo.
   -------------------------------------------------------------------- */

/* ---- photo stage: hero -> navy -----------------------------------
   One viewport-sized layer, sticky for the length of the hero and
   #electrification (margin-bottom pulls the sections up over it). As
   the story arrives the engineer fades into navy (--n, 0..1, from the
   page script) and pushes in slightly. The hero's left-hand scrim fades out with the engineer, so the centred
   story never sits on a one-sided shadow. Nothing here makes a
   stacking context above the page, so the fixed header stays on top. */
.dissolve {
  background: var(--tint, var(--ink-900));
  /* the sticky stage's negative margin lets it hang up to a screen past
     the end of the wrapper; clip it there (clip, not hidden, so sticky
     still works) so it never covers the blended sections below */
  overflow: clip;
}

.dissolve-stage {
  position: sticky;
  top: 0;
  z-index: 0;
  height: 100vh;
  height: 100lvh;
  margin-bottom: -100vh;
  margin-bottom: -100lvh;
  overflow: hidden;
  pointer-events: none;
}

.dissolve-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.dissolve-hero {
  /* the engineer stands ~70% across — keep him in narrow crops */
  object-position: 70% 30%;
  /* the plate (no engineer in it) eases back a touch on --m, and pushes
     in on --n */
  transform: scale(calc(1 + var(--n, 0) * 0.05 - var(--m, 0) * 0.01));
  transform-origin: 75% 35%;
}

/* the same frame blurred, fading up over the sharp one as the engineer
   comes forward (opacity only, so the blur is rasterised once) */
.dissolve-blur {
  filter: blur(3px);
  opacity: calc(var(--m, 0) * 0.55);
}

/* the engineer alone (transparent PNG of the same frame). On --m he
   grows three and a half percent about his feet while the plate eases
   back, so he comes forward; the plate has no engineer in it to double;
   on --n he pushes in exactly as the background does. Two scales about
   two points, written as translate-scale-translate pairs. */
.dissolve-cut {
  filter: none;
  opacity: 1;
  transform-origin: 0 0;
  transform:
    translate(75%, 35%) scale(calc(1 + var(--n, 0) * 0.05)) translate(-75%, -35%)
    translate(70%, 100%) scale(calc(1 + var(--m, 0) * 0.035)) translate(-70%, -100%);
}

/* wide screens: run the photo 15% past the right edge, pinned left, so
   the engineer sits ~80% across, clear of the copy */
@media (min-width: 921px) {
  .dissolve-hero {
    width: 115%;
    object-position: 0% 30%;
  }
}

.dissolve-navy {
  position: absolute;
  inset: 0;
  /* the live chapter tint (navy until the gas section arrives), so the
     story's ground and the blended sections below are one colour and
     never meet at a seam */
  background: var(--tint, var(--ink-900));
  opacity: var(--n, 0);
}

@media (prefers-reduced-motion: reduce) {
  .dissolve-hero {
    transform: none;
  }

  /* the cut-out stays (the plate beneath has no engineer); only the
     blur layer and the motion go */
  .dissolve-blur {
    display: none;
  }

  .dissolve-cut {
    transform: none;
  }
}

/* the hero's left-hand scrim, gone once the navy has taken over */
.dissolve-stage::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: calc(1 - var(--n, 0));
  background: linear-gradient(to right,
    color-mix(in srgb, var(--ink-900) 90%, transparent) 0%,
    color-mix(in srgb, var(--ink-900) 68%, transparent) 40%,
    transparent 70%);
}

/* laptops (1181 to 1536px): the copy reaches further across the photo,
   so the scrim does too */
@media (min-width: 1181px) and (max-width: 1536px) {
  .dissolve-stage::after {
    background: linear-gradient(to right,
      color-mix(in srgb, var(--ink-900) 90%, transparent) 0%,
      color-mix(in srgb, var(--ink-900) 76%, transparent) 45%,
      color-mix(in srgb, var(--ink-900) 50%, transparent) 66%,
      transparent 86%);
  }
}

/* narrow screens and small laptops (up to 1180px): the subject sits
   behind the copy, so darken evenly, enough for the copy to hold 4.5:1
   as it crosses his hi-vis jacket */
@media (max-width: 1180px) {
  .dissolve-stage::after {
    background: color-mix(in srgb, var(--ink-900) 72%, transparent);
  }
}

/* the hero itself is now transparent over the stage. It always fills
   the screen (copy centred in it), so nothing of the next section —
   "What is electrification?" — shows until the reader scrolls. */
.hero-wrap {
  position: relative;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  /* room for the fixed header at rest. The page script sets the exact
     measured height; these match it, so the copy doesn't jump down
     when the script arrives */
  padding-top: 9rem;
}

@media (max-width: 720px) {
  .hero-wrap {
    padding-top: 5rem;
  }
}

.hero-wrap > .hero {
  flex: 1;
  /* .container's auto margins would shrink-wrap it in a flex column */
  width: 100%;
  display: flex;
  align-items: center;
}

/* The nav contents ride the container grid so the logo and hero copy
   share a left edge. Fixed to the viewport: transparent over the hero,
   solid ink once scrolled past it. */
.hero-topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: transparent;
  transition: background-color 300ms var(--ease-out),
              box-shadow 300ms var(--ease-out);
}

/* lets the page script read the bar's resting height at once */
.hero-topbar.is-measuring,
.hero-topbar.is-measuring * {
  transition: none !important;
}

.hero-topbar.is-solid {
  background: var(--ink-900);
  box-shadow: 0 14px 36px rgba(21, 23, 46, 0.38);
}

/* compact chrome once solid */
.hero-topbar .navbar-logo {
  transition: height 300ms var(--ease-out);
}

.hero-topbar.is-solid .navbar-logo {
  height: 4.75rem;
}

/* logo flips to the white knock-out colourway: white stamp, artwork
   punched through in the header colour */
.hero-topbar .bbp-logo > rect,
.hero-topbar .bbp-logo .bbp-word,
.hero-topbar .bbp-logo .hatch-line {
  transition: fill 300ms var(--ease-out), stroke 300ms var(--ease-out);
}

/* over the teal hero the stamp container goes translucent paper (the
   VI identity-page treatment) so it doesn't fight the matching field */
.hero-topbar:not(.is-solid) .bbp-logo > rect {
  fill: rgba(245, 242, 236, 0.16);
}

.hero-topbar.is-solid .bbp-logo > rect {
  fill: var(--white);
}

.hero-topbar.is-solid .bbp-logo .bbp-word {
  fill: var(--ink-900);
}

.hero-topbar.is-solid .bbp-logo .hatch-line {
  stroke: var(--ink-900);
}

.navbar-hero {
  background: transparent;
  border-bottom: none;
  /* ride the page gutter, so the logo lines up with the copy below */
  padding-inline: var(--container-gutter);
  transition: padding-top 300ms var(--ease-out);
}

/* more air above the logo at rest; compact again once solid */
.hero-topbar:not(.is-solid) .navbar-hero {
  padding-top: var(--space-6);
}

.navbar-hero .navbar-brand {
  white-space: nowrap;
}

.navbar-logo {
  height: 7.5rem;
  width: auto;
  display: block;
  /* trim the artwork's built-in padding: vertically so the bar stays
     tight, horizontally so the visible stamp edge sits on the grid line */
  margin-block: -0.75rem;
  transform: translateX(-5%);
}

@media (max-width: 920px) {
  .navbar-hero {
    flex-wrap: wrap;
    row-gap: var(--space-3);
  }

}

/* phones: one slim row — a smaller logo, and the social icons move out
   (they're in the footer), so the fixed bar stays under ~70px and never
   hides the content scrolled beneath it */
@media (max-width: 720px) {
  .navbar-hero {
    flex-wrap: nowrap;
    padding-block: var(--space-2);
  }

  .navbar-hero .social-links {
    display: none;
  }

  .navbar-logo {
    height: 4.5rem;
    margin-block: -0.5rem;
  }

  /* already compact: the desktop solid size would make it grow */
  .hero-topbar.is-solid .navbar-logo {
    height: 4.5rem;
  }

  .hero-topbar:not(.is-solid) .navbar-hero {
    padding-top: var(--space-4);
  }
}

@media (max-width: 920px) {

  .navbar-hero .navbar-links {
    flex-wrap: wrap;
    gap: var(--space-3) var(--space-4);
  }
}

.hero {
  position: relative;
  padding-block: calc(var(--space-9) - var(--space-4)) var(--space-9);
}

.hero-copy {
  display: grid;
  gap: var(--space-5);
  justify-items: start;
  max-width: 44rem;
  will-change: opacity, transform;
}

.hero-copy h1 {
  font-size: clamp(2.4rem, 4.6vw, 3.6rem);
  color: var(--white);
}

.hero-copy .lead {
  color: rgba(245, 242, 236, 0.82);
}

.hero-lead {
  display: grid;
  gap: var(--space-3);
}

/* outline CTA takes the dark-surface colourway over the teal */
.hero-wrap .btn-outline {
  border-color: rgba(245, 242, 236, 0.5);
  color: var(--paper);
}

.hero-wrap .btn-outline:hover {
  border-color: var(--paper);
}

.hero-ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

@media (max-width: 920px) {
  .hero {
    padding-block: var(--space-8);
  }
}

/* --------------------------------------------------------------------
   Proof — the price of imported fuel. Side-on bars after the
   energy-profits.org "profit per minute" chart, on their mechanism
   (see the page script): no pin — each bar grows from the left edge
   as its own row scrolls up the viewport, and its figure counts up on
   entry. Widths stay true to the data (6% is 6/28 of the gas bar).
   Each bar is a clip-path window over a full-width fill, so the
   gradient never stretches and the figure turns from ghost to gold
   letter by letter as the bar passes (same trick as the CTA label).
   -------------------------------------------------------------------- */

/* ---- chapter colours, blended -----------------------------------------
   One fixed tint layer sits behind the page (z-index -1, above the
   body's paper). With html.tint-on (set by the page script) the bills,
   industry and security sections go transparent over it, and the
   script blends the tint navy -> red -> teal -> navy as each arrives,
   so there's no hard seam between them. The FAQs keep their own
   opaque paper. Without JS the sections keep the solid colours below. */
.page-tint {
  position: fixed;
  inset: 0;
  z-index: -1;
  background: var(--ink-900);
  pointer-events: none;
}

html.tint-on .proof,
html.tint-on .europe,
html.tint-on .security,
html.tint-on .price {
  background: transparent;
}

html.tint-on .europe {
  --sec-bg: var(--tint, var(--teal-700));
}

.faq {
  background: var(--paper);
}

/* --------------------------------------------------------------------
   Spread the word — three share cards (scripts/share-cards.js).
   Paper ground, ink type; the cards carry the brand colours.
   -------------------------------------------------------------------- */
/* Spread the word arrives as a card: the whole cream ground of the section
   is one layer (.local-bg) behind the content, with rounded top corners,
   that the page script scales from 0.92 to 1 (0.95 on phones) as the
   section's top travels from the bottom of the screen to 30% down it,
   no easing. Scaling
   about the centre of a tall layer moves its top edge up as it grows,
   which is what makes the card seem to rise, with the dark ground
   showing around it. Reduced motion:
   the layer stays at full size. */
.local {
  position: relative;
  /* above the footer, so the share menu and the "copied" note, which
     open over its top edge, stay visible and clickable */
  z-index: 3;
  background: transparent;
  color: var(--ink-900);
  padding-block: var(--space-9) var(--space-8);
}

.local-bg {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--paper);
  border-radius: 28px 28px 0 0;
  /* lifts off the dark ground as it rises */
  box-shadow: 0 -18px 50px rgba(0, 0, 0, 0.35), 0 -2px 8px rgba(0, 0, 0, 0.2);
  transform-origin: 50% 50%;
  will-change: transform;
}

.local > :not(.local-bg):not(.share-menu):not(.share-toast) {
  position: relative;
  z-index: 2;
}

@media (prefers-reduced-motion: reduce) {
  .local-bg {
    transform: none !important;
  }
}

.local .proof-title { color: var(--ink-900); }
.local .proof-standfirst { color: var(--ink-700); }

.local-head { margin-inline: 0; }

.local-form {
  margin-top: var(--space-6);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-4);
}

.local-prompt {
  flex: 0 0 100%;
  font-family: var(--font-display);
  font-size: var(--type-item);
  font-weight: var(--weight-bold);
  color: var(--ink-900);
}

.local-input {
  width: 13rem;
  padding: var(--space-3) var(--space-5);
  border: 2px solid rgba(21, 23, 46, 0.25);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--ink-900);
  font: inherit;
  font-size: var(--type-body);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.local-input::placeholder { text-transform: none; letter-spacing: normal; color: rgba(21, 23, 46, 0.45); }

.local-input:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-color: var(--ink-900);
}

/* the input matches the large CTA beside it (btn-lg: 16px padding,
   body-size type, 2px border) so the pair sits as one row */
.local-input {
  padding-block: calc(var(--space-4) - 2px);
  font-size: var(--text-body);
  line-height: 1;
}

.local-geo,
.local-link {
  padding: 0;
  border: 0;
  background: none;
  color: var(--teal-700);
  font: inherit;
  font-size: var(--type-note);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.local-msg {
  margin-top: var(--space-3);
  min-height: 1.5em;
  font-size: var(--type-note);
  color: var(--ink-700);
}

.local-msg.is-error { color: var(--oxblood-500); }

/* scrolled into view on a lookup: clear the fixed header */
.local-results { margin-top: var(--space-7); scroll-margin-top: calc(var(--header-h, 6rem) + 1rem); }
.local-results .container { margin-inline: 0; }

.local-area {
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  color: var(--teal-700);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.local-change { font-weight: var(--weight-regular); text-transform: none; letter-spacing: normal; }

.local-headline {
  margin-top: var(--space-3);
  max-width: 50rem;
  font-family: var(--font-display);
  font-size: var(--type-statement);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink-900);
}

.local-stats {
  list-style: none;
  margin: var(--space-6) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-5);
}

.local-stat {
  padding: var(--space-5);
  border-radius: var(--radius-lg);
  background: var(--white);
  box-shadow: 0 6px 18px rgba(21, 23, 46, 0.08);
}

.local-stat[hidden] { display: none; }

.local-fig {
  display: block;
  margin-bottom: var(--space-2);
  font-family: var(--font-display);
  font-size: clamp(2.25rem, 4vw, 3rem);
  font-weight: var(--weight-display);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}

.js-stat-power .local-fig { color: var(--teal-500); }
.js-stat-gas .local-fig { color: var(--oxblood-500); }
.js-stat-bill .local-fig { color: var(--ink-700); }

.local-stat p {
  font-size: var(--type-body);
  line-height: 1.45;
  color: var(--ink-700);
}

.local-sources {
  margin-top: var(--space-4);
  font-size: var(--type-note);
  color: rgba(21, 23, 46, 0.6);
}

.local-share-head {
  margin-top: var(--space-7);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

.local-subhead {
  font-family: var(--font-display);
  font-size: var(--type-item);
  font-weight: var(--weight-bold);
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink-900);
}

/* the drawn cards: a scroll-snapped row */
.local-cards {
  list-style: none;
  margin: var(--space-5) 0 0;
  padding: var(--space-2) var(--container-gutter) var(--space-6);
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: clamp(15rem, 27vw, 21rem);
  gap: var(--space-5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--container-gutter);
  scrollbar-width: none;
}

.local-cards::-webkit-scrollbar { display: none; }
.local-cards[data-format="story"] { grid-auto-columns: clamp(12rem, 19vw, 15rem); }

.local-card {
  scroll-snap-align: start;
  display: grid;
  gap: var(--space-4);
}

.local-card-img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  box-shadow: 0 10px 24px rgba(21, 23, 46, 0.18);
}

@media (max-width: 720px) {
  .local-cards { grid-auto-columns: 78vw; }
  .local-cards[data-format="story"] { grid-auto-columns: 62vw; }
  .local-input { flex: 1 1 100%; width: 100%; }
  .local-go { flex: 1 1 auto; justify-content: space-between; }
}

/* segmented toggle */
.share-format {
  display: inline-flex;
  padding: 4px;
  border-radius: var(--radius-pill);
  background: rgba(21, 23, 46, 0.08);
}

.share-format-btn {
  padding: var(--space-2) var(--space-5);
  border: 0;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--ink-700);
  font: inherit;
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  cursor: pointer;
  transition: background-color var(--hover-duration) var(--ease-out), color var(--hover-duration) var(--ease-out);
}

.share-format-btn.is-on {
  background: var(--ink-900);
  color: var(--white);
}

.share-format-btn:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
}

.share-actions {
  display: flex;
  gap: var(--space-3);
}

.share-actions { flex-wrap: wrap; }
.share-actions .btn { flex: 1 1 8.5rem; min-width: 0; }

/* narrow (story) cards: the pair stacks so neither spills into the
   next card */
.local-cards[data-format="story"] .share-actions {
  flex-direction: column;
}

.local-card { min-width: 0; }
.share-actions .btn-cta { justify-content: space-between; padding-left: var(--space-5); }

/* fallback share menu */
.share-menu {
  position: absolute;
  z-index: 10;
  min-width: 13rem;
  padding: var(--space-2);
  border-radius: var(--radius-md);
  background: var(--white);
  box-shadow: 0 14px 34px rgba(21, 23, 46, 0.25);
  display: grid;
}

.share-menu[hidden] { display: none; }

.share-menu-link {
  display: block;
  padding: var(--space-3) var(--space-4);
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink-900);
  font: inherit;
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--hover-duration) var(--ease-out);
}

.share-menu-link:hover,
.share-menu-link:focus-visible {
  background: rgba(21, 23, 46, 0.07);
}

.share-menu-link:focus-visible {
  outline: 2px solid var(--ink-900);
  outline-offset: -2px;
}

.share-toast {
  position: fixed;
  left: 50%;
  bottom: var(--space-6);
  z-index: 60;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--ink-900);
  color: var(--white);
  font-size: var(--type-note);
  opacity: 0;
  transform: translate(-50%, 10px);
  pointer-events: none;
  transition: opacity 200ms var(--ease-out), transform 200ms var(--ease-out);
}

.share-toast.is-on {
  opacity: 1;
  transform: translate(-50%, 0);
}

}

/* chapter colour: the gas-price lottery runs on the brand red
   (official VI gradient), so the white bill and paper envelope pop */
.proof {
  position: relative;
  background: var(--grad-oxblood);
  color: var(--color-text-on-dark);
}

.hbars {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  padding-block: var(--space-9) var(--space-7);
}

.hbars-head {
  /* .container's auto margins would shrink-wrap here — pin to the
     gutters like every other full-width row */
  margin-inline: 0;
}

.proof-standfirst {
  margin-top: var(--space-5);
  max-width: 40rem;
  font-size: var(--type-standfirst);
  line-height: 1.5;
  color: var(--white);
}

/* emphasis follows the house rule: translucent pill, colour unchanged
   (gold stays reserved for data figures) */
.proof-standfirst strong,
.proof-crisis-lead strong,
.proof-body strong {
  background: rgba(255, 255, 255, 0.16);
  color: inherit;
  font-weight: var(--weight-bold);
  border-radius: 0.3em;
  padding: 0.06em 0.32em;
  margin-inline: -0.04em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* the rest of a section's argument, after its chart or map: reading
   size, pinned to the gutters like the head */
.proof-body {
  margin-inline: 0;
  display: grid;
  gap: var(--space-5);
}

.proof-body > p {
  max-width: 38rem;
  font-size: var(--type-body);
  line-height: var(--leading-body);
  color: rgba(245, 242, 236, 0.9);
}

.proof-body .statement-beat {
  margin-top: var(--space-5);
}

.proof-title {
  color: var(--white);
  font-size: var(--type-title);
  font-weight: var(--weight-bold);
  line-height: 1.08;
  /* editorial voice, per the reference: sentence case, full stops —
     a deliberate exception to the all-caps display rule */
  text-transform: none;
  letter-spacing: normal;
}

/* ---- the bars ------------------------------------------------------ */

.hbars-chart {
  display: grid;
  gap: var(--space-3);
}

.hbar {
  position: relative;
}

/* both layers share one layout: the ghost sits in flow and sizes the
   row; the fill is laid exactly over it */
.hbar-layer,
.hbar-fill {
  display: grid;
  align-content: start;
  gap: var(--space-2);
  padding: var(--space-4) var(--container-gutter);
}

/* outside the bar: the same colours as inside, so a short bar whose
   label or figure runs past its end (electricity, on narrow screens)
   still reads cleanly. While a bar is growing (.is-growing, set by the
   page script) the outside text waits as a ghost on the ink. */
.hbar-layer {
  color: var(--white);
  transition: color 300ms var(--ease-out);
}

.hbar-layer .hbar-figure {
  color: var(--gold-300);
  transition: color 300ms var(--ease-out);
}

.hbar.is-growing .hbar-layer,
.hbar.is-growing .hbar-layer .hbar-figure {
  color: rgba(245, 242, 236, 0.3);
}

/* name and figure size to their text (the short-bar check measures them) */
.hbar-name,
.hbar-figure {
  justify-self: start;
}

/* short bar (.is-outside, set by the page script when the final width
   can't hold the text): label and figure sit just past the bar's end,
   and the inside copy steps aside */
.hbar.is-outside .hbar-layer {
  padding-left: calc(var(--final, 1) * 100% + var(--space-4));
}

.hbar.is-outside .hbar-fill > * {
  visibility: hidden;
}

/* the bar itself — a window clipped to --f of the row (0..1, driven
   by the page script; the inline value is the settled width). Square
   ends, as in the reference chart. */
.hbar-fill {
  position: absolute;
  inset: 0;
  color: var(--white);
  clip-path: inset(0 calc((1 - var(--f, 1)) * 100%) 0 0);
}

/* two tints of the official red: gas in the full red, electricity in a
   70% tint (still a light→dark pass of one hue, per the VI). The tint
   keeps gold figures at 3.1:1 (large-text AA) and white labels 4.8:1. */
/* gas red, electricity teal — the same meaning as the energy-mix
   chart in #electrification (teal = electric, red = gas / imported) */
.hbar-gas .hbar-fill { background: var(--grad-oxblood-lit); }
.hbar-elec .hbar-fill { background: var(--grad-teal-lit); }

.hbar-name {
  font-weight: var(--weight-semibold);
  font-size: var(--text-body-lg);
}

.hbar-figure {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: clamp(3.5rem, 9vw, 8rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

.hbar-fill .hbar-figure {
  color: var(--gold-300);
}

/* ---- the envelope: a bill opening, scrubbed to scroll --------------
   Beside the head on wide screens, under it on narrow ones. Layers,
   back to front: envelope back, the flap's open (upturned) face, the
   bill, the front pocket, the flap's shut face. The shut face folds up
   from its top edge over the first half of --a (0 -> 90deg); the open
   face then folds on up behind the bill over the second half, so the
   flap never cuts across the bill. The bill rises with --b; its figure
   counts up on its own clock once the bill starts out (page script,
   .is-live / .is-counted). Paper and ink from the palette; the
   figure in the brand red. */
.bills-head {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

@media (min-width: 1000px) {
  .bills-head {
    grid-template-columns: minmax(0, 1fr) minmax(0, 30rem);
    gap: var(--space-8);
  }
}

.env-stage {
  --a: 1; --b: 1;
  width: min(100%, 30rem);
  justify-self: center;
  margin: 0;
  /* headroom above the envelope for the bill once it's out */
  padding-top: 62%;
  /* the turning flap projects wide in 3D; never let it widen the page */
  overflow-x: clip;
}

.env {
  position: relative;
  aspect-ratio: 30 / 17;
  perspective: 900px;
}

.env-back,
.env-front,
.env-flap,
.env-bill {
  position: absolute;
}

.env-back {
  inset: 0;
  border-radius: 6px;
  background: #ddd5c4;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.45);
}

/* the front: a solid panel (so the bill is hidden until it rises over
   the top edge), with the classic V where the side and bottom flaps
   meet drawn on as a lighter fold */
.env-front {
  inset: 0;
  border-radius: 6px;
  background: linear-gradient(to bottom, #e6dfcf, #ddd5c4);
}

.env-front::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 0 0 6px 6px;
  background: linear-gradient(to bottom, #efe9dc, #e4dccb);
  clip-path: polygon(0 34%, 50% 72%, 100% 34%, 100% 100%, 0 100%);
  filter: drop-shadow(0 -1px 0 rgba(21, 23, 46, 0.12));
}

.env-flap {
  left: 0;
  right: 0;
  height: 62%;
  transform-origin: 50% 0;
  backface-visibility: hidden;
}

/* shut: points down over the pocket; folds up and away over --a 0..0.5 */
.env-flap-shut {
  top: 0;
  background: linear-gradient(to bottom, #d9d0bd, #c9bea7);
  clip-path: polygon(0 0, 100% 0, 50% 100%);
  transform: rotateX(calc(min(var(--a), 0.5) * 2 * 90deg));
  /* gone once it's edge-on, so perspective never leaves a sliver */
  opacity: clamp(0, (0.5 - var(--a)) * 40, 1);
}

/* open: points up behind the bill; unfolds over --a 0.5..1 */
.env-flap-open {
  bottom: 100%;
  transform-origin: 50% 100%;
  background: linear-gradient(to top, #d8cfbc, #cfc5b0);
  clip-path: polygon(0 100%, 100% 100%, 50% 0);
  transform: rotateX(calc((1 - max(var(--a), 0.5)) * 2 * -90deg));
  opacity: clamp(0, (var(--a) - 0.5) * 40, 1);
}

/* the bill's slot: clips anything below the envelope's bottom edge,
   open above so the bill can rise clear. It reaches up over the copy
   beside it on narrow screens, so it never takes a tap (footnote 8) */
.env-slot {
  pointer-events: none;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  top: -160%;
  overflow: hidden;
}

/* the bill: tucked inside the envelope at --b 0, risen out at 1
   (top/height in % of the slot, which is 2.6x the envelope's height) */
.env-bill {
  left: 5%;
  right: 5%;
  top: calc(160% / 2.6 + 6% / 2.6);
  height: calc(132% / 2.6);
  padding: 7% 7% 0;
  border-radius: 4px;
  background: var(--white);
  color: var(--ink-900);
  box-shadow: 0 6px 18px rgba(21, 23, 46, 0.25);
  transform: translateY(calc(var(--b) * var(--rise, -86%)));
  text-align: left;
  display: grid;
  align-content: start;
  gap: 0.35em;
}

.bill-top {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding-bottom: 0.6em;
  margin-bottom: 0.4em;
  border-bottom: 1px solid rgba(21, 23, 46, 0.15);
  font-size: clamp(0.75rem, 1vw, 0.875rem);
  color: rgba(21, 23, 46, 0.7);
}

.bill-top span:first-child {
  color: var(--ink-900);
}

.bill-fig {
  font-family: var(--font-display);
  font-size: clamp(3rem, 6vw, 4.75rem);
  font-weight: var(--weight-display);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--oxblood-500);
}

/* with the page script running, the figure stays hidden until the bill
   starts out, then fades in as it counts up (never a lone "+0%") */
.env-stage.is-live .bill-fig {
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
}

.env-stage.is-live.is-counted .bill-fig {
  opacity: 1;
}

.bill-sub {
  font-size: clamp(0.8125rem, 1.1vw, 0.9375rem);
  color: rgba(21, 23, 46, 0.75);
}

.bill-lines {
  margin-top: 0.8em;
  display: grid;
  gap: 0.35em;
  font-size: clamp(0.75rem, 1vw, 0.875rem);
}

.bill-lines p {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding-top: 0.35em;
  border-top: 1px dashed rgba(21, 23, 46, 0.2);
}

.bill-lines span:first-child {
  color: var(--ink-900);
}

.bill-lines span:last-child {
  color: rgba(21, 23, 46, 0.7);
}

/* narrow screens: the bill's text wraps taller, so it rises further */
@media (max-width: 599px) {
  .env-stage {
    padding-top: 74%;
    --rise: -96%;
  }
}

/* phones: a tighter bill, so both of its lines read in full once it's
   out (at 360px "priced by gas, most of the time" used to wrap and sit
   half inside the envelope); the narrowest screens also get more room
   to rise */
@media (max-width: 420px) {
  .env-bill {
    left: 3.5%;
    right: 3.5%;
    padding: 5% 5% 0;
  }

  .bill-top {
    padding-bottom: 0.4em;
    margin-bottom: 0.2em;
  }

  .bill-fig {
    font-size: 2.5rem;
  }

  .bill-lines {
    font-size: 0.6875rem;
  }

  .bill-lines p {
    gap: var(--space-2);
  }
}

@media (max-width: 340px) {
  .env-stage {
    padding-top: 96%;
    --rise: -118%;
  }

  .env-bill {
    height: calc(150% / 2.6);
  }
}

.env-note {
  margin-top: var(--space-4);
  font-size: var(--type-note);
  color: rgba(245, 242, 236, 0.78);
  text-align: center;
}

.hbars-note {
  margin-inline: 0;
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.55);
}

/* ---- the crisis beat: full-screen photo, type over the top ---------
   After the energy-profits.org "$300billion" panel: a lead sentence
   and a giant figure set lower left over a full-bleed image. Scrims
   melt the photo's top edge out of the ink chart above and darken the
   bottom so white type holds wherever the crop lands. */

.security {
  background: var(--ink-900);
  color: var(--color-text-on-dark);
  padding-block: var(--space-9);
}

/* copy left, photo right (the reverse of the map section above) */
@media (min-width: 1000px) {
  .split-rev {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }
}

/* statements inside the body keep their own size and colour (the
   generic .proof-body > p rule would shrink them to reading size): the
   section closers in industry and security match */
.security .proof-body > .statement,
.europe .proof-body > .statement {
  font-size: var(--type-statement);
  line-height: 1.42;
  color: var(--white);
}

/* the photo as a contained, rounded panel; cropped to keep the face
   (~41% across the source) in frame */
.security-photo {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 5;
  max-height: 80vh;
  width: 100%;
}

.security-photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 41% 20%;
  filter: brightness(0.9) contrast(1.05);
}

/* no frame at all: the photo is toned into the page navy (luminosity
   blend over an ink ground, so its grey studio wall turns the page's
   own blue-grey and darkens towards the edges), then feathered away on
   every side with long, eased ramps that start well inside the frame —
   so there's no edge, corner or lighter box to read as a border. */
.security-photo {
  background: var(--ink-900);
  isolation: isolate;
  --feather: linear-gradient(to right,
      transparent 0%, rgba(0, 0, 0, 0.25) 5%, rgba(0, 0, 0, 0.6) 12%,
      rgba(0, 0, 0, 0.9) 20%, #000 28%, #000 72%,
      rgba(0, 0, 0, 0.9) 80%, rgba(0, 0, 0, 0.6) 88%,
      rgba(0, 0, 0, 0.25) 95%, transparent 100%),
    linear-gradient(to bottom,
      transparent 0%, rgba(0, 0, 0, 0.2) 8%, rgba(0, 0, 0, 0.55) 18%,
      rgba(0, 0, 0, 0.9) 30%, #000 40%, #000 56%,
      rgba(0, 0, 0, 0.75) 70%, rgba(0, 0, 0, 0.35) 84%,
      rgba(0, 0, 0, 0.1) 94%, transparent 100%);
  -webkit-mask-image: var(--feather);
  mask-image: var(--feather);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
  border-radius: 0;
}

.security-photo img {
  mix-blend-mode: luminosity;
  filter: brightness(0.82) contrast(1.12);
}

/* sink the bright studio wall behind the head into the navy, keeping
   the face and hands lit */
.security-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 85% 62% at 50% 58%,
    transparent 36%,
    color-mix(in srgb, var(--ink-900) 55%, transparent) 70%,
    var(--ink-900) 100%);
}

.proof-crisis {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-block: var(--space-9) var(--space-8);
}

.proof-crisis-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the face sits ~41% across the source — anchor there so narrow
     (portrait) crops keep it in frame */
  object-position: 41% 20%;
  /* tame the bright studio wall so it sits nearer the ink above */
  filter: brightness(0.8) contrast(1.08);
}

.proof-crisis::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* top: a long eased fade out of the chart's ink (stepped stops
     approximate an ease-out curve, so there is no visible edge where
     the linear ramp would end) */
  background:
    linear-gradient(to bottom,
      var(--ink-900) 0%,
      color-mix(in srgb, var(--ink-900) 94%, transparent) 6%,
      color-mix(in srgb, var(--ink-900) 81%, transparent) 12%,
      color-mix(in srgb, var(--ink-900) 64%, transparent) 18%,
      color-mix(in srgb, var(--ink-900) 45%, transparent) 24%,
      color-mix(in srgb, var(--ink-900) 28%, transparent) 30%,
      color-mix(in srgb, var(--ink-900) 14%, transparent) 35%,
      color-mix(in srgb, var(--ink-900) 5%, transparent) 39%,
      transparent 42%),
    linear-gradient(to top,
      var(--ink-900) 0%,
      color-mix(in srgb, var(--ink-900) 80%, transparent) 45%,
      transparent 80%);
}

.proof-crisis-copy {
  margin-inline: 0;
  display: grid;
  gap: var(--space-5);
}

/* the security section's standfirst, over the photo */
.proof-crisis-lead {
  max-width: 40rem;
  font-size: var(--type-standfirst);
  line-height: 1.5;
  color: var(--white);
}

.proof-crisis-figure {
  font-family: var(--font-display);
  font-size: clamp(6rem, 24vw, 22rem);
  font-weight: var(--weight-display);
  line-height: 0.8;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--white);
}

.proof-crisis-close {
  max-width: 36rem;
  font-size: var(--text-body-lg);
  line-height: var(--leading-body);
  color: rgba(245, 242, 236, 0.85);
}

/* under the figure: the payoff line and the forward-looking stat side
   by side, stacking on narrow screens */
.proof-crisis-foot {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 36rem));
  gap: var(--space-5) var(--space-8);
  align-items: start;
}

.proof-stat {
  border-top: 1px solid rgba(245, 242, 236, 0.2);
  padding-top: var(--space-4);
}

.proof-stat-figure {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 5vw, 3.5rem);
  font-weight: var(--weight-display);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  color: var(--gold-300);
  margin-bottom: var(--space-3);
}

.proof-stat p {
  color: rgba(245, 242, 236, 0.75);
}

@media (max-width: 720px) {
  .proof-crisis-foot {
    grid-template-columns: 1fr;
  }
}

/* --------------------------------------------------------------------
   Europe price map — EU27 + UK coloured by household price per kWh,
   d3 "zoom to bounding box" (scripts/europe-map.js). Diverging ramp
   around the EU median: teal below, brand red above; non-priced
   neighbours sit back as faint land. The UK keeps a gold outline (gold
   = data emphasis). The map runs full bleed and is vignetted into the
   page on every edge for an editorial plate; the readout and key float
   over the darkened Atlantic (bottom left). The full ranking lives on
   appendix.html so it doesn't break the page's flow; countries are
   keyboard-focusable on the map itself.
   -------------------------------------------------------------------- */

.europe {
  position: relative;
  /* chapter colour: industry runs on the brand teal; the map's vignette
     and borders read --sec-bg so they melt into it */
  --sec-bg: var(--teal-700);
  background: var(--sec-bg);
  color: var(--color-text-on-dark);
  padding-block: var(--space-9) var(--space-7);
}

/* ---- split layout: the map one side, the argument the other ---------
   Alternates with the bills section above (copy left, envelope right):
   map left, copy right. Narrow screens stack the argument first. */
.split {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

@media (min-width: 1000px) {
  .split {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
    gap: var(--space-8);
  }
}

@media (max-width: 999px) {
  .split-copy { order: -1; }
}

/* one rhythm for every split section's copy: heading > standfirst
   tight (24px), then an even 32px between every block after it, all
   on one text measure so the right edge doesn't step in and out */
.split-copy {
  --split-measure: 38rem;
}

.split-copy > .proof-standfirst {
  margin-top: var(--space-5);
}

.split-copy .proof-body {
  margin-top: var(--space-6);
  gap: var(--space-6);
}

.split-copy .proof-standfirst,
.split-copy .proof-body > p,
.split-copy .statement,
.split-copy .statement-body {
  max-width: var(--split-measure);
}

/* one copy size: the intro paragraph and every body paragraph after it
   share size, leading and colour, so a split section uses just three
   sizes — title, copy, statement */
.split-copy .proof-body > p:not(.statement),
.split-copy .statement-body {
  font-size: var(--type-standfirst);
  line-height: 1.5;
  color: var(--white);
}

/* a statement pair inside the body joins the same even rhythm */
.split-copy .proof-body .statement-beat {
  margin-top: 0;
  gap: var(--space-6);
}

/* no hard edge anywhere: the map's land is feathered out on all four
   sides (a horizontal and a vertical ramp, intersected), so wherever a
   zoom pushes a country against the frame it dissolves into the page.
   Wide screens fade the right side longest, where it meets the copy. */
.split .europe-svg {
  --map-feather: linear-gradient(to right,
      transparent 0%, #000 12%, #000 70%, transparent 100%),
    linear-gradient(to bottom,
      transparent 0%, #000 12%, #000 86%, transparent 100%);
  -webkit-mask-image: var(--map-feather);
  mask-image: var(--map-feather);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* narrow screens: the map runs edge to edge (out through the gutters),
   feathered evenly on both sides; the readout keeps the gutter */
@media (max-width: 999px) {
  .split-media .europe-map {
    margin-inline: calc(-1 * var(--container-gutter));
  }

  .split .europe-svg {
    --map-feather: linear-gradient(to right,
        transparent 0%, #000 14%, #000 86%, transparent 100%),
      linear-gradient(to bottom,
        transparent 0%, #000 12%, #000 86%, transparent 100%);
  }

  .split-media .europe-overlay {
    padding-inline: var(--container-gutter);
  }
}

.map-title {
  font-family: var(--font-display);
  font-size: var(--type-item);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  color: var(--white);
}

.europe-hint {
  margin-top: var(--space-2);
  font-size: var(--type-note);
  color: rgba(245, 242, 236, 0.7);
}

.europe-head {
  margin-inline: 0;
  margin-bottom: var(--space-6);
}

/* ---- map ----------------------------------------------------------- */

.europe-map {
  position: relative;
}

.europe-svg {
  display: block;
  width: 100%;
  height: clamp(420px, 72vh, 720px);
  overflow: hidden;
  cursor: default;
}

/* the vignette: an oval clearing over the continent, sinking to the
   page ink at every edge — plus straight top/bottom fades so the plate
   has no visible frame against the section above and the ranking below */
.europe-map::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, var(--sec-bg) 0%, transparent 14%,
      transparent 82%, var(--sec-bg) 100%),
    radial-gradient(ellipse 62% 66% at 52% 48%,
      transparent 52%,
      color-mix(in srgb, var(--sec-bg) 55%, transparent) 74%,
      color-mix(in srgb, var(--sec-bg) 88%, transparent) 90%,
      var(--sec-bg) 100%);
}

/* readout + key, floating over the vignette's dark lower-left corner
   (above the ::after so it stays crisp) */
/* a soft pool of the section's colour behind the readout, so its type
   holds its contrast over whatever land sits under it */
.europe-overlay::before {
  content: "";
  position: absolute;
  z-index: -1;
  /* no overhang on the right: on phones the readout spans the screen,
     and anything past its edge made the page scroll sideways */
  inset: -3rem 0 -2rem -2rem;
  background: radial-gradient(ellipse at 35% 60%,
    color-mix(in srgb, var(--tint, var(--teal-700)) 88%, transparent) 0%,
    color-mix(in srgb, var(--tint, var(--teal-700)) 70%, transparent) 45%,
    transparent 72%);
  pointer-events: none;
}

.europe-overlay {
  position: absolute;
  z-index: 1;
  left: 0;
  bottom: var(--space-5);
  width: min(18rem, 48%);
  display: grid;
  gap: var(--space-5);
  pointer-events: none;
}

.europe-ctx {
  fill: rgba(245, 242, 236, 0.06);
  stroke: rgba(245, 242, 236, 0.1);
  stroke-width: 0.6px;
  vector-effect: non-scaling-stroke;
}

.europe-country {
  stroke: var(--sec-bg);
  stroke-width: 0.8px;
  vector-effect: non-scaling-stroke;
  cursor: pointer;
  transition: opacity 250ms var(--ease-out);
}

/* when one is picked, the rest step back */
.europe-svg:has(.is-picked) .europe-country:not(.is-picked) {
  opacity: 0.45;
}

.europe-country:focus {
  outline: none;
}

.europe-country:focus-visible {
  stroke: var(--color-focus);
  stroke-width: 2.5px;
}

/* the white outline is its own path above every country (see
   europe-map.js), so shared borders are never half covered */
/* countries too small to see or tap (europe-map.js): a dot to see, and a
   wider invisible ring under it that takes the click */
.europe-dot {
  stroke: var(--white);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.europe-dot-hit {
  fill: transparent;
  cursor: pointer;
  pointer-events: all;
}

.europe-hi-line {
  fill: none;
  stroke: var(--white);
  stroke-width: 1.5px;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.europe-uk-line {
  fill: none;
  stroke: var(--gold-300);
  stroke-width: 2px;
  vector-effect: non-scaling-stroke;
  pointer-events: none;
}

.europe-label text {
  font-family: var(--font-display);
  font-weight: var(--weight-bold);
  font-size: 15px;
  fill: var(--white);
  text-anchor: middle;
  paint-order: stroke;
  stroke: var(--sec-bg);
  stroke-width: 4px;
  stroke-linejoin: round;
  pointer-events: none;
  transform: translateY(-10px);
}

.europe-legend {
  display: grid;
  gap: var(--space-2);
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.7);
  pointer-events: none;
}

.europe-legend-ramp {
  display: block;
  height: 10px;
}

.europe-legend-ticks {
  display: flex;
  justify-content: space-between;
  font-variant-numeric: tabular-nums;
}

/* ---- readout card -------------------------------------------------- */

.europe-card {
  min-height: 9.5rem;
}

.europe-card-name {
  font-weight: var(--weight-semibold);
  font-size: var(--text-body-lg);
}

.europe-card-p {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: clamp(2.75rem, 4.5vw, 3.75rem);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  color: var(--gold-300);
  margin-block: var(--space-2);
}

.europe-card-p small {
  font-family: var(--font-body, inherit);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
  letter-spacing: normal;
  color: rgba(245, 242, 236, 0.7);
}

.europe-card-line {
  color: rgba(245, 242, 236, 0.85);
}

.europe-card-line strong {
  color: var(--white);
}

.europe-source {
  margin-inline: 0;
  margin-top: var(--space-4);
  max-width: 48rem;
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.75);
}

/* map couldn't load: the readout and appendix link carry the section */
.europe.no-map .europe-svg,
.europe.no-map .europe-map::after,
.europe.no-map .europe-legend {
  display: none;
}

.europe.no-map .europe-overlay {
  position: static;
  width: auto;
  max-width: 30rem;
}

/* map still loading (europe-map.js sets .map-loading until it draws or
   gives up): a slow, quiet glow where the continent will sit. It waits
   a moment first, so a quick load never shows it; no words. */
.europe.map-loading .europe-map::before {
  content: "";
  position: absolute;
  inset: 8% 16% 20% 20%;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(245, 242, 236, 0.14), transparent);
  opacity: 0;
  animation: europe-loading 1.2s var(--ease-out) 0.6s infinite alternate;
  pointer-events: none;
}

@keyframes europe-loading {
  to { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .europe.map-loading .europe-map::before {
    animation: none;
    opacity: 1;
  }
}

/* narrow: the readout drops under the map instead of floating */
@media (max-width: 720px) {
  .europe-svg {
    height: clamp(380px, 64vh, 560px);
  }

  .europe-overlay {
    /* relative (not static) so it stays above the vignette layer */
    position: relative;
    left: auto;
    bottom: auto;
    width: auto;
    margin-top: calc(-1 * var(--space-6));
  }
}

.europe-source a {
  color: var(--white);
  white-space: nowrap;
}

/* --------------------------------------------------------------------
   Electrification — a centred, one-idea-per-screen explainer straight
   after the hero, over the navy the hero photo fades into (see the
   photo stage above). What it is > where it runs (home, road, rail,
   industry — the map becoming each use) > the turn > a third vs a
   fifth (comparative bars) > the power-station analogy (highlighted) >
   steel > electrification + sign-off (a power station rises dimly behind).
   Three weights only (VI trio): black for the figures and sign-off,
   bold for the title, statement and beat line, regular for the rest.
   Two text tones: white, and one muted tone for the small print.
   -------------------------------------------------------------------- */

.story {
  --story-muted: rgba(245, 242, 236, 0.7);
  position: relative;
  color: var(--white);
  text-align: center;
  padding-bottom: var(--space-9);
}

/* each beat holds a screen; its content sits centre stage */
.story-beat {
  position: relative;
  min-height: 92vh;
  min-height: 92svh;
  display: grid;
  place-items: center;
  padding: var(--space-9) var(--container-gutter);
}

.story-beat-title {
  min-height: 80vh;
  min-height: 80svh;
}

.story-title {
  max-width: 54rem;
  margin-inline: auto;
}

.story-lede {
  max-width: 34rem;
  font-size: var(--type-standfirst);
  line-height: 1.5;
}

.story-turn {
  max-width: 46rem;
  margin-inline: auto;
}

/* ---- what is electrification: a panel of tabs ------------------------
   The title and lede centred, like the section's other beats, then a
   panel on one column: tabs on a rule, then the current use's name,
   figure and line, left-aligned (scripts/electrify.js). Photos were
   removed on 27 Oct 2026; the full-bleed photo version is in
   docs/variants/photo-tabs. */
.story-beat-elec {
  min-height: 0;
  padding-block: var(--space-6) var(--space-9);
}

.elec {
  width: 100%;
  display: grid;
  gap: var(--space-7);
}

.elec-panel {
  max-width: 44rem;
}

/* the opening beat: the question on the left in display type, the answer
   on the right as plain text; a compact 50/50, nothing animated */
.story-beat-elec-head {
  min-height: 0;
  padding-block: var(--space-9) var(--space-6);
}

/* the energy-mix chart follows the answer directly: no full-screen
   beat to centre in, and a 64px step from the answer (32px each side) */
.story-beat-cmp {
  min-height: 0;
  padding-top: var(--space-6);
}

/* the scroll cue's target, the chart's second row: it lands a step
   below the solid header, wholly on screen, so it plays. Focused by
   the cue so Tab carries on from there; it isn't a control, so no ring */
#use-it {
  scroll-margin-top: calc(var(--header-solid-h, 5.25rem) + var(--space-5));
}

#use-it:focus {
  outline: none;
}

/* ---- scroll cue ---------------------------------------------------------
   An arrow at the foot of the window while the reader rests at the top
   of #electrification (where "How it works" lands): there's more below.
   It hangs from the right-hand gutter, under the social buttons, and
   wears their tile (tone-on-tone square, white glyph, the 45° paper
   sweep on hover). It bobs three times as it arrives, then keeps still.
   Shown by the page script (.is-on); --cue-lift clears the cookie
   banner. */
.scroll-cue {
  --chip-fill: var(--paper);
  position: fixed;
  right: max(var(--container-gutter), env(safe-area-inset-right));
  bottom: calc(var(--space-6) + env(safe-area-inset-bottom) + var(--cue-lift, 0px));
  z-index: 40;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  border-radius: var(--radius-logo);
  color: var(--white);
  background-color: rgba(0, 0, 0, 0.32);
  background-image: linear-gradient(45deg, var(--chip-fill) 49.6%, transparent 50.4%);
  background-size: 300% 100%;
  background-position: 100% 0;
  background-repeat: no-repeat;
  box-shadow: inset 0 0 0 1px rgba(245, 242, 236, 0.22);
  touch-action: manipulation;
  opacity: 0;
  transform: translateY(0.75rem);
  visibility: hidden;
  pointer-events: none;
  transition: opacity 400ms var(--ease-out),
              transform 400ms var(--ease-out),
              visibility 0s linear 400ms,
              background-position var(--hover-duration) var(--ease-out),
              color var(--hover-duration) var(--ease-out);
}

/* visibility inherits rather than turning visible, so the password
   screen (which hides the page) still hides the cue */
.scroll-cue.is-on {
  opacity: 1;
  transform: none;
  visibility: inherit;
  pointer-events: auto;
  transition-delay: 0s;
}

.scroll-cue:hover {
  background-position: 0 0;
  color: var(--ink-900);
}

.scroll-cue svg {
  width: 1.375rem;
  height: 1.375rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  display: block;
}

.scroll-cue.is-on svg {
  animation: scroll-cue-bob 1.4s ease-in-out 400ms 3;
}

@keyframes scroll-cue-bob {
  0%, 100% { transform: translateY(-2px); }
  50%      { transform: translateY(4px); }
}

.scroll-cue:focus-visible {
  outline: 3px solid var(--gold-500);
  outline-offset: 2px;
}

/* phones: the chart fills the screen there and the cue would sit on
   its key; the page plainly runs on below */
@media (max-width: 720px) {
  .scroll-cue {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-cue,
  .scroll-cue.is-on {
    transform: none;
  }

  .scroll-cue.is-on svg {
    animation: none;
  }
}

/* both beats hang from the page gutter, like the logo and the hero copy
   above, so the question lines up with them at every width */
/* the question, then its answer directly beneath it (stacked on 27 Oct
   2026; it was a 50/50 with the answer to the right) */
.elec-head {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-5);
  justify-items: start;
  text-align: left;
}

.elec-head .story-title {
  margin: 0;
  /* "electrification?" is one unbreakable word: on the narrowest
     screens (under ~330px) the title shrinks so it fits */
  font-size: min(var(--type-title), 11vw);
  max-width: 12ch;
  text-wrap: balance;
  line-height: 1.3; /* air between "What is" and the highlighted word */
}

/* "electrification?" in the question: Codrops' on-scroll text highlight,
   effect 6 (MIT), minus its opening fade-out: the letters type in left
   to right while a teal bar grows in behind them (page script, on
   GSAP + ScrollTrigger; Splitting cuts the word into .word > .char
   spans). The bar is the brand teal, not the demo's orange. */
.hx {
  background: none;
  color: var(--color-highlight-start);
  display: inline-block;
  position: relative;
  white-space: nowrap;
  /* ours: undo the site's mark chip, and keep the bar's z-index -1
     inside the word's own stack so it doesn't drop behind the navy */
  padding: 0;
  margin: 0;
  font-weight: inherit;
  isolation: isolate;
}

.hx-6 {
  display: inline-flex;
  /* room inside the bar, ours (the demo's is tighter): at the ends it is
     real padding, pulled back by the margin so the word sits where it
     did; above and below it is set by the bar's own edges, further down */
  --hx-pad-x: 0.2em;
  padding-inline: var(--hx-pad-x);
  margin-inline: calc(-1 * var(--hx-pad-x));
  /* the bar starts full so the word reads without JS; the page script
     zeroes it and grows it back as the word scrolls in */
  --after-width: var(--after-width-final);
  --after-width-final: 100%;
  /* the brand teal, flat (28 Oct 2026; was the demo's orange #dc764c,
     then briefly the brand red) */
  --color-bg-highlight: var(--teal-500);
  /* white, not the demo's peach (#fadabd): about 6:1 on the teal */
  --color-highlight-start: var(--white);
}

/* the bar spans the padding box; its top and bottom are tuned for
   Montserrat Bold at this heading's line-height 1.3 so the bar sits
   0.2em clear of the tallest letter and 0.38em below the baseline
   (measured off a screenshot; the demo's own -2.5% / 15% / -10.5% /
   105% were written for a light serif at line-height 1.2 and would clip
   these ascenders) */
.hx-6::after {
  content: '';
  left: 0;
  top: 0;
  bottom: -0.075em;
  position: absolute;
  z-index: -1;
  width: var(--after-width);
  background: var(--color-bg-highlight);
  border-radius: 8px;
}

.word,
.word > .char {
  display: inline-block;
}

.elec-answer {
  margin: 0;
  max-width: 36rem;
  /* the body-copy size every section uses (18-22px); it was a step up
     at 20-24px from 27 Oct until 28 Oct 2026, when the page's type was
     made consistent */
  font-size: var(--type-standfirst);
  line-height: 1.5;
  color: var(--white);
  opacity: 0.9;
}

.elec-answer .fn a {
  color: var(--teal-100);
}

@media (max-width: 899px) {
  .elec-head {
    gap: var(--space-4);
  }
}

.elec-panel {
  display: grid;
  gap: var(--space-5);
  min-width: 0;
  align-content: start;
  text-align: left;
}

.elec-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 0 1.4rem;
  border-bottom: 1px solid rgba(245, 242, 236, 0.18);
}

.elec-tab {
  position: relative;
  font: inherit;
  font-weight: var(--weight-bold);
  font-size: 0.9rem;
  padding: 0.6em 0 0.7em;
  border: 0;
  background: none;
  color: rgba(245, 242, 236, 0.6);
  cursor: pointer;
}

.elec-tab:hover,
.elec-tab[aria-pressed="true"] {
  color: var(--white);
}

.elec-tab:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: 4px;
}

/* the underline fills during the rest while the tour runs (page script) */
.elec-tab i {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 3px;
  background: var(--gold-500);
  transform: scaleX(0);
  transform-origin: left;
}

.elec-use {
  display: grid;
  gap: 0.25em;
  min-height: 11rem;
  align-content: start;
}

.elec-use.is-in > * {
  animation: elec-rise 420ms var(--ease-out) both;
}

.elec-use-h {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2vw, 1.75rem);
  font-weight: var(--weight-bold);
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--white);
}

.elec-use-stat {
  display: block;
  font-style: normal;
  font-family: var(--font-display);
  font-size: clamp(3rem, 5.5vw, 5rem);
  font-weight: var(--weight-display);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--gold-500);
  font-variant-numeric: tabular-nums;
}

.elec-use-stat[hidden] {
  display: none;
}

.elec-use-line {
  margin: 0;
  max-width: 28rem;
  font-size: clamp(1rem, 1.25vw, 1.15rem);
  line-height: 1.5;
  color: var(--white);
  opacity: 0.88;
}

.elec-use-line .fn a {
  color: var(--teal-100);
}

@keyframes elec-rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}

@media (max-width: 899px) {
  .elec-tabs {
    flex-wrap: nowrap;
    overflow-x: auto;
    gap: 0 1.1rem;
    scrollbar-width: none;
  }

  .elec-tab {
    white-space: nowrap;
  }

  .elec-use {
    min-height: 9rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  .elec-use.is-in > * {
    animation: none;
  }
}

/* ---- comparative bars: a third vs a fifth ---------------------------
   Two bars on the same 100% width, each headed by its figure and the
   copy line it proves; the block sits centre stage, its contents left-
   aligned so figures, labels and bars share one edge. Brand fills per
   the VI: one-hue light-to-dark gradients (teal = wind & solar /
   electric, red = oil, gas and the rest) in rounded bars; the empty
   track is a neutral tint. Every segment is named in the keys below
   its bar, so identity never rests on colour. Drawn in full here; the
   page script hides each row and plays it in as it arrives
   (clip-path reveals on the segments and the bracket). */
.cmp {
  /* full content width, left edge on the heading's (27 Oct 2026; was a
     centred 46rem column) */
  width: 100%;
  margin-inline: 0;
  justify-self: stretch;
  display: grid;
  gap: var(--space-8);
  text-align: left;
  /* solid fills, not the lit gradients (27 Oct 2026): each gradient's
     middle tone, so the bars keep the weight they had */
  --grad-teal-lit: #48849a;
  --grad-oxblood-lit: #b62f36;
  /* waffle grid: rows x cols = 200 */
  --rows: 4;
  --cols: 50;
  --gap: clamp(2px, 0.3vw, 4px);
}

.cmp-label {
  max-width: 36rem; /* keep the sentence readable now the row is wide */
}

.cmp-row {
  display: grid;
  gap: var(--space-4);
}

/* the turn, split across the chart: each half heads its bar */
.cmp-line {
  font-family: var(--font-display);
  font-size: var(--type-statement);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
  text-transform: none;
  letter-spacing: normal;
  color: var(--white);
  margin-bottom: var(--space-2);
}

.cmp-head {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: var(--space-5);
}

.cmp-fig {
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 6vw, 4.5rem);
  font-weight: var(--weight-display);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1;
  /* hold the width of "33%" so the labels don't shift as figures count */
  min-width: 3.1ch;
}

.cmp-label {
  font-size: var(--type-standfirst);
  line-height: 1.5;
}

/* the waffle: 200 rounded squares per bar, one per half percentage
   point, filling column by column so each reads as a sideways bar. 4 rows
   of 50 on wider screens, 8 of 25 on phones (set on .cmp). */
.cmp-waffle {
  display: grid;
  grid-auto-flow: column;
  grid-template-rows: repeat(var(--rows), auto);
  grid-template-columns: repeat(var(--cols), minmax(0, 1fr));
  gap: var(--gap);
}

.cmp-waffle i {
  display: block;
  aspect-ratio: 1;
  border-radius: 25%;
  transition: filter var(--hover-duration) var(--ease-out);
}

/* hovering a colour dims the others (filter, so it never fights the
   page script's opacity on the squares) */
.cmp-waffle[data-hover] i { filter: saturate(0.35) brightness(0.55); }
.cmp-waffle[data-hover="clean"] .w-clean,
.cmp-waffle[data-hover="gas"] .w-gas,
.cmp-waffle[data-hover="imp"] .w-imp,
.cmp-waffle[data-hover="fossil"] .w-fossil { filter: none; }

/* the hover tooltip: a small paper pill with the colour's swatch, its
   name and its share; follows the cursor (page script) */
.cmp-tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.45em 0.75em;
  border-radius: 999px;
  background: var(--white);
  color: var(--ink-900);
  font-size: var(--type-note);
  line-height: 1.2;
  white-space: nowrap;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 8px 24px rgba(0, 0, 0, 0.3);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--hover-duration) var(--ease-out);
}

.cmp-tip.is-on { opacity: 1; }

.cmp-tip-swatch {
  width: 0.75em;
  height: 0.75em;
  border-radius: 3px;
}

.cmp-tip-val { font-weight: var(--weight-bold); }

.w-clean  { background: var(--grad-teal-lit); }
.w-gas,
.w-fossil { background: var(--grad-oxblood-lit); }
.w-imp    { background: rgba(245, 242, 236, 0.32); }

.cmp-tip .w-clean { background: #48849a; }
.cmp-tip .w-gas,
.cmp-tip .w-fossil { background: #b62f36; }
.cmp-tip .w-imp { background: #8a8b97; }

.cmp-bracket-wrap {
  display: grid;
  justify-items: start;
  gap: var(--space-2);
}

.cmp-bracket {
  display: block;
  /* spans the first 91 squares: 91% of the columns, gaps included */
  width: calc((100% + var(--gap)) * 0.91 - var(--gap));
  height: 10px;
  border: 2px solid var(--white);
  border-top: 0;
  border-radius: 0 0 6px 6px;
}

.cmp-bracket-label {
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  color: var(--white);
}

.cmp-keys {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  font-size: var(--type-note);
  color: var(--story-muted);
}

.cmp-key::before {
  content: "";
  display: inline-block;
  width: 0.75em;
  height: 0.75em;
  margin-right: 0.4em;
  border-radius: 3px;
  vertical-align: -0.05em;
}

.cmp-key-clean::before  { background: var(--grad-teal-lit); }
.cmp-key-fossil::before { background: var(--grad-oxblood-lit); }
.cmp-key-track::before  { background: rgba(245, 242, 236, 0.32); }

.cmp-note {
  font-size: var(--type-note);
  color: var(--story-muted);
}

@media (max-width: 560px) {
  .cmp {
    --rows: 8;
    --cols: 25;
    --gap: 2px;
  }

  .cmp-head {
    grid-template-columns: 1fr;
    gap: var(--space-2);
  }
}

/* ---- statement, steel, close ---------------------------------------- */
.story-statement {
  max-width: 50rem;
  margin-inline: auto;
  /* a step up from the body statements: this one closes the chapter */
  font-size: clamp(1.625rem, 3vw, 2.75rem);
}

/* the closing beat runs over a full-bleed photo. The beat isolates its
   stacking, so the photo and scrim sit at -1 and the line paints over
   them without needing a z-index of its own. */
.story-beat-close {
  overflow: hidden;
  isolation: isolate;
}

/* the closing line in two beats: the set-up in muted white, then the
   payoff on the chapter's teal highlight */
.close-setup {
  display: block;
  color: rgba(245, 242, 236, 0.75);
}

/* (the set-up line was cut 28 Oct 2026; .close-setup stays for any
   statement that wants a two-beat lead-in) */

/* teal statement highlights (the closing line, the security
   statement): the bar and white letters of "electrification?", one bar
   per rendered line (page script). Without JS each payoff is one plain
   teal band per wrapped line. */
.hl-payoff {
  display: block;
  padding: 0;
  margin-inline: 0;
  background: none;
  color: var(--white);
  font-weight: inherit;
}

.hl-payoff:not(.is-live) .hl-band {
  background: var(--teal-500);
  border-radius: 8px;
  padding: 0.04em 0.2em;
  margin-inline: -0.2em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

.story-statement .hl-payoff:not(.is-live) .hl-band {
  margin-inline: 0;
}

/* live: each line is its own block with the bar (::before) revealed to
   --w under the white letters (the ink copy that swept in with it went
   when the letters turned white, 28 Oct 2026). Left-aligned lines
   hang their padding outside the column so the text keeps its edge;
   the centred closing line centres them instead. */
.hl-line {
  --w: 100%;
  position: relative;
  isolation: isolate;
  display: block;
  width: fit-content;
  margin-left: -0.2em;
  padding-inline: 0.2em;
  white-space: nowrap;
  color: var(--white);
}

.story-statement .hl-line {
  margin-inline: auto;
}

/* a footnote moved into the last line (page script) hangs just past
   the bar's end, so the bar keeps the line's own width */
.hl-line > .fn {
  position: absolute;
  left: 100%;
  top: 0;
  margin-left: 0.15em;
  font-size: 0.45em;
}

.hl-line + .hl-line {
  margin-top: 0.14em;
}

.hl-line::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  top: 0.08em;
  bottom: 0.02em;
  width: var(--w);
  border-radius: 8px;
  background: var(--teal-500);
}

.story-close-img {
  position: absolute;
  inset: 0;
  z-index: -2; /* under the scrim, which sits at -1 */
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Torness sits right of centre: narrow screens crop to the station */
  object-position: 68% 40%;
  /* fades up as the beat scrolls in (--v, set by the page script),
     settling from a touch larger; the top edge is feathered so it never
     hard-cuts against the navy above while it's coming in */
  opacity: var(--v, 1);
  transform: scale(calc(1.05 - var(--v, 1) * 0.05));
  transform-origin: 50% 60%;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 68%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 22%, #000 68%, transparent);
}

/* the scrim is the live chapter tint (navy here, red by the time the
   gas section arrives), solid at the foot, so the beat dissolves into
   whatever colour the ground is below it rather than stopping dead */
.story-beat-close::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--tint, var(--ink-900)) 78%, transparent),
    color-mix(in srgb, var(--tint, var(--ink-900)) 62%, transparent) 45%,
    var(--tint, var(--ink-900))
  );
}

.story-copy {
  display: grid;
  justify-items: center;
  gap: var(--space-5);
  max-width: 38rem;
  margin-inline: auto;
}

.story-body {
  font-size: var(--type-standfirst);
  line-height: 1.55;
}

/* a beat, not a headline: bold at the item step, no highlight */
.story-beat-line {
  font-family: var(--font-display);
  font-size: var(--type-item);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
}

/* the closing beat: the definition the story has been building to,
   at statement size but without the highlight, so it reads as a
   conclusion that leads on into the bills section rather than an end */
.story-close {
  max-width: 44rem;
  margin-inline: auto;
  font-family: var(--font-display);
  font-size: var(--type-statement);
  font-weight: var(--weight-bold);
  line-height: var(--leading-snug);
}

.story .fn {
  font-weight: inherit;
}

.story .fn a,
.story-credit {
  color: var(--story-muted);
}

/* photo caption, small in the steel beat's lower right */
.story-credit {
  position: absolute;
  right: var(--container-gutter);
  bottom: var(--space-5);
  font-size: var(--type-note);
}

/* type hierarchy (the editorial scale in tokens.css): section title >
   payoff statement (bold, highlighted) > supporting copy. Each beat's
   copy and payoff sit tight together; beats are spaced well apart, so
   the eye reads them as separate steps. */
.statement-beat {
  display: grid;
  gap: var(--space-4);
}

.statement {
  max-width: 46rem;
  font-family: var(--font-display);
  font-size: var(--type-statement);
  font-weight: var(--weight-bold);
  /* open enough that each line's highlight band stands clear of the next */
  line-height: 1.42;
  letter-spacing: -0.01em;
}

/* the highlight borrows the logo's stamp container over the hero: the
   paper tint at 16% with the stamp's barely-rounded corners (~3.5% of
   its height), cloned per line so each wrapped line gets its own */
.statement-mark,
.statement-line {
  color: var(--white);
  font-weight: inherit;
  border-radius: 0.06em;
  padding: 0.02em 0.14em;
  margin-inline: -0.14em;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* the band is frosted glass, the same as the highlighted word in the
   electrification question: a translucent paper fill, a bright top edge
   and thin rim, a soft lift, the backdrop blurred where anything sits
   behind. The static band (no JS) carries it directly; the lines drawn
   on scroll carry it on a layer behind the text (below). */
.statement-mark {
  background: linear-gradient(180deg, rgba(245, 242, 236, 0.22), rgba(245, 242, 236, 0.1));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    inset 0 0 0 1px rgba(255, 255, 255, 0.1),
    0 10px 30px rgba(0, 0, 0, 0.22);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
  border-radius: 0.16em;
}

/* drawn on scroll: the page script splits the sentence into its
   rendered lines and fills each like a marker stroke, left to right,
   one line after another (--p, 0..1 per line). Without the script the
   plain .statement-mark band above shows in full. */
.statement-mark.is-live {
  background: none;
  box-shadow: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  padding: 0;
  margin: 0;
  border-radius: 0;
}

.statement-line {
  position: relative;
  isolation: isolate;
  background: none;
}

/* each line's glass bar, behind the text, revealed left to right (--p) */
.statement-line::before {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  top: 0;
  bottom: 0;
  width: calc(var(--p, 1) * 100%);
  border-radius: 0.16em;
  background: linear-gradient(180deg, rgba(245, 242, 236, 0.22), rgba(245, 242, 236, 0.1));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.28),
    inset 0 0 0 1px rgba(255, 255, 255, 0.1),
    0 10px 30px rgba(0, 0, 0, 0.22);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  backdrop-filter: blur(14px) saturate(1.3);
}

.statement-body {
  max-width: 38rem;
  font-size: var(--type-body);
  line-height: var(--leading-body);
  color: rgba(245, 242, 236, 0.9);
}

.statement-note {
  font-size: 0.4em;
  font-weight: var(--weight-semibold);
  vertical-align: super;
  line-height: 0;
  margin-left: 0.1em;
}

/* footnote marker in running text (hero, body copy): same link
   treatment, sized for reading type */
.fn {
  font-size: 0.65em;
  /* the weight of the text it sits in, so it never adds a weight */
  font-weight: inherit;
  vertical-align: super;
  line-height: 0;
  margin-left: 0.1em;
}

.statement-note a,
.fn a {
  color: rgba(245, 242, 236, 0.7);
  /* the underline is always there, clear until hover, so it fades in
     on the hover clock with the colour */
  text-decoration: underline;
  text-decoration-color: transparent;
  transition: color var(--hover-duration) var(--ease-out),
              text-decoration-color var(--hover-duration) var(--ease-out);
}

/* the numbers are tiny, so each gets an invisible hit area of at least
   24px around it */
.fn a {
  position: relative;
}

.fn a::after {
  content: "";
  position: absolute;
  inset: -8px -10px;
}

.statement-note a:hover,
.statement-note a:focus-visible,
.fn a:hover,
.fn a:focus-visible {
  color: var(--white);
  text-decoration-color: currentColor;
}

/* --------------------------------------------------------------------
   Appendix page (appendix.html) — the full data and sources behind the
   campaign page's charts, on the same ink as the sections they serve.
   -------------------------------------------------------------------- */

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

.page-appendix {
  background: var(--ink-900);
  color: var(--color-text-on-dark);
}

.appendix-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
  border-bottom: 1.5px solid rgba(245, 242, 236, 0.22);
}

.appendix-home img {
  display: block;
  height: 56px;
  width: auto;
}

/* a 24px target everywhere, 44px where fingers tap (the 56px logo sets
   the bar's height, so nothing moves) */
.appendix-back {
  display: inline-flex;
  align-items: center;
  min-height: var(--space-5);
  color: var(--white);
  font-size: var(--text-small);
  font-weight: var(--weight-semibold);
}

@media (pointer: coarse), (max-width: 720px) {
  .appendix-back {
    min-height: 44px;
  }
}

.appendix {
  padding-block: var(--space-8) var(--space-9);
}

.appendix-block {
  margin-top: var(--space-8);
}

.appendix-h2 {
  font-size: var(--text-h3);
  color: var(--white);
}

.appendix-meta {
  margin-top: var(--space-2);
  color: rgba(245, 242, 236, 0.7);
}

/* the image credits' links (the only links in .appendix-meta): pale
   brand teal on the ink, 13.6:1, APCA Lc 88; white on hover */
.appendix-meta a {
  color: var(--teal-100);
  transition: color var(--hover-duration) var(--ease-out);
}

.appendix-meta a:hover {
  color: var(--white);
}

/* the tables scroll sideways in their own box when they need to. Scroll
   cue: a lit edge on whichever side has more table. The ink covers
   scroll with the table (local) and sit over the light at each end, so
   the light shows only while more is hidden. (The light starts 1px in:
   Safari lets a hairline of it past the cover on a fractional edge.) */
.appendix-table-wrap {
  margin-top: var(--space-5);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  background:
    linear-gradient(to right, var(--ink-900) 50%, rgba(21, 23, 46, 0)) left / 2.5rem 100% no-repeat local,
    linear-gradient(to left, var(--ink-900) 50%, rgba(21, 23, 46, 0)) right / 2.5rem 100% no-repeat local,
    linear-gradient(to right, rgba(245, 242, 236, 0) 1px, rgba(245, 242, 236, 0.3) 1px, rgba(245, 242, 236, 0)) left / 1.25rem 100% no-repeat scroll,
    linear-gradient(to left, rgba(245, 242, 236, 0) 1px, rgba(245, 242, 236, 0.3) 1px, rgba(245, 242, 236, 0)) right / 1.25rem 100% no-repeat scroll;
}

.appendix-table {
  width: 100%;
  max-width: 56rem;
  border-collapse: collapse;
  font-size: var(--text-small);
  font-variant-numeric: tabular-nums;
}

.appendix-table th,
.appendix-table td {
  padding: 0.45rem var(--space-3);
  text-align: left;
  border-bottom: 1px solid rgba(245, 242, 236, 0.08);
}

.appendix-table thead th {
  font-weight: var(--weight-semibold);
  color: rgba(245, 242, 236, 0.6);
  border-bottom-color: rgba(245, 242, 236, 0.22);
}

.appendix-table tbody th {
  font-weight: var(--weight-regular);
  color: var(--white);
}

.appendix-table .num {
  text-align: right;
}

.appendix-table td {
  color: rgba(245, 242, 236, 0.8);
}

.appendix-bar-col {
  width: 30%;
}

.appendix-meter {
  display: block;
  height: 6px;
  width: calc(var(--w) * 100%);
  background: rgba(245, 242, 236, 0.35);
}

/* the UK row reads at a glance: bold, gold bar and figure */
.appendix-table tr.is-uk th,
.appendix-table tr.is-uk td {
  font-weight: var(--weight-bold);
  color: var(--white);
}

/* the price cell (the rank cell, where present, comes first) */
.appendix-table tr.is-uk td.num:not(:first-child) {
  color: var(--gold-300);
}

.appendix-table tr.is-uk .appendix-meter {
  background: var(--gold-300);
}

/* narrow screens: the Europe ranking keeps its bars and scrolls sideways.
   Rank, country, price and bars fill the box exactly; the comparison
   column waits just past the right edge, so the edge never cuts a word.
   Widths in rem hold the longest word in each column. */
@media (max-width: 479px) {
  .appendix-ranking {
    table-layout: fixed;
    width: calc(100% + 10rem);
    max-width: none;
  }

  .appendix-ranking th,
  .appendix-ranking td {
    padding-inline: var(--space-2);
  }

  .appendix-ranking thead th:nth-child(1) {
    width: 3.5rem;
  }

  .appendix-ranking thead th:nth-child(2) {
    width: 7rem;
  }

  .appendix-ranking thead th:nth-child(3) {
    width: 4rem;
  }

  .appendix-ranking thead th.appendix-bar-col {
    width: auto;
  }

  .appendix-ranking thead th:last-child {
    width: 10rem;
  }
}

.appendix-source {
  margin-top: var(--space-5);
  max-width: 48rem;
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2) var(--space-4);
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.7);
}

/* a second source under the same label stays in the text column */
.appendix-source dd + dd {
  grid-column: 2;
}

.appendix-source dt {
  font-weight: var(--weight-semibold);
  color: var(--white);
}

.appendix-source a {
  color: var(--white);
}

/* --------------------------------------------------------------------
   FAQs — exclusive accordion of stamp cards (lorem ipsum placeholder
   copy until the real questions land). Capped width: a full-bleed line
   length is too long for reading answers.
   -------------------------------------------------------------------- */

.faq-list {
  display: grid;
  gap: var(--space-4);
  max-width: 56rem;
}

/* FAQ sits on the light page: the shared title in ink, questions at
   the item step, answers at body size */
.faq .proof-title {
  color: var(--color-text);
}

.faq .accordion-summary {
  font-size: var(--type-item);
  font-weight: var(--weight-bold);
}

.faq .accordion-body p {
  font-size: var(--type-body);
}

/* --------------------------------------------------------------------
   Footer — logo, contact, socials and the base row, on the background
   of the VI footer board, matched by measurement: the red gradient,
   deep left (#5A1F24) to brand red right (#841E22), with two corner
   plates of 45-degree round-capped bands, each band carrying its own
   bright-to-deep gradient (assets/footer-bands-*.svg, from
   scripts/gen_footer_bands.py), pinned bottom-left and top-right.
   Temporarily hosts #involved until the sign-up section is built.
   -------------------------------------------------------------------- */

.site-footer {
  position: relative; /* over the pinned price section */
  z-index: 2;
  background:
    url("../assets/footer-bands-left.svg") left bottom / 420px 420px no-repeat,
    url("../assets/footer-bands-right.svg") right top / 420px 420px no-repeat,
    linear-gradient(90deg, var(--oxblood-700) 0%, var(--oxblood-500) 100%);
  color: var(--paper);
  padding-block: var(--space-8) var(--space-6);
}

.footer-grid {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-7);
  align-items: start;
  padding-bottom: var(--space-7);
  border-bottom: 1px solid rgba(245, 242, 236, 0.22);
}

.footer-logo {
  height: 5.5rem;
  width: auto;
  display: block;
  /* trim the artwork's built-in padding so it sits on the grid */
  margin: -0.5rem 0 0 -0.4rem;
}

.footer-contact > a {
  color: var(--paper);
  text-decoration: none;
  font-weight: var(--weight-semibold);
  transition: color var(--hover-duration) var(--ease-out);
}

.footer-contact > a:hover {
  color: var(--gold-300);
}

.footer-contact > a {
  display: block;
}

.footer-contact > a + a {
  margin-top: var(--space-3);
}

.footer-contact .social-links {
  margin-top: var(--space-5);
}

/* tile fill from the VI footer board: the deep brand red at 60%, with
   the board's corner (15 px on a 69 px tile, ~22%) */
.site-footer .social-link {
  background-color: rgba(90, 31, 36, 0.6);
  border-radius: 22%;
}

/* on the red band the hovered glyph goes oxblood instead of ink */
.site-footer .social-link:hover {
  color: var(--oxblood-500);
}

.footer-base {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  padding-top: var(--space-5);
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.75);
}

.footer-base a {
  color: inherit;
  text-decoration: none;
  transition: color var(--hover-duration) var(--ease-out);
}

.footer-base a:hover {
  color: var(--gold-300);
}

/* privacy and cookie settings, side by side; the settings control is a
   button (it opens the banner), styled as one of the links */
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-5);
}

.footer-link {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: color var(--hover-duration) var(--ease-out);
}

.footer-link:hover {
  color: var(--gold-300);
}

/* footer and share targets: at least 24px everywhere and 44px on
   touch screens, grown with padding (the footer links) or a minimum
   height (the share buttons) so the layout barely moves */
.footer-links a,
.footer-link {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

.footer-contact a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

@media (pointer: coarse) {
  .footer-links a,
  .footer-link,
  .footer-contact a {
    min-height: 44px;
  }

  .share-actions .btn {
    min-height: 44px;
  }
}

/* the appendix and privacy pages: the footer links under the content */
.appendix-foot {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  padding-block: var(--space-6) var(--space-8);
  border-top: 1.5px solid rgba(245, 242, 236, 0.22);
  font-size: var(--text-small);
  color: rgba(245, 242, 236, 0.75);
}

.appendix-foot a {
  color: inherit;
  text-decoration: none;
  transition: color var(--hover-duration) var(--ease-out);
}

.appendix-foot a:hover {
  color: var(--gold-300);
}

/* --------------------------------------------------------------------
   Cookie consent (scripts/consent.js): fixed to the foot of the window
   until the visitor chooses. Accept and Reject carry equal weight.
   -------------------------------------------------------------------- */
.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  background: var(--ink-900);
  color: var(--paper);
  box-shadow: 0 -10px 30px rgba(21, 23, 46, 0.35);
  padding-block: var(--space-4) calc(var(--space-4) + env(safe-area-inset-bottom));
}

.consent[hidden] {
  display: none;
}

.consent-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-4) var(--space-6);
}

.consent-text {
  margin: 0;
  max-width: 46rem;
  font-size: var(--text-small);
  line-height: 1.5;
  color: rgba(245, 242, 236, 0.85);
}

.consent-text a {
  color: var(--white);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.consent-actions {
  display: flex;
  gap: var(--space-3);
}

.consent-btn {
  min-height: 44px;
  min-width: 7.5rem;
  padding: 0 var(--space-5);
  border: 1.5px solid rgba(245, 242, 236, 0.6);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--white);
  font: inherit;
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  cursor: pointer;
  touch-action: manipulation;
  transition: background-color var(--hover-duration) var(--ease-out),
              color var(--hover-duration) var(--ease-out),
              border-color var(--hover-duration) var(--ease-out);
}

.consent-btn:hover {
  background: var(--white);
  border-color: var(--white);
  color: var(--ink-900);
}

.consent-btn:focus-visible {
  outline: 3px solid var(--gold-500);
  outline-offset: 2px;
}

@media (max-width: 720px) {
  .consent-actions {
    width: 100%;
  }

  .consent-btn {
    flex: 1 1 0;
  }
}

@media (max-width: 920px) {
  .footer-grid {
    grid-template-columns: 1fr;
    gap: var(--space-6);
  }
}


/* --------------------------------------------------------------------
   Keyboard focus never lands on something invisible. Scroll-driven
   effects (the hero copy's fade)
   can leave a focusable element transparent or off-screen when it's
   reached by Tab; anything holding focus is shown settled at once.
   Focused elements also scroll clear of the fixed header.
   Keyboard focus only (:focus-visible): a mouse press focuses the link
   too, and snapping the copy back then moved the button out from under
   the pointer, so the click was lost.
   -------------------------------------------------------------------- */
.hero-copy:has(:focus-visible) {
  opacity: 1 !important;
  transform: none !important;
}

:focus-visible {
  scroll-margin-top: calc(var(--header-h, 6rem) + 1rem);
  scroll-margin-bottom: 2rem;
}


/* --------------------------------------------------------------------
   How more electricity cuts the bill (#price) — after security, visual
   left, copy right (the .split layout). Deep teal chapter colour, from
   the page tint. Two scrubbed charts (page script: --a/--b/--c columns,
   --d bill bar; defaults of 1 = settled). Gas is the brand red, as in
   every chart on the page; the other bill components are neutral tints,
   each named in its own label.
   -------------------------------------------------------------------- */
/* pinned while Spread the word's card rises over it (see .local); a
   full screen tall, so the dark ground shows around the card */
.price {
  position: sticky;
  top: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: grid;
  align-items: center;
  background: var(--teal-900);
  color: var(--color-text-on-dark);
  padding-block: var(--space-9);
}

.price .proof-body {
  margin-top: var(--space-6);
  gap: var(--space-6);
}

.price .proof-body > .statement {
  font-size: var(--type-statement);
  line-height: 1.42;
  color: var(--white);
}

/* placeholder panel for the section's visual */
.viz-placeholder {
  display: grid;
  place-items: center;
  min-height: clamp(16rem, 40vh, 26rem);
  border: 2px dashed rgba(245, 242, 236, 0.3);
  border-radius: var(--radius-lg);
  color: rgba(245, 242, 236, 0.7);
  font-size: var(--type-note);
  font-weight: var(--weight-bold);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}


/* --------------------------------------------------------------------
   Skip link: off screen until a keyboard user reaches it, then a pill
   at the top left, above the header and the cookie banner.
   -------------------------------------------------------------------- */
.skip-link {
  position: fixed;
  top: var(--space-3);
  left: var(--space-3);
  z-index: 200;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--white);
  color: var(--ink-900);
  font-weight: var(--weight-bold);
  text-decoration: none;
  transform: translateY(calc(-100% - var(--space-5)));
  transition: color var(--hover-duration) var(--ease-out);
}

.skip-link:focus {
  transform: none;
}

main:focus {
  outline: none;
}

/* on the cream Spread the word ground the gold focus ring all but
   disappears (1.4:1), so it turns ink there */
.local :focus-visible {
  outline-color: var(--ink-900);
}

/* --------------------------------------------------------------------
   Windows high contrast and other forced colours: the highlight bars are
   backgrounds, which forced colours remove, so their words take the
   system text colour instead of vanishing; the chart squares, key
   swatches and map ramp keep their colours, which carry the meaning.
   -------------------------------------------------------------------- */
@media (forced-colors: active) {
  .hx-6,
  .hx-6 .char,
  .hl-payoff,
  .hl-band,
  .hl-line {
    color: CanvasText !important;
  }

  .cmp-waffle i,
  .cmp-key::before,
  .europe-legend-ramp,
  .europe-dot {
    forced-color-adjust: none;
  }
}

/* --------------------------------------------------------------------
   Print (campaign page; the sources and privacy pages share the
   general rules). Paper doesn't take the dark grounds, so all text
   prints dark; everything the scroll animations hold back prints in
   its finished state (the page script sets the chart figures to their
   values on beforeprint); full-screen beats lose their screen heights;
   decorative photos, fixed chrome and controls stay off the page. The
   chart squares and key swatches keep their colours, which carry the
   meaning.
   -------------------------------------------------------------------- */
@media print {
  html,
  body {
    background: #fff !important;
  }

  body * {
    color: #111 !important;
    -webkit-text-fill-color: currentColor !important;
    text-shadow: none !important;
    box-shadow: none !important;
  }

  /* the dark grounds and their vignettes, in case background graphics
     are switched on */
  .dissolve,
  .site-footer {
    background: none !important;
  }

  .story-beat-close::before,
  .europe-map::after,
  .europe-overlay::before,
  .security-photo::after {
    display: none !important;
  }

  .security-photo {
    background: none !important;
  }

  /* the cookie banner's reserved room at the foot (set inline by
     scripts/consent.js) */
  body {
    padding-bottom: 0 !important;
  }

  .page-tint,
  .dissolve-stage,
  .hero-topbar,
  .skip-link,
  .consent,
  .scroll-cue,
  .story-close-img,
  .local-bg,
  .share-actions,
  .share-menu,
  .share-toast,
  .footer-logo,
  .cmp-tip {
    display: none !important;
  }

  .hero-wrap,
  .hero-wrap > .hero,
  .story-beat,
  .proof-crisis,
  .price,
  section {
    min-height: 0 !important;
    position: static !important;
  }

  .hero-wrap {
    padding-top: 0 !important;
  }

  /* everything the scroll animations hold back, settled */
  .hero-copy,
  [data-rise],
  .elec-answer,
  .hx .char,
  .cmp-line,
  .cmp-label,
  .cmp-fig,
  .cmp-waffle i,
  .cmp-bracket-label,
  .cmp-keys,
  .cmp-note,
  .close-setup,
  .hl-line,
  .env-stage .bill-fig {
    opacity: 1 !important;
    transform: none !important;
  }

  .cmp-bracket {
    clip-path: none !important;
  }

  .hl-line {
    --w: 100% !important;
  }

  .env-stage {
    --a: 1 !important;
    --b: 1 !important;
  }

  .cmp-waffle i,
  .cmp-key::before {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  /* keep a chart, a post or the envelope from splitting across pages */
  .cmp-row,
  .env-stage,
  .local-card,
  figure {
    break-inside: avoid;
  }
}

/* --------------------------------------------------------------------
   Print: the sources and privacy pages (the campaign page's own print
   rules are above). On-screen controls stay off the paper; the sources
   page prints dark on white with every source's address after it.
   -------------------------------------------------------------------- */
@media print {
  /* the skip link is position: fixed and otherwise lands on every page */
  .skip-link,
  .consent,
  .appendix-back,
  .js-cookie-settings {
    display: none !important;
  }

  .page-appendix,
  .page-appendix *,
  .page-appendix *::before,
  .page-appendix *::after {
    color: #000 !important;
    background: transparent !important;
    box-shadow: none !important;
    text-shadow: none !important;
  }

  .page-appendix {
    background: #fff !important;
  }

  .page-appendix .appendix-bar,
  .page-appendix .appendix-foot {
    border-color: #bbb;
  }

  .page-appendix .appendix-table th,
  .page-appendix .appendix-table td {
    border-bottom-color: #ddd;
  }

  .page-appendix .appendix-table thead th {
    border-bottom-color: #888;
  }

  /* the whole table on paper, never a scroll box */
  .page-appendix .appendix-table-wrap {
    overflow: visible;
  }

  /* bars as borders: borders print when background graphics are off */
  .page-appendix .appendix-meter {
    height: 0;
    border-top: 6px solid #aaa;
  }

  .page-appendix .appendix-table tr.is-uk .appendix-meter {
    border-top-color: #000;
  }

  /* each source and credit link prints its address after it */
  .page-appendix .appendix-source a[href^="http"]::after,
  .page-appendix .appendix-meta a[href^="http"]::after {
    content: " (" attr(href) ")";
    font-size: 0.85em;
    overflow-wrap: anywhere;
  }

  .page-appendix .appendix-h2 {
    break-after: avoid;
  }

  .page-appendix .appendix-table tr,
  .page-appendix .appendix-source dd {
    break-inside: avoid;
  }
}
