/* ══════════════════════════════════════════════════════════════════════════
   Pre-COP31 — the public homepage.

   Loaded on one route only. precop.css supplies the identity (the palette, the
   masi geometry, the shared chrome); this file supplies the *composition*: the
   layered ocean hero, the wave transitions between sections, the programme
   rail and the illustration set.

   Three rules held throughout:

     1. Depth comes from layers moving at different speeds, not from shadows.
        The hero is six planes deep and each one moves at its own rate.

     2. Motion is atmospheric or it is absent. Waves drift, light breathes,
        particles rise. Nothing bounces, spins or demands attention, because a
        page a Minister's office opens should feel composed, not eager.

     3. Every section transition is a curve. Straight horizontal joins between
        full-width bands are what makes a page read as a stack of templates.

   All of it is gated: motion sits behind prefers-reduced-motion, reveals sit
   behind .pc-js, and the whole document is readable with neither.
   ══════════════════════════════════════════════════════════════════════════ */

/* ───────────────────────────── Foundations ───────────────────────────── */

.hp {
  --ink-on-ocean:  #ffffff;
  --ocean-1: #02132b;      /* deep water, the top of the sky */
  --ocean-2: #062a5c;
  --ocean-3: #0a4b96;
  --ocean-4: #0d6fc4;      /* the horizon */
  --ocean-5: #1f93d6;
  --reef-glow: rgba(0, 176, 88, .42);

  --shell: clamp(1.1rem, 4vw, 2.2rem);
  overflow-x: clip;         /* decoration can overhang; the page never scrolls sideways */
}

/* Section rhythm. Generous, and never the same twice in a row — equal spacing
   between every band is the other half of what makes a page look templated. */
.hp-section { position: relative; padding: clamp(3.5rem, 8vw, 7rem) 0; }
.hp-section-tight { padding: clamp(2.4rem, 5vw, 4rem) 0; }

