/* =========================================================
   UN Geneva — 2025 Annual Report
   Layout + components

   Full-bleed by default: sections run edge to edge and only
   TEXT is constrained, to a readable measure. All animation
   lives in motion.css.
   ========================================================= */

/* ---------------------------------------------------------
   Reset & base
   --------------------------------------------------------- */
*, *::before, *::after{ box-sizing: border-box; }

html{
  scroll-behavior: smooth;
  /* Anchor targets clear the sticky header (WCAG 2.2 §2.4.11) */
  scroll-padding-top: calc(var(--header-h) + 1rem);
  -webkit-text-size-adjust: 100%;
}

body{
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-serif);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg{ max-width: 100%; display: block; }
h1, h2, h3, h4{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  margin: 0;
  letter-spacing: -.015em;
}
p{ margin: 0; }
a{ color: inherit; }
button{ font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:is(section, [id])[id]{ scroll-margin-top: calc(var(--header-h) + 1rem); }

/* ---------------------------------------------------------
   Utilities
   --------------------------------------------------------- */
.visually-hidden{
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.measure{ max-width: var(--measure); }
.bleed-pad{ padding-inline: var(--gutter); }

.skip-link{
  position: fixed;
  left: 1rem; top: -4rem;
  background: var(--ink);
  color: var(--white);
  padding: .85rem 1.35rem;
  z-index: 1200;
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  text-decoration: none;
  transition: top var(--dur-s) var(--ease-out);
}
.skip-link:focus-visible{ top: 1rem; }

/* Two-tone focus ring: the white halo guarantees >=3:1 against
   any ground (paper, photograph or taupe panel). */
:focus-visible{
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--white);
  border-radius: 2px;
}
.on-dark :focus-visible,
.hero :focus-visible,
.chapter__panel :focus-visible,
.site-footer :focus-visible{
  outline-color: var(--white);
  box-shadow: 0 0 0 2px rgba(0,0,0,.65);
}

/* ---------------------------------------------------------
   Type helpers
   --------------------------------------------------------- */
.eyebrow{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--taupe-dark);          /* 4.84:1 on paper — print uses taupe here too */
  margin: 0 0 1.1rem;
}
.eyebrow--on-dark{ color: var(--blue); }

/* Section heading: a small uppercase label over a large regular-weight
   statement, modelled on journey-creative.webflow.io ("text-style-allcaps
   text-size-small" over "heading-style-h3 text-weight-normal"): 14px label,
   ~2px tracking, 32px gap, ~54px statement at line-height 1.2.
   Label in Times, statement in Frutiger 400. Both live in one <h2> so the
   section is announced by name first ("Foreword, Read and listen to…"). */
.section-heading{
  margin: 0;
  font-weight: 400;
  letter-spacing: 0;
}
.section-label{
  display: block;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: .875rem;
  line-height: 1.5;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-bottom: clamp(1.25rem, 2.2vw, 2rem);
}
.section-statement{
  display: block;
  font-family: var(--font-display);
  font-weight: var(--fw-statement);
  font-size: clamp(2rem, 4.6vw, 4.25rem);
  line-height: 1.12;
  letter-spacing: -.01em;
  color: var(--blue);
  max-width: 20em;
  text-wrap: balance;
}


.section-head{ padding-inline: var(--gutter); padding-block: clamp(3.5rem, 8vw, 7rem) 0; }

