/* ==========================================================================
   SWAN — Erasmus+ Sport Project
   Design system + site styles
   --------------------------------------------------------------------------
   Motif: "the rally arc" — the curve shared by a table-tennis rally,
   a neural connection forming, and a swan's neck.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Fonts — self-hosted (SIL Open Font License, see assets/fonts/*-OFL.txt)
   Self-hosted rather than loaded from Google Fonts so that no visitor IP
   address is sent to a third party without consent (GDPR).
   -------------------------------------------------------------------------- */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/BricolageGrotesque-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("../fonts/BricolageGrotesque-Bold.woff2") format("woff2");
  font-weight: 700 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/InstrumentSans-Regular.woff2") format("woff2");
  font-weight: 400 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/InstrumentSans-Bold.woff2") format("woff2");
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("../fonts/InstrumentSans-Italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "DM Mono";
  src: url("../fonts/DMMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "DM Mono";
  src: url("../fonts/DMMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Tokens
   -------------------------------------------------------------------------- */
:root {
  /* Brand blues — carried over from the existing SWAN palette */
  --navy-950: #071b3d;
  --navy-900: #0a2450;
  --blue-800: #0c2f7a;
  --blue-700: #12409b; /* primary */
  --blue-600: #1a4fb4;
  --blue-500: #2c67ce;
  --blue-300: #7ba3e6;

  /* Sky tints — the light band from the current site */
  --sky-300: #a9cce3;
  --sky-200: #c5dcea;
  --sky-100: #e4eff7;
  --sky-50: #f2f8fc;

  /* Warm neutrals — the footer peach */
  --peach-100: #fceae4;
  --peach-200: #f9dbd1;

  /* Brand cyan, from the SWAN logo */
  --cyan-500: #22ace3;
  --cyan-600: #1791c3;
  --cyan-100: #d2ecf8;
  --cyan-50: #eaf7fc;

  /* The one accent: the ball */
  --coral-500: #d2694a;
  --coral-600: #b8543a;

  --white: #ffffff;
  --grey-100: #eef2f6;
  --grey-400: #8ea0b5;
  --grey-600: #56687e;

  /* Semantic */
  --bg: var(--white);
  --text: #12233d;
  --text-soft: var(--grey-600);
  --text-invert: #eaf2fb;
  --rule: #dbe6f0;

  /* Type */
  --font-display: "Bricolage Grotesque", "Trebuchet MS", system-ui, sans-serif;
  --font-body: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "DM Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  /* Fluid type scale */
  --step--1: clamp(0.83rem, 0.79rem + 0.18vw, 0.94rem);
  --step-0: clamp(1.0625rem, 1.03rem + 0.18vw, 1.1875rem);
  --step-1: clamp(1.25rem, 1.18rem + 0.35vw, 1.5rem);
  --step-2: clamp(1.5rem, 1.36rem + 0.7vw, 2rem);
  --step-3: clamp(1.85rem, 1.6rem + 1.25vw, 2.75rem);
  --step-4: clamp(2.25rem, 1.8rem + 2.25vw, 4rem);
  --step-5: clamp(2.75rem, 2rem + 3.5vw, 5.25rem);

  /* Space */
  --space-xs: 0.5rem;
  --space-sm: 0.875rem;
  --space-md: 1.5rem;
  --space-lg: 2.5rem;
  --space-xl: 4rem;
  --space-2xl: clamp(4rem, 3rem + 5vw, 7.5rem);

  /* Shape */
  --radius-sm: 8px;
  --radius: 14px;
  --radius-lg: 22px;

  --shadow-sm: 0 1px 2px rgba(7, 27, 61, 0.06), 0 2px 8px rgba(7, 27, 61, 0.04);
  --shadow-md: 0 4px 12px rgba(7, 27, 61, 0.07), 0 16px 40px rgba(7, 27, 61, 0.08);
  --shadow-lg: 0 8px 24px rgba(7, 27, 61, 0.1), 0 32px 64px rgba(7, 27, 61, 0.12);

  --container: 1180px;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --------------------------------------------------------------------------
   2. Reset + base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg,
video {
  max-width: 100%;
  height: auto;
  display: block;
}

a {
  color: var(--blue-700);
  text-decoration-color: rgba(18, 64, 155, 0.32);
  text-underline-offset: 3px;
}

a:hover {
  text-decoration-color: currentColor;
}

h1,
h2,
h3,
h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--navy-900);
  margin: 0 0 0.5em;
  text-wrap: balance;
}

h1 {
  font-size: var(--step-5);
  letter-spacing: -0.035em;
}
h2 {
  font-size: var(--step-4);
  letter-spacing: -0.03em;
}
h3 {
  font-size: var(--step-2);
}
h4 {
  font-size: var(--step-1);
}

p {
  margin: 0 0 1.1em;
  text-wrap: pretty;
}

p:last-child {
  margin-bottom: 0;
}

::selection {
  background: var(--blue-700);
  color: var(--white);
}

:focus-visible {
  outline: 3px solid var(--coral-500);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--space-md);
  z-index: 200;
  background: var(--navy-950);
  color: var(--white);
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  font-weight: 600;
  text-decoration: none;
  transition: top 0.2s var(--ease);
}

.skip-link:focus {
  top: 0;
}

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

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */
.container {
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
}

/* Narrow reading measure that still starts on the container's left edge,
   so headings, body copy and section heads all share one alignment. */
.container--narrow {
  width: min(100% - 2.5rem, var(--container));
  margin-inline: auto;
}

.container--narrow > * {
  max-width: 46rem;
}

/* Body copy set in two columns where the container is wide enough. A single
   column would either stop at a 46rem measure and leave the right-hand half
   of the section empty, or run the full width at about 110 characters a
   line, which is past the point where the eye loses its place. Two columns
   fill the width at roughly 68 characters each. */
.about-copy > p {
  margin-bottom: 0;
}

@media (min-width: 901px) {
  .about-copy {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: clamp(2rem, 1rem + 3vw, 3.5rem);
    align-items: start;
  }
}

@media (max-width: 900px) {
  .about-copy > p + p {
    margin-top: 1.1em;
  }
}

.section {
  padding-block: var(--space-2xl);
  position: relative;
}

.section--tight {
  padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem);
}

.section--sky {
  background: var(--sky-100);
}

.section--sky-deep {
  background: linear-gradient(180deg, var(--sky-200) 0%, var(--sky-100) 100%);
}

.section--peach {
  background: var(--peach-100);
}

.section--navy {
  background: var(--navy-950);
  color: var(--text-invert);
}

.section--navy h2,
.section--navy h3,
.section--navy h4 {
  color: var(--white);
}

/* Section heading block */
.section-head {
  max-width: 46rem;
  margin-bottom: var(--space-xl);
}

.section-head--center {
  margin-inline: auto;
  text-align: center;
}

/* Lets a long heading run the full container width instead of being folded
   by the 46rem measure, while the supporting paragraph keeps that measure.
   Below ~700px the heading no longer fits on one line and wraps normally. */
.section-head--wide {
  max-width: none;
}

