/* ============================================================
   AJUSTEMENTS WORDPRESS
   Tout ce qui n'existe pas dans le wireframe : barre d'admin,
   images réelles à la place des placeholders, formulaires CF7,
   états cachés pilotés par main.js. Aucun autre fichier CSS ne
   doit être modifié : tokens/typography/base sont des copies
   conformes du wireframe.
   ============================================================ */

/* Les panneaux pilotés par JS restent invisibles même si leur classe
   pose un display explicite. */
[hidden] {
  display: none !important;
}

/* Barre d'admin WordPress : l'en-tête est sticky/fixe sous elle. */
body.admin-bar .entete {
  top: var(--wp-admin--admin-bar--height, 32px);
}

/* Wordmark de l'en-tête : dégradé en barre pleine, blanc quand l'en-tête
   flotte sur le héros (swap de variantes de Header.jsx : les deux logos
   sont rendus, le CSS n'en montre qu'un, et le logotype repasse en
   currentColor à l'état flottant). */
.entete .wordmark__logo--blanc {
  display: none;
}
.entete--flottante .wordmark__logo--blanc {
  display: inline;
}
/* !important : la variante dégradé porte un display inline-block en
   style inline (nécessaire au masque), qui gagnerait sinon. */
.entete--flottante .wordmark__logo--degrade {
  display: none !important;
}
.entete--flottante .logotype--degrade {
  fill: currentColor;
}

/* Image réelle affichée dans un conteneur .ph : mêmes coins et le label
   n'existe pas — l'img remplace le placeholder. */
img.ph {
  display: block;
  object-fit: cover;
  width: 100%;
}
/* Le visuel de tête de carte déborde du padding (pleine largeur de la
   carte) : sa largeur calculée doit gagner sur le width de img.ph. */
img.fiche__photo {
  width: calc(100% + var(--sp-5) * 2);
  max-width: none;
}

/* Contenu d'article (blocs Gutenberg) : on retombe sur la .prose du
   wireframe, déjà stylée par base.css. */
.prose > p + p {
  margin-top: 1em;
}

/* Description d'antenne multi-paragraphes dans l'intro de tête de page
   (the_content dans un div, le reset global annule les marges). */
.tete-page__intro p + p {
  margin-top: 0.8em;
}

/* Le bandeau Grand Trail : base.css référence /photos/…, chemin du
   wireframe — on repointe vers la copie embarquée dans le thème. */
.bandeau--illustre::before {
  background-image: url('../img/hero-trail-coutach.jpg');
}

/* Alternance gauche/droite des blocs (infrastructures) : la classe
   existait dans le wireframe sans règle associée. */
.grille--2 .ordre-second {
  order: 1;
}

/* ——— Titres sur une ligne quand ils le peuvent ———————————————— */
/* base.css plafonne les titres de tête de page à 14ch : « La semaine
   au club » ou « Adhésion & licences » cassaient en deux lignes alors
   que la place ne manque pas. On rend la pleine largeur ; text-wrap:
   balance répartit proprement les titres vraiment longs. */
.tete-page__titre {
  max-width: none;
  text-wrap: balance;
}
.produit__nom {
  max-width: none;
  text-wrap: balance;
}

/* Vignette latérale des cartes de pratiques : coins gauches arrondis
   (au rayon de la carte), coins droits vifs — l'image se prolonge dans
   la ligne de la carte au lieu de flotter avec ses propres coins. */
.fiche--laterale .fiche__vignette {
  border-radius: var(--r-md) 0 0 var(--r-md);
}