.editorial{
  font-family: var(--font-serif);
  font-size: var(--fs-lead);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.editorial p + p{ margin-top: 1.15em; }

/* Rule mark used as a section divider — echoes the print's dashes */
.rule{
  width: 100%; height: 1px;
  background: var(--line);
  border: 0; margin: 0;
}

/* ---------------------------------------------------------
   Buttons
   --------------------------------------------------------- */
.btn{
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: var(--fs-small);
  letter-spacing: .02em;
  padding: 1rem 1.7rem;
  min-height: 48px;
  text-decoration: none;
  border: 1.5px solid transparent;
  transition: background var(--dur-s) var(--ease-out),
              color var(--dur-s) var(--ease-out),
              border-color var(--dur-s) var(--ease-out);
}
.btn__icon{ flex-shrink: 0; transition: transform var(--dur-s) var(--ease-out); }

/* Large CTA. At >=18.66px semibold this is "large text" under WCAG, so the
   3:1 bar applies and white on the brand blue (3.04:1) is compliant. Do not
   reduce this below 1.175rem without also darkening the fill. */
.btn--lg{
  font-size: 1.1875rem;
  padding: 1.1rem 2rem;
  min-height: 56px;
}
.btn--lg .btn__soon{ font-size: .8125rem; }
.btn:hover .btn__icon{ transform: translate(3px, 0); }
.btn--download:hover .btn__icon{ transform: translate(0, 3px); }

.btn--primary{ background: var(--blue); color: var(--white); }
.btn--primary:hover{ box-shadow: inset 0 0 0 2px rgba(255,255,255,.6); }   /* no second blue: outline, not a darker fill */

.btn--ghost{
  background: rgba(255,255,255,.08);
  color: var(--white);
  border-color: rgba(255,255,255,.8);
}
/* Only the hero sits on photography, so only the hero needs the blur.
   On the solid taupe panels it showed nothing and still cost a composite
   on every scrolled frame — inside the sticky chapters, of all places. */
.btn--ghost.hero__cta{ backdrop-filter: blur(8px); }
.btn--ghost:hover{ background: var(--white); color: var(--ink); }

/* Light-ground counterpart to .btn--ghost, for the paper sections where a
   white outline would disappear. Brand blue, label and border alike, so it
   reads as an accent rather than a heavy ink box. Note the blue is 2.58:1
   on paper: below the bar for both the label and the border, the same
   accepted blue-on-paper exception as the section statements and the stat
   figures. Logged in tools/contrast-check.py. Hover fills to recover it. */
.btn--outline{
  background: transparent;
  color: var(--blue);
  border-color: var(--blue);
}
.btn--outline:hover{ background: var(--blue); color: var(--white); }


/* Missing-asset state: the file isn't on the server yet */
.btn[aria-disabled="true"]{
  opacity: .55;
  cursor: not-allowed;
  pointer-events: none;
}
.btn__soon{
  font-weight: var(--fw-regular);
  font-size: .75rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .85;
}

/* On narrow screens the "coming soon" note takes its own line
   rather than squeezing the label into a ragged column. */
@media (max-width: 560px){
  .btn{ flex-wrap: wrap; padding: .85rem 1.3rem; row-gap: .25rem; }
  .btn__soon{ flex-basis: 100%; }
}

/* ---------------------------------------------------------
   Header
   --------------------------------------------------------- */
.site-header{
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 900;
  height: var(--header-h);
  display: flex;
  align-items: center;
  padding-inline: var(--content-inset);
  gap: clamp(1rem, 3vw, 2.5rem);
  color: var(--white);
  transition: background var(--dur-m) var(--ease-out),
              color var(--dur-m) var(--ease-out),
              border-color var(--dur-m) var(--ease-out);
  border-bottom: 1px solid transparent;
}
/* Over the hero the bar is transparent; past it, solid white.
   Fully opaque, so no backdrop-filter is needed (nothing shows through)
   and we avoid the extra compositing layer it would cost. */
.site-header.is-solid{
  background: var(--white);
  color: var(--ink);
  border-bottom-color: var(--line);
}
.site-header__logo{ display: inline-flex; flex-shrink: 0; margin-inline-end: auto; }
.site-header__logo img{ height: clamp(36px, 4.1vw, 48px); width: auto; }
/* The supplied logo is solid UN blue; invert to white over the hero */
.site-header:not(.is-solid) .site-header__logo img{ filter: brightness(0) invert(1); }

.site-nav{ margin-inline-start: 0; }
.site-nav__list{
  display: flex;
  gap: clamp(1rem, 2.2vw, 2rem);
  list-style: none;
  margin: 0; padding: 0;
}
.site-nav__link{
  font-family: var(--font-display);
  font-size: var(--fs-label);
  letter-spacing: .06em;
  text-decoration: none;
  padding: .4rem 0;
  position: relative;
  white-space: nowrap;
  opacity: .8;
  transition: opacity var(--dur-s) var(--ease-out);
}
.site-nav__link::after{
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1.5px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-s) var(--ease-out);
}
.site-nav__link:hover{ opacity: 1; }
.site-nav__link:hover::after,
.site-nav__link[aria-current="true"]::after{ transform: scaleX(1); }
.site-nav__link[aria-current="true"]{ opacity: 1; font-weight: var(--fw-semi); }

@media (max-width: 900px){ .site-nav{ display: none; } }

.lang-switch{
  display: inline-flex;
  align-items: center;
  position: relative;
  flex-shrink: 0;
  /* Pinned right by the logo's auto end-margin, so this holds whether or
     not the nav is rendered at the current width. */
  margin-inline-start: 0;
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--fw-semi);
  border: 1px solid currentColor;
}
.lang-switch__btn{
  padding: .45rem .75rem;
  letter-spacing: .06em;
  position: relative;
  z-index: 1;
  opacity: .7;
  transition: opacity var(--dur-s) var(--ease-out), color var(--dur-s) var(--ease-out);
}
.lang-switch__btn.is-active{ opacity: 1; color: var(--white); }
.site-header:not(.is-solid) .lang-switch__btn.is-active{ color: var(--ink); }
.lang-switch__btn:not(.is-active):hover{ opacity: 1; }
/* Sliding indicator, positioned by JS (FLIP) */
.lang-switch__pill{
  position: absolute;
  top: 0; bottom: 0; left: 0;
  background: currentColor;
  z-index: 0;
  transition: transform var(--dur-s) var(--ease-out), width var(--dur-s) var(--ease-out);
}