.section-head--wide > h2 {
  max-width: none;
  text-wrap: balance;
}

.section-head--wide > p:not(.eyebrow) {
  max-width: 50rem;
}

.section-head p {
  color: var(--text-soft);
  font-size: var(--step-1);
  line-height: 1.6;
}

.section--navy .section-head p {
  color: #b7c9e2;
}

/* The eyebrow: mono, tracked, with a leading arc tick */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-600);
  margin: 0 0 1rem;
  font-weight: 500;
}

.eyebrow::before {
  content: "";
  width: 1.75rem;
  height: 0.6rem;
  flex: none;
  border-top: 1.5px solid currentColor;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: 0.75;
}

.section--navy .eyebrow,
.section--navy-soft .eyebrow {
  color: var(--sky-300);
}

/* --------------------------------------------------------------------------
   4. The rally arc — signature motif
   -------------------------------------------------------------------------- */
.arc-divider {
  display: block;
  width: 100%;
  height: 48px;
  color: var(--sky-300);
  overflow: visible;
}

.arc-divider path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-dasharray: 2 9;
  stroke-linecap: round;
  opacity: 0.9;
}

.arc-divider circle {
  fill: var(--coral-500);
}

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */
.btn {
  --btn-bg: var(--blue-700);
  --btn-fg: var(--white);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.5rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease),
    background-color 0.25s var(--ease);
  box-shadow: 0 2px 6px rgba(12, 47, 122, 0.22);
}

.btn:hover {
  background: var(--blue-600);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(12, 47, 122, 0.28);
}

.btn:active {
  transform: translateY(0);
}

.btn__ball {
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--coral-500);
  flex: none;
  transition: transform 0.35s var(--ease);
}

.btn:hover .btn__ball {
  transform: translateX(3px) scale(1.15);
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--blue-700);
  border-color: rgba(18, 64, 155, 0.28);
  box-shadow: none;
}

.btn--ghost:hover {
  background: rgba(18, 64, 155, 0.06);
  border-color: var(--blue-700);
  box-shadow: none;
}

.btn--light {
  --btn-bg: var(--white);
  --btn-fg: var(--blue-700);
  box-shadow: var(--shadow-sm);
}

.btn--light:hover {
  background: var(--white);
}

.btn--sm {
  padding: 0.6rem 1.1rem;
  font-size: 0.9rem;
}

/* Text link with a travelling ball */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 600;
  text-decoration: none;
  color: var(--blue-700);
}

.link-arrow::after {
  content: "";
  width: 1.4rem;
  height: 1.5px;
  background: currentColor;
  transition: width 0.25s var(--ease);
}

.link-arrow:hover::after {
  width: 2.2rem;
}

/* --------------------------------------------------------------------------
   6. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.82);
  backdrop-filter: saturate(150%) blur(14px);
  -webkit-backdrop-filter: saturate(150%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.site-header.is-stuck {
  border-bottom-color: var(--rule);
  box-shadow: 0 4px 20px rgba(7, 27, 61, 0.06);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  min-height: 4.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  text-decoration: none;
  color: var(--navy-900);
  flex: none;
}

.brand__mark {
  width: 2.5rem;
  height: 2.5rem;
  flex: none;
}

.brand__logo {
  height: 2.9rem;
  width: auto;
  flex: none;
}

@media (max-width: 520px) {
  .brand__logo {
    height: 2.4rem;
  }
}

.site-footer .brand__logo {
  height: 3rem;
}

.brand__text {
  display: flex;
  flex-direction: column;
  line-height: 1.05;
}

.brand__name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.35rem;
  letter-spacing: -0.03em;
  color: var(--blue-700);
}

.brand__tag {
  font-family: var(--font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--grey-400);
}

.nav__menu {
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1.6vw, 1.75rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

.nav__link {
  position: relative;
  display: block;
  padding: 0.4rem 0.15rem;
  font-size: 0.98rem;
  font-weight: 500;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.2s var(--ease);
}

.nav__link:hover {
  color: var(--blue-700);
}

/* Underline is an arc segment, not a bar */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -2px;
  height: 6px;
  border-top: 2px solid var(--blue-700);
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  opacity: 0;
  transform: scaleX(0.4);
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
}

.nav__link:hover::after {
  opacity: 0.45;
  transform: scaleX(0.85);
}

.nav__link[aria-current="page"] {
  color: var(--blue-700);
  font-weight: 600;
}

.nav__link[aria-current="page"]::after {
  opacity: 1;
  transform: scaleX(1);
  border-top-color: var(--coral-500);
}

/* Language switcher ------------------------------------------------------ */
.flag-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.flag {
  width: 1.35rem;
  height: 0.9rem;
  flex: none;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(7, 27, 61, 0.14);
}

.lang {
  position: relative;
  flex: none;
}

.lang__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.55rem;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--white);
  color: var(--navy-900);
  font: inherit;
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.lang__toggle:hover {
  border-color: var(--sky-300);
  background: var(--sky-50);
}

.lang__code {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.06em;
}

.lang__chev {
  width: 0.6rem;
  height: 0.4rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform 0.2s var(--ease);
}

.lang__toggle[aria-expanded="true"] .lang__chev {
  transform: rotate(180deg);
}

.lang__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  z-index: 60;
  min-width: 12.5rem;
  margin: 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}

.lang__item {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.45rem 0.55rem;
  border-radius: 6px;
  font-size: 0.92rem;
  line-height: 1.2;
  color: var(--navy-900);
  text-decoration: none;
}

a.lang__item:hover {
  background: var(--sky-50);
}

.lang__item--current {
  font-weight: 600;
  background: var(--sky-100);
}

.lang__item--soon {
  color: var(--grey-400);
  cursor: default;
}

.lang__item--soon .flag {
  opacity: 0.55;
}

.lang__item em {
  margin-left: auto;
  font-family: var(--font-mono);
  font-style: normal;
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--grey-400);
}

.nav__social {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-left: 0.25rem;
}

.nav__social a {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  color: var(--blue-700);
  transition: background-color 0.2s var(--ease), transform 0.2s var(--ease);
}

.nav__social a:hover {
  background: var(--sky-100);
  transform: translateY(-1px);
}

.nav__social svg {
  width: 1.15rem;
  height: 1.15rem;
  fill: currentColor;
}

/* Only ever shown behind the mobile menu; must not become a flex item. */
.nav__scrim {
  display: none;
}

.nav__toggle {
  display: none;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--navy-900);
  cursor: pointer;
}

.nav__toggle span,
.nav__toggle span::before,
.nav__toggle span::after {
  display: block;
  width: 1.15rem;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: transform 0.3s var(--ease), opacity 0.2s var(--ease);
}

.nav__toggle span {
  margin: 0 auto;
  position: relative;
}

.nav__toggle span::before,
.nav__toggle span::after {
  content: "";
  position: absolute;
  left: 0;
}

.nav__toggle span::before {
  top: -6px;
}
.nav__toggle span::after {
  top: 6px;
}

.nav__toggle[aria-expanded="true"] span {
  background: transparent;
}