.hp-eyebrow {
  display: inline-flex; align-items: center; gap: .55rem;
  font-size: .7rem; font-weight: 800; letter-spacing: .2em; text-transform: uppercase;
  color: var(--brand); margin-bottom: .9rem;
}
.hp-eyebrow::before {
  content: ''; width: 1.9rem; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--brand), var(--reef-2));
}
.hp-eyebrow-light { color: rgba(255,255,255,.86); }
.hp-eyebrow-light::before { background: linear-gradient(90deg, #fff, var(--reef-2)); }

.hp-h2 {
  font-size: clamp(1.85rem, 4.2vw, 3.15rem);
  font-weight: 800; letter-spacing: -.035em; line-height: 1.05;
  margin: 0 0 .8rem;
}
.hp-lede {
  font-size: clamp(1rem, 1.35vw, 1.14rem); line-height: 1.65;
  color: var(--muted); max-width: 38rem;
}
.hp-on-ocean .hp-h2   { color: #fff; }
.hp-on-ocean .hp-lede { color: rgba(255,255,255,.78); }

/* ═════════════════════════════════ HERO ═══════════════════════════════ */

.hp-hero {
  position: relative;
  /* Sized so the whole composition — marks, title, copy, buttons, and the
     first crest of the wave — lands inside one screen. A hero taller than the
     viewport hides its own best moment below the fold. */
  min-height: min(100svh, 54rem);
  display: flex; flex-direction: column; justify-content: center;
  isolation: isolate; overflow: hidden;
  padding: clamp(6rem, 11vh, 8rem) 0 clamp(6.5rem, 13vh, 9.5rem);
  color: var(--ink-on-ocean);
  background: linear-gradient(178deg,
              var(--ocean-1) 0%, var(--ocean-2) 26%, var(--ocean-3) 58%,
              var(--ocean-4) 84%, var(--ocean-5) 100%);
}

/* — Layer 1 · atmosphere ————————————————————————————————
   Two slow lights: a cold one high and left, a warm reef-green one low and
   right. They breathe out of phase, which is what stops a static gradient
   from reading as a flat printed panel. */
.hp-glow {
  position: absolute; inset: -20% -10%; z-index: -6; pointer-events: none;
  background:
    radial-gradient(38rem 26rem at 18% 14%, rgba(120, 200, 255, .30), transparent 68%),
    radial-gradient(44rem 30rem at 86% 74%, var(--reef-glow), transparent 66%);
  animation: hpBreathe 16s ease-in-out infinite alternate;
}
@keyframes hpBreathe {
  from { opacity: .75; transform: scale(1) translate3d(0, 0, 0); }
  to   { opacity: 1;   transform: scale(1.07) translate3d(-1.5%, 1.5%, 0); }
}

/* — Layer 2 · masi cloth, drifting —————————————————————————
   The tapa geometry from the identity layer, laid as a runner down the left
   the way a masi actually hangs, and drifting slowly upward. */
.hp-tapa {
  position: absolute; inset: -10% 0; z-index: -5; pointer-events: none;
  background-image: var(--tapa); background-size: 148px 148px;
  opacity: .3;
  animation: hpDrift 60s linear infinite;
  -webkit-mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.35) 42%, transparent 72%);
          mask-image: linear-gradient(105deg, #000 0%, rgba(0,0,0,.35) 42%, transparent 72%);
}
@keyframes hpDrift {
  from { background-position: 0 0; }
  to   { background-position: 148px -296px; }
}

/* — Layer 3 · particles ————————————————————————————————
   Sea spray. Positions and timings come from the template as custom
   properties, so the field is deterministic — the same page every load, no
   random-number generator running in the browser. */
.hp-particles { position: absolute; inset: 0; z-index: -4; pointer-events: none; overflow: hidden; }
.hp-particle {
  position: absolute; left: var(--x); top: var(--y);
  width: var(--s); height: var(--s); border-radius: 50%;
  background: radial-gradient(circle at 32% 30%, rgba(255,255,255,.95), rgba(150,220,255,.15) 70%);
  opacity: 0;
  animation: hpFloat var(--d) ease-in-out var(--delay) infinite;
}
@keyframes hpFloat {
  0%   { opacity: 0;   transform: translate3d(0, 18px, 0) scale(.7); }
  18%  { opacity: .85; }
  70%  { opacity: .5; }
  100% { opacity: 0;   transform: translate3d(var(--dx, 14px), -78px, 0) scale(1.15); }
}

/* — Layer 4 · islands ——————————————————————————————————
   The horizon. Sits behind the copy and ahead of the cloth, and moves at a
   third of scroll speed so the hero opens up as the reader leaves it. */
.hp-islands {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: -3;
  pointer-events: none; line-height: 0;
  will-change: transform;
}
.hp-islands svg { display: block; width: 100%; height: auto; }

/* — Layer 5 · the wave stack ————————————————————————————
   Three bands, each a doubled path translating a full half of its own width,
   so the loop is seamless. Different speeds and different opacities is the
   whole trick: one wave reads as decoration, three read as water. */
.hp-waves {
  position: absolute; left: 0; right: 0; bottom: -1px; z-index: -2;
  line-height: 0; pointer-events: none;
}
.hp-wave { display: block; width: 200%; height: clamp(64px, 9vw, 132px); }
.hp-wave + .hp-wave { position: absolute; left: 0; bottom: 0; }
.hp-wave-anim { animation: hpWave var(--dur, 22s) linear infinite; }
@keyframes hpWave {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* — Layer 6 · content ——————————————————————————————————— */
.hp-hero-inner { position: relative; z-index: 1; }

.hp-hero-marks { margin-bottom: clamp(1.4rem, 3vw, 2.2rem); }
.hp-hero-marks .arms  { height: clamp(3rem, 5vw, 4.2rem); }
.hp-hero-marks .event { height: clamp(2.6rem, 4.2vw, 3.6rem); }

.hp-hero-dates {
  display: inline-flex; align-items: center; gap: .6rem;
  font-size: clamp(.72rem, 1.1vw, .84rem); font-weight: 800;
  letter-spacing: .26em; text-transform: uppercase;
  color: rgba(255,255,255,.9); margin-bottom: 1rem;
}
.hp-hero-dates .dot {
  width: .42rem; height: .42rem; border-radius: 50%; background: var(--reef-2);
  box-shadow: 0 0 0 0 rgba(0,176,88,.7);
  animation: hpPulse 2.6s ease-out infinite;
}
@keyframes hpPulse {
  0%   { box-shadow: 0 0 0 0 rgba(0,176,88,.65); }
  70%  { box-shadow: 0 0 0 .7rem rgba(0,176,88,0); }
  100% { box-shadow: 0 0 0 0 rgba(0,176,88,0); }
}

.hp-hero-title {
  font-size: clamp(2.9rem, 8.4vw, 6.6rem);
  font-weight: 800; letter-spacing: -.055em; line-height: .9;
  margin: 0 0 .5rem; color: #fff;
  text-shadow: 0 18px 60px rgba(2, 16, 40, .5);
}
.hp-hero-title .thin {
  display: block; font-weight: 300; letter-spacing: -.02em;
  font-size: .3em; line-height: 1.15; margin-top: .38em; max-width: 20em;
  color: rgba(255,255,255,.9);
}
.hp-hero-lede {
  font-size: clamp(.98rem, 1.35vw, 1.14rem); line-height: 1.6;
  color: rgba(255,255,255,.84); max-width: 33rem; margin: 1.15rem 0 0;
}
.hp-hero-where {
  display: flex; align-items: center; gap: .55rem; flex-wrap: wrap;
  color: rgba(255,255,255,.76); margin-top: .9rem; font-size: .96rem;
}

/* Buttons. The primary is white on the ocean — the highest contrast available
   without inventing a colour that is not in the mark. */
.hp-cta { display: flex; flex-wrap: wrap; gap: .7rem; margin-top: clamp(1.6rem, 3.5vw, 2.4rem); }
.hp-btn {
  display: inline-flex; align-items: center; gap: .55rem;
  padding: .82rem 1.5rem; border-radius: 999px; border: 1.5px solid transparent;
  font-weight: 700; font-size: .96rem; text-decoration: none; cursor: pointer;
  transition: transform .24s cubic-bezier(.22,1,.36,1), box-shadow .24s ease,
              background .24s ease, border-color .24s ease, color .24s ease;
}
.hp-btn i, .hp-btn svg { transition: transform .28s cubic-bezier(.22,1,.36,1); }
.hp-btn:hover, .hp-btn:focus-visible { transform: translateY(-2.5px); }
.hp-btn:focus-visible { outline: 3px solid var(--reef-2); outline-offset: 3px; }

.hp-btn-primary {
  background: #fff; color: var(--brand-deep);
  box-shadow: 0 12px 30px -12px rgba(0, 20, 60, .8);
}
.hp-btn-primary:hover { color: var(--brand-deep); box-shadow: 0 18px 40px -14px rgba(0,20,60,.9); }
.hp-btn-primary:hover i { transform: translateX(3px); }

.hp-btn-ghost {
  background: rgba(255,255,255,.1); color: #fff; border-color: rgba(255,255,255,.4);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.hp-btn-ghost:hover { background: rgba(255,255,255,.2); border-color: #fff; color: #fff; }

.hp-btn-solid {
  background: linear-gradient(130deg, var(--brand-2), var(--brand));
  color: #fff; box-shadow: 0 12px 28px -12px rgba(0,60,150,.8);
}
.hp-btn-solid:hover { color: #fff; }
.hp-btn-solid:hover i { transform: translateX(3px); }

/* Scroll cue — a vertical rule with a bead running down it. */
.hp-cue {
  position: absolute; left: 50%; bottom: clamp(4.5rem, 9vw, 7rem);
  transform: translateX(-50%); z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: .6rem;
  color: rgba(255,255,255,.6); font-size: .62rem;
  letter-spacing: .24em; text-transform: uppercase; font-weight: 700;
}
.hp-cue-rail {
  width: 1px; height: 3rem; background: rgba(255,255,255,.28); position: relative; overflow: hidden;
}
.hp-cue-rail::after {
  content: ''; position: absolute; left: -1px; width: 3px; height: 1.1rem; border-radius: 3px;
  background: linear-gradient(180deg, transparent, var(--reef-2), transparent);
  animation: hpCue 2.4s cubic-bezier(.6,0,.4,1) infinite;
}
@keyframes hpCue {
  0%   { transform: translateY(-1.2rem); opacity: 0; }
  35%  { opacity: 1; }
  100% { transform: translateY(3rem);    opacity: 0; }
}

/* ══════════════════════ STAT RIBBON — on the water ════════════════════
   The counts sit in the trough between the hero's waves and the first band
   of content, half in each. Boxing them would have made a fifth row of
   rectangles; letting them straddle the join makes the two sections one
   composition instead of two stacked ones. */

.hp-ribbon {
  position: relative; z-index: 2;
  margin-top: clamp(-4.5rem, -7vw, -6.5rem);
  padding-bottom: clamp(1.5rem, 4vw, 2.5rem);
}
.hp-ribbon-grid {
  display: grid; grid-template-columns: repeat(4, 1fr);
  gap: clamp(.6rem, 2vw, 1.6rem);
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.4);
          backdrop-filter: blur(18px) saturate(1.4);
  border: 1px solid color-mix(in srgb, var(--brand) 14%, transparent);
  border-radius: clamp(16px, 2.5vw, 26px);
  padding: clamp(1.2rem, 3vw, 2rem) clamp(1rem, 3vw, 2.4rem);
  box-shadow: 0 30px 70px -34px rgba(2, 26, 62, .55);
}
.hp-stat { text-align: center; position: relative; }
.hp-stat + .hp-stat::before {
  content: ''; position: absolute; left: calc(-1 * clamp(.3rem, 1vw, .8rem)); top: 12%; bottom: 12%;
  width: 1px; background: var(--line);
}
.hp-stat-value {
  font-size: clamp(1.7rem, 4.4vw, 3.1rem); font-weight: 800;
  letter-spacing: -.05em; line-height: 1;
  background: linear-gradient(135deg, var(--brand-deep), var(--brand-2) 60%, var(--reef));
  -webkit-background-clip: text; background-clip: text; color: transparent;
  font-variant-numeric: tabular-nums;
}
.hp-stat-label {
  margin-top: .45rem; font-size: clamp(.62rem, 1.1vw, .74rem); font-weight: 700;
  letter-spacing: .13em; text-transform: uppercase; color: var(--muted);
}

/* ═══════════════════════════ ANNOUNCEMENTS ════════════════════════════
   Rendered only when the Ministry has published something. An empty
   "latest news" panel on a conference homepage says the conference is not
   happening. */
.hp-notice {
  display: grid; grid-template-columns: auto 1fr auto; gap: 1rem; align-items: start;
  padding: 1.15rem 1.3rem; border-radius: var(--radius);
  background: var(--surface); border: 1px solid var(--line);
  border-left: 4px solid var(--nc, var(--brand));
  transition: transform .3s cubic-bezier(.22,1,.36,1), box-shadow .3s ease;
}
.hp-notice:hover { transform: translateX(4px); box-shadow: var(--shadow); }
.hp-notice.urgent    { --nc: var(--coral); }
.hp-notice.important { --nc: #d97706; }
.hp-notice.notice    { --nc: var(--brand); }
.hp-notice.info      { --nc: var(--brand-2); }
.hp-notice-icon {
  width: 2.3rem; height: 2.3rem; border-radius: 10px; flex: none;
  display: grid; place-items: center; color: var(--nc);
  background: color-mix(in srgb, var(--nc) 12%, transparent);
}
.hp-notice-title { font-weight: 700; margin-bottom: .15rem; }
.hp-notice-when  { color: var(--muted); font-size: .8rem; white-space: nowrap; }

/* ══════════════════ THE PACIFIC IS AT THE HEART ═══════════════════════
   An asymmetric composition: the illustration takes the wider column and
   overhangs its grid cell, the facts orbit it. Deliberately not a
   two-equal-columns text-and-picture row. */

.hp-pacific {
  background:
    radial-gradient(60rem 40rem at 85% 10%, color-mix(in srgb, var(--brand-2) 9%, transparent), transparent 62%),
    var(--surface-2);
}
.hp-pacific-grid {
  display: grid; grid-template-columns: 1.15fr .85fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
}


.hp-fact { display: flex; gap: 1rem; padding: 1.1rem 0; border-bottom: 1px solid var(--line); }
.hp-fact:last-child { border-bottom: 0; }
.hp-fact-mark {
  width: 2.7rem; height: 2.7rem; flex: none; border-radius: 12px;
  display: grid; place-items: center;
  background: linear-gradient(140deg,
              color-mix(in srgb, var(--brand) 12%, transparent),
              color-mix(in srgb, var(--reef-2) 14%, transparent));
  color: var(--brand);
}
.hp-fact-title { font-weight: 700; margin-bottom: .15rem; }
.hp-fact-text  { color: var(--muted); font-size: .93rem; line-height: 1.55; }

/* ════════════════════ PROGRAMME — the cinematic rail ══════════════════
   A horizontal, snapping rail rather than a grid of cards. The programme is
   a sequence in time, so it reads along an axis; a 3 × 2 grid of identical
   boxes throws that away and looks like every other conference site. */

.hp-rail-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 1.5rem; flex-wrap: wrap; margin-bottom: clamp(1.6rem, 3vw, 2.4rem);
}
.hp-rail-wrap { position: relative; }

/* Bleeds to the viewport edge so the last card is visibly cut off — the
   signal that the rail continues. Padding restores the container gutter. */
.hp-rail {
  display: flex; gap: clamp(.9rem, 2vw, 1.4rem);
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  padding: .5rem calc(50vw - min(50vw, 600px) + .25rem) 1.6rem;
  margin: 0 calc(50% - 50vw);
  scrollbar-width: thin; scrollbar-color: var(--brand) transparent;
}
.hp-rail::-webkit-scrollbar { height: 6px; }
.hp-rail::-webkit-scrollbar-track { background: var(--line); border-radius: 6px; }
.hp-rail::-webkit-scrollbar-thumb { background: var(--brand); border-radius: 6px; }

.hp-ev {
  flex: 0 0 clamp(16rem, 27vw, 20.5rem); scroll-snap-align: start;
  position: relative; display: flex; flex-direction: column;
  padding: 1.4rem; border-radius: 20px; text-decoration: none;
  background: var(--surface); border: 1px solid var(--line);
  overflow: hidden; isolation: isolate;
  transition: transform .34s cubic-bezier(.22,1,.36,1), box-shadow .34s ease,
              border-color .34s ease;
}
/* The type colour washes up from the foot on hover — the card's own accent
   arriving, rather than a generic grey lift. */
.hp-ev::before {
  content: ''; position: absolute; inset: auto 0 0 0; height: 100%; z-index: -1;
  background: linear-gradient(0deg, color-mix(in srgb, var(--evc, var(--brand)) 13%, transparent), transparent 55%);
  opacity: 0; transition: opacity .34s ease;
}
.hp-ev:hover, .hp-ev:focus-visible {
  transform: translateY(-6px);
  box-shadow: 0 26px 50px -26px rgba(2, 30, 70, .5);
  border-color: color-mix(in srgb, var(--evc, var(--brand)) 40%, transparent);
}
.hp-ev:hover::before, .hp-ev:focus-visible::before { opacity: 1; }

.hp-ev-date {
  display: flex; align-items: baseline; gap: .45rem; margin-bottom: .9rem;
  color: var(--evc, var(--brand)); font-weight: 800;
}
.hp-ev-day   { font-size: 2.1rem; line-height: .9; letter-spacing: -.05em; }
.hp-ev-month { font-size: .74rem; letter-spacing: .16em; text-transform: uppercase; }
.hp-ev-time  { margin-left: auto; font-size: .78rem; color: var(--muted); font-weight: 700; }

.hp-ev-title {
  font-size: 1.06rem; font-weight: 700; line-height: 1.35; color: var(--ink);
  margin: 0 0 .55rem;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.hp-ev-meta { font-size: .84rem; color: var(--muted); display: grid; gap: .28rem; }
.hp-ev-foot {
  margin-top: auto; padding-top: 1rem;
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
}
.hp-ev-type {
  font-size: .66rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--evc, var(--brand));
  background: color-mix(in srgb, var(--evc, var(--brand)) 12%, transparent);
  padding: .3rem .6rem; border-radius: 999px;
}
.hp-ev-state { font-size: .78rem; font-weight: 700; display: inline-flex; align-items: center; gap: .35rem; }
.hp-ev-state::before { content: ''; width: .45rem; height: .45rem; border-radius: 50%; background: currentColor; }
.hp-ev-state.open   { color: var(--reef); }
.hp-ev-state.wait   { color: #d97706; }
.hp-ev-state.closed { color: var(--muted); }
.hp-ev-go {
  position: absolute; right: 1.1rem; bottom: 1.1rem; opacity: 0;
  transform: translateX(-6px); transition: opacity .3s ease, transform .3s ease;
  color: var(--evc, var(--brand));
}
.hp-ev:hover .hp-ev-go, .hp-ev:focus-visible .hp-ev-go { opacity: 1; transform: none; }

/* ═══════════════════════ PILLARS — offset stack ═══════════════════════
   Five items in a three-column grid, with the second row nudged down and
   inward. An even grid of five leaves a hole; an offset one reads as a
   deliberate arrangement. */
.hp-pillars-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2.4vw, 1.6rem);
}
.hp-pillar {
  position: relative; display: block; text-decoration: none;
  padding: clamp(1.4rem, 2.6vw, 2rem); border-radius: 20px;
  background: var(--surface); border: 1px solid var(--line); overflow: hidden;
  transition: transform .34s cubic-bezier(.22,1,.36,1), box-shadow .34s ease;
}
.hp-pillar:nth-child(4), .hp-pillar:nth-child(5) { margin-top: clamp(0rem, 2.5vw, 2rem); }
.hp-pillar::after {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: var(--pc, var(--brand)); transform: scaleX(0); transform-origin: left;
  transition: transform .42s cubic-bezier(.22,1,.36,1);
}
.hp-pillar:hover, .hp-pillar:focus-visible {
  transform: translateY(-5px); box-shadow: 0 24px 46px -26px rgba(2, 30, 70, .45);
}
.hp-pillar:hover::after, .hp-pillar:focus-visible::after { transform: scaleX(1); }
.hp-pillar-icon { color: var(--pc, var(--brand)); margin-bottom: 1rem; }
.hp-pillar-title { font-size: 1.08rem; font-weight: 700; color: var(--ink); margin: 0 0 .45rem; }
.hp-pillar-text  { font-size: .92rem; line-height: 1.6; color: var(--muted); margin: 0; }

/* ═══════════════ ONE PLATFORM, EVERY EVENT — the journey ══════════════
   The five steps a participant actually passes through, on a rail with a
   light travelling along it. The QR panel beside it assembles itself out of
   its own modules, which is a truer illustration of what the platform does
   than a stock icon of a QR code. */

.hp-journey {
  position: relative; color: #fff; overflow: hidden;
  background:
    radial-gradient(50rem 34rem at 88% 12%, rgba(0,176,88,.2), transparent 62%),
    linear-gradient(150deg, var(--ocean-1) 0%, var(--ocean-2) 45%, var(--ocean-3) 100%);
}
.hp-journey::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image: var(--tapa); background-size: 160px 160px; opacity: .2;
}
.hp-journey > .container { position: relative; z-index: 1; }

.hp-journey-grid {
  display: grid; grid-template-columns: .95fr 1.05fr;
  gap: clamp(2rem, 5vw, 4rem); align-items: center;
}

.hp-steps { position: relative; margin-top: 2rem; }
/* The rail behind the steps, and the light that runs down it. */
.hp-steps::before {
  content: ''; position: absolute; left: 1.35rem; top: 1.4rem; bottom: 1.4rem; width: 2px;
  background: linear-gradient(180deg, rgba(255,255,255,.1), rgba(255,255,255,.28), rgba(255,255,255,.1));
}
.hp-steps::after {
  content: ''; position: absolute; left: 1.25rem; top: 0; width: 4px; height: 4.5rem;
  border-radius: 4px; background: linear-gradient(180deg, transparent, var(--reef-2), transparent);
  filter: blur(1px);
  animation: hpRun 5.5s cubic-bezier(.55,0,.45,1) infinite;
}
@keyframes hpRun {
  0%   { transform: translateY(0);      opacity: 0; }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateY(calc(100% * 5)); opacity: 0; }
}

.hp-step { display: flex; gap: 1.15rem; padding: .85rem 0; position: relative; }
.hp-step-num {
  width: 2.7rem; height: 2.7rem; flex: none; border-radius: 50%;
  display: grid; place-items: center; font-weight: 800; font-size: .9rem;
  background: rgba(255,255,255,.1); border: 1.5px solid rgba(255,255,255,.28);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  position: relative; z-index: 1;
  transition: background .3s ease, border-color .3s ease, transform .3s ease;
}
.hp-step:hover .hp-step-num { background: var(--reef-2); border-color: var(--reef-2); transform: scale(1.08); }
.hp-step-title { font-weight: 700; color: #fff; margin-bottom: .1rem; }
.hp-step-text  { color: rgba(255,255,255,.72); font-size: .92rem; line-height: 1.55; }

/* The QR illustration. Modules fade in one after another, then the whole
   thing holds — an assembly, not a flicker. */
.hp-qr { position: relative; display: grid; place-items: center; }
.hp-qr svg { width: min(100%, 26rem); height: auto; overflow: visible; }
.hp-qr-mod { fill: #fff; opacity: .1; }
.hp-qr-anim { animation: hpQr 4.5s ease-in-out infinite; }
@keyframes hpQr {
  0%, 8%    { opacity: .1; }
  38%, 76%  { opacity: .95; }
  100%      { opacity: .1; }
}
.hp-qr-frame { fill: none; stroke: var(--reef-2); stroke-width: 2.5; stroke-linecap: round; }
.hp-qr-scan {
  fill: url(#hpScanGrad);
  animation: hpScan 3.6s cubic-bezier(.5,0,.5,1) infinite;
}
@keyframes hpScan {
  0%, 100% { transform: translateY(0); opacity: 0; }
  10%      { opacity: 1; }
  50%      { transform: translateY(180px); opacity: 1; }
  90%      { opacity: 0; }
}

/* ═════════════════ WHAT YOU CAN DO — illustrated cards ════════════════ */
.hp-do-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: clamp(1rem, 2.2vw, 1.5rem);
}
.hp-do {
  padding: clamp(1.5rem, 2.6vw, 2rem); border-radius: 20px;
  background: var(--surface); border: 1px solid var(--line);
  transition: transform .34s cubic-bezier(.22,1,.36,1), box-shadow .34s ease;
}
.hp-do:hover { transform: translateY(-5px); box-shadow: 0 24px 46px -26px rgba(2,30,70,.4); }
.hp-do-icon { margin-bottom: 1.1rem; color: var(--brand); }
.hp-do-title { font-size: 1.06rem; font-weight: 700; margin: 0 0 .4rem; color: var(--ink); }
.hp-do-text  { font-size: .93rem; line-height: 1.6; color: var(--muted); margin: 0; }

/* ═══════════════════════════ ICON SYSTEM ══════════════════════════════
   Line illustrations rather than a glyph font: they carry the palette, they
   scale to any size, and each one can animate the part of itself that
   actually means something — the wave moves, the ring pulses, the signal
   travels. Drawing animations run once when the card is revealed. */
.hp-ico { width: 3.1rem; height: 3.1rem; display: block; overflow: visible; }
.hp-ico .s { fill: none; stroke: currentColor; stroke-width: 1.7;
             stroke-linecap: round; stroke-linejoin: round; }
.hp-ico .f { fill: currentColor; }
.hp-ico .accent { stroke: var(--reef-2); }

/* Stroke-draw, triggered when the parent card is revealed. */
.pc-js [data-reveal] .hp-ico .draw { stroke-dasharray: 200; stroke-dashoffset: 200; }
.pc-js [data-reveal].is-in .hp-ico .draw {
  animation: hpDraw 1.5s cubic-bezier(.22,1,.36,1) forwards;
}
@keyframes hpDraw { to { stroke-dashoffset: 0; } }

.hp-ico .bob   { animation: hpBob 4.5s ease-in-out infinite; }
.hp-ico .bob-2 { animation: hpBob 4.5s ease-in-out .8s infinite; }
@keyframes hpBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2.2px); }
}
.hp-ico .spin { animation: hpSpin 18s linear infinite; transform-origin: 50% 50%; }
@keyframes hpSpin { to { transform: rotate(360deg); } }
.hp-ico .beat { animation: hpBeat 3.4s ease-in-out infinite; transform-origin: 50% 50%; }
@keyframes hpBeat {
  0%, 100% { transform: scale(1);    opacity: .85; }
  50%      { transform: scale(1.09); opacity: 1; }
}