/* ——— Planning : ajustements ponctuels ——————————————————————— */
/* Badges d'état des séances (annulée / modifiée / événement). */
.planning__badge {
  display: inline-block;
  margin-left: var(--sp-2);
  padding: 1px 8px 2px;
  border-radius: 2px;
  font-size: var(--fs-xs);
  font-weight: 650;
  vertical-align: middle;
  white-space: nowrap;
}
.planning__badge--annule {
  background: color-mix(in srgb, var(--c-accent) 10%, transparent);
  color: var(--c-secondary);
}
.planning__badge--modifie {
  background: color-mix(in srgb, var(--c-vif) 14%, transparent);
  color: var(--c-vif);
}
.planning__badge--evenement {
  background: var(--c-accent);
  color: var(--c-on-accent);
}
.planning__creneau--annule .planning__heures,
.planning__creneau--annule .planning__pratique a,
.planning__creneau--annule .planning__public,
.planning__creneau--annule .planning__lieu {
  text-decoration: line-through;
  opacity: 0.55;
}
/* La colonne du jour se contente de 115px — « Mercredi 10 sept. » y tient
   encore — et se rapproche des horaires : les pixels rendus vont aux
   colonnes fluides, dont le descriptif de séance. Sous 900px, base.css
   empile le jour au-dessus de ses créneaux : rien à reprendre là. */
@media (min-width: 901px) {
  .planning__jour {
    grid-template-columns: 115px minmax(0, 1fr);
    gap: var(--sp-3);
  }
}

/* Les conditions d'accès se rangent sous le nom de la séance, en second
   plan : la colonne qu'elles occupaient revient au descriptif. */
.planning__public {
  display: block;
  font-weight: 400;
  margin-top: 2px;
}
.planning__note {
  color: var(--c-secondary);
  font-size: var(--fs-sm);
}
.planning__date {
  margin-left: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--c-secondary);
  letter-spacing: 0;
}
/* Barre du planning : période à gauche, groupe de vues tout à droite.
   Elle emprunte .semaine-nav au ticker de /semaine/ (mêmes gestes, même
   remplacement de #planning par fetch) et n'ajoute que ses écarts. */
.planning-nav {
  gap: var(--sp-2);
}
/* Chevron des boutons de période : plus gros que le texte, mais sans
   peser sur la hauteur du bouton (line-height ramené à 0). */
.planning-nav__chevron {
  font-size: 1.35em;
  line-height: 0;
  vertical-align: -0.06em;
  color: var(--c-faint);
}
.btn:hover .planning-nav__chevron {
  color: inherit;
}

/* Groupe segmenté des deux vues : un seul bloc, un filet entre les deux,
   la vue active en plein. Poussé au bout de la ligne. */
.planning-nav__vues {
  margin-left: auto;
  display: inline-flex;
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  overflow: hidden;
}
.planning-nav__vue {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 40px;
  color: var(--c-secondary);
  background: var(--c-surface);
  transition: background 0.15s ease, color 0.15s ease;
}
.planning-nav__vue + .planning-nav__vue {
  border-left: 1px solid var(--c-line);
}
.planning-nav__vue:hover {
  background: var(--c-raised);
  color: var(--c-text);
}
.planning-nav__vue.est-active {
  background: var(--c-accent);
  color: var(--c-on-accent);
}

/* ---------- Calendrier mensuel (onglet « Calendrier ») ----------
   Grille lundi→dimanche : chaque case est un lien vers sa semaine
   dépliée. Les créneaux y sont réduits à « heure + libellé » ; au-delà
   de trois, un « +N » tient la promesse sans casser la hauteur de rang. */

.planning-mois {
  border: 1px solid var(--c-hairline);
  border-top: 2px solid var(--c-line);
}

.planning-mois__entete,
.planning-mois__grille {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.planning-mois__entete {
  border-bottom: 1px solid var(--c-hairline);
  background: var(--c-raised);
}

.planning-mois__nom-jour {
  padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-secondary);
}

.planning-mois__nom-jour + .planning-mois__nom-jour {
  border-left: 1px solid var(--c-hairline);
}

.planning-mois__jour {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 108px;
  padding: var(--sp-2);
  border-top: 1px solid var(--c-hairline);
  color: inherit;
  transition: background 0.15s ease;
}

/* Les six premières cases forment la première ligne : pas de filet au-dessus */
.planning-mois__jour:nth-child(-n + 7) {
  border-top: 0;
}

.planning-mois__jour:not(:nth-child(7n + 1)) {
  border-left: 1px solid var(--c-hairline);
}