.nav__toggle[aria-expanded="true"] span::before {
  transform: translateY(6px) rotate(45deg);
}

.nav__toggle[aria-expanded="true"] span::after {
  transform: translateY(-6px) rotate(-45deg);
}

@media (max-width: 900px) {
  .nav__toggle {
    display: grid;
    place-items: center;
  }

  /* Absolute, not fixed: the header's backdrop-filter makes it the
     containing block for fixed descendants, which would trap the panel. */
  .nav__panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Above the scrim: both start at the foot of the header, and without
       this the scrim covers the panel and swallows every tap on a link. */
    z-index: 2;
    max-height: min(70vh, 34rem);
    background: var(--white);
    border-top: 1px solid var(--rule);
    box-shadow: 0 16px 32px rgba(7, 27, 61, 0.12);
    padding: var(--space-sm) 1.25rem var(--space-lg);
    overflow-y: auto;
    overscroll-behavior: contain;
    display: flex;
    flex-direction: column;
    gap: var(--space-md);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease),
      visibility 0.25s;
  }

  .nav__panel.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }

  .nav__scrim {
    display: block;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1;
    height: 100vh;
    background: rgba(7, 27, 61, 0.45);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s var(--ease), visibility 0.25s;
    pointer-events: none;
  }

  .nav:has(.nav__panel.is-open) .nav__scrim {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .nav__menu {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .nav__menu li + li {
    border-top: 1px solid var(--rule);
  }

  .nav__link {
    padding: 1rem 0.25rem;
    font-size: 1.15rem;
  }

  .nav__link::after {
    display: none;
  }

  .nav__link[aria-current="page"] {
    color: var(--coral-600);
  }

  .nav__social {
    margin-left: 0.25rem;
  }

  .lang__toggle {
    width: 100%;
    justify-content: flex-start;
    padding: 0.6rem 0.75rem;
  }

  .lang__toggle .lang__chev {
    margin-left: auto;
  }

  /* Opens in flow rather than as an overlay: the panel scrolls, so an
     absolutely positioned menu would be clipped by it. */
  .lang__menu {
    position: static;
    margin-top: 0.4rem;
    min-width: 0;
    box-shadow: none;
    background: var(--sky-50);
  }
}

@media (min-width: 901px) {
  /* Let the nav take the room between the logo and the right edge and space
     the links out across it, rather than bunching them in the corner. */
  .nav__panel {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex: 1;
    gap: clamp(0.75rem, 2vw, 2rem);
  }

  .nav__menu {
    flex: 1;
    justify-content: space-between;
    max-width: 41rem;
  }

  /* Keeps clear air between the logo and the first link at narrow desktop
     widths, where the menu would otherwise run right up to the mark. */
  .nav {
    gap: clamp(2rem, 5vw, 5rem);
  }
}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: linear-gradient(168deg, var(--sky-200) 0%, var(--sky-100) 55%, var(--white) 100%);
  overflow: hidden;
  padding-block: clamp(3.5rem, 2rem + 7vw, 7rem) clamp(3.5rem, 2rem + 6vw, 6rem);
}

.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr);
  gap: clamp(2rem, 3vw, 3.5rem);
  align-items: center;
}

@media (max-width: 900px) {
  .hero__grid {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
}

.hero__title {
  font-size: clamp(2.5rem, 1.85rem + 2.7vw, 4.25rem);
  margin-bottom: 1rem;
  max-width: 15ch;
}

.hero__title em {
  font-style: normal;
  color: var(--blue-700);
  position: relative;
}

/* Kept on one line only where there is room for it. Below this the phrase
   is wider than the screen, and refusing to wrap pushed the whole hero
   column off the right edge. */
@media (min-width: 901px) {
  .hero__title em {
    white-space: nowrap;
  }
}

/* Same highlight on a page hero heading, but allowed to wrap: the phrases
   there are longer than the one on the home page. */
.page-hero h1 em {
  font-style: normal;
  color: var(--blue-700);
}

.hero__lede {
  font-size: var(--step-1);
  line-height: 1.55;
  color: var(--navy-900);
  max-width: 38rem;
  margin-bottom: 1.25rem;
}

.hero__body {
  color: var(--text-soft);
  max-width: 38rem;
  margin-bottom: var(--space-lg);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem;
  align-items: center;
}

/* The rally: animated arc + ball */
.rally {
  position: relative;
  width: 116%;
  max-width: 38rem;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
}

@media (max-width: 900px) {
  .rally {
    width: 100%;
    max-width: 26rem;
  }
}

/* The 3D rally has no fallback artwork, by design.

   A flat SVG copy of the same scene used to sit behind the stage, so every
   visit painted one picture and then swapped it for another once Three.js
   had loaded - 280ms measured locally, noticeably longer over the wire,
   because the two module files come to 733 KB. Two versions of the same
   rally, one replacing the other, read as a glitch rather than as a
   fallback, so the SVG is gone.

   When the scene cannot run at all - no WebGL, data saver on, the module
   failed, or the visitor asked for less motion - the art is removed rather
   than replaced, and the hero becomes a single text column. */
.rally__stage {
  position: absolute;
  inset: 0;
  display: none;
}

.rally__stage canvas {
  display: block;
  width: 100% !important;
  height: 100% !important;
}

.rally.is-3d .rally__stage {
  display: block;
  animation: rally-in 0.45s var(--ease) both;
}

@keyframes rally-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* The caption belongs to the scene, so it arrives with it rather than
   sitting under an empty square while Three.js downloads. */
.rally:not(.is-3d) .rally__caption {
  opacity: 0;
}

.rally.is-3d .rally__caption {
  opacity: 1;
  transition: opacity 0.45s var(--ease) 0.1s;
}

/* is-flat is set by motion.js when the scene is not going to happen. */
.rally.is-flat,
.hero__art:has(.rally.is-flat) {
  display: none;
}

.hero__grid:has(.rally.is-flat) {
  grid-template-columns: minmax(0, 1fr);
}

@media (prefers-reduced-motion: reduce) {
  /* motion.js returns before the scene is ever built, so nothing will
     arrive to fill the square. */
  .hero__art {
    display: none;
  }

  .hero__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

.rally__caption {
  position: absolute;
  left: 50%;
  bottom: -0.5rem;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--blue-600);
  opacity: 0.75;
  text-align: center;
  white-space: nowrap;
}

/* --------------------------------------------------------------------------
   8. Scoreboard (stats)
   -------------------------------------------------------------------------- */
.scoreboard {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  background: var(--white);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}

@media (max-width: 780px) {
  .scoreboard {
    grid-template-columns: repeat(2, 1fr);
  }
}

.stat {
  padding: clamp(1.5rem, 1rem + 2vw, 2.5rem) clamp(1rem, 0.5rem + 1.5vw, 1.75rem);
  text-align: center;
  position: relative;
}

.stat + .stat {
  border-left: 1px solid var(--rule);
}

@media (max-width: 780px) {
  .stat:nth-child(3) {
    border-left: none;
  }
  .stat:nth-child(n + 3) {
    border-top: 1px solid var(--rule);
  }
}

.stat__value {
  font-family: var(--font-display);
  font-size: clamp(2.5rem, 2rem + 2.5vw, 3.75rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--blue-700);
  display: block;
  margin-bottom: 0.5rem;
  font-variant-numeric: tabular-nums;
}

.stat__label {
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-soft);
  line-height: 1.4;
  display: block;
}