/* ═════════════════════════════ PARTNERS ═══════════════════════════════
   A slow rail of the institutions taking part. Duplicated once in the
   markup and translated by exactly half, so it loops without a seam; paused
   on hover so a name can actually be read. */
.hp-partners { background: var(--surface-2); overflow: hidden; }
.hp-marquee {
  display: flex; width: max-content; gap: 0;
  animation: hpMarquee 62s linear infinite;
}
.hp-marquee:hover, .hp-marquee:focus-within { animation-play-state: paused; }
@keyframes hpMarquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
.hp-marquee-set { display: flex; gap: clamp(.7rem, 1.8vw, 1.2rem); padding-right: clamp(.7rem, 1.8vw, 1.2rem); }
.hp-partner {
  flex: none; display: flex; align-items: center; gap: .7rem;
  padding: .85rem 1.35rem; border-radius: 999px; white-space: nowrap;
  background: var(--surface); border: 1px solid var(--line);
  font-size: .9rem; font-weight: 600; color: var(--ink-2);
}
.hp-partner-tag {
  font-size: .62rem; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: var(--brand); background: var(--brand-soft);
  padding: .2rem .5rem; border-radius: 999px;
}
/* Fade the rail into the page at both ends rather than cutting it off. */
.hp-marquee-mask {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 7%, #000 93%, transparent);
}

