/*
  ============================================================================
  MAIN — couche de composants. Ne consomme QUE des rôles sémantiques.
  ============================================================================

  ⚠️ Aucune valeur hexadécimale dans ce fichier. Si un rôle manque, on l'ajoute
  dans `tokens.css` — on ne l'écrit pas ici. La règle date de l'époque des trois
  chartes ; elle tient toujours, pour une autre raison : une couleur en dur
  échappe à `npm run contrast`, qui ne mesure que ce qui est déclaré en tokens.

  ⚠️ `brandings.css` n'existe plus — le site n'a qu'une charte. Ne pas remettre
  d'import : `fonts.css` puis `tokens.css`, et c'est tout.
*/
@import url("fonts.css");
@import url("tokens.css");

/* ================================================================== Base */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /*
    ⚠️ AUCUNE RÉSERVE PAR DÉFAUT, ET C'EST SOLIDAIRE DU HEADER. Le header n'est
    sticky qu'à partir de 64em (voir « Header » plus bas) : en dessous, il défile
    avec la page et ne masque donc aucune cible d'ancre. Une réserve y
    décalerait les ancres vers le bas sans raison.

    Historique utile : la valeur a été de 6,75rem sous 30em et de 5rem au-delà,
    du temps où le header était sticky partout et ne portait que deux liens
    d'épreuve (97 px sur mobile, 62-65 px au-delà). Le menu en compte QUATRE
    depuis le retrait du bouton de conversion : replié, il monte à 132 px, ce
    qui reste trop pour rester collé en haut d'un écran de téléphone (il valait
    175 px à cinq éléments).
  */
  scroll-padding-top: 0;
  -webkit-text-size-adjust: 100%;
}

/*
  La réserve n'existe que là où le header est réellement sticky, et elle vaut sa
  hauteur mesurée sur une ligne (62-65 px). ⚠️ Le point de rupture est le MÊME
  que celui de `position: sticky` : les désynchroniser rendrait la cible de
  `#deposer-demande` — la conversion du site — masquée sous la barre.
*/
@media (min-width: 64em) {
  html {
    scroll-padding-top: 5rem;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--bg-page);
  color: var(--text-body);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  /* Réserve pour la barre d'action mobile, qui est en `position: fixed` et
     recouvrirait sinon la fin du footer. Remise à 0 quand la barre disparaît —
     les deux valeurs bougent ensemble, voir `.sticky-cta`.

     ⚠️ `--cookie-banner-h` s'y AJOUTE : le bandeau cookies est lui aussi en
     `position: fixed`, et il est bien plus haut que la barre. Sa hauteur est
     MESURÉE par assets/js/tracking.js (elle dépend de la longueur des textes et
     du nombre de boutons, donc de site.json) et posée sur `<html>`. Elle vaut
     0px quand le bandeau est fermé — c'est le repli de `var()`, et c'est aussi
     ce que voit un visiteur sans JavaScript. */
  padding-bottom: calc(4.5rem + var(--cookie-banner-h, 0px));
}

img,
svg {
  max-width: 100%;
}

img {
  height: auto;
}