/* --------------------------------------------------------------------------
   9. Cards
   -------------------------------------------------------------------------- */
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.6rem, 1.15rem + 1.6vw, 2.2rem);
  /* A little lift at rest, not only on hover, so the card sits on the band
     rather than being painted onto it. */
  box-shadow: 0 1px 2px rgba(7, 27, 61, 0.04), 0 8px 20px rgba(7, 27, 61, 0.045);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}

/* On a tinted band the default rule is the same value as the ground, so the
   card reads as a solid tile with no edge. Step the border up one shade to
   restore the outlined look the cards have on white. */
.section--sky .card,
.section--sky .deliverable,
.section--sky .objective {
  border-color: var(--sky-200);
}

.card h3 {
  color: var(--navy-900);
}

.card:hover {
  transform: translateY(-4px);
  border-color: var(--sky-300);
  box-shadow: var(--shadow-md);
}

/* The icon is this family's mark, the way the numeral is the objectives' and
   the arc is the target groups'. A lit disc rather than a flat square: a
   soft gradient and a ring give it a surface to sit on. */
.card__icon {
  position: relative;
  display: grid;
  place-items: center;
  width: 3.4rem;
  height: 3.4rem;
  margin-bottom: 1.15rem;
  border-radius: 50%;
  background: radial-gradient(120% 120% at 30% 22%, var(--white) 0%, var(--sky-100) 62%, var(--sky-200) 100%);
  box-shadow: inset 0 0 0 1px var(--sky-200), 0 2px 6px rgba(7, 27, 61, 0.06);
  color: var(--blue-700);
  transition: box-shadow 0.3s var(--ease), transform 0.3s var(--ease);
}

.card:hover .card__icon {
  transform: translateY(-2px);
  box-shadow: inset 0 0 0 1px var(--sky-300), 0 6px 14px rgba(7, 27, 61, 0.1);
}

.card__icon svg {
  width: 1.85rem;
  height: 1.85rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.card__icon-accent {
  stroke: var(--coral-500);
}

.card:hover .card__icon {
  background: var(--sky-200);
}

.card h3 {
  font-size: var(--step-1);
}

.card p {
  color: var(--text-soft);
  font-size: 1rem;
}

.card p:last-child {
  margin-bottom: 0;
}

.grid {
  display: grid;
  gap: clamp(1rem, 0.5rem + 1.5vw, 1.75rem);
}

.grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.grid--3 {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.grid--4 {
  grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 960px) {
  .grid--3,
  .grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 620px) {
  .grid--2,
  .grid--3,
  .grid--4 {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Wayfinding cards (home) */
.waycard {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 11rem;
  padding: clamp(1.4rem, 1rem + 1.4vw, 1.9rem);
  background: var(--blue-700);
  color: var(--white);
  border-radius: var(--radius);
  text-decoration: none;
  overflow: hidden;
  isolation: isolate;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
}

.waycard::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(
    120% 120% at 85% 0%,
    var(--blue-600) 0%,
    var(--blue-700) 45%,
    var(--blue-800) 100%
  );
  transition: transform 0.5s var(--ease);
}

.waycard:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-lg);
}

.waycard:hover::before {
  transform: scale(1.12);
}

.waycard__icon {
  width: 2.25rem;
  height: 2.25rem;
  color: var(--sky-200);
  margin-bottom: 0.9rem;
}

.waycard__icon svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.waycard__title {
  font-family: var(--font-display);
  font-size: var(--step-1);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}

.waycard__title::after {
  content: "";
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--coral-500);
  flex: none;
  transition: transform 0.3s var(--ease);
}

.waycard:hover .waycard__title::after {
  transform: scale(1.6);
}

.waycard__desc {
  font-size: 0.92rem;
  color: rgba(226, 238, 252, 0.78);
  margin: 0.35rem 0 0;
  line-height: 1.5;
}

/* --------------------------------------------------------------------------
   10. Objectives — numbered because they genuinely are 1..4 in the project
   -------------------------------------------------------------------------- */
/* Objectives.
   These genuinely are a sequence — four objectives worked in order across
   the 34 months — so the number is the structure, not an ornament. It is
   set large and outlined, cropped by the top of the card, the way a set of
   points would be lettered in print. Same card shape as the target groups
   on this page; blue rather than coral, and a numeral rather than the arc. */
.objective {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1.15rem + 1.4vw, 2.1rem);
  overflow: hidden;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

.objective:hover {
  transform: translateY(-4px);
  border-color: var(--sky-300);
  box-shadow: var(--shadow-md);
}

.objective__num {
  position: absolute;
  top: -1.1rem;
  right: 1rem;
  font-family: var(--font-display);
  font-size: clamp(4.75rem, 3.4rem + 4vw, 7rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.05em;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--sky-300);
  text-stroke: 1.5px var(--sky-300);
  pointer-events: none;
  user-select: none;
  transition: transform 0.45s var(--ease), -webkit-text-stroke-color 0.45s var(--ease);
}

.objective:hover .objective__num {
  transform: translateY(0.25rem);
  -webkit-text-stroke-color: var(--blue-300);
}

.objective h3 {
  position: relative;
  font-size: var(--step-1);
  /* margin, not padding, so the rule stops short of the numeral too */
  margin: 0 clamp(2.5rem, 1.7rem + 2.6vw, 3.6rem) 0 0;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--sky-200);
}

.objective p {
  position: relative;
  color: var(--text-soft);
  font-size: 1rem;
  margin: 0;
}

/* --------------------------------------------------------------------------
   10b. Pull quote — the swan metaphor
   -------------------------------------------------------------------------- */
.pullquote {
  position: relative;
  margin: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(1.25rem, 1rem + 1.5vw, 2.25rem);
  row-gap: 0.85rem;
  align-items: start;
  padding: clamp(1.75rem, 1.25rem + 2vw, 2.75rem);
  background: var(--sky-50);
  border: 1px solid var(--sky-200);
  border-left: 3px solid var(--coral-500);
  border-radius: var(--radius);
}

@media (max-width: 640px) {
  .pullquote {
    grid-template-columns: 1fr;
    row-gap: 1.1rem;
  }
}

.pullquote__mark {
  width: clamp(7rem, 5rem + 6vw, 11rem);
  aspect-ratio: 1;
  height: auto;
  flex: none;
  grid-column: 1;
  /* Spans the caption row as well as the quote, so it sits against the whole
     text column rather than starting a line below it. */
  grid-row: 1 / span 2;
  align-self: center;
  /* contain, and no tile behind it: the artwork is transparent, so a filled
     panel would show as a square against the quote's own background. */
  object-fit: contain;
}

.pullquote blockquote {
  margin: 0;
}