/* ═══════════════════════ SECTION TRANSITIONS ══════════════════════════
   Curved joins between bands. A shared element so the shape is defined once
   and only the fill and flip change. */
.hp-curve { display: block; width: 100%; height: clamp(40px, 5vw, 84px); line-height: 0; }
.hp-curve.flip { transform: rotate(180deg); }

/* ══════════════════════════ RESPONSIVE ════════════════════════════════
   Not "stack everything". Each composition is re-thought at the width where
   it stops working: the rail keeps its horizontal axis (it is a phone's
   natural gesture), the stat ribbon goes two-up rather than four-across, the
   Pacific composition puts the illustration above the facts. */

@media (max-width: 74.99em) {
  .hp-pacific-grid,
  .hp-journey-grid { grid-template-columns: 1fr; }
  .hp-journey-grid .hp-qr { order: -1; }
  .hp-pillars-grid { grid-template-columns: repeat(2, 1fr); }
  .hp-pillar:nth-child(4), .hp-pillar:nth-child(5) { margin-top: 0; }
  .hp-pillar:nth-child(3), .hp-pillar:nth-child(4) { margin-top: clamp(0rem, 2vw, 1.5rem); }
}

@media (max-width: 47.99em) {
  .hp-hero {
    min-height: auto;
    padding: clamp(6rem, 20vh, 8rem) 0 clamp(6.5rem, 18vh, 9rem);
  }
  .hp-hero-title { font-size: clamp(2.6rem, 15vw, 4.4rem); }
  .hp-cue { display: none; }             /* a phone reader already knows to scroll */
  .hp-cta { gap: .6rem; }
  .hp-btn { padding: .78rem 1.25rem; font-size: .92rem; flex: 1 1 auto; justify-content: center; }

  /* Two-up, and the divider becomes a grid line rather than four hairlines. */
  .hp-ribbon { margin-top: clamp(-3rem, -8vw, -4rem); }
  .hp-ribbon-grid { grid-template-columns: repeat(2, 1fr); gap: 1.4rem 1rem; }
  .hp-stat + .hp-stat::before { display: none; }
  .hp-stat:nth-child(n+3) { padding-top: 1.2rem; border-top: 1px solid var(--line); }

  .hp-pillars-grid { grid-template-columns: 1fr; }
  .hp-pillar:nth-child(n) { margin-top: 0; }

  .hp-notice { grid-template-columns: auto 1fr; }
  .hp-notice-when { grid-column: 2; }

  .hp-ev { flex-basis: min(80vw, 19rem); }
  .hp-rail { padding-left: var(--shell); padding-right: var(--shell); }

  .hp-steps::before { left: 1.2rem; }
  .hp-steps::after  { left: 1.1rem; }
}