a {
  color: var(--accent-bright);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

a:hover {
  text-decoration-thickness: 2px;
}

/*
  Focus visible. `outline` et non `box-shadow` : le mode contrastes forcés de
  Windows supprime les ombres portées et ne garde que les outlines — avec une
  ombre, il n'y aurait AUCUN focus visible dans ce mode. `--focus-ring` est une
  variable de contexte : les sections sombres la repassent en blanc plus bas, et
  l'héritage des custom properties suffit, sans dupliquer cette règle.
*/
:focus-visible {
  outline: var(--focus-w) solid var(--focus-ring);
  outline-offset: var(--focus-offset);
}

/* ================================================= Titres et prose partagée */
h1,
h2,
h3 {
  color: var(--text-strong);
  font-family: var(--font-display);
  font-weight: var(--display-weight);
  line-height: var(--lh-tight);
  letter-spacing: var(--display-tracking);
  margin: 0 0 var(--sp-4);
  text-wrap: balance;
  /*
    ⚠️ Garde-fou de DÉBORDEMENT, pas de confort. Un mot long en capitales à
    `--fs-hero` déborde la fenêtre : « CONFIDENTIALITÉ » réclame ~333 px à
    320 px de large, et `npm run layout` attrapait le scroll horizontal qui en
    résultait sur /politique-de-confidentialite/.

    `break-word` ne coupe QUE lorsque le mot ne tient pas sur une ligne à lui
    seul — les titres courts ne bougent pas.

    ⚠️ Pas de `hyphens: auto` ici, et ne pas le remettre. Il ajoutait bien le
    trait d'union (le `lang="fr"` du document donne le dictionnaire), mais il
    coupait en plein mot alors que le mot tenait sur la ligne SUIVANTE :
    « DOSSARDS RÉ- / SERVÉS » dans le hero de /devenir-association-beneficiaire/. Un titre en
    capitales à `--fs-hero` veut le retour à la ligne, pas la césure.
    Contrepartie assumée : la coupure du garde-fou ci-dessus se fait sans signe.
    ⚠️ Les deux dépôts d'épreuve n'ont jamais porté cette déclaration — ils sont
    déjà conformes, rien à y changer.
  */
  overflow-wrap: break-word;
}

h1,
h2 {
  text-transform: var(--display-transform);
}

/*
  `pre-line` rend actif le saut de ligne écrit dans le JSON (« \n » dans
  `hero.title`). C'est le seul levier de mise en page laissé à la rédaction :
  le contenu vit en JSON, donc pas de `<br>` à poser dans un gabarit paginé,
  et un titre de hero se coupe là où la phrase le demande, pas là où la
  largeur tombe.

  ⚠️ Ne vaut QUE pour le saut de ligne : `pre-line` réduit toujours les suites
  d'espaces, donc l'espace du gabarit entre `{{ doc.hero.title }}` et le `<em>`
  reste un espace simple. Et `text-wrap: balance` (plus haut) continue
  d'équilibrer chacun des deux fragments ainsi obtenus.

  ⚠️ Les deux gabarits écrivent leur `<h1>` sur UNE ligne source ; y revenir à
  la ligne rendrait ce retour visible dans la page.
*/
h1 {
  font-size: var(--fs-hero);
  white-space: pre-line;
}

h2 {
  font-size: var(--fs-h2);
}

/*
  h3 reste en bas-de-casse et droit, dans les trois thèmes. Deux raisons : les
  h3 portent des phrases (« Des collecteurs déjà motivés ») et non des libellés,
  et une page qui empile capitales + oblique à trois niveaux de titre devient
  illisible. C'est la règle des deux dépôts d'épreuve, reprise telle quelle.
*/
h3 {
  font-size: var(--fs-h3);
  line-height: var(--lh-snug);
  text-transform: none;
  font-style: normal;
}

p {
  margin: 0 0 var(--sp-4);
  max-width: var(--measure);
}

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

strong {
  color: var(--text-strong);
  font-weight: 700;
}

/* Surtitre. En capitales dans les trois thèmes : c'est un libellé, pas une
   phrase, et sa fonction est de nommer la section. */
.eyebrow {
  display: block;
  margin: 0 0 var(--sp-3);
  color: var(--accent-bright);
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  max-width: none;
}

.eyebrow--on-dark {
  color: var(--text-highlight-on-dark);
}

.lead {
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
}

/* ================================================================ Structure */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--narrow {
  max-width: 820px;
}

.section {
  position: relative;
  padding-block: var(--section-y);
}

.section--alt {
  background: var(--bg-alt);
}

.section--soft {
  background: var(--accent-soft);
}

/*
  Sections sombres. Trois choses basculent ensemble, et il faut les trois : la
  couleur du texte, celle des titres, et l'anneau de focus — un anneau bleu sur
  un aplat bleu nuit ne se voit pas (mesuré à 1,7:1 dans le dépôt Marathon).
*/
.section--accent,
.section--accent-deep,
.section--night {
  color: var(--text-on-dark-muted);
  --focus-ring: var(--c-white);
}

.section--accent {
  background: var(--bg-accent);
}

.section--accent-deep {
  background: var(--bg-accent-deep);
}

.section--night {
  background: var(--bg-night);
}

.section--accent h1,
.section--accent h2,
.section--accent h3,
.section--accent-deep h1,
.section--accent-deep h2,
.section--accent-deep h3,
.section--night h1,
.section--night h2,
.section--night h3 {
  color: var(--text-on-dark);
}

.section--accent strong,
.section--accent-deep strong,
.section--night strong {
  color: var(--text-on-dark);
}

.section--accent a:not(.btn),
.section--accent-deep a:not(.btn),
.section--night a:not(.btn) {
  color: var(--text-highlight-on-dark);
}

.section__head {
  margin-bottom: var(--sp-12);
}

.section__head > p {
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
}

/*
  Filet de marque : la signature graphique la moins coûteuse à décliner. Le
  neutre en fait un aplat, les deux épreuves un dégradé — `--rule-brand` change
  de NATURE d'un thème à l'autre, d'où `background` et non `background-color`.
*/
.rule {
  width: 100%;
  max-width: 240px;
  height: var(--rule-h);
  margin: 0 0 var(--sp-6);
  border: 0;
  background: var(--rule-brand);
}

.rule--full {
  max-width: none;
}

/* ================================================================= Boutons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.75rem 1.5rem;
  border: 2px solid transparent;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 700;
  letter-spacing: 0.02em;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

.btn--primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--text-on-accent);
}

.btn--primary:hover {
  background: var(--accent-deep);
  border-color: var(--accent-deep);
}

/* Bouton fantôme sur fond CLAIR : le trait porte l'accent, donc il est à
   `--accent`, pas à une bordure décorative. */
.btn--ghost {
  background: transparent;
  border-color: var(--accent);
  color: var(--accent);
}

.btn--ghost:hover {
  background: var(--accent);
  color: var(--text-on-accent);
}

/*
  Bouton fantôme sur fond SOMBRE. `--border-on-dark` vaut 0,55 d'opacité et pas
  0,24 : ce trait est la seule limite du bouton, il lui faut 3:1 (WCAG 1.4.11).
*/
.btn--ghost-dark {
  background: transparent;
  border-color: var(--border-on-dark);
  color: var(--text-on-dark);
}

.btn--ghost-dark:hover {
  background: var(--c-white);
  border-color: var(--c-white);
  color: var(--text-strong);
}

.btn--lg {
  padding: 1rem 2rem;
  font-size: var(--fs-body);
}

.btn--sm {
  padding: 0.5rem 1rem;
  font-size: var(--fs-eyebrow);
}

.btn--block {
  width: 100%;
}

@media (min-width: 40em) {
  .btn--block {
    width: auto;
  }
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
}

.actions__note {
  margin-top: var(--sp-4);
  font-size: var(--fs-small);
  color: var(--text-body);
}

/* ====================================================== Hero : sous-titre et chiffres */
/*
  Seconde ligne du titre de page. `<p>` et non `<h2>` : un titre de niveau 2 ici
  ouvrirait une section qui n'existe pas, et se mélangerait aux vrais <h2> de la
  page dans le plan du document. Il prend la fonte d'affichage de la charte
  parce qu'il PROLONGE le h1 — c'est une ligne de titre, pas du chapô.
*/
.section__head > p.hero__subtitle,
.hero__subtitle {
  margin: var(--sp-3) 0 var(--sp-6);
  max-width: none;
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--fs-subtitle);
  font-weight: var(--display-weight);
  letter-spacing: var(--display-tracking);
  line-height: var(--lh-tight);
  text-transform: var(--display-transform);
}