.planning-mois__jour:hover {
  background: var(--c-raised);
}

.planning-mois__jour--hors-mois {
  background: color-mix(in srgb, var(--c-hairline) 40%, transparent);
}

.planning-mois__jour--hors-mois .planning-mois__num,
.planning-mois__jour--hors-mois .planning-mois__creneau {
  opacity: 0.5;
}

.planning-mois__jour--vide {
  color: var(--c-faint);
}

/* Repère de jour utile seulement en liste (petit écran) : en grille,
   l'en-tête de colonne le dit déjà. */
.planning-mois__jour-abrege {
  display: none;
  font-size: var(--fs-xs);
  color: var(--c-faint);
}

.planning-mois__num {
  font-weight: 650;
  font-size: var(--fs-sm);
  color: var(--c-secondary);
}

/* Aujourd'hui : pastille pleine sur le seul numéro, pas sur la case —
   la case active reste celle que l'on survole. */
.planning-mois__jour--aujourdhui .planning-mois__num {
  align-self: flex-start;
  min-width: 1.6em;
  padding: 1px 5px;
  border-radius: 999px;
  text-align: center;
  background: var(--c-action);
  color: var(--c-on-action);
}

.planning-mois__creneau {
  display: flex;
  gap: 6px;
  align-items: baseline;
  font-size: var(--fs-xs);
  line-height: 1.3;
  border-left: 2px solid var(--c-action);
  padding-left: 5px;
}

.planning-mois__heure {
  font-weight: 650;
  white-space: nowrap;
}

.planning-mois__libelle {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--c-secondary);
}

.planning-mois__creneau--annule {
  border-left-color: var(--c-faint);
  text-decoration: line-through;
  opacity: 0.6;
}

.planning-mois__creneau--modifie {
  border-left-color: var(--c-vif);
}

.planning-mois__creneau--evenement {
  border-left-color: var(--c-accent);
}

.planning-mois__reste {
  font-size: var(--fs-xs);
  color: var(--c-faint);
  padding-left: 7px;
}

/* Sous 780px la grille de sept colonnes devient illisible : le mois se
   relit en liste, une ligne par jour, et les jours vides disparaissent. */
@media (max-width: 780px) {
  .planning-mois__entete {
    display: none;
  }

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

  .planning-mois__jour {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: var(--sp-2);
    min-height: 0;
    border-left: 0 !important;
    border-top: 1px solid var(--c-hairline);
  }

  .planning-mois__jour--vide,
  .planning-mois__jour--hors-mois {
    display: none;
  }

  .planning-mois__jour-abrege {
    display: inline;
    order: -1;
  }

  .planning-mois__num {
    min-width: 1.5em;
  }
}

/* Mini-carte (fiches événements du Club) : image en tête + nom. */
.fiche--mini__nom {
  font-size: var(--fs-lg);
  margin-top: var(--sp-4);
}

/* Puce-carte compacte (pratiques, page Le club) : image carrée à
   gauche, nom centré à droite — la hauteur se réduit à la vignette. */
.fiche--compacte {
  grid-template-columns: 64px minmax(0, 1fr);
}
.fiche--compacte .fiche__vignette {
  aspect-ratio: 1 / 1;
}
.fiche--compacte .fiche__corps {
  /* le corps de fiche est un flex en colonne : justify-content centre
     verticalement, le texte reste aligné à gauche. */
  justify-content: center;
  padding-block: var(--sp-3);
}
.fiche--compacte__nom {
  font-size: var(--fs-md);
  line-height: 1.2;
}

/* Cartes partenaires : logo en tête (jamais recadré), monogramme de
   repli tant que le logo n'est pas fourni (image mise en avant). */
.fiche.partenaire {
  align-items: center;
  text-align: center;
  justify-content: center;
  min-height: 190px;
}
.partenaire__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 72px;
  width: 100%;
  margin-bottom: var(--sp-2);
}
.partenaire__logo img {
  max-height: 100%;
  max-width: 70%;
  width: auto;
  object-fit: contain;
}
.partenaire__monogramme {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  border-radius: var(--r-sm);
  border: 1px solid var(--c-line);
  background: var(--c-raised);
  color: var(--c-secondary);
  font-size: var(--fs-xl);
  font-weight: 750;
}