@media (max-width: 29.99em) {
  .hp-hero-marks { display: flex; gap: .8rem; }
  .hp-hero-marks .arms  { height: 2.5rem; }
  .hp-hero-marks .event { height: 2.1rem; }
  .hp-ribbon-grid { padding: 1.1rem .9rem; }
}

/* ═══════════════════════════ REDUCED MOTION ═══════════════════════════
   Everything decorative stops. The page keeps every layer, every colour and
   every piece of information — it simply holds still. Nothing here is load-
   bearing, which is the test a motion system has to pass. */
@media (prefers-reduced-motion: reduce) {
  .hp-glow, .hp-tapa, .hp-particle, .hp-wave-anim,
  .hp-marquee, .hp-qr-anim, .hp-qr-scan, .hp-hero-dates .dot,
  .hp-ico .bob, .hp-ico .bob-2, .hp-ico .spin, .hp-ico .beat,
  .hp-steps::after, .hp-cue-rail::after {
    animation: none !important;
  }
  .hp-particle { opacity: .5; }
  .hp-qr-mod   { opacity: .85; }
  .pc-js [data-reveal] .hp-ico .draw { stroke-dashoffset: 0; }
  .hp-islands  { transform: none !important; }
  .hp-ev:hover, .hp-do:hover, .hp-pillar:hover, .hp-btn:hover { transform: none; }
  /* The marquee is a moving element by definition; held still it must at
     least not clip its own content off the right edge. */
  .hp-marquee { flex-wrap: wrap; width: 100%; }
}