/*
  Les chiffres clés du PROGRAMME, sur une ligne. Ils ont remplacé la grille de
  quatre tuiles par épreuve : le contenu livré donne des chiffres agrégés sur
  les deux courses — une grille de tuiles serait disproportionnée pour trois
  valeurs qui ne dépendent plus d'une course.

  Le séparateur est en `::before` sur les items SUIVANTS, jamais après le
  dernier, et il est décoratif : `aria-hidden` n'existe pas en CSS, mais un
  pseudo-élément n'est de toute façon pas restitué comme du texte par les
  lecteurs d'écran modernes lorsqu'il ne porte que de la ponctuation.
*/
.hero__stats {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-4);
  margin: var(--sp-8) 0 0;
  padding: 0;
  max-width: none;
  list-style: none;
  color: var(--text-strong);
  font-size: var(--fs-small);
  font-weight: 700;
}

/*
  ⚠️ Le séparateur n'existe qu'à partir du moment où les chiffres tiennent
  RÉELLEMENT sur une ligne. En dessous, la liste passe en colonne et un point
  médian en tête de ligne se lit comme une puce mal réglée — le CSS ne sait pas
  détecter un retour à la ligne, d'où le point de rupture explicite.
*/
.hero__stats {
  flex-direction: column;
}

@media (min-width: 48em) {
  .hero__stats {
    flex-direction: row;
  }

  .hero__stats li + li::before {
    content: "\00B7 ";
    margin-right: var(--sp-4);
    color: var(--border-strong);
    font-weight: 400;
  }
}

/*
  ⚠️ PAS DE PHOTO EN PIED DE HERO — retirée le 4 septembre 2026, et ce n'est pas
  un oubli. La seule photo disponible pour cet emplacement était un recadrage de
  `hero-foule-2027.jpg` (dépôt Marathon) amputé de sa bande de barrières ASICS :
  ce qui rendait le cliché admissible ici le vidait aussi de son sujet. Le hero
  garde donc son `padding-bottom` normal, et `.section--hero` a disparu avec la
  figure — la classe ne servait QU'À passer ce padding à 0 pour coller la photo
  à l'aplat de `.section--alt`.
  Toute réintroduction d'image ici doit repasser par la règle « aucune épreuve
  n'est nommée » : voir docs/design-system.md.
*/

/* ========================================================= Les événements */
/*
  ⚠️ Cette liste est la SEULE de la page à parler d'une autre épreuve que celle
  du branding courant : elle les liste toutes. Le style reste donc neutre — pas
  de lockup, pas de couleur d'épreuve — sinon la carte du Semi porterait la
  charte du Marathon sur la page du Marathon, ce qui serait faux.
*/
.events {
  display: grid;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

.event {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-3) var(--sp-6);
  padding: var(--sp-6);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--bg-surface);
}

/* Le nom et la date occupent la place restante ; le bouton et son lien restent
   groupés à droite en grand écran, et repassent dessous en petit. */
.event__head {
  flex: 1 1 14rem;
}

.event__head h3 {
  margin: 0;
}

.event__date {
  margin: var(--sp-1) 0 0;
  max-width: none;
  font-size: var(--fs-small);
}

/*
  Les actions de la carte : LE bouton de demande, puis un lien discret SOUS lui.

  ⚠️ COLONNE, ET C'EST LE POINT. « Consulter le site dédié » était un
  `btn--ghost` à GAUCHE du bouton de demande jusqu'au 4 septembre 2026 : deux
  boutons de même taille côte à côte se lisent comme deux actions de même rang,
  alors qu'une seule est la conversion de la page. Le lien passe dessous, en
  `--fs-small` : la hiérarchie se voit sans rien lire.

  ⚠️ IL N'Y A PLUS DE PASTILLE DE STATUT (`.event__status`), et le lien discret
  n'est pas le retour du `.event__more` (« En savoir plus ») d'avant le
  3 septembre 2026 : ce qu'on reprochait à celui-là était de ne pas dire où il
  menait. Le statut, lui, vit toujours dans le LIBELLÉ du bouton principal.

  `margin-left: auto` colle le groupe à droite quand la carte tient sur une
  ligne ; en dessous, `.event` se replie et le groupe passe sous le titre, à
  gauche.
*/
.event__actions {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-left: auto;
  /*
    ⚠️ Pleine largeur SOUS 480 px, et le bouton s'y étire : « DÉPOSER UNE
    DEMANDE D'INTÉRÊT » ne tient pas en largeur automatique à cette taille, et
    un bouton court collé à gauche de la carte se lisait comme un accident.
    Étiré, le repli se lit comme une intention.
  */
  width: 100%;
  align-items: stretch;
}

/*
  Le lien discret. `--text-body` et non `--accent-bright` : un lien bleu sous un
  bouton bleu rejoue l'égalité de rang que la colonne vient de défaire. Le
  soulignement porte l'affordance de lien, la couleur d'accent arrive au survol.

  ⚠️ Centré sur le bouton (`align-self: center`) et non aligné à gauche : sous
  480 px le bouton occupe toute la carte, un lien collé à son bord gauche
  paraîtrait détaché de lui.
*/
.event__site-link {
  align-self: center;
  color: var(--text-body);
  font-size: var(--fs-small);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.event__site-link:hover {
  color: var(--accent-bright);
}

@media (min-width: 30em) {
  .event__actions {
    width: auto;
    align-items: center;
  }
}

/* ============================ Comment ça marche : prose + illustration */
/*
  Deux colonnes à partir de 60em — la prose, puis une photo verticale.

  ⚠️ LE CONTENEUR EST LE CONTENEUR PLEIN, et ça se tient avec la grille : la
  colonne de texte y mesure ~540 px, soit la longueur de ligne qu'un
  `container--narrow` (820 px) donnait en pleine largeur. Remettre
  `container--narrow` sans retirer la grille couperait la prose à ~380 px.

  ⚠️ Sous 60em, une seule colonne et la photo EN DERNIER : elle illustre le
  bloc, elle ne l'introduit pas. Au-dessus du texte, elle repousserait le titre
  de section hors du premier écran.
*/
.how {
  display: grid;
  gap: var(--sp-8);
}

@media (min-width: 60em) {
  .how {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.72fr);
    gap: var(--sp-16);
    align-items: center;
  }
}