/* Lignes de listes (agenda, journal…) : un padding latéral, compensé
   par des marges négatives pour garder l'alignement du contenu — le
   fond blanc du survol respire au lieu de coller au texte. */
.ligne {
  padding-inline: var(--sp-4);
  margin-inline: calc(var(--sp-4) * -1);
}
a.ligne:hover {
  border-radius: var(--r-sm);
}

/* Phrase-accent : la conclusion d'une section de présentation, mise en
   valeur sous la prose (page Le club). */
.accent-phrase {
  margin-top: var(--sp-6);
  padding-left: var(--sp-5);
  border-left: 3px solid var(--c-action);
  font-size: var(--fs-xl);
  font-weight: 750;
  line-height: 1.25;
  max-width: 32ch;
  text-wrap: balance;
}

/* Mention sous un tarif (« 100 € pour le 2e enfant ») : toutes les
   cellules du tableau réservent la place d'une petite ligne, si bien que
   la mention s'y loge sans déborder et sans que la ligne concernée soit
   plus haute que les autres. */
.tableau--tarifs td {
  padding-bottom: calc(var(--sp-4) + 1.1em);
}
.tableau--tarifs td.montant {
  position: relative;
}
.montant__mention {
  position: absolute;
  left: 0;
  bottom: calc(var(--sp-4) - 0.15em);
  font-size: var(--fs-xs);
  font-weight: 400;
  line-height: 1.1;
  white-space: nowrap;
}

/* ——— Ticker de semaine (page planning d'entraînement) ———————— */
.semaine-nav {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-bottom: var(--sp-6);
}
.semaine-nav__centre {
  position: relative;
}
/* Le champ date vit sous le bouton : invisible, mais le picker natif
   (showPicker) s'ancre dessus. En repli (navigateur sans showPicker),
   la classe --repli le révèle. */
.semaine-nav__centre input[type="date"],
.semaine-nav__centre input[type="month"] {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  pointer-events: none;
  border: 0;
}
.semaine-nav__centre--repli input[type="date"],
.semaine-nav__centre--repli input[type="month"] {
  position: static;
  opacity: 1;
  pointer-events: auto;
  margin-top: var(--sp-2);
  width: 100%;
}
/* Le bouton central est un ghost ; le rappel « cette semaine » s'affiche
   sous la date, hors flux : sa présence ne décale ni la date ni la ligne. */
.semaine-nav__centre .btn {
  position: relative;
}
/* Filtre par antenne, calé au bout de la ligne du ticker. */
.semaine-nav__filtre {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
}
.semaine-nav__filtre label {
  font-size: var(--fs-xs);
}
.semaine-nav__filtre select {
  padding: 10px 14px;
  border: 1px solid var(--c-line);
  border-radius: var(--r-sm);
  background: var(--c-surface);
  font: inherit;
  color: inherit;
}

.semaine-nav__hint {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%);
  margin-top: 2px;
  font-size: var(--fs-xs);
  white-space: nowrap;
  text-transform: none;
  letter-spacing: normal;
}

/* Formulaires Contact Form 7 dans le gabarit .formulaire du wireframe. */
.formulaire .wpcf7-form p {
  margin: 0;
}
.formulaire .wpcf7-not-valid-tip {
  color: #b3261e;
  font-size: var(--fs-sm);
  margin-top: 4px;
}
.formulaire .wpcf7-response-output {
  border: 1px solid var(--c-line);
  padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-sm);
}
.formulaire .wpcf7-spinner {
  display: none;
}