.pullquote blockquote p {
  font-family: var(--font-display);
  font-size: var(--step-2);
  font-weight: 500;
  line-height: 1.35;
  letter-spacing: -0.02em;
  color: var(--navy-900);
  margin: 0;
}

.pullquote blockquote {
  grid-column: 2;
  grid-row: 2;
}

.pullquote figcaption {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-soft);
}

@media (max-width: 640px) {
  .pullquote figcaption,
  .pullquote__mark,
  .pullquote blockquote {
    grid-column: 1;
    grid-row: auto;
  }
}

/* --------------------------------------------------------------------------
   11. Activity cards (with art panel)
   -------------------------------------------------------------------------- */
.activity {
  display: flex;
  flex-direction: column;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease);
}

.activity:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
}

.media {
  position: relative;
  aspect-ratio: 16 / 9;
  background: linear-gradient(140deg, var(--blue-700) 0%, var(--blue-800) 100%);
  display: grid;
  place-items: center;
  overflow: hidden;
}

.media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: radial-gradient(
    rgba(255, 255, 255, 0.16) 1px,
    transparent 1px
  );
  background-size: 14px 14px;
  opacity: 0.6;
}

.media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 2;
}

.media__glyph {
  position: relative;
  z-index: 1;
  width: 46%;
  max-width: 9.5rem;
  color: var(--sky-200);
  opacity: 0.92;
}

.media__glyph svg {
  width: 100%;
  height: auto;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.media--sky {
  background: linear-gradient(140deg, var(--sky-200) 0%, var(--sky-100) 100%);
}

.media--sky .media__glyph {
  color: var(--blue-700);
  opacity: 0.5;
}

.media--sky::after {
  background-image: radial-gradient(rgba(18, 64, 155, 0.14) 1px, transparent 1px);
}

.activity__body {
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
}

.activity__body p {
  color: var(--text-soft);
  font-size: 1rem;
  margin: 0;
}

.activity__body strong {
  color: var(--blue-700);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   12. Target groups
   -------------------------------------------------------------------------- */
/* Target groups.
   The card carries the site's own mark rather than generic decoration: the
   rally arc with the ball on it, the same figure as the hero, the eyebrow
   tick and the underline on the current nav item. Cropped by the corner, so
   it reads as a stroke through the box rather than a sticker on it. */
.audience {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  background: var(--white);
  border: 1px solid var(--coral-500);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1.15rem + 1.4vw, 2.1rem);
  overflow: hidden;
  transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease),
    border-color 0.35s var(--ease);
}

/* the arc */
.audience::before {
  content: "";
  position: absolute;
  top: -3.2rem;
  right: -3.2rem;
  width: 7rem;
  height: 7rem;
  border-radius: 50%;
  border: 1.5px solid rgba(210, 105, 74, 0.5);
  transition: transform 0.45s var(--ease), border-color 0.45s var(--ease);
  pointer-events: none;
}

/* the ball, sitting on it */
.audience::after {
  content: "";
  position: absolute;
  top: 1.72rem;
  right: 3.05rem;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--coral-500);
  transition: transform 0.45s var(--ease);
  pointer-events: none;
}

.audience:hover {
  transform: translateY(-4px);
  border-color: var(--coral-600);
  box-shadow: 0 4px 14px rgba(184, 84, 58, 0.09), 0 20px 44px rgba(184, 84, 58, 0.13);
}

/* the rally carries on */
.audience:hover::before {
  transform: scale(1.13);
  border-color: rgba(210, 105, 74, 0.75);
}

.audience:hover::after {
  transform: translate(-0.5rem, -0.42rem);
}

.audience h3 {
  position: relative;
  font-size: var(--step-1);
  color: var(--navy-900);
  margin: 0;
  padding-right: 2.5rem;
}

.audience p {
  position: relative;
  font-size: 0.98rem;
  color: var(--text-soft);
  margin: 0;
}

/* --------------------------------------------------------------------------
   13. Resources — work packages
   -------------------------------------------------------------------------- */
/* Generous air on either side of the dividing rule, so each work package
   reads as its own block rather than as a continuation of the one above. */
.wp {
  border-top: 1px solid var(--rule);
  padding-top: clamp(3rem, 2rem + 3.5vw, 5rem);
  margin-top: clamp(3.5rem, 2.25rem + 4.5vw, 6rem);
}

.wp:first-of-type {
  border-top: none;
  margin-top: 0;
  padding-top: 0;
}

.wp__head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.75rem 1.25rem;
  margin-bottom: 0.75rem;
}

.wp__tag {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--white);
  background: var(--blue-700);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  white-space: nowrap;
}

.wp__title {
  font-size: var(--step-2);
  margin: 0;
}

.wp__note {
  color: var(--text-soft);
  max-width: 52rem;
  margin-bottom: var(--space-lg);
}

.wp__note strong {
  color: var(--navy-900);
  font-weight: 600;
}

/* Deliverable card */
.deliverable {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}

.deliverable:hover {
  transform: translateY(-4px);
  border-color: var(--sky-300);
  box-shadow: var(--shadow-md);
}

.deliverable__code {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--coral-600);
  text-transform: uppercase;
}

.deliverable__title {
  font-size: var(--step-1);
  margin: 0;
}

.deliverable__meta {
  font-size: 0.9rem;
  color: var(--text-soft);
  margin: 0;
}

.deliverable__meta strong {
  color: var(--navy-900);
  font-weight: 600;
}

.deliverable .btn {
  margin-top: auto;
  align-self: flex-start;
}

/* Upcoming state */
.upcoming {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 1.5rem;
  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
  background: var(--sky-50);
  border: 1px dashed var(--sky-300);
  border-radius: var(--radius);
}

.upcoming__badge {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--blue-700);
  background: var(--white);
  border: 1px solid var(--sky-300);
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  white-space: nowrap;
}

.upcoming p {
  margin: 0;
  color: var(--text-soft);
  font-size: 1rem;
}

/* --------------------------------------------------------------------------
   14. News
   -------------------------------------------------------------------------- */
.news-list {
  display: flex;
  flex-direction: column;
}

/* Info callout. Navy panel with the brand cyan, the same pairing as the
   grant code, so an aside reads as an aside against the pale sections.
   Reusable: title plus one short paragraph. */
.note {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 0.7rem;
  row-gap: 0.3rem;
  /* Centres the mark against a single-line note, and sits it against the
     first line when there is a body paragraph underneath. */
  align-items: center;
  max-width: 46rem;
  margin-top: 1.75rem;
  padding: clamp(1rem, 0.8rem + 0.7vw, 1.35rem) clamp(1.1rem, 0.85rem + 0.9vw, 1.5rem);
  background: var(--navy-950);
  border: 1px solid rgba(34, 172, 227, 0.32);
  border-radius: var(--radius-lg);
}

.note__icon {
  grid-column: 1;
  grid-row: 1;
  align-self: center;
  display: block;
  width: 1.1rem;
  height: 1.1rem;
  color: var(--cyan-500);
}

/* Only pull the rows apart when there actually is a second line. */
.note:has(.note__body) {
  align-items: start;
}