/* A filled accent shape takes the reef green as fill, not stroke. */
.hp-ico .f.accent { fill: var(--reef-2); stroke: none; }

/* ─────────────────── Hero corrections after first render ────────────────
   Written from looking at the rendered page rather than at the markup.

   1. The cue sat under the buttons in the centre column and collided with
      them. It belongs at the edge, out of the reading path.
   2. The island ridge was hidden behind the wave stack: lifting it clear
      puts the horizon where a horizon goes — above the water.
   3. One visible wave is decoration; the depth only reads when all three
      bands are distinguishable, which means separating them vertically as
      well as by opacity.
   4. The spray was so faint it may as well not have been rendered. */

.hp-cue {
  left: auto; right: clamp(1rem, 3vw, 2.4rem);
  bottom: clamp(7rem, 15vw, 10.5rem);
  transform: none;
  writing-mode: vertical-rl;
  gap: .9rem;
}
.hp-cue-rail { width: 1px; height: 3.4rem; }
@media (max-height: 46rem) { .hp-cue { display: none; } }

.hp-islands { bottom: clamp(34px, 4.5vw, 62px); }

/* Each band sits a little higher than the one in front, so the crests stay
   distinguishable instead of collapsing into a single silhouette. */
.hp-waves .hp-wave:nth-child(1) { height: clamp(78px, 11vw, 158px); }
.hp-waves .hp-wave:nth-child(2) { height: clamp(70px, 10vw, 145px); }
.hp-waves .hp-wave:nth-child(3) { height: clamp(60px, 8.4vw, 124px); }

.hp-particle {
  background: radial-gradient(circle at 32% 30%, #fff, rgba(160,225,255,.35) 62%, transparent 78%);
  box-shadow: 0 0 8px rgba(180,235,255,.5);
}
@keyframes hpFloat {
  0%   { opacity: 0;   transform: translate3d(0, 18px, 0) scale(.7); }
  16%  { opacity: 1; }
  72%  { opacity: .7; }
  100% { opacity: 0;   transform: translate3d(var(--dx, 14px), -86px, 0) scale(1.2); }
}

.hp-tapa { opacity: .42; }

/* ─────────────── Pacific composition and rail, after review ─────────────
   The illustration was sized by its grid cell rather than by what it had to
   say, so at desktop width it became a pale 700px disc with a few dots in
   it. Capped, deepened, and given its rings back. */

/* The rail is aligned with the heading above it and bleeds off the right
   edge only. Running it off BOTH edges detached it from the column its own
   title sits in, which read as a mistake rather than as a device. */
.hp-rail-wrap { margin-right: calc(50% - 50vw); }
.hp-rail {
  margin: 0;
  padding: .5rem calc(50vw - 50%) 1.6rem 0;
  scroll-padding-left: 0;
}
@media (max-width: 47.99em) {
  .hp-rail { padding-right: var(--shell); }
}

/* ═══════════════ Corrections from the full-page render ════════════════ */

/* The Pacific composition. Sized by its grid cell, the illustration came out
   as a pale disc adrift in half a screen of nothing. It now fills a column
   sized for it, and the water is deep enough to read as water. */
.hp-pacific-grid { grid-template-columns: 1fr 1.06fr; gap: clamp(2rem, 4vw, 3.5rem); }

/* Auto-fit gave four columns and left a ragged two-card row underneath.
   Three and three is a composition; four and two is a leftover. */
@media (min-width: 62em) {
  .hp-do-grid { grid-template-columns: repeat(3, 1fr); }
}
/* Cards in a row share a height, so the calls to action line up instead of
   floating at whatever height each card's copy happens to end. */
.hp-do { display: flex; flex-direction: column; }
.hp-do-text { flex: 1; }

.hp-ico { width: 3.4rem; height: 3.4rem; }
.hp-fact-mark .hp-ico { width: 1.6rem; height: 1.6rem; }

@media (prefers-reduced-motion: reduce) {
  /* The rail's second copy exists only so the animation can loop seamlessly.
     Held still it is simply every name printed twice, so it goes. */
  .hp-marquee-set[aria-hidden="true"] { display: none; }
  .hp-marquee-set { flex-wrap: wrap; row-gap: .7rem; }
}

/* On a phone the hero's padding was in viewport-height units, which on a tall
   handset reserved 450px of empty ocean around 350px of content. Width-based
   units keep the proportions the design intends without letting the device's
   height dictate how much nothing is on screen. */
@media (max-width: 47.99em) {
  .hp-hero { padding: clamp(5.5rem, 15vw, 7.5rem) 0 clamp(4.5rem, 15vw, 7rem); }
}

/* ══════════════════════════ THE GLOBE ═════════════════════════════════
   A sphere, not a disc. Three things do all the work: the ocean's radial
   gradient puts the light source up and to the left, the limb gradient
   darkens the edge where a sphere curves away, and the specular highlight
   sits where that light would actually catch. Take any one of them out and
   it collapses back into a flat circle with a map on it. */

.hp-globe { position: relative; max-width: 32rem; margin-inline: auto; }
.hp-globe svg { width: 100%; height: auto; display: block; overflow: visible; }

.hp-globe-land path,
.hp-globe-land circle { fill: url(#hpTerra); }

.hp-globe-grid ellipse {
  fill: none; stroke: #cfe9ff; stroke-opacity: .13; stroke-width: 1;
}
.hp-globe-grid .equator { stroke-opacity: .22; stroke-dasharray: 5 7; }

.hp-globe-rim {
  fill: none; stroke: #7fd0ff; stroke-opacity: .3; stroke-width: 1.5;
}
.hp-globe-spec { fill: url(#hpSpec); }

/* One revolution. The strip is drawn twice and slid by exactly one map
   width, so the end state is pixel-identical to the start and the loop is
   invisible. Slow on purpose: this is a background that happens to move,
   not a thing demanding to be watched. */
.hp-globe-spin { animation: hpGlobeSpin 64s linear infinite; }
@keyframes hpGlobeSpin {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-1 * var(--globe-w)), 0, 0); }
}

/* ── Fiji ───────────────────────────────────────────────────────────────
   The marker travels with the land, because it has to: a spotlight pinned
   to the middle of the screen would spend most of every revolution
   pointing at open ocean. */
.hp-fiji-halo {
  fill: url(#hpSpot);
  transform-box: fill-box; transform-origin: center;
  animation: hpFijiBreathe 3.4s ease-in-out infinite;
}
@keyframes hpFijiBreathe {
  0%, 100% { transform: scale(.86); opacity: .75; }
  50%      { transform: scale(1.12); opacity: 1; }
}

.hp-fiji-ring {
  fill: none; stroke: #6bf0a8; stroke-width: 1.4; opacity: 0;
  transform-box: fill-box; transform-origin: center;
  animation: hpFijiPing 2.3s cubic-bezier(.2,.6,.3,1) infinite;
}
@keyframes hpFijiPing {
  0%   { transform: scale(.35); opacity: .95; }
  70%  { opacity: .35; }
  100% { transform: scale(3.6); opacity: 0; }
}

.hp-fiji-isle { fill: #7dffbe; }
.hp-fiji-dot  { fill: #ffffff; }

/* The legend. The marker is on the far side of the world for part of every
   revolution, so what identifies it has to live outside the sphere. */
.hp-globe-note {
  display: flex; align-items: center; justify-content: center; gap: .55rem;
  margin: .4rem 0 0; font-size: .84rem; font-weight: 600; color: var(--muted);
  letter-spacing: .01em;
}
.hp-globe-key {
  width: .62rem; height: .62rem; border-radius: 50%; flex: none;
  background: var(--reef-2);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--reef-2) 22%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .hp-globe-spin { animation: none; }
  .hp-fiji-halo  { animation: none; opacity: 1; }
  .hp-fiji-ring  { animation: none; opacity: .5; }
}

/* ═════════════════ SECTION JOINS, REBUILT ═══════════════════════════════
   The old approach put a separate <svg> band between two sections and filled
   it with a single flat colour. Between a light page and a band painted with
   a *gradient*, that flat colour can only match at one point — which is how a
   near-black stripe ended up lying across the bottom of the ocean band, where
   its fill (#02132b, the gradient's top) met the gradient's bottom.

   These live inside the band and are filled with the page colour either side.
   The join is then a shape cut out of the band and cannot drift out of step
   with it, whatever the band is painted with. */
.hp-journey-wave {
  position: absolute; left: 0; right: 0; width: 100%;
  height: clamp(42px, 5.5vw, 90px);
  line-height: 0; z-index: 1; pointer-events: none;
}
.hp-journey-wave.top    { top: -1px; }
.hp-journey-wave.bottom { bottom: -1px; }

/* Room for the waves, so the copy never runs under one. */
.hp-journey, .hp-pacific {
  padding-top: calc(clamp(3.5rem, 8vw, 7rem) + clamp(42px, 5.5vw, 90px));
}
.hp-journey { padding-bottom: calc(clamp(3.5rem, 8vw, 7rem) + clamp(42px, 5.5vw, 90px)); }

/* The band itself. The green light was landing over the blue at low opacity
   and mixing to a flat teal across the whole lower half — the one colour that
   is in neither the mark nor the palette. Moved into the top corner, where it
   reads as light rather than as a tint. */
.hp-journey {
  background:
    radial-gradient(38rem 26rem at 84% 6%, rgba(0,176,88,.26), transparent 60%),
    radial-gradient(46rem 34rem at 12% 96%, rgba(13,111,196,.5), transparent 66%),
    linear-gradient(168deg, #02132b 0%, #062a5c 52%, #0a3f86 100%);
}

/* The rail's scrollbar was a heavy blue bar the width of the section — a
   control shouting louder than the cards it scrolls. Thin, quiet, and only
   fully present when the reader is on the rail. */
.hp-rail { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--brand) 30%, transparent) transparent; }
.hp-rail::-webkit-scrollbar { height: 4px; }
.hp-rail::-webkit-scrollbar-track { background: transparent; }
.hp-rail::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--brand) 22%, transparent);
  border-radius: 4px;
}
.hp-rail:hover::-webkit-scrollbar-thumb,
.hp-rail:focus-within::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--brand) 55%, transparent);
}