/* Champs obligatoires : l'astérisque est posée par le CSS à partir de
   aria-required, l'attribut que CF7 met lui-même sur le contrôle. Rien
   à écrire dans le libellé de chaque formulaire — rendre un champ
   obligatoire dans le back-office suffit à le signaler, et le retirer
   fait disparaître la marque.
   Le rouge est celui des messages d'erreur juste au-dessus : dans un
   formulaire, l'obligation et le manquement parlent d'une même voix.
   Deux « content » de suite : le second donne à l'astérisque un texte
   alternatif vide, car elle est décorative — aria-required porte déjà
   l'information aux lecteurs d'écran, qui l'annonceraient sinon deux
   fois. Un navigateur qui ignore cette syntaxe écarte la seule seconde
   déclaration et garde la première : l'astérisque reste visible. */
.champ:has([aria-required="true"]) label::after {
  content: '*';
  content: '*' / '';
  color: #b3261e;
  margin-left: 3px;
  font-weight: 700;
}

/* ——— Boutique : pile de visuels ————————————————————————————————— */
/* Un article porte plusieurs vues (le dos du maillot, un détail). Elles
   sont toutes rendues, empilées dans la boîte .ph, une seule opaque :
   main.js les enchaîne au survol de la carte en boutique, ou au clic
   sur une vignette en fiche produit. Sans JS, la première reste seule
   visible — l'état au repos de la grille. */
/* Les visuels sont des rendus 3D posés sur un fond blanc pur (normalisé
   à l'import). En `multiply` sur une carte claire, ce blanc disparaît —
   le vêtement se détache sans détourage, avec l'ombre de contact du
   rendu qui le pose sur la page. Un détourage par seuil était exclu :
   sur les maillots blancs, le tissu a exactement la valeur du fond.
   Le conteneur ne doit donc porter aucun fond, sinon l'image se
   mélangerait avec lui au lieu de la carte. */
.visuel-produit {
  display: block;
  background: none;
}

.visuel-produit__vue {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  mix-blend-mode: multiply;
  opacity: 0;
  transition: opacity 0.35s ease, transform 0.4s ease;
}

/* La carte referme le groupe de fusion : le mélange s'arrête à son
   fond et ne descend pas jusqu'à la page. */
.fiche {
  isolation: isolate;
}

/* Léger rapprochement au survol : le produit avance vers le lecteur,
   son ombre de rendu suit. Le débordement est absorbé par la marge du
   cadrage, jamais par le vêtement. */
.article:hover .visuel-produit__vue {
  transform: scale(1.045);
}

@media (prefers-reduced-motion: reduce) {
  .article:hover .visuel-produit__vue {
    transform: none;
  }
}

.visuel-produit__vue.est-visible {
  opacity: 1;
}

/* Repère du nombre de vues : discret, et seulement quand la carte est
   survolée — au repos la grille reste une grille de produits. */
.visuel-produit__puces {
  position: absolute;
  left: 50%;
  bottom: var(--sp-3);
  transform: translateX(-50%);
  display: flex;
  gap: 5px;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.article:hover .visuel-produit__puces,
.article:focus-visible .visuel-produit__puces {
  opacity: 1;
}

.visuel-produit__puce {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--c-text) 22%, transparent);
  transition: background 0.25s ease;
}

.visuel-produit__puce.est-active {
  background: var(--c-text);
}

/* ——— Fiche produit : vignettes de la galerie ——————————————————— */
/* base.css pose déjà la grille .produit__vignettes ; ici les boutons,
   qui ne doivent rien garder du bouton natif. */
.produit__vignettes .vignette {
  display: block;
  padding: 0;
  border: 1px solid var(--c-hairline);
  border-radius: var(--r-md);
  overflow: hidden;
  background: none;
  cursor: pointer;
  aspect-ratio: 1/1;
  transition: border-color 0.2s ease;
}

/* Même fusion que le grand visuel : la vignette est un cadre, pas une
   tuile blanche posée sur la page. */
.produit__vignettes .vignette img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  mix-blend-mode: multiply;
}

.produit__vignettes .vignette:hover {
  border-color: var(--c-accent-dim);
}

.produit__vignettes .vignette.est-active {
  border-color: var(--c-accent);
  box-shadow: inset 0 0 0 1px var(--c-accent);
}