.note:has(.note__body) .note__icon {
  align-self: start;
  margin-top: 0.16rem;
}

.note__icon svg {
  width: 100%;
  height: 100%;
  fill: currentColor;
  display: block;
}

/* The mark punched out of the disc, so it stays legible on the cyan. */
.note__glyph {
  fill: var(--navy-950);
}

.note .note__title {
  grid-column: 2;
  grid-row: 1;
  font-family: var(--font-display);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.35;
  color: var(--cyan-500);
  margin: 0;
}

.note .note__body {
  grid-column: 2;
  grid-row: 2;
  font-size: 0.95rem;
  line-height: 1.55;
  color: #b7c9e2;
  margin: 0;
}

@media (max-width: 520px) {
  .note {
    column-gap: 0.55rem;
  }
}

/* Closed entries are rows in a list, divided by a rule and nothing else —
   five identical filled cards read as one block rather than five items.
   The entry you open becomes a card and lifts out of the list, which is
   where the separation is actually needed. */
.news-item {
  position: relative;
  background: transparent;
  border: 0;
  /* A neutral rule, and a definite one: it is the only thing dividing one
     entry from the next, so it has to be read at a glance. Deliberately not
     a blue — the cyan accent stays the only coloured line here. */
  border-top: 1px solid var(--grey-400);
  border-radius: 0;
  transition: background-color 0.3s var(--ease), box-shadow 0.35s var(--ease);
}

.news-item:last-child {
  border-bottom: 1px solid var(--grey-400);
}

/* The accent that marks the row you are pointing at, and the one you opened. */
.news-item::before {
  content: "";
  position: absolute;
  top: -1px;
  bottom: -1px;
  left: 0;
  width: 3px;
  background: var(--cyan-500);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.3s var(--ease);
  z-index: 1;
}

.news-item:hover {
  background: var(--cyan-50);
}

.news-item:hover::before {
  transform: scaleY(1);
}

/* Open: out of the list and onto the page. */
.news-item[open] {
  background: var(--white);
  border-top-color: transparent;
  border-radius: var(--radius-lg);
  box-shadow: 0 0 0 1px var(--cyan-500), 0 6px 16px rgba(23, 145, 195, 0.09),
    0 22px 48px rgba(23, 145, 195, 0.13);
  margin-block: 1.25rem;
  overflow: hidden;
}

.news-item[open]::before {
  transform: scaleY(1);
}

/* A rule between two closed rows is enough; drop the one that would double
   up against an open card's own edge. */
.news-item[open] + .news-item,
.news-item[open]:last-child {
  border-top-color: transparent;
}

.news-item__summary {
  display: block;
  padding: clamp(1.4rem, 1rem + 1.4vw, 2rem);
  cursor: pointer;
  list-style: none;
}

.news-item__summary::-webkit-details-marker {
  display: none;
}

.news-item__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--blue-600);
  margin-bottom: 0.75rem;
}

.news-item__type {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-weight: 500;
}

.news-item__type::before {
  content: "";
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--coral-500);
  flex: none;
}

.news-item__date {
  color: var(--text-soft);
  position: relative;
  padding-left: 1rem;
}

/* A dot, not a rule: at this size a 1px line reads as a stray dash rather
   than a separator. Echoes the middot used between the project codes in the
   footer, kept small so it does not compete with the coral type marker. */
.news-item__date::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--grey-400);
}

.news-item__title {
  font-size: var(--step-2);
  margin: 0 0 0.9rem;
  max-width: 46rem;
  transition: color 0.2s var(--ease);
}

.news-item:hover .news-item__title {
  color: var(--blue-700);
}

.news-item__more {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.6rem 1.2rem;
  border: 1.5px solid rgba(18, 64, 155, 0.3);
  border-radius: 999px;
  background: var(--white);
  font-weight: 600;
  font-size: 0.93rem;
  line-height: 1;
  color: var(--blue-700);
  transition: background-color 0.25s var(--ease), color 0.25s var(--ease),
    border-color 0.25s var(--ease);
}

.news-item__summary:hover .news-item__more,
.news-item[open] .news-item__more {
  background: var(--blue-700);
  border-color: transparent;
  color: var(--white);
}

.news-item__more::after {
  content: "";
  width: 0.55rem;
  height: 0.55rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-1px, -1px);
  transition: transform 0.3s var(--ease);
}

.news-item[open] .news-item__more::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}

.news-item__more-label--less {
  display: none;
}

.news-item[open] .news-item__more-label--more {
  display: none;
}

.news-item[open] .news-item__more-label--less {
  display: inline;
}

.news-item__detail {
  padding: 0 clamp(1.4rem, 1rem + 1.4vw, 2rem) clamp(1.4rem, 1rem + 1.4vw, 2rem);
}

.news-item__detail-inner {
  border-top: 1px solid var(--rule);
  padding-top: 1.4rem;
  max-width: 60rem;
  color: var(--text-soft);
}

.news-item__detail-inner p:last-child {
  margin-bottom: 0;
}

.news-item__detail-inner strong {
  color: var(--navy-900);
  font-weight: 600;
}

.news-item__detail-inner ul,
.news-item__detail-inner ol {
  margin: 0 0 1.1em;
  padding-left: 1.25rem;
}

/* Images inside an expanded entry. One <figure class="news-item__figure">
   per image; wrap two or more in <div class="news-item__gallery"> to set
   them side by side. Always give each <img> width and height attributes:
   the open animation measures the panel before the image has loaded. */
.news-item__figure {
  margin: 0 0 1.2em;
}

.news-item__figure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-sm);
  background: var(--sky-100);
}

.news-item__figure figcaption {
  margin-top: 0.55rem;
  font-family: var(--font-mono);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  color: var(--grey-600);
}

.news-item__gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
  margin-bottom: 1.2em;
}

.news-item__gallery .news-item__figure {
  margin-bottom: 0;
}

.news-item__detail-inner li {
  margin-bottom: 0.4em;
}

/* --------------------------------------------------------------------------
   14b. Legal pages
   The privacy notice is long, numbered prose. It reuses .container--narrow for
   its reading measure and only needs rhythm: room around each numbered
   heading, and lists that sit in the same measure as the paragraphs.
   -------------------------------------------------------------------------- */
.legal {
  color: var(--text-soft);
}

.legal h2 {
  margin-top: 2.6rem;
  margin-bottom: 0.9rem;
  font-size: clamp(1.15rem, 0.6vw + 1rem, 1.4rem);
}

.legal h2:first-child {
  margin-top: 0;
}

.legal p {
  margin-bottom: 1rem;
}

.legal ul {
  margin: 0 0 1.2rem;
  padding-left: 1.25rem;
  max-width: 46rem;
}

.legal li {
  margin-bottom: 0.45rem;
}

.legal strong {
  color: var(--navy-900);
  font-weight: 600;
}

/* Address and labelled blocks, set tighter than running prose. */
.legal__block {
  line-height: 1.6;
}

/* --------------------------------------------------------------------------
   15. Partners
   -------------------------------------------------------------------------- */