/* The figures card was cutting the crest of the front wave in half. Sitting a
   little lower, it rests on the water instead of slicing it. */
.hp-ribbon { margin-top: clamp(-3rem, -5vw, -4.5rem); }

/* ─────────────────── Globe and ocean band, after review ─────────────────
   The globe was drawn on a 480-unit canvas but only occupied the middle 388
   of it, so a fifth of every pixel it was given went to empty margin. The
   viewBox is cropped to the artwork and the cap raised: same file, half again
   the presence. */
.hp-globe { max-width: 37rem; }

/* The green light was set at .26 across the top corner of the ocean band and
   mixed with the navy into a flat teal — a colour that is in neither the mark
   nor the palette, and the thing that made this section look muddy. It is now
   a highlight rather than a wash, and the blue does the lifting. */
.hp-journey {
  background:
    radial-gradient(26rem 18rem at 90% 4%,  rgba(0,176,88,.15), transparent 62%),
    radial-gradient(52rem 38rem at 14% 98%, rgba(13,111,196,.55), transparent 68%),
    radial-gradient(40rem 30rem at 78% 62%, rgba(31,147,214,.22), transparent 66%),
    linear-gradient(168deg, #02132b 0%, #062a5c 55%, #0a3f86 100%);
}

/* The Pacific section had a column of nothing under a small globe. Tighter
   rhythm, and the two halves meet in the middle of the page rather than
   drifting apart. */
.hp-pacific { padding-bottom: clamp(2.6rem, 5.5vw, 4.5rem); }
.hp-pacific-grid { align-items: center; gap: clamp(1.5rem, 3.5vw, 3rem); }

/* `margin-inline: auto` on a grid item overrides justify-self:stretch, so the
   item stops filling its column and shrinks to fit its content instead. Its
   content here is an <svg width="100%"> — which, with nothing to be 100% OF,
   falls back to the SVG default of 300px. That is the whole reason this
   illustration has been rendering at a third of the size it was given: not the
   viewBox, not the max-width, but two words of centring. An explicit width
   restores the fill, and the auto margins then do only what they were for. */
.hp-globe { width: 100%; max-width: 37rem; }


/* ══════════════ GLOBE — real coastlines, real projection ═══════════════
   The land and the graticule are single paths whose `d` the server writes
   once and home.js rewrites as the Earth turns, so everything here is
   presentation only. */
.hp-globe-land {
  /* Filled, not stroked: at 500px across a 2.6px coastline reads as a
     wire diagram. The fill-rule keeps overlapping rings from cancelling. */
  fill: none;
  stroke: url(#hpTerra); stroke-width: 2.6;
  stroke-linejoin: round; stroke-linecap: round;
  paint-order: stroke;
  filter: drop-shadow(0 0 3px rgba(0, 190, 100, .35));
}
.hp-globe-grid {
  fill: none; stroke: #cfe9ff; stroke-opacity: .14; stroke-width: .9;
}
.hp-fiji { transition: opacity .35s linear; }

/* Filled, not merely outlined. Subpaths broken at the limb close on a chord,
   which is where the coastline genuinely meets the horizon, so the fill is
   correct rather than a happy accident. */
.hp-globe-land {
  fill: url(#hpTerra); fill-rule: nonzero;
  stroke: #7df0b0; stroke-opacity: .5; stroke-width: .8;
  filter: none;
}

/* ── The rail, centred ───────────────────────────────────────────────────
   Bleeding the rail off the right edge was meant to signal "this continues".
   It reads instead as a section that has slipped off its axis, because the
   heading above it is centred in the page and the cards are not. The rail now
   sits in the same column as its own title, and a fade at the right edge does
   the signalling the bleed was there for. */
.hp-rail-wrap {
  margin-right: 0;
  position: relative;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 4.5rem), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 4.5rem), transparent);
}
.hp-rail { padding: .5rem 4.5rem .4rem 0; }
/* With nothing left to scroll there is nothing to hint at, so the fade goes. */
.hp-rail-wrap.is-end {
  -webkit-mask-image: none; mask-image: none;
}
@media (max-width: 47.99em) {
  .hp-rail { padding-right: 2.5rem; }
  .hp-rail-wrap {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 2.5rem), transparent);
            mask-image: linear-gradient(90deg, #000 calc(100% - 2.5rem), transparent);
  }
}