/*
  `.section__head` porte une marge basse de 3rem, calibrée pour un titre qui
  précède une grille. Ici il précède une prose : la même marge ouvrirait un trou
  au milieu de la colonne.
*/
.how__body > .section__head {
  margin-bottom: var(--sp-6);
}

.how__figure {
  position: relative;
  margin: 0;
}

.how__figure img {
  display: block;
  position: relative;
  /* Au-dessus de l'aplat décalé du ::before. */
  z-index: 1;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  /* Le visage est dans le tiers haut : un cadrage centré le décapite. */
  object-position: 50% 28%;
  border-radius: var(--radius-lg);
}

@media (min-width: 60em) {
  .how__figure img {
    /* Le format natif de la photo (602x852). En colonne, plus de recadrage à
       faire : c'est la hauteur qui porte le bloc face à la prose. */
    aspect-ratio: 3 / 4;
    object-position: 50% 50%;
  }

  /*
    Aplat décalé derrière la photo — la seule respiration graphique de la page
    en dehors des aplats de section.

    ⚠️ IL DÉBORDE VERS LA GOUTTIÈRE INTERNE, jamais vers le bord de l'écran :
    le décalage de 1,5rem se loge dans le `gap` de 4rem à gauche et dans le
    padding bas de la section en dessous. C'est pour ça qu'il n'existe QU'À
    PARTIR DE 60em — empilé, la colonne touche la gouttière du conteneur
    (1,25rem au minimum) et l'aplat sortirait de la page, ce que
    `npm run layout` signalerait en débordement horizontal.
  */
  .how__figure::before {
    content: "";
    position: absolute;
    z-index: 0;
    left: calc(var(--sp-6) * -1);
    bottom: calc(var(--sp-6) * -1);
    width: 62%;
    height: 58%;
    background: var(--accent-soft);
    border-radius: var(--radius-lg);
  }
}

/* ============================================================ Bandeau photo */
/*
  Une respiration pleine largeur entre les étapes et la section sombre.

  ⚠️ IMAGE DE FOND, pas de `<img>` : le bandeau n'a pas de rapport de forme à
  respecter — sa hauteur est fixée par le `clamp`, la photo s'y recadre. Un
  `<img>` demanderait `object-fit` + `aspect-ratio` pour le même résultat, et
  exposerait un élément vide de plus à l'arbre d'accessibilité.

  ⚠️ Cette hauteur est un PLANCHER autant qu'un plafond : sous ~140 px, une
  photo de foule ne se lit plus et le bandeau passe pour une bande de couleur
  sale.
*/
.photo-band {
  height: clamp(150px, 24vw, 280px);
  background-image: url("/assets/img/band-coureurs.jpg");
  background-size: cover;
  background-position: center;
}

/* =========================================== Phrase mise en avant (statement) */
/*
  Une phrase isolée, en gras, qui porte la promesse d'un bloc — « L'intégralité
  des dons collectés revient à l'association », « L'éligibilité ne garantit pas
  l'attribution ». Le document livré les met en gras sur leur propre ligne :
  c'est une phrase d'appui, pas un paragraphe de plus.

  Sur fond sombre, la couleur est reprise par `.section--night strong` ; d'où le
  `<strong>` implicite du poids ici et la couleur héritée plutôt que forcée.
*/
.statement {
  margin-top: var(--sp-6);
  color: var(--text-strong);
  font-size: var(--fs-lead);
  font-weight: 700;
  line-height: var(--lh-snug);
}

.section--night .statement,
.section--accent-deep .statement {
  color: var(--text-on-dark);
}

/* ============================================================== Sous-blocs */
/*
  Deux sous-blocs sous un même titre de section — les conditions d'éligibilité
  et les règles d'attribution. Les fusionner en une seule liste ferait
  disparaître exactement ce qu'il fallait dire : remplir les conditions ne donne
  pas droit à des dossards.
*/
.subsections {
  display: grid;
  gap: var(--sp-12);
}

@media (min-width: 60em) {
  .subsections {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-8) var(--sp-16);
  }
}

.subsection h3 {
  margin-top: 0;
}

.subsection .statement {
  margin-top: var(--sp-4);
}

/* ========================================================= Étapes numérotées */
.steps__grid {
  display: grid;
  gap: var(--sp-8);
  margin: 0;
  padding: 0;
  list-style: none;
  /* Le compteur porte la numérotation : elle ne doit JAMAIS être écrite dans les
     titres, sinon insérer une étape demande de renuméroter la prose. */
  counter-reset: step;
}

@media (min-width: 48em) {
  .steps__grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 72em) {
  .steps__grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.step {
  counter-increment: step;
}

.step::before {
  content: counter(step);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  margin-bottom: var(--sp-4);
  background: var(--accent-soft);
  border-radius: var(--radius-pill);
  color: var(--text-on-soft);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: var(--display-weight);
  line-height: 1;
}

.step h3 {
  margin-bottom: var(--sp-2);
}

.step p {
  margin: 0;
  font-size: var(--fs-small);
}

/* =============================================================== Checklists */
.checklist {
  display: grid;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
  max-width: var(--measure);
}

.checklist li {
  position: relative;
  padding-left: 2rem;
}

/*
  La coche est un pseudo-élément et pas un caractère du texte : elle est
  décorative, un lecteur d'écran n'a pas à l'annoncer avant chaque item. La
  structure <ul>/<li> porte déjà l'information « liste ».
*/
.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 0.75rem;
  height: 0.4rem;
  border-left: 2.5px solid var(--accent-bright);
  border-bottom: 2.5px solid var(--accent-bright);
  transform: rotate(-45deg);
}