/* Un visuel détouré (fond transparent) se pose normalement : le fondre
   l'effacerait dès que le produit est clair — des chaussettes blanches
   sur une carte crème. Il n'emporte pas non plus l'ombre de contact que
   les rendus ont incrustée, on la lui rend donc en CSS, calquée sur sa
   silhouette. */
.visuel-produit__vue--detoure,
.produit__vignettes .vignette img.vignette__detouree {
  mix-blend-mode: normal;
}

.visuel-produit__vue--detoure {
  filter: drop-shadow(0 10px 12px color-mix(in srgb, var(--c-shadow) 70%, transparent));
}

/* ——— Formulaires : loader à l'envoi, confirmation à l'arrivée ————— */
/* Une interface à part, réservée à la confirmation : le formulaire n'est
   remplacé qu'une fois le message parti. main.js lui passe la hauteur
   mesurée du formulaire, sans quoi la page se replierait d'un coup sous
   le curseur au moment de la bascule. */
.formulaire-etat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  text-align: center;
  padding: var(--sp-7) var(--sp-5);
  border: 1px solid var(--c-hairline);
  border-radius: var(--r-md);
  background: var(--c-surface);
}
.formulaire-etat:focus-visible {
  outline: 2px solid var(--c-accent);
  outline-offset: 3px;
}
.formulaire-etat__titre {
  font-family: 'Big Shoulders Display', 'Arial Narrow', 'Archivo', sans-serif;
  font-weight: 750;
  line-height: 1.02;
  font-size: var(--fs-lg);
  margin: 0;
}
.formulaire-etat__texte {
  margin: 0;
  max-width: 42ch;
  font-size: var(--fs-sm);
  color: var(--c-secondary);
}

/* Pendant l'envoi, le formulaire reste en place : seul le bouton
   travaille. CF7 pose de lui-même la classe « submitting » sur le
   formulaire et glisse un <span class="wpcf7-spinner"> juste après le
   bouton — on reprend ce span plutôt que d'en injecter un autre, mais
   habillé aux couleurs du thème (le sien est un disque sombre).
   Un <input type="submit"> n'accepte pas d'enfant ni de ::before : le
   conteneur du bouton sert donc de repère de position, ajusté à sa
   largeur pour que l'anneau tombe au centre du bouton et non de la
   colonne. */
.formulaire div:has(> .wpcf7-submit) {
  position: relative;
  width: max-content;
  max-width: 100%;
}
/* Le libellé s'efface plutôt que le bouton ne s'élargisse : la mise en
   page ne bouge pas d'un pixel au moment du clic. Le texte reste dans
   le DOM, donc lisible par un lecteur d'écran. */
.formulaire.submitting .wpcf7-submit {
  color: transparent;
  pointer-events: none;
}
.formulaire.submitting .wpcf7-spinner {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  /* Le disque et la bille orbitale de CF7 sont écrasés : il ne reste que
     l'anneau, un quart plus dense, qui se lit même à 20 px. */
  background: none;
  opacity: 1;
  border: 2px solid color-mix(in srgb, var(--c-on-accent) 35%, transparent);
  border-top-color: var(--c-on-accent);
  border-radius: 50%;
  animation: formulaire-tourne 0.7s linear infinite;
}
.formulaire .wpcf7-spinner::before {
  content: none;
}
@keyframes formulaire-tourne {
  to { transform: rotate(360deg); }
}
/* Sans animation, l'anneau figé se lirait comme un décor : on le pointille
   pour qu'il se distingue au moins du bouton au repos. */
@media (prefers-reduced-motion: reduce) {
  .formulaire.submitting .wpcf7-spinner {
    animation: none;
    border-color: var(--c-on-accent);
    border-style: dotted;
  }
}

/* La confirmation se distingue de l'attente par le fond et le filet
   d'accent : à la lecture, l'envoi est visiblement terminé. */
.formulaire-etat--ok {
  background: var(--c-raised);
  border-color: transparent;
  border-left: 3px solid var(--c-action);
}