.partner {
  display: flex;
  flex-direction: column;
  gap: 0.85rem;
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  padding: clamp(1.4rem, 1rem + 1.2vw, 1.9rem);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease),
    border-color 0.3s var(--ease);
}

.partner:hover {
  transform: translateY(-4px);
  border-color: var(--sky-300);
  box-shadow: var(--shadow-md);
}

/* A fixed box rather than a fixed height: the real partner logos run from
   0.7:1 to 4.3:1, and sizing them by height alone would make the widest four
   times the visual weight of the tallest. */
.partner__logo {
  height: 3.75rem;
  display: flex;
  align-items: center;
}

.partner__logo img {
  max-height: 100%;
  max-width: 12rem;
  width: auto;
  object-fit: contain;
}

.partner__logo-fallback {
  display: grid;
  place-items: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: var(--radius-sm);
  background: var(--sky-100);
  color: var(--blue-700);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.1rem;
  letter-spacing: -0.02em;
}

.partner__role {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--coral-600);
}

.partner__name {
  font-size: 1.15rem;
  margin: 0;
}


.partner p {
  font-size: 0.96rem;
  color: var(--text-soft);
  margin: 0;
}

.partner__link {
  margin-top: auto;
  padding-top: 0.5rem;
}

/* Slot waiting to be filled in */
.partner--placeholder {
  border-style: dashed;
  border-color: var(--sky-300);
  background: rgba(255, 255, 255, 0.55);
}

.partner--placeholder .partner__name,
.partner--placeholder .partner__role {
  color: var(--grey-400);
}

.partner--placeholder .partner__logo-fallback {
  background: var(--white);
  color: var(--grey-400);
  border: 1px dashed var(--sky-300);
}

/* Coordinator gets a marked card */
.partner--lead {
  border-color: var(--blue-500);
  box-shadow: 0 0 0 1px rgba(44, 103, 206, 0.25);
}

.partner__badge {
  position: absolute;
  top: -0.7rem;
  left: clamp(1.4rem, 1rem + 1.2vw, 1.9rem);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--white);
  background: var(--blue-700);
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
}

.partner {
  position: relative;
  scroll-margin-top: 7rem;
}

.partner.is-flagged {
  border-color: var(--coral-500);
  box-shadow: 0 0 0 2px rgba(210, 105, 74, 0.28);
}

/* Partner logo banner — one combined image, replaceable as a single file */
.partners-banner {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--white);
  padding: clamp(1rem, 0.6rem + 1.2vw, 1.6rem) clamp(0.9rem, 0.5rem + 1vw, 1.4rem);
  display: flex;
  justify-content: center;
}

.partners-banner img {
  /* Sized by the file's own pixels, capped by the card. An image narrower
     than the card is shown at its native size rather than stretched, so it
     never blurs; a wider one fills the card and is sharp on retina too. */
  width: auto;
  max-width: 100%;
  height: auto;
}

/* Consortium map — Natural Earth geometry, partner countries filled */
.cmap {
  position: relative;
  background: var(--sky-50);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(0.75rem, 0.5rem + 1.5vw, 1.5rem);
}

.cmap__svg {
  width: 100%;
  height: auto;
  display: block;
}

.cmap__land path {
  fill: var(--sky-200);
  stroke: var(--sky-50);
  stroke-width: 1;
  pointer-events: none;
}

.cmap__country {
  pointer-events: none;
  fill: var(--blue-700);
  stroke: var(--white);
  stroke-width: 1.2;
  transition: fill 0.25s var(--ease);
}

.cmap__country.is-active {
  fill: var(--cyan-500);
}

.cmap__pin {
  cursor: pointer;
}

.cmap__halo {
  fill: var(--cyan-500);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}

.cmap__pin:hover .cmap__halo,
.cmap__pin:focus-visible .cmap__halo {
  opacity: 0.28;
}

.cmap__dot {
  fill: var(--white);
  stroke: var(--blue-800);
  stroke-width: 3;
  transition: fill 0.2s var(--ease);
}

.cmap__pin--lead .cmap__dot {
  fill: var(--coral-500);
  stroke: var(--coral-600);
}

.cmap__pin:hover .cmap__dot {
  fill: var(--cyan-500);
}

/* White casing keeps labels legible over land, sea and filled countries */
/* An invisible, finger-sized hit area per pin. The drawn halo is only about
   20px across on a phone, which is well under a comfortable tap target. */
.cmap__hit {
  r: 26px;
  fill: transparent;
  pointer-events: fill;
}

@media (max-width: 900px) {
  .cmap__hit {
    r: 62px;
  }
}

.cmap__abbr,
.cmap__place {
  paint-order: stroke fill;
  stroke: var(--white);
  stroke-width: 3.5px;
  stroke-linejoin: round;
  -webkit-user-select: none;
  user-select: none;
}

.cmap__abbr {
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.01em;
  fill: var(--navy-950);
}

.cmap__place {
  font-family: var(--font-mono);
  font-size: 12.5px;
  fill: var(--blue-800);
}

@media (max-width: 620px) {
  .cmap__abbr { font-size: 22px; }
  .cmap__place { font-size: 16px; }
  .cmap__dot { r: 11; }
}

.cmap__note {
  margin: 1.25rem 0 0;
  font-size: 0.92rem;
  color: var(--text-soft);
  /* Runs the width of the map rather than a 46rem measure: it is one short
     sentence pair, not a paragraph, and the map above it is this wide.
     Deliberately not balanced: this is running text, so each line should
     fill before the next one starts. */
  max-width: none;
}

/* Country strip */
.countries {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.countries li {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  letter-spacing: 0.06em;
  color: var(--blue-700);
  background: var(--white);
  border: 1px solid var(--sky-300);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
}

/* --------------------------------------------------------------------------
   16. CTA band
   -------------------------------------------------------------------------- */
.cta-band {
  position: relative;
  background: var(--navy-950);
  color: var(--text-invert);
  border-radius: var(--radius-lg);
  padding: clamp(2rem, 1.5rem + 3vw, 3.5rem);
  overflow: hidden;
  isolation: isolate;
}

.cta-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(
      90% 140% at 100% 0%,
      rgba(44, 103, 206, 0.55) 0%,
      transparent 60%
    ),
    radial-gradient(70% 120% at 0% 100%, rgba(210, 105, 74, 0.28) 0%, transparent 55%);
}

.cta-band h2 {
  color: var(--white);
  max-width: 22ch;
}

.cta-band p {
  color: #b7c9e2;
  max-width: 46rem;
}

/* --------------------------------------------------------------------------
   16b. EU funding statement (end of The Project)
   -------------------------------------------------------------------------- */
.funding {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(1.75rem, 1rem + 3vw, 3.5rem);
  align-items: center;
}

@media (max-width: 820px) {
  .funding {
    grid-template-columns: minmax(0, 1fr);
  }
}

.funding__text h2 {
  font-size: var(--step-3);
  max-width: 16ch;
}

.funding__text p {
  color: var(--text-soft);
  max-width: 38rem;
}

/* The grant code reads as an identifier, so it is set as one: the brand
   cyan from the logo, on navy. Cyan on white measures 2.6:1, well under the
   4.5:1 needed at this size; on navy it is 6.6:1. */