/* ══════════════════ HERO PHOTOGRAPH AND ITS SCRIM ═════════════════════
   The gradient the hero used to be is still underneath, and still the
   fallback: if the photograph 404s or has not been uploaded, the panel is
   the branded ocean it always was rather than bare white. */

.hp-hero-media {
  position: absolute; left: 0; right: 0; z-index: -7;
  /* Extends past the hero on both edges — clipped by .hp-hero's own
     overflow — so the parallax has travel room. Without it, shifting the
     layer at all would expose the ocean gradient at whichever edge it
     moved away from. */
  top: -9%; bottom: -9%;
  overflow: hidden;
  will-change: transform;
  /* home.js sets this transform straight from scroll position — a pure
     function of where the page is, nothing on a timer. This transition is
     what turns that into smooth motion: a mouse wheel fires in discrete
     jumps, not a continuous stream, and each update eases into place
     instead of snapping. Short and bounded on purpose, so it settles a
     fixed moment after the *last* scroll rather than drifting on once the
     reader has stopped — a photograph still moving after you stop
     scrolling is what reads as wrong, not as depth. */
  transition: transform .15s cubic-bezier(.22, .61, .36, 1);
}
.hp-hero-media picture { display: block; width: 100%; height: 100%; }
.hp-hero-media img {
  width: 100%; height: 100%; object-fit: cover;
  /* Focal point: keeps the speaker and the front of the room in frame while
     the text column sits over the darker left side. */
  object-position: 62% 46%;
}

/* The scrim. Weighted hard to the left, where every word is, and thinning to
   the right so the room is still legible as a photograph rather than as a
   dark rectangle. Two layers: a directional wash for the copy, and a floor
   under the waves so the bottom edge does not fight them.

   Colour, not black. A neutral scrim over a warm Pacific interior turns it
   grey; the ocean navy keeps the photograph on the same palette as
   everything else on the page. */
/* Two attempts either side of this one. The first was so dark (93% falling to
   38%, plus a second wash over the top) that the photograph read as the
   presenter and nothing else — no delegates, no carved panels, no room. The
   second went too far the other way and left the headline sitting on bare
   photograph with the navigation washing out against it.

   This one is shaped rather than uniform: full weight behind the text column on
   the left, releasing quickly across the middle so the seated delegates and the
   carved posts come through, and a short band along the top so the navigation
   always has ground to sit on whatever the picture is doing behind it. */
.hp-hero-scrim {
  position: absolute; inset: 0; z-index: -6; pointer-events: none;
  background:
    linear-gradient(100deg,
      rgba(2, 19, 43, .88) 0%,
      rgba(3, 24, 54, .78) 22%,
      rgba(5, 40, 88, .5)  42%,
      rgba(8, 62, 122, .24) 62%,
      rgba(13, 111, 196, .1) 100%),
    linear-gradient(180deg, rgba(2,19,43,.62) 0%, rgba(2,19,43,.18) 12%, transparent 26%),
    linear-gradient(0deg, rgba(2,19,43,.45) 0%, transparent 26%);
}

/* A real photograph replaces the need for illustrated atmosphere entirely —
   this banner already carries its own wave motif and corner pattern, baked in.
   Stacking the gradient glow, the drifting cloth and the sea-spray particles on
   top of it was decoration competing with the thing it was decorating, and
   together with the heavy scrim above is why the photo read as almost nothing
   but the presenter. All three are switched off on the hero now; they still do
   their job everywhere else on the page. */
.hp-hero .hp-glow,
.hp-hero .hp-tapa,
.hp-hero .hp-particles { display: none; }

@media (max-width: 47.99em) {
  .hp-hero-media img { object-position: 58% 44%; }
  /* Nothing is parallaxed on a phone, so the layer needs no travel room. */
  .hp-hero-media { top: 0; bottom: 0; }
  .hp-hero-scrim {
    background:
      linear-gradient(180deg,
        rgba(2, 19, 43, .9) 0%, rgba(4, 32, 70, .82) 45%,
        rgba(6, 52, 105, .78) 78%, rgba(4, 32, 63, .7) 100%);
  }
}

@media (prefers-reduced-motion: reduce) {
  .hp-hero-media { transition: none; transform: none !important; }
}

/* The islands and the cloth are now moved by home.js as scroll-driven layers,
   so they need the same short, bounded easing the photograph has — otherwise
   they snap between a wheel's discrete ticks while the picture behind them
   glides, which reads as three separate faults rather than one effect. */
.hp-islands, .hp-tapa { transition: transform .15s cubic-bezier(.22,.61,.36,1); }
@media (prefers-reduced-motion: reduce) {
  .hp-islands, .hp-tapa { transition: none; transform: none !important; }
}

/* ── Hero framing ────────────────────────────────────────────────────────
   The photograph is 2.5 : 1 and the hero is nearly square on a laptop, so
   `cover` was cropping most of the room away — the audience, the masi on the
   walls and the whole left of the frame. Shortening the hero brings its shape
   closer to the picture's, so far more of the photograph survives the crop. */
.hp-hero {
  min-height: min(84svh, 44rem);
  padding: clamp(5rem, 9vh, 6.5rem) 0 clamp(5.5rem, 11vh, 8rem);
}
/* Panned left, where the audience and the carved posts are, rather than centred
   on the speaker with everything either side of her cut off. */
.hp-hero-media img { object-position: 46% 42%; }

/* Only one mark here now, so it does not need the paired-marks spacing. */
.hp-hero-marks { margin-bottom: clamp(1.1rem, 2.2vw, 1.6rem); }
.hp-hero-marks .event { height: clamp(2.8rem, 4.4vw, 3.8rem); }

@media (max-width: 47.99em) {
  .hp-hero { min-height: auto; }
  .hp-hero-media img { object-position: 52% 42%; }
}