/* Scrolled header (solid white): the language switch and the nav underline
   take the brand blue. Over the hero both stay white. The switch's border and
   sliding pill use currentColor, so setting its colour recolours all three. */
.site-header.is-solid .lang-switch{ color: var(--blue); }
.site-header.is-solid .lang-switch__btn{ opacity: 1; }          /* full blue, not faded */
.site-header.is-solid .lang-switch__btn.is-active{ color: var(--white); }
.site-header.is-solid .lang-switch__btn:not(.is-active):hover{
  text-decoration: underline;
  text-underline-offset: 3px;
}
.site-header.is-solid .site-nav__link::after{ background: var(--blue); }

/* ---------------------------------------------------------
   Hero
   --------------------------------------------------------- */
.hero{
  position: relative;
  height: 100svh;
  min-height: 600px;
  overflow: hidden;
  background: var(--ink);
  isolation: isolate;
}
.hero__track{ position: absolute; inset: 0; }
.hero__slide{
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
}
.hero__slide.is-active{ opacity: 1; visibility: visible; z-index: 2; }
.hero__img{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.hero__scrim{
  position: absolute; inset: 0;
  background:
    linear-gradient(0deg, rgba(4,12,18,.86) 0%, rgba(4,12,18,.42) 42%, rgba(4,12,18,.12) 68%),
    linear-gradient(90deg, rgba(4,12,18,.5) 0%, rgba(4,12,18,0) 55%);
}
/* Inverted for the cover slide: the weight moves to the top, following the
   text. Without this the type would sit on the photograph's own mid-tone. */
.hero__slide[data-slide="0"] .hero__scrim{
  background:
    linear-gradient(180deg, rgba(4,12,18,.74) 0%, rgba(4,12,18,.54) 45%, rgba(4,12,18,.16) 75%),
    linear-gradient(90deg, rgba(4,12,18,.42) 0%, rgba(4,12,18,0) 62%);
}
.hero__content{
  position: absolute;
  left: 0; right: 0;
  bottom: clamp(5.5rem, 12vh, 9rem);
  padding-inline: var(--content-inset);
  color: var(--white);
}

/* Slide 1 reproduces the printed cover, where the title sits near the TOP
   of the page rather than the foot. It clears the sticky header, and the
   slide's scrim is inverted to match (see below) so the type still has a
   dark ground to sit on. */
.hero__slide[data-slide="0"] .hero__content{
  top: calc(var(--header-h) + clamp(2.75rem, 10vh, 6.5rem));   /* breathing room below the logo */
  bottom: auto;
}
.hero__eyebrow{ color: var(--blue); }
/* The hero reproduces the printed cover, which is set in Times at regular
   weight in sentence case — not the semibold Frutiger used for section
   headings. Times has a smaller x-height than Frutiger, so the scale is
   nudged up and the leading opened to match the cover's proportions. */
.hero__title{
  color: var(--white);
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.25rem, 5.8vw, 5.25rem);
  line-height: 1.14;
  letter-spacing: 0;
  margin-bottom: 1.8rem;
  /* em-based so the cover's line breaks ("UN Geneva at 80:" /
     "building resilient multilateralism" / "for tomorrow") hold at every
     size instead of shifting with the viewport. Do not use `ch` here: it is
     measured from the "0" glyph and gives a different measure per font. */
  max-width: 14em;
}
.hero__cta{ display: inline-flex; }

/* Controls */
.hero__controls{
  position: absolute;
  right: var(--content-inset);
  bottom: 2rem;
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--white);
}
.hero__arrow{
  width: 44px; height: 44px;
  border: 1.5px solid rgba(255,255,255,.55);
  border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--dur-s) var(--ease-out), border-color var(--dur-s) var(--ease-out);
}
.hero__arrow:hover{ background: rgba(255,255,255,.2); border-color: var(--white); }

.hero__dots{ display: flex; gap: .55rem; }
.hero__dots button{
  width: 32px; height: 2px;
  background: rgba(255,255,255,.4);
  transition: background var(--dur-s) var(--ease-out);
  padding: 11px 0;              /* visible rule is 2px; padding carries the 24px target */
  background-clip: content-box;
  box-sizing: content-box;
}
.hero__dots button[aria-current="true"]{ background: var(--white); background-clip: content-box; }