/* Scoped to beat `.funding__text p`, which is otherwise more specific and
   was quietly overriding the colour below. */
.funding__text .funding__code {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--cyan-500);
  background: var(--navy-950);
  border: 1px solid var(--navy-950);
  border-radius: var(--radius-sm);
  padding: 0.7rem 1.05rem;
  margin-bottom: 1.1rem;
}

.funding__link {
  margin-bottom: 0;
}

.funding__card {
  background: var(--white);
  border: 1px solid var(--rule);
  border-radius: var(--radius-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
  text-align: center;
  box-shadow: var(--shadow-sm);
}

.funding__card img {
  width: min(100%, 12rem);
  margin: 0 auto 1.4rem;
}

.funding__card p {
  font-size: 0.9rem;
  line-height: 1.65;
  color: var(--text-soft);
  margin: 0;
  text-wrap: pretty;
}

/* --------------------------------------------------------------------------
   17. Page hero (interior pages)
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  background: linear-gradient(170deg, var(--sky-200) 0%, var(--sky-100) 70%, var(--white) 100%);
  padding-block: clamp(3rem, 2rem + 5vw, 5.5rem) clamp(2.5rem, 2rem + 4vw, 4.5rem);
  overflow: hidden;
}

/* Shares the .container element, so constrain the children rather than the
   block itself — a max-width here would re-centre it against the viewport. */
.page-hero__inner {
  position: relative;
  z-index: 1;
}

.page-hero h1 {
  font-size: var(--step-4);
  margin-bottom: 0.75rem;
  max-width: 20ch;
}

.page-hero p {
  font-size: var(--step-1);
  line-height: 1.6;
  color: var(--navy-900);
  max-width: 44rem;
}

.page-hero__decor {
  position: absolute;
  right: -6rem;
  top: 50%;
  transform: translateY(-50%);
  width: 30rem;
  height: 30rem;
  color: var(--blue-500);
  opacity: 0.16;
  pointer-events: none;
}

.page-hero__decor svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
}

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

/* --------------------------------------------------------------------------
   18. Footer
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--peach-100);
  padding-block: var(--space-xl) var(--space-lg);
  border-top: 1px solid var(--peach-200);
}

.footer__top {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--space-lg);
  padding-bottom: var(--space-lg);
}

@media (max-width: 860px) {
  .footer__top {
    grid-template-columns: 1fr 1fr;
  }
  .footer__brand {
    grid-column: 1 / -1;
  }
}

@media (max-width: 520px) {
  .footer__top {
    grid-template-columns: 1fr;
  }
}

.footer__brand .brand {
  margin-bottom: 0.9rem;
}

.footer__tagline {
  font-size: 0.96rem;
  color: var(--grey-600);
  max-width: 26rem;
  margin: 0;
}

.footer__heading {
  font-family: var(--font-mono);
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey-600);
  margin: 0 0 0.9rem;
}

.footer__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.footer__list a {
  color: var(--navy-900);
  text-decoration: none;
  font-size: 0.98rem;
  transition: color 0.2s var(--ease);
}

.footer__list a:hover {
  color: var(--blue-700);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.footer__funding {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: var(--space-md);
  align-items: center;
  padding-block: var(--space-md);
  border-top: 1px solid var(--peach-200);
  border-bottom: 1px solid var(--peach-200);
}

@media (max-width: 700px) {
  .footer__funding {
    grid-template-columns: 1fr;
  }
}

.footer__eu {
  width: 11rem;
  flex: none;
}

.footer__disclaimer {
  font-size: 0.82rem;
  line-height: 1.6;
  color: var(--grey-600);
  margin: 0;
}

/* Set like the footer's other mono labels — uppercase, tracked, muted —
   rather than as a dark line under grey text. */
.footer__id {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--grey-600);
  margin: 0.75rem 0 0;
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  padding-top: var(--space-md);
  font-size: 0.85rem;
  color: var(--grey-600);
}

.footer__social {
  display: flex;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

.footer__social a {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 50%;
  background: var(--white);
  color: var(--blue-700);
  transition: transform 0.2s var(--ease), background-color 0.2s var(--ease);
}

.footer__social a:hover {
  transform: translateY(-2px);
  background: var(--blue-700);
  color: var(--white);
}

.footer__social svg {
  width: 1.1rem;
  height: 1.1rem;
  fill: currentColor;
}

/* --------------------------------------------------------------------------
   18b. Reading progress + hero depth layer
   -------------------------------------------------------------------------- */
.progress {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--cyan-500), var(--blue-600) 60%, var(--coral-500));
  z-index: 200;
  pointer-events: none;
}

/* Three.js constellation sits behind the hero content.
   Masked away from the left half so it never crosses the running text. */
.hero__depth {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.2s var(--ease);
  -webkit-mask-image: linear-gradient(95deg, transparent 30%, rgba(0, 0, 0, 0.45) 52%, #000 70%);
  mask-image: linear-gradient(95deg, transparent 30%, rgba(0, 0, 0, 0.45) 52%, #000 70%);
}

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

.hero__depth.is-ready {
  opacity: 1;
}

.hero > .container {
  position: relative;
  z-index: 1;
}

/* --------------------------------------------------------------------------
   19. Scroll reveal
   -------------------------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

.reveal-group > * {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.reveal-group.is-visible > * {
  opacity: 1;
  transform: none;
}

.reveal-group.is-visible > *:nth-child(1) { transition-delay: 0ms; }
.reveal-group.is-visible > *:nth-child(2) { transition-delay: 70ms; }
.reveal-group.is-visible > *:nth-child(3) { transition-delay: 140ms; }
.reveal-group.is-visible > *:nth-child(4) { transition-delay: 210ms; }
.reveal-group.is-visible > *:nth-child(5) { transition-delay: 280ms; }
.reveal-group.is-visible > *:nth-child(6) { transition-delay: 350ms; }

/* --------------------------------------------------------------------------
   20. Motion & print preferences
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .reveal,
  .reveal-group > * {
    opacity: 1;
    transform: none;
  }
}

@media print {
  .site-header,
  .nav__toggle,
  .cta-band {
    display: none;
  }

  body {
    color: #000;
  }
}

/* --------------------------------------------------------------------------
   14. Utilities lifted out of style="" attributes
   These were inline attributes until the site adopted a Content-Security-
   Policy that forbids inline styles. Same declarations, now in the cascade.
   -------------------------------------------------------------------------- */
.hero__actions--cta { margin-top: 1.75rem; }

/* A ghost button sitting on one of the dark bands. */
/* A platform mark inside a button. Sized in em so it tracks the label, and
   filled with currentColor so it inherits every .btn variant's colour. */
.btn__icon {
  width: 1.05em;
  height: 1.05em;
  fill: currentColor;
  flex: none;
}

.btn--on-dark {
  --btn-fg: #e4eff7;
  border-color: rgba(228, 239, 247, .35);
}

.container--spaced { margin-top: var(--space-xl); }

.footer__legal { margin: 0; }