.checklist--on-dark li::before {
  border-color: var(--text-highlight-on-dark);
}

.checklist__note {
  margin-top: var(--sp-8);
  font-size: var(--fs-small);
}

/* ===================================================================== FAQ */
.faq__list {
  max-width: 860px;
  border-top: 1px solid var(--border);
}

.faq__item {
  border-bottom: 1px solid var(--border);
}

.faq__item summary {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 700;
  line-height: var(--lh-snug);
  cursor: pointer;
  list-style: none;
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

/* Le chevron est dessiné en CSS et marqué décoratif : `<details>` porte déjà
   l'état ouvert/fermé pour les technologies d'assistance. */
.faq__item summary::after {
  content: "";
  flex: 0 0 auto;
  width: 0.6rem;
  height: 0.6rem;
  margin-top: 0.4em;
  border-right: 2.5px solid var(--accent-bright);
  border-bottom: 2.5px solid var(--accent-bright);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.faq__item[open] summary::after {
  transform: rotate(-135deg);
}

.faq__answer {
  padding-bottom: var(--sp-6);
}

.faq__answer p {
  font-size: var(--fs-small);
}

.faq__answer p + p {
  margin-top: var(--sp-3);
}

.faq__answer ul {
  margin: var(--sp-3) 0 0;
  padding-left: 1.25rem;
  font-size: var(--fs-small);
}

.faq__answer li + li {
  margin-top: var(--sp-2);
}

/* --- Groupes de la FAQ ---
   La page FAQ est longue : sans découpage, elle se lit comme un mur. Chaque
   groupe porte son propre titre et son propre filet. */
.faq-group + .faq-group {
  margin-top: var(--sp-16);
}

.faq-group__head {
  margin-bottom: var(--sp-6);
}

.faq-group__head h2 {
  margin-bottom: var(--sp-2);
}

.faq-group__head p {
  font-size: var(--fs-small);
}

/* --- Sommaire ---
   Il n'est pas décoratif : c'est le seul moyen d'atteindre une question précise
   sans dérouler toute la page. D'où un vrai <nav> avec un intitulé. */
.toc {
  padding: var(--sp-6);
  background: var(--accent-soft);
  border-radius: var(--radius-md);
}

.toc__title {
  margin: 0 0 var(--sp-4);
  color: var(--text-on-soft);
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.toc__list {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 48em) {
  .toc__list {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--sp-2) var(--sp-8);
  }
}

.toc__list a {
  color: var(--text-on-soft);
  font-size: var(--fs-small);
  font-weight: 700;
}

/* ============================================================ Bloc plateforme */
.platform__mark {
  /*
    ⚠️ Le SVG du logotype Alvarum n'a PAS de viewBox : son rapport vient du
    couple width/height intrinsèque. Ne piloter QU'UNE dimension — hauteur fixe,
    largeur auto — sinon il se déforme.
  */
  height: 30px;
  width: auto;
  margin-bottom: var(--sp-6);
}

@media (min-width: 48em) {
  .platform__mark {
    height: 40px;
  }
}

/* ============================================================ Bloc de fin */
.cta-final {
  position: relative;
  overflow: hidden;
  background: var(--bg-night);
  color: var(--text-on-dark-muted);
  text-align: center;
  --focus-ring: var(--c-white);
}

.cta-final h2,
.cta-final strong {
  color: var(--text-on-dark);
}

/* Le titre du bloc de fin tient sur DEUX phrases — c'est la forme du contenu
   livré. En flux inline, la coupure tombait au milieu de la seconde
   (« FAITES-/EN PROFITER »), ce qui se lit mal en capitales. `display: block`
   n'empêche pas le dégradé : `background-clip: text` s'applique aussi bien à un
   bloc. ⚠️ Ne vaut QUE pour `.cta-final` : sur le h1 du hero, la coupure
   naturelle est la bonne. */
.cta-final h2 em {
  display: block;
}

.cta-final p {
  margin-inline: auto;
  font-size: var(--fs-lead);
}

.cta-final .btn {
  margin-top: var(--sp-8);
}

/* Le monogramme est décoratif (`alt=""` dans le template) : il ne porte aucune
   information que le titre ne dise déjà. Absent du thème neutre, qui n'en a
   pas — d'où le `{% if %}` côté template plutôt qu'une image vide ici. */
.cta-final__monogram {
  position: absolute;
  right: -2rem;
  bottom: -2rem;
  width: 220px;
  opacity: 0.14;
  pointer-events: none;
}

/* ================================================================== Header */
/*
  ⚠️ Ce header n'a ni panneau mobile, ni hamburger — il en avait un, plein écran
  sous 1200 px, avec le JS qui va avec ; `assets/js/nav.js` a été supprimé et le
  site n'exécute plus aucun JS. La barre porte QUATRE ENTRÉES ET RIEN D'AUTRE
  (le plan de /devenir-association-beneficiaire/, puis la FAQ), là où elle n'a longtemps porté
  que les deux liens d'épreuve. ⚠️ LE BOUTON DE CONVERSION EN A ÉTÉ RETIRÉ le
  4 septembre 2026 : cinquième élément et le plus large, il coûtait 200 px de
  menu et un rang de header entier sur téléphone.

  ⚠️ CE QUI TIENT LE REPLI, sans JS : `flex-wrap` sur `.header__inner` ET sur
  `.header__nav-list`. La liste passe sous la marque quand elle ne tient plus à
  côté d'elle, puis se coupe en deux rangs. Les entrées restent en `nowrap`
  individuellement — « Rejoindre le programme » sur deux lignes ne serait pas une
  dégradation acceptable.

  ⚠️ LE HEADER N'EST STICKY QU'À PARTIR DE 64em, ET C'EST UNE CONSÉQUENCE DU
  NOMBRE D'ENTRÉES. Mesuré à quatre entrées (`npm run layout`, le
  4 septembre 2026) : le menu demande 513 px, il les a à côté de la marque dès
  ~784 px de fenêtre et la barre tient alors sur une ligne, 62-65 px ; entre
  ~558 et ~783 px elle passe sous la marque sur un rang, 97 px ; en dessous elle
  se coupe en deux rangs, 132 px. Une barre de 132 px collée en haut mange
  encore un septième d'un écran de téléphone. En dessous du seuil elle défile
  donc avec la page ; la conversion y reste permanente par la barre d'action
  mobile (`partials/sticky-cta.njk`), qui existe pour ça.
  ⚠️ Les trois paliers ont BAISSÉ avec le retrait du bouton (714 px de menu,
  175/139/104 px de header) : le seuil de 64em est désormais plus prudent qu'il
  n'a besoin de l'être, et l'abaisser demanderait de bouger `scroll-padding-top`
  du même coup.
  ⚠️ Le seuil est répété dans `scroll-padding-top` (en haut de ce fichier) :
  changer l'un sans l'autre masque la cible des ancres du menu. Toute entrée
  ajoutée ou rallongée demande de relancer `npm run layout` et de reporter les
  hauteurs ici.
*/
.header {
  z-index: 50;
  background: var(--bg-page);
  border-bottom: 1px solid var(--border-light);
}

@media (min-width: 64em) {
  .header {
    position: sticky;
    top: 0;
  }
}

.header__inner {
  display: flex;
  align-items: center;
  /*
    `wrap` à TOUTES les largeurs, et c'est une correction d'accessibilité venue
    du dépôt du Semi : en `nowrap`, à 200 % de zoom TEXTE, la barre sortait de la
    fenêtre. Le rendu est identique tant qu'elle tient.
  */
  flex-wrap: wrap;
  /* Gouttière horizontale resserrée par rapport aux deux liens d'épreuve
     (`--sp-6`) : quatre entrées à espacer, pas deux. */
  gap: var(--sp-2) var(--sp-4);
  padding-block: var(--sp-3);
}

/*
  ⚠️ PAS DE LOCKUP, donc pas d'image : la marque est du TEXTE sur deux lignes.
  Le site n'est celui d'aucune épreuve — y poser un logo dirait le contraire — et
  c'est la seconde ligne (« pour les associations ») qui le distingue des deux
  sites d'épreuve, qui parlent aux coureurs.
*/
.header__brand {
  display: flex;
  flex-direction: column;
  margin-right: auto;
  text-decoration: none;
}

.header__brand-name {
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.05;
  text-transform: uppercase;
}

.header__brand-name strong {
  font-weight: var(--display-weight);
}

/* Seconde ligne : subordonnée au nom du programme, donc plus petite et en
   bas-de-casse — deux lignes en capitales se liraient comme deux marques. */
.header__brand-sub {
  color: var(--text-body);
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 500;
  line-height: 1.2;
}

.header__nav-list {
  display: flex;
  flex-wrap: wrap;
  /* `center` et non `baseline` : les entrées n'ont plus le bouton de conversion
     à côté d'elles (retiré le 4 septembre 2026), mais un alignement sur la ligne
     de base décentrerait tout élément plus haut qu'un lien qu'on remettrait ici. */
  align-items: center;
  gap: var(--sp-2) var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
  `nowrap` par entrée : « Rejoindre le programme » sur deux lignes n'est pas une
  dégradation acceptable. C'est la LISTE qui se replie — sous la marque quand la
  place manque à côté d'elle, puis sur deux rangs.

  ⚠️ LE SÉLECTEUR N'EXCLUT PLUS RIEN, parce qu'il n'y a plus de bouton dans
  cette liste (retiré le 4 septembre 2026). Il portait un `:not(.header__cta)` :
  `.header__nav-list a` (spécificité 0,1,1) l'emportait sur `.btn--primary`
  (0,1,0) et repeignait le libellé du bouton en `--text-strong`, du quasi-noir
  sur le bleu d'accent. ⚠️ Reposer un `.btn` ici demande de remettre
  l'exclusion.
*/
.header__nav-list a {
  color: var(--text-strong);
  font-family: var(--font-display);
  font-size: var(--fs-nav);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-decoration: none;
  text-transform: uppercase;
  white-space: nowrap;
}

.header__nav-list a:hover {
  color: var(--accent-bright);
  text-decoration: underline;
}

/* L'entrée qui désigne la page ouverte (la FAQ ; les trois autres sont des
   ancres de section, et une section n'est pas une page). Soulignée EN PLUS de la
   couleur : la couleur seule ne porte pas une information. */
.header__nav-list a[aria-current="page"] {
  color: var(--accent-bright);
  text-decoration: underline;
  text-underline-offset: 0.25em;
}

/* ================================================================== Footer */
/*
  Fond NOIR (voir « Rôles du FOOTER » dans tokens.css). Il n'y a plus qu'un
  footer : il portait auparavant le lockup et la signature verbale de la
  provenance, tous deux disparus avec les brandings. Reste le nom du programme,
  les liens, et le crédit Alvarum.
*/
.footer {
  padding-top: var(--section-y);
  background: var(--footer-bg);
  color: var(--footer-text);
  --focus-ring: var(--footer-focus);
}

.footer__grid {
  display: grid;
  gap: var(--sp-12);
  padding-bottom: var(--sp-12);
}

@media (min-width: 48em) {
  .footer__grid {
    grid-template-columns: 1.5fr 1fr;
  }
}

.footer__brand {
  color: var(--footer-text-strong);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: var(--display-weight);
  text-transform: uppercase;
}

.footer__tagline {
  font-size: var(--fs-small);
}

.footer__links {
  display: grid;
  gap: var(--sp-3);
  align-content: start;
}

.footer__links a {
  color: var(--footer-text-strong);
  font-size: var(--fs-small);
}

/*
  « Cookies » — la dernière entrée du pied de page, qui ROUVRE le bandeau de
  consentement.

  ⚠️ C'est un `<button>`, pas un `<a>` : il ne mène à aucune page. Il doit donc
  se dessiner comme les liens qui l'entourent sans en être un — d'où la remise à
  zéro des styles de bouton natif (`appearance`, fond, bordure, `text-align`) et
  le soulignement, qui est ce qui le rend cliquable à l'œil dans cette colonne.
*/
.footer__cookies {
  appearance: none;
  padding: 0;
  border: 0;
  background: none;
  color: var(--footer-text-strong);
  font: inherit;
  font-size: var(--fs-small);
  text-align: left;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
  cursor: pointer;
  /* `justify-self: start` : sans lui, le bouton prend toute la largeur de la
     grille du footer et sa zone cliquable s'étend loin après le mot. */
  justify-self: start;
}

.footer__cookies:hover {
  text-decoration-thickness: 2px;
}

/*
  « Propulsé par Alvarum », sur toutes les pages : le programme est une offre de
  l'organisateur de chaque épreuve, mais tout le PROCESSUS (inscription des
  associations, demandes de dossard, pré-inscription des coureurs, collecte) est
  opéré sur Alvarum.

  ⚠️ Version BLANCHE du logotype : le lockup bleu #3545ee sur le noir du footer
  est illisible.
*/
.footer__powered {
  display: inline-flex;
  align-items: center;
  /* Le crédit se replie sur deux lignes plutôt que de déborder : le lockup fait
     141 px à 22 px de haut, et sous ~330 px de fenêtre il ne tient plus à côté
     de son libellé. Mesuré par `npm run layout`, qui attrapait un scroll
     horizontal de 4 px à 320 px. */
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-8);
  text-decoration: none;
}

.footer__powered-label {
  color: var(--footer-text);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.footer__powered-logo {
  height: 22px;
  width: auto;
}

.footer__legal {
  padding-block: var(--sp-6);
  border-top: 1px solid var(--footer-border);
  font-size: var(--fs-eyebrow);
}

.footer__legal p {
  max-width: none;
}

/* 0,85 et non 0,75 : à 12 px, la mention doit rester lisible. Sur noir, 0,85
   donne 10,7:1. */
.footer__provider {
  margin-top: var(--sp-1);
  opacity: 0.85;
}

/* ====================================================== Barre d'action mobile */
/*
  ⚠️ Elle ne prend plus le relais d'un CTA de header — le header n'en a plus —
  mais son point de rupture reste SOLIDAIRE du `padding-bottom` du body : la
  barre est en `position: fixed` et recouvrirait sinon la fin du footer. Les
  deux valeurs bougent ensemble.
*/
.sticky-cta {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 40;
  padding: var(--sp-3) var(--gutter);
  padding-bottom: max(var(--sp-3), env(safe-area-inset-bottom));
  background: var(--bg-page);
  border-top: 1px solid var(--border-light);
}

.sticky-cta .btn {
  width: 100%;
}

@media (min-width: 75em) {
  .sticky-cta {
    display: none;
  }

  body {
    padding-bottom: var(--cookie-banner-h, 0px);
  }
}

/* ============================================================ Bandeau cookies */
/*
  ⚠️ DISCRET, NON BLOQUANT, ET IL NE RECOUVRE RIEN DE DURABLE.

  Trois décisions de mise en forme, et les trois portent du sens :

    1. AUCUN VOILE, aucun `backdrop`, aucun centrage à l'écran. Le bandeau est
       une barre en bas de page : la page reste lisible et utilisable sans
       répondre. Un voile ferait de la question un péage ;
    2. il se pose AU-DESSUS de la barre d'action mobile (`bottom: 4.5rem` sous
       75em, la hauteur de `.sticky-cta`), et pas dessous : deux barres
       superposées cacheraient la conversion, qui est la raison d'être du site.
       Le `z-index` s'insère ENTRE la barre d'action (40) et le header (50) ;
    3. `max-height: 70vh` + défilement interne : sur un téléphone en paysage,
       trois boutons et deux paragraphes dépassent la hauteur de l'écran, et un
       bandeau plus grand que la fenêtre n'a plus de bouton atteignable.

  ⚠️ Le contenu est plafonné à `--container` et NON à `container--narrow` : le
  bandeau doit s'aligner sur le reste de la page, sinon il flotte de travers
  au-dessus du footer.
*/
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 4.5rem;
  z-index: 45;
  padding: var(--sp-4) var(--gutter);
  padding-bottom: max(var(--sp-4), env(safe-area-inset-bottom));
  max-height: 70vh;
  overflow-y: auto;
  background: var(--cookie-bg);
  color: var(--cookie-text);
  border-top: 1px solid var(--cookie-border);
  box-shadow: var(--cookie-shadow);
}

@media (min-width: 75em) {
  /* La barre d'action mobile a disparu à ce seuil (voir `.sticky-cta`) : le
     bandeau redescend au ras de la fenêtre. ⚠️ Le seuil est SOLIDAIRE de celui
     de `.sticky-cta` — les désynchroniser laisse soit un trou de 4,5rem sous le
     bandeau, soit deux barres l'une sur l'autre. */
  .cookie-banner {
    bottom: 0;
  }
}

.cookie-banner__inner {
  position: relative;
  max-width: var(--container);
  margin: 0 auto;
  display: grid;
  gap: var(--sp-4);
  /* Réserve pour la croix, qui est en absolu dans ce bloc. */
  padding-right: var(--sp-8);
}

@media (min-width: 60em) {
  /*
    Au-delà, le texte et les boutons tiennent côte à côte : le bandeau fait une
    seule ligne haute, ce qui est la forme la moins intrusive. En dessous, les
    boutons passent sous le texte — les mettre à côté à 390px les réduirait à
    des cibles de 90px de large.
  */
  .cookie-banner__inner {
    grid-template-columns: 1fr auto;
    align-items: center;
    gap: var(--sp-8);
  }
}

.cookie-banner__title {
  margin: 0 0 var(--sp-1);
  font-weight: 700;
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.cookie-banner__body {
  margin: 0;
  font-size: var(--fs-small);
  /* La mesure du texte courant s'applique aussi ici : une phrase qui court sur
     1200px ne se lit pas. */
  max-width: var(--measure);
}

.cookie-banner__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/*
  ⚠️ TOUS LES BOUTONS SONT DE MÊME TAILLE ET DANS LE MÊME FLUX. Le refus est un
  bouton à côté de l'accord, pas un lien relégué : la CNIL demande qu'il soit
  aussi simple à actionner. Seul le REMPLISSAGE distingue l'accord (primaire) du
  reste — c'est une hiérarchie visuelle, pas une différence d'effort.
*/
.cookie-banner__actions .btn {
  /*
    ⚠️ DEUX BOUTONS PAR RANG, PAS TROIS EMPILÉS. Avec `flex: 1 1 auto`, les
    trois réponses prenaient chacune toute la largeur : le bandeau montait à
    375 px sur un écran de 390, soit près de la moitié de la fenêtre — ce n'est
    plus un bandeau discret, c'est un panneau. La base à 50 % les apparie.
  */
  flex: 1 1 calc(50% - var(--sp-3));
  justify-content: center;
}

@media (min-width: 60em) {
  .cookie-banner__actions .btn {
    flex: 0 0 auto;
  }
}

/*
  La croix ne vaut ni accord ni refus : elle met la question en veille pour
  l'onglet. Elle est donc DISCRÈTE — mais garde une cible de 44px, parce qu'un
  bouton de fermeture minuscule est le premier reproche fait aux bandeaux.
*/
.cookie-banner__close {
  position: absolute;
  top: calc(-1 * var(--sp-2));
  right: calc(-1 * var(--sp-2));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--cookie-text);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
}

.cookie-banner__close:hover {
  background: var(--bg-alt);
}

/* ========================================================== Pages juridiques */
/*
  Mentions légales et politique de confidentialité : beaucoup de titres, peu de
  hiérarchie. Deux écarts avec le reste du site, et les deux sont voulus :

    1. les `h2` descendent à `--fs-h3` et perdent les capitales. Une page qui
       empile huit `h2` à `--fs-h2` (jusqu'à 2,75rem, en capitales) se lit comme
       huit affiches, pas comme un document ;
    2. la mesure reste celle du texte courant (`container--narrow`), parce que
       c'est du texte suivi et rien d'autre.
*/
.legal__updated {
  margin-bottom: var(--sp-12);
  color: var(--text-body);
  font-size: var(--fs-small);
  font-style: italic;
}

.legal__section + .legal__section {
  margin-top: var(--sp-12);
}

.legal .legal__section h2 {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-h3);
  line-height: var(--lh-snug);
  text-transform: none;
}

.legal__body p + p,
.legal__body ul {
  margin-top: var(--sp-4);
}

.legal__body ul {
  padding-left: var(--sp-6);
}

.legal__body li + li {
  margin-top: var(--sp-2);
}

/* ================================================================ Utilitaires */
.skip-link {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 100;
  padding: var(--sp-3) var(--sp-4);
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: var(--fs-small);
  font-weight: 700;
  /* Hors écran mais FOCALISABLE — `display: none` le retirerait de l'ordre de
     tabulation, et le lien d'évitement ne servirait plus à rien. */
  transform: translateY(-120%);
}

.skip-link:focus-visible {
  transform: translateY(0);
}

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

.notice {
  padding: var(--sp-6);
  background: var(--accent-soft);
  border-left: var(--rule-h) solid var(--accent-bright);
  border-radius: var(--radius-sm);
}

.notice h3 {
  margin-bottom: var(--sp-2);
}

.notice p {
  margin: 0;
  font-size: var(--fs-small);
  color: var(--text-on-soft);
}

/* ================================================== Le mot mis en avant (<em>) */
/*
  Les titres de contenu se coupent en deux : `title` + `titleEm`, le second dans
  un `<em>`. Les deux chartes d'épreuve y posaient un DÉGRADÉ découpé sur le
  texte (`background-clip: text`), avec le garde-fou qui allait avec — le
  sélecteur devait lister nommément les brandings qui avaient un dégradé, faute
  de quoi le titre devenait invisible sur ceux qui n'en avaient pas.

  Plus de dégradé, donc plus de garde-fou : le fragment prend simplement la
  couleur d'accent. ⚠️ `font-style: inherit` reste nécessaire — un `<em>` est
  italique par défaut, et l'italique n'est pas dans la charte des titres.
*/
h1 em,
h2 em {
  color: var(--accent-bright);
  font-style: inherit;
}

/* ⚠️ Sur fond sombre, l'accent bleu tombe à 2,4:1 : c'est la menthe qui prend
   le relais (10:1). Sélecteurs plus spécifiques que la règle ci-dessus, donc
   l'ordre du fichier n'y change rien. */
.section--accent h1 em,
.section--accent h2 em,
.section--accent-deep h1 em,
.section--accent-deep h2 em,
.section--night h1 em,
.section--night h2 em,
.cta-final h2 em {
  color: var(--text-highlight-on-dark);
}