/* Play/pause with the print's radial tick-ring as progress */
.hero__playpause{
  position: relative;
  width: 44px; height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
.hero__ring{ position: absolute; inset: 0; width: 44px; height: 44px; transform: rotate(-90deg); }
.hero__ring circle{ fill: none; stroke-width: 1.5; }
.hero__ring .ring-track{ stroke: rgba(255,255,255,.3); }
.hero__ring .ring-progress{ stroke: var(--white); stroke-dasharray: 128.8; stroke-dashoffset: 128.8; }
.icon-play[hidden], .icon-pause[hidden]{ display: none; }

.hero__scroll-cue{
  position: absolute;
  min-height: 24px;             /* WCAG 2.2 2.5.8 */
  padding-block: .25rem;
  left: var(--content-inset);
  bottom: 2.15rem;
  z-index: 5;
  color: var(--white);
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  font-family: var(--font-display);
  font-size: .75rem;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  text-decoration: none;
}
@media (max-width: 700px){
  .hero__scroll-cue{ display: none; }
  .hero__controls{ left: var(--gutter); right: var(--gutter); justify-content: space-between; }
}

/* ---------------------------------------------------------
   Foreword
   --------------------------------------------------------- */
.foreword{
  background: var(--white);
  padding-block: clamp(4rem, 9vw, 8.5rem);
  padding-inline: var(--content-inset);
}
.foreword__grid{
  display: grid;
  grid-template-columns: minmax(260px, 360px) minmax(0, 1fr);
  gap: clamp(2.5rem, 6vw, 6rem);
  align-items: start;
}
.foreword__aside{ position: sticky; top: calc(var(--header-h) + 2rem); }
.foreword__portrait{ margin: 0 0 1.75rem; overflow: hidden; aspect-ratio: 1; background: var(--paper); }
.foreword__portrait img{ width: 100%; height: 100%; object-fit: cover; }

/* Heading spans the full content width above the portrait + text columns. */
.foreword__head{ margin-bottom: clamp(2.5rem, 5vw, 4.5rem); }
.foreword__body{ margin-block: 0 2.5rem; }   /* body now starts level with the portrait */
.foreword__signature{ border-top: 1px solid var(--line); padding-top: 1.5rem; }
.foreword__signature-name{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: 1.2rem;
  color: var(--blue);
}
.foreword__signature-title{
  font-family: var(--font-serif);
  font-style: italic;
  color: var(--ink-muted);
  font-size: var(--fs-small);
  margin-top: .2rem;
}

/* Audio player — "hairline": no box, an outlined play button that fills
   when playing, and a single line that grows as the recording plays. */
.audio-player{
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 1.1rem 0 .85rem;
}
.audio-player__row{ display: flex; align-items: center; gap: 1rem; }
.audio-player__toggle{
  flex-shrink: 0;
  width: 52px; height: 52px;
  border-radius: 50%;
  border: 1.5px solid var(--blue);
  color: var(--blue);
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--dur-s) var(--ease-out), color var(--dur-s) var(--ease-out);
}
.audio-player__toggle:hover,
.audio-player.is-playing .audio-player__toggle{ background: var(--blue); color: var(--white); }
.audio-player__toggle .icon-play{ margin-left: 2px; }
.audio-player__body{ flex: 1; min-width: 0; }
.audio-player__label{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);      /* heaviest weight in the kit */
  font-size: .9375rem;
  line-height: 1.3;
}
/* Disclosure line under the label: regular weight, muted. */
.audio-player__voice:empty{ display: none; }   /* English has no note */
.audio-player__voice{
  display: block;
  font-weight: var(--fw-regular);
  font-size: .8125rem;
  color: var(--ink-muted);
  margin-top: .1rem;
}
.audio-player__note{
  font-family: var(--font-display);
  font-size: .75rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: .3rem;
}
.audio-player__total,
.audio-player__times{
  font-family: var(--font-display);
  font-size: .75rem;
  color: var(--ink-muted);
  font-variant-numeric: tabular-nums;
}
.audio-player__total{ align-self: flex-start; padding-top: .15rem; }

/* The line: a 1px taupe track (3.8:1 on white, so the control stays
   visible before playback), a 3px blue fill, and a knob that appears on
   hover, focus or while playing. */