/* La porte de sortie de la confirmation : un bouton discret, en retrait
   du titre, qui redonne le formulaire vidé. */
.formulaire-etat__retour {
  margin-top: var(--sp-2);
}

/* Taille et quantité tiennent sur une ligne : ce sont deux réglages
   courts d'un même geste, les séparer étirerait le formulaire pour rien.
   La quantité, toujours à un ou deux chiffres, prend la portion congrue.
   Sous 480 px, la ligne se déplie pour garder des cibles tactiles
   confortables. */
.champ-duo {
  display: grid;
  grid-template-columns: 1fr 100px;
  gap: var(--sp-4);
  align-items: end;
}
@media (max-width: 480px) {
  .champ-duo {
    grid-template-columns: 1fr;
  }
}

/* ——— Parcours d'un événement ————————————————————————————————— */
/* Une carte par format. Le tracé GPX y est une silhouette, pas une
   carte : ni fond tuilé, ni échelle, ni interaction — on reconnaît la
   forme d'une boucle, on lit le profil, et on va sur le site officiel
   pour le reste. Le SVG est inline, donc il prend les couleurs du
   thème et reste net à toutes les tailles. */
.parcours {
  display: grid;
  /* Le corps pousse le profil contre le bord bas, quelle que soit la
     hauteur du nom : les cartes d'une même rangée s'alignent. */
  grid-template-rows: auto 1fr auto;
  border: 1px solid var(--c-hairline);
  border-radius: var(--r-lg);
  background: var(--g-surface-douce);
  overflow: hidden;
}

/* Boîte de proportions fixes : deux parcours d'emprises différentes
   (une boucle large, un aller-retour étiré) occupent la même place, et
   le preserveAspectRatio du SVG centre chaque tracé dedans. */
.parcours__carte {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: var(--sp-5) var(--sp-5) 0;
}

.parcours__trace {
  width: 100%;
  height: 100%;
  overflow: visible;
}

.parcours__ligne {
  fill: none;
  stroke: var(--c-accent);
  /* Épaisseur exprimée dans l'espace du viewBox, qui fait 100 de large :
     0.9 donne un trait fin et lisible à toutes les tailles de carte. */
  stroke-width: 0.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.parcours__borne {
  stroke: var(--c-surface);
  stroke-width: 0.9;
}

.parcours__borne--depart { fill: var(--c-action); }
.parcours__borne--arrivee { fill: var(--c-vif); }

.parcours__corps {
  padding: var(--sp-5);
  display: grid;
  gap: var(--sp-1);
  align-content: start;
}

.parcours__nom {
  font-size: var(--fs-xl);
  margin: 0;
}

.parcours__distance {
  margin: 0;
  color: var(--c-secondary);
  font-size: var(--fs-md);
}

/* Le profil altimétrique court d'un bord à l'autre, au ras du bas :
   c'est une signature de la carte, pas un graphique à lire au mètre —
   d'où l'absence d'axes et l'étirement horizontal assumé. */
.parcours__profil {
  display: block;
  width: 100%;
  height: 46px;
}

.parcours__profil path {
  fill: color-mix(in srgb, var(--c-accent) 14%, transparent);
  stroke: color-mix(in srgb, var(--c-accent) 55%, transparent);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

/* Sous 900 px la grille à trois colonnes serre trop les tracés. */
@media (max-width: 900px) {
  .grille--parcours {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 560px) {
  .grille--parcours {
    grid-template-columns: 1fr;
  }
}

/* Corps de page en blocs : la colonne de lecture reste à 68ch (.prose),
   mais un bloc mis en « pleine largeur » ou « large » doit pouvoir en
   sortir, sinon aligncenter et alignfull rendent la même chose. */
.prose--page {
  margin-inline: auto;
}

.prose--page > .alignwide {
  width: min(1000px, 100%);
  max-width: none;
  margin-inline: auto;
}

.prose--page > .alignfull {
  width: calc(100vw - var(--gutter) * 2);
  max-width: calc(100vw - var(--gutter) * 2);
  margin-left: 50%;
  transform: translateX(-50%);
}