.audio-player__scrubber{ position: relative; height: 22px; margin-top: .9rem; }
.audio-player__track{ position: absolute; left: 0; right: 0; top: 10px; height: 1px; background: var(--taupe); }
.audio-player__fill{ position: absolute; left: 0; top: 9px; height: 3px; width: 0; background: var(--blue); }
.audio-player__knob{
  position: absolute; left: 0; top: 6px;
  width: 9px; height: 9px; margin-left: -4.5px;
  border-radius: 50%;
  background: var(--blue);
  opacity: 0;
  transition: opacity var(--dur-s) var(--ease-out);
}
.audio-player__scrubber:hover .audio-player__knob,
.audio-player__scrubber:focus-within .audio-player__knob,
.audio-player.is-playing .audio-player__knob{ opacity: 1; }
.audio-player__scrubber input[type="range"]{
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.audio-player__scrubber:focus-within{
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  box-shadow: 0 0 0 3px var(--white);
}
.audio-player__times{ display: flex; justify-content: space-between; margin-top: .1rem; }

.audio-player.is-unavailable .audio-player__toggle,
.audio-player.is-unavailable .audio-player__total,
.audio-player.is-unavailable .audio-player__scrubber,
.audio-player.is-unavailable .audio-player__times{ display: none; }

@media (max-width: 900px){
  .foreword__grid{ grid-template-columns: 1fr; }
  .foreword__aside{ position: static; max-width: 420px; }
}

/* ---------------------------------------------------------
   Chapters — full-bleed 50/50 split (the printed spread)
   --------------------------------------------------------- */
.chapters{ background: var(--white); }
.chapters__head{ padding: clamp(4rem, 9vw, 8rem) var(--content-inset) clamp(2.5rem, 5vw, 4rem); }

.chapter{ position: relative; }

/* .chapter__pin is what actually lays out the media/panel split; .chapter
   itself only exists to give that pin scroll room. Below 861px there is
   no reliable way to fit full panel copy inside a height-clipped pinned
   box, so the pin is only engaged at 861px+ (see the block near the
   bottom of this section) and .chapter__pin is a plain, un-pinned grid
   row everywhere below that. */
.chapter__pin{
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  min-height: 88vh;
}
.chapter__media{ position: relative; overflow: hidden; background: var(--ink); }
.chapter__media img{ width: 100%; height: 100%; object-fit: cover; }

.chapter__panel{
  background: var(--taupe-panel);
  color: var(--white);
  display: flex;
  flex-direction: column;
  padding: clamp(2rem, 5vw, 5.5rem);

  /* Put the panel's TEXT on the same 1400px column as the header and every
     other section, while the taupe field itself still bleeds to the screen
     edge. --content-inset resolves its 100% against the element, which here
     is only half the viewport — but because the panel is exactly half,
     (100vw - content-max)/2 reduces to (100% - content-max/2). */
  --panel-inset: max(var(--gutter), calc(100% - var(--content-max) / 2));
}
/* The panel's OUTER edge (the one facing the screen edge) carries the inset;
   the inner edge, at the seam with the photograph, keeps its design padding. */
.chapter:not(.chapter--reverse) .chapter__panel{ padding-right: var(--panel-inset); }
.chapter--reverse .chapter__panel{ padding-left: var(--panel-inset); }
.chapter--reverse .chapter__media{ order: 2; }
.chapter--reverse .chapter__panel{ order: 1; }

.chapter__label{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: clamp(1.25rem, 1.8vw, 1.75rem);
  /* Follows the printed report, which sets these labels in a lighter blue
     than the brand colour. 2.83:1 on the panel — short of the 3:1 bar for
     large text, so still logged in tools/contrast-check.py, but far better
     than the 1.78:1 the brand blue gave here. */
  color: var(--blue-light);
  text-align: right;
  margin-bottom: clamp(2rem, 5vw, 4rem);
}
.chapter__title{
  font-size: var(--fs-chapter);
  line-height: var(--lh-snug);
  color: var(--white);
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
  max-width: 16ch;
}
.chapter__body{
  font-family: var(--font-serif);
  font-size: var(--fs-lead);
  line-height: var(--lh-body);
  color: var(--white);
  max-width: 44ch;
}
.chapter__cta{ margin-top: 0; padding-top: clamp(1.75rem, 3vw, 2.5rem); }   /* follows the text, not the panel foot */

@media (max-width: 860px){
  .chapter__pin{ grid-template-columns: 1fr; min-height: 0; }
  .chapter__media{ min-height: 56vh; }
  .chapter--reverse .chapter__media{ order: 0; }
  .chapter--reverse .chapter__panel{ order: 0; }
  /* Stacked: the panel spans the full width, so use the normal inset. */
  .chapter__panel,
  .chapter:not(.chapter--reverse) .chapter__panel,
  .chapter--reverse .chapter__panel{ padding-inline: var(--content-inset); }
  .chapter__label{ margin-bottom: 1.5rem; }
  .chapter__cta{ padding-top: 2rem; }
}

/* ---------------------------------------------------------
   Chapters — pin + stack (861px+)

   Borrowed from the 2024 site's Chapters section
   (sites.ungeneva.org/annualreport/2024): each chapter pins full-height
   while the page scrolls past it, and the next chapter's opaque panel
   slides up to cover it — no z-index needed, later DOM order already
   paints on top. .chapter is given extra height above .chapter__pin's
   own so there is scroll distance for the pin to hold before the next
   chapter's box arrives. The entrance zoom that plays while a chapter
   pins in is in motion.css, in the same 861px+ block.
   --------------------------------------------------------- */
@media (min-width: 861px){
  /* 140vh against an 88vh pin leaves roughly half a screen of hold:
     enough for the pin to register, short of feeling stuck. At 180vh
     it held for 92vh, a full extra screen of motionless scrolling. */
  .chapter{ min-height: 140vh; }
  .chapter__pin{
    position: sticky;
    top: 0;
    overflow: hidden;
  }
}

/* ---------------------------------------------------------
   2025 in Numbers
   Follows the printed spread: large two-tone icon, heading in ink, then
   running prose with the figures picked out in blue, and a short taupe
   rule closing each statement. No rule between the columns — the line on
   the spread is the fold, not a design element.
   --------------------------------------------------------- */
.numbers{
  background: var(--paper);
  padding-block: clamp(4rem, 9vw, 8rem);
}
.numbers__grid{ padding-inline: var(--content-inset); }
.numbers__head{
  margin-inline: var(--content-inset);
  margin-block-end: clamp(2.5rem, 6vw, 4.5rem);
}
.numbers__cta{
  margin-inline: var(--content-inset);
  margin-block-start: clamp(.5rem, 1.5vw, 1rem);
}

/* A real grid rather than multi-column: multicol packs each column on its
   own, so headings and body copy land at different heights across a row.
   Row spacing is 0 here and lives under each closing rule instead, so the
   subgrid below can't pick up a gap between its own bands. */
.numbers__grid{
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: clamp(2.5rem, 5vw, 4.5rem);
  row-gap: 0;
}
@media (min-width: 1250px){
  .numbers__grid{ grid-template-columns: repeat(3, 1fr); }
}

/* Each entry hands its three bands — icon, heading, prose — up to the parent
   grid via subgrid, so headings sit on one line and body copy on another
   right across the row, however tall the icon or heading happens to be.
   Without subgrid support the entry still spans its three tracks and simply
   falls back to its own flow. No padding or border on .stat: either would
   offset its tracks from the parent's and undo the alignment. */
.stat{
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
}

/* Bottom-aligned, so the optically-scaled icons share a baseline and the
   gap down to the heading is identical in every entry. */
.stat__icon{
  align-self: end;
  width: calc(clamp(96px, 11vw, 168px) * var(--icon-scale, 1));
  aspect-ratio: 1;
  overflow: hidden;
  margin-bottom: clamp(.9rem, 1.8vw, 1.4rem);
}
/* `contain` centres the artwork in the square box, which leaves the short,
   wide icons floating. Anchoring to the bottom lands every artwork on the
   same baseline — the viewBoxes are all tight, so the visible ink aligns,
   not just the box. */
.stat__icon img{
  width: 100%;
  height: 100%;
  object-fit: contain;
  object-position: bottom;
}

/* Optical sizing. The icons carry different amounts of internal whitespace,
   so a single box size makes some read heavy and others light. These few are
   nudged to match the rest by eye. Scaling the BOX rather than the image
   keeps the heading below it clear, and the default stays 1. */
.stat__icon[data-icon="NGO"],
.stat__icon[data-icon="Library-and-Archives"]{ --icon-scale: .8; }

.stat__icon[data-icon="Peace"],
.stat__icon[data-icon="Security-and-Safety"]{ --icon-scale: 1.2; }

/* 1.2 x 1.2 - the chain artwork is drawn much smaller inside its viewBox
   than the rest, so it needs a second nudge to carry the same weight. */
.stat__icon[data-icon="Conference-on-Disarmament"]{ --icon-scale: 1.44; }

/* Heading: Frutiger semibold in ink (600 is the kit's maximum). */
.stat__label{
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: clamp(1.05rem, 1.35vw, 1.25rem);
  line-height: 1.25;
  letter-spacing: -.005em;
  color: var(--ink);
  margin-bottom: .7rem;
  max-width: 24ch;
}

/* Running prose, figures inline — as the print sets it. */
.stat__text{
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  line-height: 1.55;
  color: var(--ink-soft);
}
.stat__num{
  font-family: var(--font-serif);
  font-weight: 700;
  font-size: 1.35em;
  line-height: 1;
  color: var(--blue);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.stat__unit{ font-family: var(--font-serif); }

/* The short dash that closes each statement on the printed page. */
/* Sits inside .stat__text so it stays welded to its own sentence rather
   than being pushed down to clear the longest one in the row. Its bottom
   margin is what separates one row of entries from the next. */
.stat__rule{
  display: block;
  width: 26px;
  height: 1px;
  background: var(--taupe);
  margin-top: clamp(1rem, 2vw, 1.4rem);
  margin-bottom: clamp(2.5rem, 5vw, 3.75rem);
}

@media (max-width: 900px){
  .numbers__grid{ grid-template-columns: 1fr; }
}
@media (max-width: 560px){
  .stat__icon{ width: calc(84px * var(--icon-scale, 1)); }
}

/* ---------------------------------------------------------
   Highlights gallery — full bleed, tight gutter
   --------------------------------------------------------- */
.gallery{ background: var(--white); }   /* no bottom padding: the closing band sits flush */
.gallery__head{ padding: clamp(4rem, 9vw, 8rem) var(--content-inset) clamp(2rem, 4vw, 3rem); }

.gallery__grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: clamp(150px, 19vw, 280px);
  gap: 3px;
}
.gallery__item{
  position: relative;
  overflow: hidden;
  padding: 0;
  width: 100%; height: 100%;
  background: var(--ink);
  display: block;
}
.gallery__item img{ width: 100%; height: 100%; object-fit: cover; }
.gallery__item::after{
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(4,12,18,.8) 0%, rgba(4,12,18,0) 55%);
  opacity: 0;
  transition: opacity var(--dur-s) var(--ease-out);
}
.gallery__item:hover::after,
.gallery__item:focus-visible::after{ opacity: 1; }
.gallery__caption{
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 1;
  padding: 1rem;
  color: var(--white);
  font-family: var(--font-display);
  font-size: .78rem;
  line-height: 1.45;
  text-align: left;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity var(--dur-s) var(--ease-out), transform var(--dur-s) var(--ease-out);
}
.gallery__item:hover .gallery__caption,
.gallery__item:focus-visible .gallery__caption{ opacity: 1; transform: none; }

/* Editorial rhythm: two hero tiles per twelve */
.gallery__item:nth-child(12n+1){ grid-column: span 2; grid-row: span 2; }
.gallery__item:nth-child(12n+8){ grid-column: span 2; grid-row: span 2; }

/* Touch devices can't hover — keep captions visible */
@media (hover: none){
  .gallery__item::after{ opacity: 1; }
  .gallery__caption{ opacity: 1; transform: none; }
}
@media (max-width: 900px){
  .gallery__grid{ grid-template-columns: repeat(2, 1fr); }
  .gallery__item:nth-child(12n+1),
  .gallery__item:nth-child(12n+8){ grid-column: span 2; grid-row: span 1; }
}
@media (max-width: 560px){
  .gallery__grid{ grid-template-columns: 1fr; grid-auto-rows: 240px; }
  .gallery__item:nth-child(12n+1),
  .gallery__item:nth-child(12n+8){ grid-column: span 1; }
}

/* ---------------------------------------------------------
   Lightbox — native <dialog> (free focus trap + inert bg)
   --------------------------------------------------------- */
.lightbox{
  border: 0;
  padding: 0;
  max-width: 100vw;
  max-height: 100vh;
  width: 100vw;
  height: 100vh;
  background: transparent;
  color: var(--white);
  overflow: hidden;
}
.lightbox::backdrop{ background: rgba(4, 10, 14, .97); backdrop-filter: blur(6px); }
.lightbox__inner{
  position: relative;
  height: 100%;
  display: grid;
  place-items: center;
  padding: clamp(3.5rem, 7vw, 5rem) clamp(3.5rem, 8vw, 7rem);
}
.lightbox__figure{
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
  max-width: min(1100px, 100%);
  max-height: 100%;
}
.lightbox__figure img{
  max-height: 62vh;
  width: auto;
  max-width: 100%;
  margin-inline: auto;
  object-fit: contain;
}
.lightbox__figure figcaption{ max-width: 80ch; margin-inline: auto; }
.lightbox__caption{ font-family: var(--font-serif); font-size: 1rem; line-height: 1.6; }
.lightbox__credit{ color: rgba(255,255,255,.72); font-size: .85rem; font-style: italic; margin-top: .5rem; }
.lightbox__count{
  font-family: var(--font-display);
  color: var(--blue);
  font-size: .72rem;
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* Counter and Share share one row under the caption. */
.lightbox__meta{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: .9rem;
}

/* --- Share --- */
.lightbox__share{ position: relative; flex-shrink: 0; }
.share-btn{
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  padding: .5rem 1.05rem;
  border: 1px solid rgba(255,255,255,.55);
  border-radius: 999px;
  color: var(--white);
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: .8125rem;
  letter-spacing: .04em;
  transition: background var(--dur-s) var(--ease-out), border-color var(--dur-s) var(--ease-out);
}
.share-btn:hover,
.share-btn[aria-expanded="true"]{ background: rgba(255,255,255,.14); border-color: var(--white); }

/* Opens upwards from the button so it never runs off the bottom edge. */
.share-panel{
  position: absolute;
  right: 0;
  bottom: calc(100% + .6rem);
  width: 15rem;
  padding: .45rem;
  background: #111820;
  border: 1px solid rgba(255,255,255,.18);
  border-radius: 10px;
  box-shadow: 0 18px 40px rgba(0,0,0,.45);
  z-index: 2;
  text-align: left;
}
.share-panel[hidden]{ display: none; }
.share-panel__title{
  font-family: var(--font-display);
  font-size: .72rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(255,255,255,.72);
  padding: .45rem .6rem .3rem;
}
.share-panel__list{ list-style: none; margin: 0; padding: 0; }
.share-panel__item{
  display: flex;
  align-items: center;
  gap: .7rem;
  width: 100%;
  min-height: 44px;
  padding: .5rem .6rem;
  border-radius: 6px;
  color: var(--white);
  text-decoration: none;
  font-family: var(--font-display);
  font-size: .9375rem;
  text-align: left;
  transition: background var(--dur-xs) var(--ease-out);
}
.share-panel__item:hover,
.share-panel__item:focus-visible{ background: rgba(255,255,255,.1); }
.share-panel__item svg{ flex-shrink: 0; }
.share-panel__item.is-done svg{ color: var(--blue); }   /* "Link copied" confirmation */

/* "Copy link" is also the route to platforms with no web share endpoint —
   Instagram above all, which offers no share URL at all. The hint says so
   rather than pretending there is an Instagram button. Regular weight and
   stacked under the label: it is an aside, not a second label, and the
   menu is only 15rem wide. Hidden while the button reads "Link copied". */
.share-panel__text{
  display: flex;
  flex-direction: column;
  gap: .1rem;
  min-width: 0;
}
.share-panel__hint{
  font-weight: var(--fw-regular);
  font-size: .75rem;
  line-height: 1.3;
  color: rgba(255,255,255,.72);
}
.share-panel__item.is-done .share-panel__hint{ display: none; }
.lightbox__close,
.lightbox__nav{
  position: absolute;
  background: rgba(255,255,255,.1);
  color: var(--white);
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  transition: background var(--dur-s) var(--ease-out);
}
.lightbox__close:hover, .lightbox__nav:hover{ background: rgba(255,255,255,.25); }
.lightbox__close{ top: clamp(1rem,3vw,2rem); right: clamp(1rem,3vw,2rem); width: 46px; height: 46px; }
.lightbox__nav{ top: 50%; transform: translateY(-50%); width: 48px; height: 48px; }
.lightbox__nav--prev{ left: clamp(.5rem, 2vw, 1.75rem); }
.lightbox__nav--next{ right: clamp(.5rem, 2vw, 1.75rem); }
@media (max-width: 640px){
  .lightbox__nav{ top: auto; bottom: 1rem; transform: none; width: 44px; height: 44px; }
  .lightbox__figure img{ max-height: 48vh; }
}

/* ---------------------------------------------------------
   Closing band
   --------------------------------------------------------- */
.closing{
  background: var(--taupe-panel);
  color: var(--white);
  padding: clamp(4rem, 9vw, 7.5rem) var(--content-inset);
  text-align: center;
}
.closing__title{
  font-size: var(--fs-section);
  line-height: var(--lh-tight);
  color: var(--white);
  max-width: 22ch;
  margin-inline: auto;
  margin-bottom: 1rem;
  text-wrap: balance;
}
.closing__text{
  font-family: var(--font-serif);
  font-size: var(--fs-lead);
  color: rgba(255,255,255,.92);   /* 4.86:1 on --taupe-panel; .82 would be 4.25:1 */
  max-width: 52ch;
  margin-inline: auto;
  margin-bottom: 2.5rem;
}
.closing__actions{ display: flex; flex-wrap: wrap; gap: 1rem; justify-content: center; }

/* ---------------------------------------------------------
   Footer
   --------------------------------------------------------- */
.site-footer{ background: var(--ink); color: var(--white); padding: clamp(2.5rem, 5vw, 3.5rem) var(--content-inset); }
.site-footer__inner{
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.75rem;
}
.site-footer__logo{ height: 40px; width: auto; filter: brightness(0) invert(1); }
.site-footer__social{ display: flex; gap: .5rem; margin-inline: -.25rem; }
.site-footer__social a{
  color: rgba(255,255,255,.8);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px; height: 32px;    /* WCAG 2.2 2.5.8 */
  transition: color var(--dur-s) var(--ease-out);
}
.site-footer__social a:hover{ color: var(--blue); }
.site-footer__legal{
  display: flex; flex-wrap: wrap;
  gap: .75rem 1.75rem;
  font-family: var(--font-display);
  font-size: var(--fs-label);
}
.site-footer__legal a{
  color: rgba(255,255,255,.78);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  min-height: 24px;             /* WCAG 2.2 2.5.8 */
}
.site-footer__legal a:hover{ color: var(--white); text-decoration: underline; }

/* ---------------------------------------------------------
   Scroll progress
   --------------------------------------------------------- */
.scroll-progress{
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  background: var(--blue);
  transform-origin: 0 50%;
  transform: scaleX(0);
  z-index: 950;
}

/* ---------------------------------------------------------
   Increased-contrast preference
   --------------------------------------------------------- */
@media (prefers-contrast: more){
  :root{
    --ink-soft: #1F2325;
    --ink-muted: #33383A;
    --taupe-dark: #554F42;
    --taupe-panel: #5F5A4D;
    --line: rgba(22,25,28,.32);
  }
  .hero__scrim{ background: linear-gradient(0deg, rgba(0,0,0,.92) 0%, rgba(0,0,0,.6) 50%, rgba(0,0,0,.35) 100%); }
  .btn{ border-color: currentColor; }
}
