/*
 * components.css — composants partagés par le thème et les vues du plugin.
 * Registre D10 (07/09/2026) : éditorial, presque monochrome, filets 1 px, aucune ombre, aucun aplat de couleur
 * décoratif, accent Court blue réservé au focus et à un seul élément par écran. Les statuts s'expriment par un
 * libellé en petites capitales et un point discret — jamais par un fond coloré, jamais par la couleur seule.
 * Aucune valeur en dur : tout vient de tokens.css. Nommage BEM léger `.spp-<bloc>__<partie>--<variante>`.
 * Spec : docs/architecture/15-design-system.md §2 (amendé D10) ; .claude/rules/frontend.md.
 */

/* ================================================================== Marque, en-tête, navigation */

/*
 * L'en-tête (D27) : une barre d'un noir franc, fine, **fixée en haut** — la navigation ne quitte jamais
 * l'écran. Le seul aplat de l'écran est le bouton
 * « Réserver », blanc sur noir. Sur l'accueil, la barre se pose sur la photo du hero et ne garde qu'un voile.
 *
 * La barre porte la classe `spp-on-dark` (parts/header.html) : elle reçoit les rôles du thème sombre, et
 * l'accent y devient blanc.
 */
header.wp-block-template-part:has(> .spp-header),
/*
 * Vues servies par le plugin (`spp-view--themed`) : `block_header_area()` y rend le groupe **sans**
 * l'enveloppe `<header class="wp-block-template-part">` des gabarits de blocs. Le sélecteur ci-dessus
 * n'y trouvait donc rien et la barre défilait avec la page — contraire à D27 (« la navigation ne quitte
 * jamais l'écran »), et trompeur pour tout élément collant qui se cale sous elle. Constaté le 22/09/2026
 * sur le HTML réellement servi par wp.southpadelpark.fr/tournois/.
 */
.spp-view--themed > .wp-site-blocks > .spp-header {
  position: sticky;
  top: 0;
  z-index: var(--spp-z-sticky);
}

/* `.admin-bar` et `.spp-view--themed` sont portées par le MÊME élément (`<body>`) : sélecteur composé,
   sans espace. Avec une espace, la règle exigerait que l'une descende de l'autre et ne s'appliquerait jamais. */
.admin-bar.spp-view--themed > .wp-site-blocks > .spp-header {
  top: 32px;
}

@media (max-width: 782px) {
  .admin-bar.spp-view--themed > .wp-site-blocks > .spp-header {
    top: 46px;
  }
}

.admin-bar header.wp-block-template-part:has(> .spp-header) {
  top: 32px;
}

@media (max-width: 782px) {
  .admin-bar header.wp-block-template-part:has(> .spp-header) {
    top: 46px;
  }
}

.spp-header {
  /* D44 : une barre fine. Elle ne porte plus que la marque, le mot « Menu » et l'action. */
  padding-block: var(--spp-space-3);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
  background-color: var(--spp-color-night);
  color: var(--spp-fg);
}

/*
 * Les liens de la barre prennent la couleur du texte — **sauf les boutons**, qui ont la leur.
 *
 * Sans l'exclusion, `.spp-header a` (0,1,1) battait `.spp-button--primary` (0,1,0) : le bouton du panneau
 * de menu ressortait blanc sur blanc, un rectangle vide. Mesuré à l'écran avant livraison.
 *
 * `:not(:where(...))` et non `:not(...)` : `:not()` prend la spécificité de son argument. Écrite
 * `:not(.spp-button)`, la règle passait à (0,2,1) et cassait cette fois le bouton du **bloc WordPress**,
 * dont la règle ne pèse que (0,2,0) — un défaut chassait l'autre. `:where()` ne pèse rien : la règle garde
 * (0,1,1) et se contente d'écarter les deux formes de bouton.
 */
.spp-header a:not(:where(.spp-button, .wp-block-button__link)) {
  color: var(--spp-fg);
}

/* La marque n'est pas un lien de prose : pas de soulignement sous le nom du club. */
.spp-brand a {
  text-decoration: none;
}

/*
 * Accueil : la barre flotte sur le hero, avec un voile qui assombrit (lisibilité), jamais une couleur.
 *
 * `fixed` et non `absolute` : en `absolute`, la barre défilait avec la page et disparaissait dès le premier
 * écran — la seule page du site où la navigation quittait l'écran, contre D27. Les deux valeurs sortent
 * l'élément du flux, la photo du hero passe donc dessous exactement pareil : rien ne bouge, la barre reste.
 */
.home header.wp-block-template-part:has(> .spp-header) {
  position: fixed;
  inset: 0 0 auto;
  z-index: var(--spp-z-sticky);
}

.home .spp-header {
  border-bottom-color: transparent;
  background-color: transparent;
  background-image: linear-gradient(180deg, rgba(10, 10, 10, 0.72), rgba(10, 10, 10, 0));
  transition: background-color var(--spp-duration-base) var(--spp-easing);
}

/*
 * …et dès qu'on a quitté le haut, elle reprend son noir plein : un voile dégradé posé sur une section
 * claire ne cache rien, et le menu blanc y devenait illisible. `spp-scrolled` est posée sur `<html>` par
 * `assets/js/header.js` ; sans JavaScript la barre garde son voile, qui reste lisible sur la photo.
 */
.spp-scrolled .home .spp-header {
  background-color: var(--spp-color-night);
  background-image: none;
  border-bottom-color: var(--spp-border);
}

.spp-header__inner {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4);
}

.spp-header__right {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--spp-space-5);
}

.spp-brand {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  gap: var(--spp-space-3);
  color: inherit;
  text-decoration: none;
}

.spp-brand__logo,
.spp-brand .wp-block-site-logo img {
  display: block;
  width: auto;
  height: auto;
  max-height: 34px;
}

.spp-brand .wp-block-site-logo {
  margin: 0;
  line-height: 0;
}

.spp-brand__wordmark {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-label) * 1.35);
  font-weight: 800;
  letter-spacing: 0.1em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Sous 560 px, la balle suffit : le nom du club est écrit en toutes lettres dès le premier écran. */
@media (max-width: 559px) {
  .spp-brand__wordmark {
    display: none;
  }
}

/*
 * ---- La navigation déployée, sur ordinateur (D45).
 *
 * Sept entrées en petites capitales espacées, sur une ligne, à droite de la marque. En dessous de
 * 1100 px elles ne tiennent plus avec le nom du club et le bouton d'action : on repasse alors au panneau
 * plein écran. WordPress ne sait replier qu'en dessous de 600 px (`overlayMenu: mobile`), d'où les deux
 * règles qui étendent son comportement mobile jusqu'à 1100.
 */
.spp-nav .wp-block-navigation__container:not(.is-menu-open *) {
  gap: 1.3rem;
}

.spp-nav .wp-block-navigation-item__content {
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* La page ouverte est soulignée en permanence ; les autres ne le sont qu'au survol (voir « Liens »). */
.spp-nav .current-menu-item > .wp-block-navigation-item__content {
  background-size: 100% var(--spp-border-width);
}

/*
 * WordPress déplie la navigation dès 600 px et cache le bouton « Menu ». Entre 600 et 1100 px, sept
 * entrées plus la marque plus l'action ne tiennent pas sur une ligne : on y prolonge son comportement
 * mobile. Ces deux règles sont celles qui servaient déjà avant D44 — elles ont fait leurs preuves.
 */
@media (min-width: 600px) and (max-width: 1099px) {
  .spp-nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
    display: flex;
  }

  .spp-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
    display: none;
  }
}

/* ---- Le bouton qui ouvre le menu : un mot, pas un pictogramme. */
/*
 * **Pas de `display` ici.** C'est WordPress qui décide quand ce bouton paraît : caché au-dessus de 600 px,
 * montré en dessous. En écrivant `display: flex` dans cette règle — même spécificité, feuille chargée
 * après — on le rendait visible **en permanence**, à côté de la navigation dépliée. Nos deux règles de
 * repli (600–1100 px) posent le `display` là où il le faut, et nulle part ailleurs.
 */
.spp-nav .wp-block-navigation__responsive-container-open,
.spp-nav .wp-block-navigation__responsive-container-close {
  align-items: center;
  gap: var(--spp-space-2);
  padding: 0;
  border: 0;
  background: none;
  color: var(--spp-fg);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
}

/*
 * Deux traits devant le mot : le geste du burger, sans le pictogramme.
 *
 * `:not(:has(svg))` parce que le bloc Navigation retombe sur son icône si `hasIcon` n'est pas pris en
 * compte : on ne veut pas deux burgers l'un à côté de l'autre. Dans ce cas, c'est l'icône du cœur qui
 * s'affiche, mise à la bonne taille juste en dessous.
 */
.spp-nav .wp-block-navigation__responsive-container-open:not(:has(svg))::before {
  content: "";
  width: 18px;
  height: 9px;
  border-top: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
}

.spp-nav .wp-block-navigation__responsive-container-open svg,
.spp-nav .wp-block-navigation__responsive-container-close svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
}

.spp-nav .wp-block-navigation__responsive-container-open:hover,
.spp-nav .wp-block-navigation__responsive-container-close:hover {
  opacity: 0.75;
}

/*
 * ---- Le panneau plein écran.
 *
 * Sélecteurs doublés (`.spp-nav.wp-block-navigation …`) : le cœur peint le panneau en **blanc sur noir**
 * par défaut, avec `.wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container
 * .is-menu-open`, qui pèse quatre classes. Nos règles n'en pesaient que trois et perdaient : le menu
 * s'ouvrait **blanc sur blanc**, illisible, et la liste s'alignait à droite en sept lignes. Personne ne
 * l'avait vu parce que personne n'avait ouvert le menu — il fallait pour cela un vrai clic dans un vrai
 * navigateur (`bin/replay --click`).
 *
 * Le motif déclare aussi `overlayBackgroundColor` / `overlayTextColor` : c'est le mécanisme prévu par
 * WordPress, et il colore ce que nos règles ne couvrent pas. Les deux se complètent, aucun ne suffit.
 */
.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open.has-modal-open {
  /*
   * Cinq classes, pour battre celle du cœur qui en pèse autant :
   *   `.wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container
   *    .is-menu-open:not(.disable-default-overlay)` → fond blanc, texte noir.
   * `has-modal-open` est posée par WordPress en même temps que `is-menu-open` : la condition est la même,
   * elle ne fait qu'ajouter du poids. Le motif déclare en plus `overlayBackgroundColor`/`overlayTextColor`,
   * qui est la voie prévue par le cœur ; les deux disent la même chose et se couvrent l'une l'autre.
   */
  padding: 0;
  background-color: var(--spp-color-night);
  color: var(--spp-color-white);
}

.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close {
  max-width: none;
  height: 100%;
  padding: var(--spp-space-4) var(--spp-gutter) var(--spp-space-7);
}

.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog {
  display: flex;
  flex-direction: column;
  max-width: var(--spp-layout-max);
  height: 100%;
  margin-inline: auto;
}

.spp-nav .wp-block-navigation__responsive-container-close {
  align-self: flex-end;
  /* Sa propre ligne : posé en absolu, il retombait sur la première entrée du menu. */
  flex: none;
  min-height: 34px;
  margin-bottom: var(--spp-space-4);
}

/*
 * La liste est calée en haut et laisse le bas de l'écran au pied du panneau (coordonnées, action,
 * réseaux). Celui-ci est en position fixe — il ne pousse rien — donc c'est ici qu'on lui réserve sa place,
 * sans quoi la dernière entrée du menu lui passe dessous. Constaté à l'image : « Contact » chevauchait
 * « Le club ».
 */
.spp-nav.wp-block-navigation .is-menu-open .wp-block-navigation__responsive-container-content {
  --spp-menu-foot: 260px;

  display: flex;
  align-items: flex-start;
  flex: 1;
  padding-block: var(--spp-space-5) var(--spp-menu-foot);
}

@media (min-width: 700px) {
  .spp-nav.wp-block-navigation .is-menu-open .wp-block-navigation__responsive-container-content {
    --spp-menu-foot: 190px;
  }
}

/*
 * Les entrées, numérotées, en très grandes capitales. Le numéro vient d'un compteur : ajouter une entrée
 * dans Apparence → Menus renumérote la liste toute seule.
 */
.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
  counter-reset: spp-menu;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: var(--spp-space-2);
  width: 100%;
  align-items: stretch;
  text-align: left;
  /* Le `ul` du bloc Navigation garde ses puces dans le panneau : une pastille devant chaque numéro. */
  margin: 0;
  padding-left: 0;
  list-style: none;
}

.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
  counter-increment: spp-menu;
  /*
   * Mesuré : le cœur pose `align-items: flex-end` sur chaque entrée quand la barre est alignée à droite
   * (`justifyContent: right`). L'entrée étant une colonne flexible, cela pousse le lien **contre le bord
   * droit** du panneau — les sept entrées s'y empilaient sous le bouton de fermeture. La barre garde son
   * alignement à droite, le panneau repart de la gauche.
   */
  align-items: flex-start;
  justify-content: flex-start;
}

.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open a {
  display: flex;
  align-items: baseline;
  /*
   * La barre aligne ses entrées à droite (`justifyContent: right`), et cet alignement descend dans le
   * panneau : les sept entrées s'y collaient au bord droit, sous le bouton de fermeture. Dans le panneau
   * la lecture repart de la gauche, quel que soit le réglage de la barre.
   */
  justify-content: flex-start;
  text-align: left;
  gap: var(--spp-space-4);
  padding-block: var(--spp-space-2);
  font-family: var(--spp-font-sport);
  font-size: clamp(1.75rem, 5.4vw, 3.5rem);
  font-weight: 800;
  letter-spacing: 0.012em;
  line-height: 0.95;
  text-transform: uppercase;
}

.spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open a::before {
  content: counter(spp-menu, decimal-leading-zero);
  flex: none;
  min-width: 2.4em;
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--spp-fg-muted);
  font-variant-numeric: tabular-nums;
}

/*
 * ---- Le pied du panneau : coordonnées et horaires.
 *
 * Il est écrit dans `parts/header.html`, hors du panneau — le bloc Navigation ne rend que des entrées de
 * menu. On le révèle, en position fixe par-dessus le panneau, quand celui-ci est ouvert. `:has()` sert ici
 * de lien entre deux branches du DOM que rien d'autre ne relie.
 */
.spp-menu-aside {
  display: none;
}

.spp-header:has(.wp-block-navigation__responsive-container.is-menu-open) .spp-menu-aside {
  display: grid;
  gap: var(--spp-space-5);
  position: fixed;
  /*
   * 100001, pas un token. Le bloc Navigation de WordPress pose son panneau à `z-index: 100000` **en dur**
   * dans sa propre feuille : l'échelle du thème s'arrête à 60, et ce pied serait passé derrière le
   * panneau sans jamais s'afficher. On se cale sur la valeur du cœur, avec ce commentaire pour dire
   * pourquoi le nombre est écrit tel quel.
   */
  z-index: 100001;
  inset-inline: max(var(--spp-gutter), calc((100vw - var(--spp-layout-max)) / 2));
  inset-block-end: var(--spp-space-7);
  padding-top: var(--spp-space-5);
  border-top: var(--spp-border-width) solid rgb(255 255 255 / 20%);
  color: var(--spp-color-white);
  font-size: var(--spp-text-small);
  line-height: var(--spp-text-small-leading);
}

@media (min-width: 700px) {
  .spp-header:has(.wp-block-navigation__responsive-container.is-menu-open) .spp-menu-aside {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--spp-space-8);
    align-items: end;
  }
}

.spp-menu-aside__action {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spp-space-4) var(--spp-space-6);
}

/*
 * `:not(.spp-button)` : sans cette exclusion, le bouton « Réserver une piste » héritait du blanc et se
 * retrouvait **blanc sur blanc** — un rectangle vide. Vu à l'image avant livraison.
 */
.spp-menu-aside a:not(.spp-button) {
  color: var(--spp-color-white);
}

/*
 * Dans le panneau, les réseaux tiennent sur une ligne : il n'y a pas la place d'une colonne de plus.
 * Sélecteur doublé (`.spp-social.spp-social--row`) : `.spp-social`, définie plus bas avec la même
 * spécificité, gagnait l'égalité et les remettait en colonne.
 */
.spp-social.spp-social--row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Le libellé sert d'étiquette accessible ; à l'écran le sigle suffit, la place manque. */
.spp-social.spp-social--row .spp-social__link {
  gap: 0;
  min-height: var(--spp-target-min);
  min-width: var(--spp-target-min);
  justify-content: center;
  font-size: 0;
}

.spp-social.spp-social--row .spp-social__link::before {
  width: 24px;
  height: 24px;
}

.spp-menu-aside__block {
  margin: 0;
}

.spp-menu-aside .spp-label {
  display: block;
  margin-bottom: var(--spp-space-2);
  color: var(--spp-fg-muted);
}

/* Le pied du panneau mange de la place : les entrées se serrent pour lui laisser le bas de l'écran. */
@media (max-height: 760px) {
  .spp-nav.wp-block-navigation .wp-block-navigation__responsive-container.is-menu-open a {
    font-size: clamp(1.5rem, 5vw, 2.5rem);
  }
}

/* ---- Repli sans JavaScript : le bouton du bloc Navigation n'ouvre alors rien. */
.spp-nav-noscript {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-2) var(--spp-space-5);
  margin: var(--spp-space-3) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.spp-header .spp-button,
.spp-header .spp-button .wp-block-button__link {
  min-height: var(--spp-target-min);
  padding-inline: var(--spp-space-5);
}

/* Sous 480 px, l'action reste, le mot « Réserver » suffit — la barre ne doit jamais passer sur deux lignes. */
@media (max-width: 479px) {
  .spp-header__right {
    gap: var(--spp-space-4);
  }

  .spp-header .spp-button .wp-block-button__link {
    padding-inline: var(--spp-space-4);
  }
}

/* ================================================================== En-tête de section */

/*
 * L'en-tête d'une section éditoriale (D27) : un numéro, l'intitulé en petites capitales, un filet qui file
 * jusqu'au bord, puis le titre en grand.
 *
 * Pourquoi il existe. Les séparateurs numérotés de D27 étaient posés **sur le filet entre deux sections**
 * (base.css) — et retirés à chaque jonction noir/blanc, où la pastille aurait flotté sur la mauvaise
 * couleur. Sur l'accueil, où presque toutes les jonctions changent de couleur, il ne restait donc
 * quasiment aucun numéro : la page avait perdu son repère de lecture. Ici le numéro est **dans le flux**
 * de la section : il tient sur n'importe quel fond.
 *
 * Plus de numéro depuis le 02/11/2026 (D73) : un intitulé et son filet suffisent.
 */
.spp-sectionhead {
  margin-bottom: var(--spp-space-7);
}

.spp-sectionhead__meta {
  display: flex;
  align-items: center;
  gap: var(--spp-space-3);
  margin: 0 0 var(--spp-space-4);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

/* Le filet part de l'intitulé et va jusqu'au bord du conteneur : c'est lui qui « ouvre » la section. */
.spp-sectionhead__meta::after {
  content: "";
  flex: 1;
  height: var(--spp-border-width);
  background-color: currentColor;
  opacity: 0.35;
}

.spp-sectionhead__title {
  margin: 0;
  font-size: calc(var(--spp-text-h1) * 1.05);
}

/*
 * Le chapô s'aligne sur le titre.
 *
 * Dans une disposition contrainte, WordPress centre chaque enfant (`margin-left/right: auto !important`) :
 * un élément à qui l'on donne une mesure plus étroite se retrouve **centré** au lieu de rester au fil du
 * texte. Mesuré sur l'accueil en ligne le 24/09/2026 : le titre commençait à 36 px du bord, son chapô à
 * 163 px. C'est le décalage qu'on voyait le plus, avant même le contenu.
 */
.spp-sectionhead__lead {
  max-width: 56ch;
  margin: var(--spp-space-4) 0 0 !important;
  font-size: var(--spp-text-body-l);
  line-height: var(--spp-text-body-l-leading);
  color: var(--spp-fg-muted);
}

/* Même correction pour les utilitaires de mesure employés directement dans une section contrainte. */
.spp-section > .spp-u-measure,
.spp-section > .spp-u-measure-wide {
  margin-inline: 0 auto !important;
}

/* ================================================================== Faits clés d'une section */

/*
 * Un couple intitulé / valeur par ligne, séparés par un filet. Sert à poser, sous le texte d'une section,
 * les quelques chiffres qui décident vraiment — la durée d'un créneau, l'heure du dernier départ.
 *
 * Ils étaient déjà dans le texte courant, noyés dans la phrase. Sortis en lignes, ils se lisent d'un coup
 * d'œil, et la section cesse d'être un bloc de prose. Aucun chiffre n'est ajouté ici : ce sont les mêmes,
 * aux mêmes sources.
 */
.spp-keyfacts {
  margin: var(--spp-space-5) 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--spp-text-small);
}

.spp-keyfacts__item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spp-space-2) var(--spp-space-4);
  padding-block: var(--spp-space-3);
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-keyfacts__item:last-child {
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-keyfacts__k {
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-keyfacts__v {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h4) * 1.05);
  font-weight: 800;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  text-align: right;
}

/* ================================================================== Pied de page */

/*
 * Le pied de page en deux temps (D27, D38).
 *
 * 1. Une **bande claire** d'appel à l'action ferme la page : « Viens taper la balle », les deux gestes du
 *    club (réserver, le calendrier), et les faits qui décident — six pistes, ouvert dès 9 h. Elle donne au
 *    pied de page ce qui lui manquait : une raison d'y arriver.
 * 2. Une **bande noire**, ouverte par un biseau, qui porte la marque en très grand, les coordonnées, le
 *    plan du site, les réseaux et la ligne légale.
 *
 * Le biseau tombe donc **toujours sur une vraie jonction de couleur**, quelle que soit la page : c'est la
 * bande claire du pied de page qui précède le noir, jamais la dernière section de la page. C'est ce qui
 * permet d'appliquer D38 partout sans savoir comment chaque gabarit se termine.
 */
.spp-footer-cta {
  padding-block: var(--spp-space-9);
  /* Un fond peint, sinon le biseau du bloc suivant ne révèle rien (leçon D38 du 22/09/2026). */
  background-color: var(--spp-bg);
  color: var(--spp-fg);
}

.spp-footer-cta__inner {
  display: grid;
  gap: var(--spp-space-6);
  align-items: end;
}

@media (min-width: 900px) {
  .spp-footer-cta__inner {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--spp-space-8);
  }
}

.spp-footer-cta__say > * {
  margin-block: 0;
}

.spp-footer-cta__title {
  margin-block: var(--spp-space-3) var(--spp-space-3);
  font-family: var(--spp-font-sport);
  font-size: var(--spp-text-h2);
  font-weight: 800;
  line-height: 0.92;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}

.spp-footer-cta__lead {
  max-width: 42ch;
  color: var(--spp-fg-muted);
}

.spp-footer-cta__actions {
  gap: var(--spp-space-3);
}

/*
 * La scène noire. Le biseau mord la bande **sombre** — elle peint son fond d'un bord à l'autre, la découpe
 * laisse donc voir le fond de page, clair comme la bande d'appel juste au-dessus.
 */
.spp-footer {
  clip-path: polygon(0 var(--spp-slant), 100% 0, 100% 100%, 0 100%);
  padding-block: calc(var(--spp-space-8) + var(--spp-slant)) var(--spp-space-6);
  background-color: var(--spp-color-night);
  color: var(--spp-fg);
  font-size: var(--spp-text-small);
  line-height: var(--spp-text-small-leading);
}

.spp-footer a {
  color: var(--spp-fg);
}

/*
 * ---- La marque, en très grand, sur toute la largeur.
 *
 * Damien tient au nom du club écrit en grand ici. Il l'était déjà, mais coincé dans une colonne : « SOUTH
 * PADEL » passait à la ligne et « PARK » laissait un demi-écran vide à sa droite. Le nom occupe maintenant
 * sa propre ligne, et son corps est **calculé sur la largeur du bloc** plutôt que sur celle de l'écran.
 *
 * `cqw` et non `vw` : le bloc est plafonné à 1280 px, alors que la fenêtre continue de s'élargir. En `vw`,
 * le nom débordait dès 1600 px de large. Mesuré le 24/09/2026 dans la police du thème : « South Padel Park »
 * fait 680 px à 100 px de corps, soit 14,3 cqw pour remplir la largeur sans la toucher.
 *
 * Volontairement **sans `nowrap`** : pendant le chargement de la police, un caractère de secours plus large
 * ferait déborder la page (interdit : aucun défilement horizontal). Sans `nowrap`, il passe à la ligne une
 * fraction de seconde, puis se range sur une seule ligne dès que la vraie police arrive.
 */
.spp-footer__brand {
  container-type: inline-size;
  margin-bottom: var(--spp-space-7);
  padding-bottom: var(--spp-space-6);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-footer__mark {
  margin: 0;
  font-family: var(--spp-font-sport);
  /* Repli pour un navigateur sans unités de conteneur : la déclaration suivante y est simplement ignorée. */
  font-size: clamp(3rem, 11vw, 10rem);
  font-size: clamp(2.5rem, 14.3cqw, 13rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 0.85;
  text-transform: uppercase;
}

/* Au-dessus du nom : ce qu'est le club, à gauche ; la balle du logo, à droite. */
.spp-footer__brandside {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4);
  margin-bottom: var(--spp-space-5);
}

.spp-footer__logo {
  display: block;
  flex: none;
  line-height: 0;
}

.spp-footer__logo img {
  display: block;
  width: auto;
  height: 64px;
}

.spp-footer__claim {
  margin: 0;
  max-width: 48ch;
  color: var(--spp-fg-muted);
}

/* ---- Les colonnes. Le plan du site en prend deux : c'est la plus longue liste, et la plus utile. */
.spp-footer__grid {
  display: grid;
  gap: var(--spp-space-7) var(--spp-space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 600px) {
  .spp-footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1000px) {
  .spp-footer__grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .spp-footer__col--wide {
    grid-column: span 2;
  }
}

.spp-footer__col > * {
  margin-block: 0;
}

.spp-footer__col > * + * {
  margin-top: var(--spp-space-3);
}

.spp-footer h2,
.spp-footer h3 {
  margin: 0 0 var(--spp-space-4);
  padding-bottom: var(--spp-space-3);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-footer ul {
  padding-left: 0;
  list-style: none;
}

/* Les horaires en deux colonnes alignées : le jour à gauche, l'heure à droite, comme un tableau d'affichage. */
.spp-footer__hours {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: start;
  gap: var(--spp-space-2) var(--spp-space-5);
}

.spp-footer__hours > span:nth-child(odd) {
  color: var(--spp-fg-muted);
}

.spp-footer__links {
  display: grid;
  gap: var(--spp-space-3) var(--spp-space-5);
}

@media (min-width: 1000px) {
  .spp-footer__links {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.spp-footer__lines a {
  display: inline-block;
  min-height: var(--spp-space-6);
}

/*
 * ---- Réseaux sociaux : le sigle de chaque réseau, dessiné en masque CSS.
 *
 * Le masque prend la couleur du texte : les trois sigles restent donc en noir et blanc comme le reste de
 * l'interface (D27 — aucune couleur de marque), et suivent le thème sans qu'on ait à livrer six fichiers.
 * Le nom du réseau reste écrit à côté : sans CSS, ou si le masque n'est pas géré, il reste un lien lisible
 * — l'information n'est jamais portée par le seul pictogramme.
 */
.spp-social {
  display: grid;
  gap: var(--spp-space-2);
}

.spp-social__link {
  display: inline-flex;
  align-items: center;
  gap: var(--spp-space-3);
  min-height: var(--spp-target-min);
}

.spp-social__link::before {
  content: "";
  flex: none;
  width: 22px;
  height: 22px;
  background-color: currentColor;
  -webkit-mask: var(--spp-social-icon) center / contain no-repeat;
  mask: var(--spp-social-icon) center / contain no-repeat;
}

.spp-social__link--instagram {
  --spp-social-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9'%3E%3Crect x='2.6' y='2.6' width='18.8' height='18.8' rx='5.4'/%3E%3Ccircle cx='12' cy='12' r='4.4'/%3E%3Ccircle cx='17.4' cy='6.6' r='1.25' fill='%23000' stroke='none'/%3E%3C/svg%3E");
}

.spp-social__link--facebook {
  --spp-social-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M22 12.06C22 6.5 17.52 2 12 2S2 6.5 2 12.06C2 17.08 5.66 21.24 10.44 22v-7.03H7.9v-2.91h2.54V9.85c0-2.52 1.49-3.91 3.77-3.91 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.78-1.63 1.57v1.89h2.78l-.44 2.91h-2.34V22C18.34 21.24 22 17.08 22 12.06z'/%3E%3C/svg%3E");
}

.spp-social__link--tiktok {
  --spp-social-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23000'%3E%3Cpath d='M16.9 2h-3.2v13.1a2.6 2.6 0 1 1-2.2-2.57V9.28a5.72 5.72 0 1 0 5.4 5.71V8.53a6.86 6.86 0 0 0 4 1.29V6.6A3.72 3.72 0 0 1 16.9 2z'/%3E%3C/svg%3E");
}

/* ================================================================== Partenaires (D54) */

/*
 * Les logos des partenaires, en silhouette de la couleur du texte : blancs sur une bande noire, noirs sur une
 * bande claire (D27 — aucune couleur d'interface hors logo du club et photos). Même technique que les sigles des
 * réseaux ci-dessus (D42) ; fichiers hébergés par le site, sources dans docs/reference/sponsors.md. Le nom reste
 * écrit à côté du logo : c'est lui le texte du lien.
 */
.spp-partners {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(16rem, 100%), 1fr));
  gap: var(--spp-space-7);
  margin: var(--spp-space-6) 0;
  padding: 0;
  list-style: none;
}

.spp-partners__item {
  display: grid;
  gap: var(--spp-space-2);
  align-content: start;
}

.spp-partners__link {
  display: grid;
  gap: var(--spp-space-3);
  justify-items: start;
  min-height: var(--spp-target-min);
  color: inherit;
  text-decoration: none;
}

.spp-partners__logo {
  display: block;
  width: 9rem;
  aspect-ratio: 3 / 2;
  background-color: currentColor;
  -webkit-mask: var(--spp-partner-logo) left center / contain no-repeat;
  mask: var(--spp-partner-logo) left center / contain no-repeat;
  transition: opacity var(--spp-duration-base) var(--spp-easing);
}

.spp-partners__name {
  font-weight: 600;
}

.spp-partners__link:hover .spp-partners__logo,
.spp-partners__link:focus-visible .spp-partners__logo {
  opacity: 0.72;
}

.spp-partners__link:hover .spp-partners__name,
.spp-partners__link:focus-visible .spp-partners__name {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.spp-partners__about {
  margin: 0;
  color: var(--spp-fg-muted);
  font-size: var(--spp-text-small);
}

.spp-partners__link--cupra {
  --spp-partner-logo: url("../img/partenaires/cupra.svg");
}

.spp-partners__link--carepolis {
  --spp-partner-logo: url("../img/partenaires/carepolis.svg");
}

/* ================================================================== Avis Google (D59) */

/*
 * La carte « Ton avis compte » de l'accueil : noire, fendue comme le hero — photo à gauche, panneau à droite,
 * coupés par la diagonale `--spp-slant`. Le « G » de Google et les étoiles sont des masques peints de la couleur
 * du texte, comme les sigles des réseaux (D42), jamais la couleur de marque (D27). Les étoiles sont vides : elles
 * invitent à noter, elles n'affichent aucune note (D18). Sous 900 px, photo au-dessus, panneau dessous.
 */
/* `minmax(0, 1fr)` : une colonne libre prendrait la largeur du bouton, et la carte débordait de 28 px à 360 px (D82). */
.spp-review {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin-block: var(--spp-space-6) 0;
  background-color: var(--spp-bg);
  color: var(--spp-fg);
}

/* La photo couvre toute la colonne, quelle que soit la hauteur du panneau voisin. */
.spp-review__media {
  position: relative;
  min-height: 15rem;
}

.spp-review__media .spp-media {
  position: absolute;
  inset: 0;
}

.spp-review__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.spp-review__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--spp-space-4);
  padding: var(--spp-space-7) var(--spp-space-5);
}

/* La disposition « flux » du cœur ajoute une marge haute à chaque enfant : l'écart vient ici du `gap`. */
.spp-review .spp-review__body > * {
  margin-block: 0;
}

/* Même marge sur les deux colonnes : elle décalait le panneau de 24 px sous le haut de la carte (mesuré le
   20/10/2026), d'où un texte plus bas que centré. Deux classes pour passer devant la règle du cœur. */
.spp-review > .spp-review__media,
.spp-review > .spp-review__body {
  margin-block: 0;
}

@media (min-width: 900px) {
  .spp-review {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  }

  .spp-review__media {
    min-height: 28rem;
    clip-path: polygon(0 0, 100% 0, calc(100% - var(--spp-slant)) 100%, 0 100%);
  }

  .spp-review__body {
    padding: var(--spp-space-8) var(--spp-space-8) var(--spp-space-8) var(--spp-space-6);
  }
}

/* Le libellé du bouton passe à la ligne plutôt que de sortir de la carte, sur les petits téléphones. */
.spp-review .spp-button {
  max-width: 100%;
  white-space: normal;
}

.spp-review__badge {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spp-space-3) var(--spp-space-5);
}

.spp-review__mark {
  flex: none;
  width: 3.5rem;
  height: 3.5rem;
  background-color: currentColor;
  -webkit-mask: var(--spp-review-mark) center / contain no-repeat;
  mask: var(--spp-review-mark) center / contain no-repeat;
  --spp-review-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 48'%3E%3Cpath d='M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z'/%3E%3Cpath d='M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z'/%3E%3Cpath d='M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z'/%3E%3Cpath d='M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z'/%3E%3C/svg%3E");
}

.spp-review__stars {
  flex: none;
  width: 9.6rem;
  height: 1.6rem;
  background-color: currentColor;
  -webkit-mask: var(--spp-review-star) left center / 1.92rem 1.6rem repeat-x;
  mask: var(--spp-review-star) left center / 1.92rem 1.6rem repeat-x;
  --spp-review-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28.8 24'%3E%3Cpath d='M12 2.6l2.83 5.94 6.53.84-4.79 4.5 1.22 6.47L12 17.18l-5.79 3.17 1.22-6.47-4.79-4.5 6.53-.84z' fill='none' stroke='%23000' stroke-width='1.6' stroke-linejoin='round'/%3E%3C/svg%3E");
}

.spp-review__badge-label {
  flex-basis: 100%;
  color: var(--spp-fg-muted);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
}

.spp-review__title {
  font-family: var(--spp-font-sport);
  font-size: var(--spp-text-h2);
  font-weight: var(--spp-text-h2-weight);
  line-height: var(--spp-text-h2-leading);
  text-transform: uppercase;
}

.spp-review__lead {
  max-width: 38ch;
  font-size: var(--spp-text-body-l);
  line-height: var(--spp-text-body-l-leading);
}

/* ---- La ligne légale, tout en bas. */
.spp-footer__legal {
  display: grid;
  gap: var(--spp-space-3);
  margin-top: var(--spp-space-8);
  padding-top: var(--spp-space-4);
  border-top: var(--spp-border-width) solid var(--spp-border);
  color: var(--spp-fg-muted);
  font-size: calc(var(--spp-text-small) * 0.92);
}

.spp-footer__legal > * {
  margin-block: 0;
}

@media (min-width: 700px) {
  .spp-footer__legal {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: baseline;
  }
}

.spp-footer__legallinks {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-2) var(--spp-space-4);
}

/*
 * Pas de point de séparation entre les liens légaux : il n'existait que comme caractère collé au lien,
 * donc lu à voix haute et souligné au survol avec lui. L'espacement de la grille sépare aussi bien.
 */

/* ================================================================== Liens de navigation et d'action */

/*
 * Le trait se déploie de zéro à toute la largeur au survol et au focus. Geste relevé sur tout le corpus
 * (Padel Social Club : 50 transitions en .4s ; Aspria : `opacity .5s`) — c'est un dégradé de fond, pas
 * `text-decoration` : seul `background-size` s'anime, le trait part toujours du bord gauche, et rien ne
 * bouge dans la mise en page. `prefers-reduced-motion` met --spp-duration-line à zéro : le trait apparaît
 * alors d'un coup, l'information reste, seul le mouvement disparaît.
 *
 * Réservé aux liens qui ne sont PAS dans un bloc de texte : barre de navigation, pied de page, rangée
 * d'actions. Les liens de prose gardent leur soulignement permanent (base.css) — la couleur des liens est
 * héritée du texte, un lien sans trait au repos y serait indétectable (WCAG 1.4.1).
 */
.spp-nav a,
.spp-footer a,
.spp-linkrow a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 0 var(--spp-border-width);
  padding-bottom: 0.12em;
  transition: background-size var(--spp-duration-line) var(--spp-easing);
}

.spp-nav a:hover,
.spp-nav a:focus-visible,
.spp-nav .current-menu-item > a,
.spp-footer a:hover,
.spp-footer a:focus-visible,
.spp-linkrow a:hover,
.spp-linkrow a:focus-visible {
  background-size: 100% var(--spp-border-width);
}

/*
 * Rangée d'actions en fin de section : un paragraphe qui ne contient que des liens, jamais de la prose.
 * Les liens y sont composés en petites capitales espacées — la signature « private club » mesurée chez
 * The Ned (99 × uppercase, 62 × letter-spacing .15em) — et portent au repos un filet discret : c'est lui
 * qui signale la cible sans recourir à la couleur, et sur lui que vient s'écrire le trait d'encre.
 */
.spp-linkrow {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-5);
  margin-top: var(--spp-space-5);
}

.spp-linkrow a {
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  line-height: var(--spp-text-label-leading);
  text-transform: uppercase;
  background-image:
    linear-gradient(currentColor, currentColor),
    linear-gradient(var(--spp-fg-muted), var(--spp-fg-muted));
  background-size: 0 var(--spp-border-width), 100% var(--spp-border-width);
  padding-bottom: 0.5em;
}

.spp-linkrow a:hover,
.spp-linkrow a:focus-visible {
  background-size: 100% var(--spp-border-width), 100% var(--spp-border-width);
}

/* ================================================================== Boutons */

/*
 * Un seul bouton plein par écran. Le plein est `ink` sur fond clair (et `chalk` sur fond sombre) : l'accent
 * bleu n'est pas une couleur de bouton par défaut (D10). `--accent` existe pour le cas rare où un écran
 * doit signaler une action vive (inscription ouverte, live).
 */
/*
 * Le bouton au sommet incliné (D45).
 *
 * Le bord haut monte légèrement vers la droite — la même inclinaison que les séparateurs de sections et
 * que la fente du hero, en plus court. C'est ce qui fait qu'un bouton appartient à la page plutôt que d'y
 * être posé.
 *
 * **La face est peinte par un pseudo-élément, pas par le bouton.** Découper le bouton lui-même
 * (`clip-path`) emporterait aussi son **anneau de focus** : la cible deviendrait invisible au clavier, ce
 * qui est éliminatoire. Le pseudo porte donc le fond, le contour et la découpe ; le bouton ne garde que
 * le texte et son anneau, qui reste entier.
 *
 * Conséquence pour les variantes : elles ne posent plus `background-color` / `border-color`, mais
 * `--spp-button-fill` et `--spp-button-line`. Une variante qui écrirait encore les propriétés directes
 * peindrait derrière le pseudo et perdrait le biseau.
 */
.spp-button,
.spp-button .wp-block-button__link {
  --spp-button-slant: 6px;
  --spp-button-fill: transparent;
  --spp-button-line: transparent;
  --spp-button-sweep: transparent;

  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spp-space-2);
  min-height: calc(var(--spp-target-min) + 4px);
  /* Le retrait haut absorbe l'inclinaison : le libellé reste optiquement centré. */
  padding: calc(var(--spp-space-3) + var(--spp-button-slant)) var(--spp-space-6) var(--spp-space-3);
  border: 0;
  background-color: transparent;
  font-family: var(--spp-font-text);
  font-size: calc(var(--spp-text-label) * 1.1);
  font-weight: 600;
  letter-spacing: 0.14em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--spp-duration-fast) var(--spp-easing);
}

/*
 * **Deux couches, parce qu'un contour ne se découpe pas.**
 *
 * Première version : une seule couche, avec `border` et `clip-path`. Le contour est dessiné sur le
 * rectangle *avant* la découpe — il restait donc droit pendant que la face, elle, était biseautée. Sur un
 * bouton à contour (« Voir le calendrier »), on voyait un trait horizontal coupé net et aucun trait le
 * long de la diagonale. C'est le défaut que Damien a vu : « les boutons sont rognés mais le contour ne
 * suit pas ».
 *
 * La solution est de ne jamais dessiner de bordure : on empile **deux silhouettes découpées à
 * l'identique** — celle du dessous en couleur de trait, celle du dessus rentrée d'un trait et en couleur
 * de face. Ce qui dépasse entre les deux *est* le contour, et il suit la découpe par construction.
 *
 * Conséquence : la face d'un bouton « à contour » n'est pas transparente, elle prend la couleur de la
 * surface (`--spp-bg`, qui vaut précisément le fond du contexte : blanc en bande claire, nuit en bande
 * sombre). Un bouton posé sur une surface qui n'est pas `--spp-bg` — une photo, une carte élevée — doit
 * donc redéfinir `--spp-button-fill` lui-même.
 */
.spp-button::before,
.spp-button::after,
.spp-button .wp-block-button__link::before,
.spp-button .wp-block-button__link::after {
  content: "";
  position: absolute;
  clip-path: polygon(0 var(--spp-button-slant), 100% 0, 100% 100%, 0 100%);
  transition: background-color var(--spp-duration-fast) var(--spp-easing);
}

/* Dessous : la silhouette pleine, en couleur de trait. */
.spp-button::before,
.spp-button .wp-block-button__link::before {
  inset: 0;
  z-index: -2;
  background-color: var(--spp-button-line);
}

/*
 * Dessus : la même silhouette, rentrée de l'épaisseur du trait, en couleur de face.
 *
 * Elle porte aussi **le balayage au survol** : un dégradé deux fois plus large que le bouton, dont la
 * moitié gauche est en couleur de survol et la moitié droite transparente. Au repos on montre la moitié
 * transparente ; au survol on fait glisser jusqu'à la moitié colorée. La couleur traverse donc le bouton
 * de gauche à droite, en épousant le biseau — puisque c'est la même silhouette découpée.
 *
 * Aucune ombre, aucun agrandissement, deux couleurs : le mouvement vient de la forme, pas d'un effet
 * plaqué. 201 % et non 200 % : à la largeur exacte, l'arrondi du navigateur laissait un liseré d'un pixel.
 */
.spp-button::after,
.spp-button .wp-block-button__link::after {
  inset: var(--spp-border-width);
  z-index: -1;
  background-color: var(--spp-button-fill);
  background-image: linear-gradient(to right, var(--spp-button-sweep) 50%, transparent 50%);
  background-size: 201% 100%;
  background-position: 100% 0;
  background-repeat: no-repeat;
  transition:
    background-position var(--spp-duration-base) var(--spp-easing),
    background-color var(--spp-duration-fast) var(--spp-easing);
}

.spp-button:hover::after,
.spp-button:focus-visible::after,
.spp-button .wp-block-button__link:hover::after,
.spp-button .wp-block-button__link:focus-visible::after {
  background-position: 0 0;
}

/* L'enveloppe du bloc WordPress ne doit rien peindre : c'est le lien qui est le bouton (D42). */
.wp-block-button.spp-button::before,
.wp-block-button.spp-button::after {
  content: none;
}

/*
 * Le bloc bouton de WordPress porte la classe **sur son enveloppe**, et la règle ci-dessus l'applique à
 * l'enveloppe *et* au lien : les deux étaient peints et rembourrés. Mesuré le 23/09/2026 sur l'en-tête en
 * ligne — l'aplat blanc faisait 211 × 70 px pour un lien de 161 × 44 px, d'où cette dalle qui touchait le
 * haut et le bas de la barre, et une zone cliquable plus petite que ce qu'on voyait. L'enveloppe redevient
 * un simple conteneur ; seul le lien est un bouton.
 */
.wp-block-button.spp-button {
  display: inline-flex;
  min-height: 0;
  padding: 0;
  border: 0;
  background-color: transparent;
}

.spp-button--primary,
.spp-button--primary .wp-block-button__link {
  --spp-button-fill: var(--spp-fg);
  --spp-button-line: var(--spp-fg);
  --spp-button-sweep: var(--spp-accent-hover);

  color: var(--spp-bg);
}

/*
 * Pas de flèche dans les boutons (D44).
 *
 * Elle était ajoutée à chaque bouton d'action et avançait au survol. Trois raisons de la retirer : elle
 * répète ce que le bouton dit déjà, elle alourdit un libellé en capitales espacées, et elle est lue à voix
 * haute par certains lecteurs d'écran (« flèche vers la droite ») puisqu'elle vient d'un `content`.
 * Le bouton se suffit : un aplat, un libellé, un contour.
 */

.spp-button--secondary,
.spp-button--secondary .wp-block-button__link {
  --spp-button-fill: var(--spp-bg);
  --spp-button-line: var(--spp-fg);
  --spp-button-sweep: var(--spp-fg);

  color: var(--spp-fg);
}

.spp-button--secondary:hover,
.spp-button--secondary:focus-visible,
.spp-button--secondary .wp-block-button__link:hover,
.spp-button--secondary .wp-block-button__link:focus-visible {
  color: var(--spp-bg);
}

.spp-button--ghost {
  color: var(--spp-fg-muted);
  padding-inline: var(--spp-space-2);
}

.spp-button--ghost:hover {
  color: var(--spp-fg);
}

.spp-button--accent,
.spp-button--accent .wp-block-button__link {
  --spp-button-fill: var(--spp-accent);
  --spp-button-line: var(--spp-accent);
  --spp-button-sweep: var(--spp-accent-hover);

  color: var(--spp-accent-fg);
}

.spp-button[disabled],
.spp-button[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
}

.spp-button[aria-busy="true"] {
  cursor: progress;
}

.spp-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spp-space-3);
}

/* Un libellé long passe à la ligne : sans cela, il élargit tout son bloc et la page défile de côté (/contact/, D83). */
@media (max-width: 480px) {
  .spp-actions > .spp-button {
    width: 100%;
    white-space: normal;
    text-align: center;
  }
}

/* ================================================================== Statut (D10 : texte + point) */

.spp-status {
  display: inline-flex;
  align-items: baseline;
  gap: var(--spp-space-2);
  margin: 0;
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  line-height: var(--spp-text-label-leading);
  text-transform: uppercase;
  color: var(--spp-fg);
  white-space: nowrap;
}

.spp-status::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: var(--spp-radius-pill);
  background-color: currentColor;
  transform: translateY(-0.1em);
}

/* La couleur n'est qu'un renfort : le libellé porte seul l'information (WCAG 1.4.1). */
.spp-status--open {
  color: var(--spp-status-success);
}

.spp-status--waitlist {
  color: var(--spp-status-warning);
}

/* Le live est le seul statut qui prend le volt, et seulement sur fond sombre (où il est éclatant). */
.spp-status--live {
  color: var(--spp-focus);
}

[data-theme="dark"] .spp-status--live {
  color: var(--spp-accent);
}

.spp-status--closed,
.spp-status--muted {
  color: var(--spp-fg-muted);
}

.spp-status--danger {
  color: var(--spp-status-danger);
}

/* ================================================================== Petites cartes de tournois (D62, D73) */

/*
 * Une petite carte par tournoi, dans l'ordre où un joueur cherche : quand, quoi, à quelle heure, reste-t-il de la place.
 * Toute la carte est un seul lien. Sa face est claire quel que soit le fond (`data-theme="light"` sur la carte) : sur la
 * bande noire elle ressort seule, sans filet ni quadrillage. Le haut est incliné comme celui des boutons (D45). Les états
 * et leurs libellés viennent du moteur (`TournamentCard`), le thème ne fait que les poser.
 */
.spp-agenda {
  --spp-agenda-slant: var(--spp-space-2);

  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spp-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .spp-agenda {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--spp-space-4);
  }
}

@media (min-width: 1100px) {
  .spp-agenda {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.spp-agenda__item {
  min-width: 0;
  margin: 0;
}

.spp-agenda__link {
  display: flex;
  flex-direction: column;
  gap: var(--spp-space-2);
  height: 100%;
  padding: calc(var(--spp-space-4) + var(--spp-agenda-slant)) var(--spp-space-4) var(--spp-space-4);
  background-color: var(--spp-bg);
  color: var(--spp-fg);
  text-decoration: none;
  clip-path: polygon(0 var(--spp-agenda-slant), 100% 0, 100% 100%, 0 100%);
  transition: transform var(--spp-duration-base) var(--spp-easing);
}

/* Dans la carte : la découpe couperait un anneau posé à l'extérieur. */
.spp-agenda__link:focus-visible {
  outline: 2px solid var(--spp-fg);
  outline-offset: -6px;
}

/* Sur un écran tactile, le survol resterait collé après le toucher. */
@media (hover: hover) {
  .spp-agenda__link:hover {
    transform: translateY(calc(var(--spp-space-1) * -1));
  }

  .spp-agenda__link:hover .spp-agenda__cta {
    text-decoration-thickness: 2px;
  }
}

.spp-agenda__date {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas:
    "day month"
    "day weekday";
  column-gap: var(--spp-space-2);
  align-items: center;
  justify-items: start;
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  line-height: 1.2;
  text-transform: uppercase;
}

.spp-agenda__day {
  grid-area: day;
  font-family: var(--spp-font-sport);
  font-size: clamp(2.5rem, 2.2rem + 0.8vw, 3rem);
  font-weight: 800;
  letter-spacing: 0;
  line-height: 0.9;
  font-variant-numeric: tabular-nums;
}

.spp-agenda__month {
  grid-area: month;
}

.spp-agenda__weekday {
  grid-area: weekday;
  color: var(--spp-fg-muted);
}

.spp-agenda__title {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--spp-space-2);
  margin-top: var(--spp-space-1);
  font-family: var(--spp-font-sport);
  font-size: clamp(1.375rem, 1.2rem + 0.6vw, 1.75rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
  text-transform: uppercase;
}

.spp-agenda__draw {
  font-weight: 500;
  color: var(--spp-fg-muted);
}

.spp-agenda__time {
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
  font-variant-numeric: tabular-nums;
}

.spp-agenda__places {
  min-width: 0;
}

/* « Complet, liste d'attente (3) » doit pouvoir passer à la ligne dans une petite carte. */
.spp-agenda .spp-status {
  white-space: normal;
}

.spp-agenda__gauge {
  display: block;
  height: 2px;
  margin-top: var(--spp-space-2);
  background-color: color-mix(in srgb, currentColor 18%, transparent);
}

.spp-agenda__gauge > span {
  display: block;
  height: 100%;
  background-color: currentColor;
}

/* Calée en bas : les actions s'alignent d'une carte à l'autre, même si un libellé prend deux lignes. */
.spp-agenda__cta {
  margin-top: auto;
  padding-top: var(--spp-space-2);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-decoration: underline;
  text-decoration-thickness: var(--spp-border-width);
  text-transform: uppercase;
  text-underline-offset: 0.35em;
}

/* ================================================================== Vue des tournois : cartes ou calendrier (D67) */

/*
 * L'interrupteur : un curseur plein glisse sous le libellé choisi, dont le texte prend la couleur du fond. Il reste
 * invisible tant que le module ne l'a pas réveillé : sans JavaScript, aucun bouton mort, et sa place est déjà réservée,
 * donc la page ne saute pas quand il apparaît. Tout passe par les jetons : il vaut sur fond noir comme sur fond blanc.
 */
.spp-views {
  display: grid;
  align-content: start;
  gap: var(--spp-space-5);
  min-width: 0;
}

/* Le temps que la hauteur suive le changement de vue (D82) : `clip` ne crée pas de zone de défilement. */
[data-spp-views].is-morphing {
  overflow: clip;
}

.spp-views > .spp-viewswitch {
  justify-self: end;
}

.spp-viewswitch {
  position: relative;
  isolation: isolate;
  display: inline-grid;
  grid-template-columns: 1fr 1fr;
  border: var(--spp-border-width) solid var(--spp-fg);
  visibility: hidden;
}

.spp-viewswitch.is-ready {
  visibility: visible;
}

.spp-viewswitch::before {
  content: "";
  position: absolute;
  inset: 0 50% 0 0;
  z-index: -1;
  background-color: var(--spp-fg);
  transition: transform var(--spp-duration-base) var(--spp-easing);
}

.spp-viewswitch[data-current="calendar"]::before {
  transform: translateX(100%);
}

.spp-viewswitch__option {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--spp-space-2);
  min-height: var(--spp-target-min);
  padding: 0 var(--spp-space-4);
  border: 0;
  background: none;
  color: var(--spp-fg);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  cursor: pointer;
  transition:
    color var(--spp-duration-fast) var(--spp-easing),
    scale var(--spp-duration-fast) var(--spp-easing);
}

.spp-viewswitch__option[aria-pressed="true"] {
  color: var(--spp-bg);
}

.spp-viewswitch__option:active {
  scale: 0.97;
}

.spp-viewswitch__option:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 2px;
}

/* Sur le calendrier `/tournois/`, l'interrupteur vit dans la barre du décompte ; sur téléphone, il y prend sa ligne. */
@media (max-width: 599px) {
  .spp-views > .spp-viewswitch {
    justify-self: stretch;
  }

  .spp-calendar__bar {
    flex-wrap: wrap;
  }

  .spp-calendar__bar .spp-viewswitch {
    order: 3;
    width: 100%;
  }
}

/* Le mois : un vrai tableau, lu comme tel par un lecteur d'écran. */
.spp-tcal {
  --spp-tcal-line: color-mix(in srgb, var(--spp-fg) 24%, transparent);
}

.spp-tcal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4);
  margin-bottom: var(--spp-space-4);
}

.spp-tcal__title {
  margin: 0;
  font-family: var(--spp-font-sport);
  font-size: clamp(2rem, 1.5rem + 2vw, 3.25rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
}

.spp-tcal__nav {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--spp-target-min);
  height: var(--spp-target-min);
  border: var(--spp-border-width) solid var(--spp-fg);
  background: none;
  color: var(--spp-fg);
  cursor: pointer;
  transition:
    background-color var(--spp-duration-fast) var(--spp-easing),
    color var(--spp-duration-fast) var(--spp-easing);
}

.spp-tcal__nav::before {
  content: "";
  width: 0.6rem;
  height: 0.6rem;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
  transform: translateX(-2px) rotate(45deg);
}

.spp-tcal__nav--prev::before {
  transform: translateX(2px) rotate(-135deg);
}

.spp-tcal__nav:hover:not(:disabled),
.spp-tcal__nav:focus-visible {
  background-color: var(--spp-fg);
  color: var(--spp-bg);
}

.spp-tcal__nav:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 2px;
}

.spp-tcal__nav:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Le glissement du mois reste dans son cadre : il ne doit pas créer de défilement horizontal. */
.spp-tcal__body {
  overflow: hidden;
}

.spp-tcal__grid {
  width: 100%;
  margin: 0;
  border-collapse: separate;
  border-spacing: var(--spp-space-1);
  table-layout: fixed;
}

.spp-tcal__grid th {
  padding: var(--spp-space-2);
  border: 0;
  background: none;
  color: var(--spp-fg-muted);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: 0.1em;
  text-align: center;
  text-transform: uppercase;
}

/* Sans bordures (D73) : les chiffres alignés font la grille, et les tournois ressortent seuls. */
.spp-tcal__cell {
  height: 3rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--spp-fg);
  text-align: center;
  vertical-align: middle;
}

.spp-tcal__day {
  font-family: var(--spp-font-sport);
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1;
  color: var(--spp-fg-muted);
  font-variant-numeric: tabular-nums;
}

.spp-tcal__cell--today .spp-tcal__day {
  color: var(--spp-fg);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}

/* Téléphone : le jour à tournoi est un bouton plein, et le toucher réduit les cartes du dessous à ce jour-là. */
button.spp-tcal__day {
  display: block;
  width: 100%;
  height: 2.75rem;
  border: 0;
  background-color: var(--spp-fg);
  color: var(--spp-bg);
  cursor: pointer;
}

/* Le jour choisi se retourne : contour et chiffre, plus d'aplat. */
button.spp-tcal__day[aria-pressed="true"] {
  outline: 2px solid var(--spp-fg);
  outline-offset: -2px;
  background-color: transparent;
  color: var(--spp-fg);
}

button.spp-tcal__day:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 2px;
}

/* Sur le calendrier `/tournois/`, le fond est clair : la carte s'en détache par un gris. */
.spp-tcal__list {
  margin-top: var(--spp-space-5);
}

.spp-section:not(.spp-section--dark) .spp-tcal__list .spp-agenda__link {
  background-color: var(--spp-bg-muted);
}

.spp-tcal__list .spp-agenda__item[hidden] {
  display: none;
}

.spp-tcal__all {
  margin-top: var(--spp-space-4);
  padding: var(--spp-space-3) 0;
  border: 0;
  background: none;
  color: var(--spp-fg);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-decoration: underline;
  text-transform: uppercase;
  text-underline-offset: 0.35em;
  cursor: pointer;
}

.spp-tcal__all[hidden] {
  display: none;
}

.spp-tcal__empty {
  margin: var(--spp-space-4) 0 0;
  color: var(--spp-fg-muted);
}

/* Grand écran : chaque tournoi s'écrit dans sa case. Plein s'il est ouvert, en pointillé en liste d'attente, en
   simple contour sinon : la forme dit l'état avec le libellé, jamais une couleur (D27). */
@media (min-width: 760px) {
  .spp-tcal__cell {
    height: 7rem;
    padding: var(--spp-space-2);
    text-align: left;
    vertical-align: top;
  }

  .spp-tcal__cell--on .spp-tcal__day {
    color: var(--spp-fg);
  }

  .spp-tcal__events {
    display: grid;
    gap: var(--spp-space-1);
    margin: var(--spp-space-1) 0 0;
    padding: 0;
    list-style: none;
  }

  .spp-tcal__events li {
    margin: 0;
  }
}

.spp-tcal__event {
  display: block;
  padding: var(--spp-space-2);
  border: var(--spp-border-width) solid var(--spp-fg);
  background-color: var(--spp-fg);
  color: var(--spp-bg);
  text-decoration: none;
  transition:
    background-color var(--spp-duration-fast) var(--spp-easing),
    color var(--spp-duration-fast) var(--spp-easing);
}

.spp-tcal__event--waitlist,
.spp-tcal__event--closed,
.spp-tcal__event--muted,
.spp-tcal__event--past {
  background-color: transparent;
  color: var(--spp-fg);
}

.spp-tcal__event--waitlist {
  border-style: dashed;
}

.spp-tcal__event--closed,
.spp-tcal__event--muted,
.spp-tcal__event--past {
  border-color: var(--spp-tcal-line);
}

.spp-tcal__event:hover,
.spp-tcal__event:focus-visible {
  border-color: var(--spp-fg);
  background-color: transparent;
  color: var(--spp-fg);
}

.spp-tcal__event--waitlist:hover,
.spp-tcal__event--closed:hover,
.spp-tcal__event--muted:hover,
.spp-tcal__event--past:hover,
.spp-tcal__event--waitlist:focus-visible,
.spp-tcal__event--closed:focus-visible,
.spp-tcal__event--muted:focus-visible,
.spp-tcal__event--past:focus-visible {
  background-color: var(--spp-fg);
  color: var(--spp-bg);
}

.spp-tcal__event:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 2px;
}

.spp-tcal__eventtitle {
  display: block;
  font-family: var(--spp-font-sport);
  font-size: 1.25rem;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
  text-transform: uppercase;
}

.spp-tcal__eventdraw {
  font-weight: 500;
}

.spp-tcal__eventinfo {
  display: block;
  margin-top: var(--spp-space-1);
  font-size: var(--spp-text-small);
  line-height: 1.25;
}

/*
 * Le calendrier de l'accueil (D82) : un petit mois à côté des tournois du mois, pas une page entière. Mesuré à 901 px de haut
 * contre 302 pour les cartes, dans sa forme précédente. Le titre du mois prend place à côté de l'interrupteur, sur la ligne
 * qu'il occupe déjà : la hauteur gagnée est celle d'un en-tête de plus, et rien ne saute quand on change de vue.
 */
.spp-views--compact {
  --spp-tcal-side: 22rem;
}

.spp-views--compact .spp-tcal__title {
  font-size: clamp(1.375rem, 1.2rem + 0.6vw, 1.75rem);
}

.spp-views--compact .spp-tcal__grid {
  border-spacing: 2px;
}

.spp-views--compact .spp-tcal__grid th {
  padding: var(--spp-space-1);
}

.spp-views--compact .spp-tcal__day {
  font-size: 1.0625rem;
}

.spp-views--compact button.spp-tcal__day {
  transition:
    background-color var(--spp-duration-fast) var(--spp-easing),
    color var(--spp-duration-fast) var(--spp-easing);
}

@media (min-width: 760px) {
  .spp-views--compact {
    position: relative;
  }

  .spp-views--compact .spp-tcal__head {
    position: absolute;
    top: 0;
    left: 0;
    width: var(--spp-tcal-side);
    margin: 0;
  }

  .spp-views--compact .spp-tcal__month {
    display: grid;
    grid-template-columns: var(--spp-tcal-side) minmax(0, 1fr);
    column-gap: var(--spp-space-6);
    align-items: start;
  }

  .spp-views--compact .spp-tcal__grid {
    grid-row: 1 / span 3;
  }

  .spp-views--compact .spp-tcal__list,
  .spp-views--compact .spp-tcal__all,
  .spp-views--compact .spp-tcal__empty {
    grid-column: 2;
    justify-self: start;
  }

  .spp-views--compact .spp-tcal__empty {
    margin-top: var(--spp-space-2);
  }

  /* Les règles du grand calendrier valent à cet écran : ici, la case ne porte que son chiffre. */
  .spp-views--compact .spp-tcal__cell {
    height: var(--spp-target-min);
    padding: 0;
    text-align: center;
    vertical-align: middle;
  }

  .spp-views--compact button.spp-tcal__day {
    color: var(--spp-bg);
  }

  .spp-views--compact button.spp-tcal__day[aria-pressed="true"] {
    color: var(--spp-fg);
  }
}

/* La même carte que la vue Cartes, couchée : date à gauche, tableau au-dessus, heure et places dessous. */
.spp-views--compact .spp-tcal__list {
  justify-self: stretch;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--spp-space-2);
}

.spp-views--compact .spp-tcal__list .spp-agenda__link {
  display: grid;
  grid-template-columns: 3rem auto minmax(0, 1fr);
  grid-template-areas:
    "date title title"
    "date time places";
  gap: 2px var(--spp-space-3);
  align-items: center;
  padding: calc(var(--spp-space-3) + var(--spp-agenda-slant)) var(--spp-space-4) var(--spp-space-3);
}

.spp-views--compact .spp-tcal__list .spp-agenda__date {
  grid-area: date;
  grid-template-columns: 1fr;
  grid-template-areas:
    "day"
    "month";
  justify-items: center;
}

.spp-views--compact .spp-tcal__list .spp-agenda__day {
  font-size: 1.75rem;
}

.spp-views--compact .spp-tcal__list .spp-agenda__weekday {
  display: none;
}

.spp-views--compact .spp-tcal__list .spp-agenda__title {
  grid-area: title;
  margin: 0;
  font-size: 1.25rem;
}

.spp-views--compact .spp-tcal__list .spp-agenda__time {
  grid-area: time;
}

.spp-views--compact .spp-tcal__list .spp-agenda__places {
  grid-area: places;
}

@media (min-width: 760px) {
  .spp-views--compact .spp-tcal__list {
    margin-top: 0;
  }
}

@media (min-width: 1100px) {
  .spp-views--compact .spp-tcal__list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Le changement de vue se joue dans `tournament-views.js` (D82). Ici, le mois glisse dans le sens où l'on va. */
@media (prefers-reduced-motion: no-preference) {
  .spp-tcal__month.is-next {
    animation: spp-monthnext var(--spp-duration-slow) var(--spp-easing);
  }

  .spp-tcal__month.is-prev {
    animation: spp-monthprev var(--spp-duration-slow) var(--spp-easing);
  }
}

@keyframes spp-monthnext {
  from {
    opacity: 0;
    transform: translateX(var(--spp-space-6));
  }
}

@keyframes spp-monthprev {
  from {
    opacity: 0;
    transform: translateX(calc(var(--spp-space-6) * -1));
  }
}

/* ================================================================== En-tête en deux colonnes, cartes en portrait (D69) */

/*
 * La construction que Damien a choisie sur la section « fastrack team » de fastracksales.com, dans notre registre :
 * surtitre et grand titre à gauche, texte et liens à droite, puis une rangée compacte de cartes, photo et nom dessous.
 * Sert aux événements du club ; servira aux coachs dès que leurs photos seront là.
 */
.spp-sectionhead--split {
  display: grid;
  gap: var(--spp-space-4);
}

.spp-sectionhead--split .spp-sectionhead__meta {
  margin: 0;
}

/* `!important` : la règle de base du chapô en porte un, à cause de la disposition contrainte de WordPress. */
.spp-sectionhead--split .spp-sectionhead__lead {
  margin-top: 0 !important;
}

.spp-sectionhead--split .spp-linkrow {
  margin-top: var(--spp-space-4);
  margin-bottom: 0;
}

@media (min-width: 900px) {
  .spp-sectionhead--split {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: var(--spp-space-8);
    align-items: end;
  }

  .spp-sectionhead--split .spp-sectionhead__meta {
    grid-column: 1 / -1;
  }

  .spp-sectionhead--split .spp-sectionhead__side {
    justify-self: end;
    max-width: 36rem;
  }
}

/*
 * Les cartes en quinconce : une sur deux descend d'un cran. C'est ce décalage qui donne son rythme à la rangée.
 * Deux colonnes sur téléphone, trois sur tablette, cinq sur grand écran : jamais une carte seule sur sa ligne à 5.
 */
.spp-pcards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--spp-space-5) var(--spp-space-3);
  align-items: start;
  margin: 0;
  padding: 0;
  list-style: none;
}

.spp-pcard {
  margin: 0;
  padding-top: var(--spp-space-3);
  border-top: var(--spp-border-width) solid color-mix(in srgb, var(--spp-fg) 28%, transparent);
}

.spp-pcard:nth-child(even) {
  margin-top: var(--spp-space-6);
}

@media (min-width: 760px) {
  .spp-pcards {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--spp-space-6) var(--spp-space-4);
  }

  .spp-pcard:nth-child(even) {
    margin-top: 0;
  }

  .spp-pcard:nth-child(3n + 2) {
    margin-top: var(--spp-space-7);
  }
}

@media (min-width: 1100px) {
  .spp-pcards {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }

  .spp-pcard:nth-child(3n + 2) {
    margin-top: 0;
  }

  .spp-pcard:nth-child(even) {
    margin-top: var(--spp-space-7);
  }
}

.spp-pcard__link {
  display: block;
  color: var(--spp-fg);
  text-decoration: none;
}

.spp-pcard__link:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 4px;
}

/*
 * La photo et ce qu'elle a derrière elle. Trois couches : une forme en biais volt qui dépasse à droite et en bas, une
 * petite rayure posée dessus, et la photo, découpée elle aussi. Le volt est la couleur de la balle du logo : Damien l'a
 * voulue ici (D72), c'est la seule entorse au noir et blanc de l'interface (D27). La rayure reste noire quel que soit le
 * fond de la section : c'est sur la forme qu'elle se lit.
 */
.spp-pcard__media {
  position: relative;
  isolation: isolate;
  aspect-ratio: 4 / 5;
}

.spp-pcard__media::before {
  content: "";
  position: absolute;
  inset: 12% -5% 0 8%;
  z-index: 0;
  background-color: var(--spp-color-volt);
  clip-path: polygon(0 9%, 94% 0, 100% 86%, 9% 100%, 0 84%);
  transition: transform var(--spp-duration-slow) var(--spp-easing);
}

.spp-pcard__media::after {
  content: "";
  position: absolute;
  right: -5%;
  bottom: 7%;
  z-index: 1;
  width: 42%;
  height: var(--spp-space-2);
  background-image: repeating-linear-gradient(90deg, var(--spp-color-night) 0 var(--spp-space-2), transparent var(--spp-space-2) var(--spp-space-4));
}

.spp-pcard__img {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
  clip-path: polygon(4% 0, 100% 0, 96% 94%, 0 100%, 0 8%);
  transition: transform var(--spp-duration-slow) var(--spp-easing);
}

@media (hover: hover) {
  .spp-pcard__link:hover .spp-pcard__img {
    transform: translateY(calc(var(--spp-space-1) * -1));
  }

  .spp-pcard__link:hover .spp-pcard__media::before {
    transform: translate(var(--spp-space-1), calc(var(--spp-space-1) * -1)) rotate(-1deg);
  }

  .spp-pcard__link:hover .spp-pcard__title {
    text-decoration: underline;
    text-decoration-thickness: 2px;
    text-underline-offset: 0.15em;
  }
}

/* La date sur la photo, comme le numéro de la ligne d'agenda : c'est ce qu'on cherche d'abord dans un événement. */
.spp-pcard__date {
  position: absolute;
  top: 8%;
  left: 0;
  z-index: 3;
  display: flex;
  align-items: baseline;
  gap: var(--spp-space-2);
  padding: var(--spp-space-1) var(--spp-space-3);
  background-color: var(--spp-color-night);
  color: var(--spp-color-chalk);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
}

.spp-pcard__day {
  font-family: var(--spp-font-sport);
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: 0;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.spp-pcard__name {
  padding-top: var(--spp-space-4);
}

.spp-pcard__title {
  margin: 0;
  font-family: var(--spp-font-sport);
  font-size: clamp(1.25rem, 1.1rem + 0.5vw, 1.625rem);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1.06;
  text-transform: uppercase;
}

.spp-pcard__meta {
  margin: var(--spp-space-1) 0 0;
  color: var(--spp-fg-muted);
  font-size: var(--spp-text-small);
}

/* La page d'un événement se lit comme un article (D70) : la photo reste à côté du texte pendant qu'on le lit. */
.spp-split--article {
  align-items: start;
}

@media (min-width: 900px) {
  .spp-split--article .spp-split__media {
    position: sticky;
    top: calc(var(--spp-header-h) + var(--spp-space-4));
  }
}

.spp-clubevent__body {
  max-width: 62ch;
  font-size: var(--spp-text-body-l);
  line-height: var(--spp-text-body-l-leading);
}

.spp-clubevent__body > * + * {
  margin-top: var(--spp-space-4);
}

.spp-clubevent__body ul,
.spp-clubevent__body ol {
  padding-left: var(--spp-space-5);
}

.spp-clubevent__body a:not(:where(.spp-linkrow a)) {
  text-decoration: underline;
  text-underline-offset: 0.15em;
}

.spp-clubevent__photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr));
  gap: var(--spp-space-4);
  margin: var(--spp-space-7) 0 0;
  padding: 0;
  list-style: none;
}

.spp-clubevent__photos li {
  margin: 0;
}

.spp-clubevent__photos img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* Le pied d'une section : son action à gauche, ses liens secondaires à droite. */
.spp-section > .spp-sectionfoot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4) var(--spp-space-6);
  margin-block-start: var(--spp-space-6);
}

.spp-sectionfoot > * {
  margin: 0;
}

/* La photo mord le texte par la diagonale du hero et des sections (D38, D44), penchée du même côté. */
@media (min-width: 900px) {
  .spp-split--slanted .spp-split__media {
    clip-path: polygon(var(--spp-slant) 0, 100% 0, 100% 100%, 0 100%);
  }
}

/* ================================================================== Liste éditoriale */

/*
 * Remplace la grille de cartes pour les listes de tournois, de tarifs et d'actualités (D10) :
 * une ligne par élément, filets 1 px, colonnes qui s'empilent sous 768 px.
 */
.spp-editorial-list {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-editorial-list__item {
  margin: 0;
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-editorial-list__link {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--spp-space-2);
  padding-block: var(--spp-space-5);
  color: inherit;
  text-decoration: none;
  transition: opacity var(--spp-duration-fast) var(--spp-easing);
}

.spp-editorial-list__link:hover {
  opacity: 0.62;
  color: inherit;
}

.spp-editorial-list__date {
  margin: 0;
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

.spp-editorial-list__title {
  margin: 0;
  font-family: var(--spp-font-display);
  font-size: var(--spp-text-h3);
  font-weight: var(--spp-text-h3-weight);
  line-height: var(--spp-text-h3-leading);
}

.spp-editorial-list__meta {
  margin: 0;
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

@media (min-width: 768px) {
  .spp-editorial-list__link {
    grid-template-columns: 10rem 1fr auto;
    align-items: baseline;
    gap: var(--spp-space-5);
    padding-block: var(--spp-space-6);
  }

  .spp-editorial-list__body {
    display: grid;
    gap: var(--spp-space-1);
  }
}

/* ================================================================== Faits (terme / valeur) */

.spp-facts {
  margin: 0 0 var(--spp-space-7);
  padding: 0;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-facts__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--spp-space-1);
  padding-block: var(--spp-space-3);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-facts dt {
  margin: 0;
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-facts dd {
  margin: 0;
}

@media (min-width: 600px) {
  .spp-facts__row {
    grid-template-columns: minmax(9rem, 16rem) 1fr;
    gap: var(--spp-space-5);
    align-items: baseline;
  }
}

/* ================================================================== Tableaux éditoriaux */

/* Tarifs, horaires, grilles : en-têtes de ligne en petites capitales, chiffres alignés. */
.spp-table tbody th[scope="row"] {
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-body);
  font-weight: 600;
}

.spp-table td:last-child,
.spp-table th:last-child {
  padding-right: 0;
  text-align: right;
  white-space: nowrap;
}

/* ================================================================== Chiffres clés */

.spp-figures {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-6) var(--spp-space-8);
  margin: var(--spp-space-7) 0 0;
  padding: 0;
  list-style: none;
}

.spp-figures__item {
  margin: 0;
}

.spp-figures__value {
  font-size: calc(var(--spp-text-h1) * 0.78);
}

@media (min-width: 760px) {
  .spp-figures--band {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.spp-figures__value {
  display: block;
  font-family: var(--spp-font-display);
  font-size: var(--spp-text-h1);
  font-weight: var(--spp-text-h1-weight);
  line-height: 1;
  letter-spacing: var(--spp-text-h1-tracking);
}

.spp-figures__label {
  display: block;
  margin-top: var(--spp-space-2);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

/* ================================================================== Carte (objets du moteur) */

/* D10 : la carte est réservée aux objets du moteur (match, équipe) — bord fin, aucune ombre. */
.spp-card {
  margin: 0;
  padding: var(--spp-space-5);
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: var(--spp-radius-sm);
  background-color: var(--spp-bg-elevated);
}

.spp-card__title {
  margin: 0 0 var(--spp-space-2);
  font-size: var(--spp-text-h4);
  font-weight: var(--spp-text-h4-weight);
}

.spp-card__meta {
  margin: 0;
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

/* ================================================================== Flux d'actualités */

.spp-feed {
  gap: var(--spp-space-7) var(--spp-space-6);
}

.spp-card--post {
  padding: 0;
  border: 0;
  background: transparent;
}

.spp-card--post .wp-block-post-title {
  margin-block: var(--spp-space-2);
  font-size: var(--spp-text-h3);
}

.spp-card--post .wp-block-post-featured-image img {
  border-radius: var(--spp-radius-none);
}

.spp-card--post .wp-block-post-excerpt {
  color: var(--spp-fg-muted);
}

.spp-article__header {
  margin-bottom: var(--spp-space-6);
}

.spp-article__meta {
  gap: var(--spp-space-3);
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

.spp-article__footer {
  margin-top: var(--spp-space-7);
  padding-top: var(--spp-space-4);
  border-top: var(--spp-border-width) solid var(--spp-border);
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

.spp-post-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--spp-space-4);
  margin-top: var(--spp-space-8);
  padding-top: var(--spp-space-5);
  border-top: var(--spp-border-width) solid var(--spp-border);
  font-size: var(--spp-text-small);
}

/* ================================================================== Formulaires */

.spp-form {
  display: grid;
  gap: var(--spp-space-6);
  max-width: var(--spp-layout-content);
}

.spp-fieldset {
  margin: 0;
  padding: var(--spp-space-5);
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: var(--spp-radius-sm);
}

.spp-legend {
  padding-inline: var(--spp-space-2);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--spp-space-4);
}

.spp-field {
  display: grid;
  gap: var(--spp-space-2);
  /*
   * Un élément de grille se dimensionne par défaut sur son contenu (`min-width: auto`). Un `select` dont
   * l'option la plus longue dépasse la colonne élargit donc la piste et déborde sur la suivante — constaté
   * le 11/09/2026 sur « Séminaire ou journée d'entreprise », qui recouvrait le champ voisin.
   */
  min-width: 0;
  /*
   * Sans cela, un champ à deux lignes (libellé + saisie) placé dans une rangée dont le voisin en a trois
   * (libellé + saisie + aide) répartit ses lignes sur toute la hauteur : les saisies d'une même rangée ne
   * s'alignent plus. On tasse en haut, la rangée reste une ligne.
   */
  align-content: start;
}

.spp-field > span,
.spp-field > label {
  font-size: var(--spp-text-small);
  font-weight: 600;
}

.spp-field input,
.spp-field select,
.spp-field textarea {
  width: 100%;
  min-width: 0;
  min-height: var(--spp-target-min);
  padding: var(--spp-space-2) var(--spp-space-3);
  border: var(--spp-border-width) solid var(--spp-fg-muted);
  border-radius: var(--spp-radius-sm);
  background-color: var(--spp-bg-elevated);
  color: var(--spp-fg);
}

.spp-field input:focus-visible,
.spp-field select:focus-visible,
.spp-field textarea:focus-visible {
  border-color: var(--spp-focus);
}

.spp-field__help {
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

/*
 * Le champ à corriger (D41, D74), signalé par le serveur ou dès la saisie.
 *
 * Le trait de gauche et le liseré disent *où* ; la phrase de `.spp-field__error` dit *quoi*. L'information
 * n'est donc jamais portée par la seule couleur — règle d'accessibilité du projet — et reste lisible par
 * quelqu'un qui ne distingue pas le rouge.
 */
.spp-field--error {
  padding-left: var(--spp-space-3);
  border-left: 3px solid var(--spp-status-danger);
}

.spp-field--error input,
.spp-field--error select,
.spp-field--error textarea {
  border-color: var(--spp-status-danger);
}

.spp-field__error {
  display: block;
  font-size: var(--spp-text-small);
  font-weight: 600;
  color: var(--spp-status-danger);
}

/* Le repère « ! » évite d'avoir à reconnaître la couleur pour repérer la ligne fautive. */
.spp-field__error::before {
  content: '! ';
  font-weight: 700;
}

.spp-field--check label {
  display: flex;
  align-items: flex-start;
  gap: var(--spp-space-3);
  font-weight: 400;
}

.spp-field--check input {
  flex: none;
  width: 20px;
  min-height: 20px;
  height: 20px;
  margin-top: 0.2em;
}

.spp-honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.spp-form__status {
  min-height: 1.5em;
  font-size: var(--spp-text-small);
  font-weight: 600;
}

.spp-form__status--error {
  color: var(--spp-status-danger);
}

/*
 * Le récapitulatif au-dessus du bouton (D74) : on vient de cliquer, c'est là qu'on regarde. Chaque ligne amène à sa
 * case et disparaît quand elle est corrigée. Les liens gardent la couleur d'erreur et leur soulignement.
 */
.spp-form__count {
  margin: 0 0 var(--spp-space-2);
  font-weight: 700;
}

.spp-form__errors {
  display: grid;
  gap: var(--spp-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-weight: 400;
}

.spp-form__errors a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.spp-form__status--success {
  color: var(--spp-status-success);
}

.spp-form__status--pending {
  color: var(--spp-fg-muted);
}

.spp-search .wp-block-search__input {
  min-height: var(--spp-target-min);
  border: var(--spp-border-width) solid var(--spp-fg-muted);
  border-radius: var(--spp-radius-sm);
  background-color: var(--spp-bg-elevated);
}

.spp-search .wp-block-search__button {
  min-height: var(--spp-target-min);
  border: var(--spp-border-width) solid var(--spp-fg);
  border-radius: var(--spp-radius-sm);
  background-color: var(--spp-fg);
  color: var(--spp-bg);
}

/* ================================================================== États : vide, note, à compléter */

.spp-empty,
.spp-note {
  margin: 0;
  padding: var(--spp-space-5);
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: var(--spp-radius-sm);
  color: var(--spp-fg-muted);
}

/* Le repli du calendrier porte deux paragraphes : ils ne doivent pas se coller l'un à l'autre. */
.spp-empty > * {
  margin-block: 0;
}

.spp-empty > * + * {
  margin-top: var(--spp-space-4);
}

.spp-success {
  padding: var(--spp-space-6);
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: var(--spp-radius-sm);
  background-color: var(--spp-bg-elevated);
}

/*
 * « À compléter » : contenu que Damien doit fournir (D11 — jamais inventer). Visible, sobre, repérable
 * par l'installateur de pages ; à retirer dès que le contenu réel arrive.
 */
/*
 * « À compléter » : un pense-bête d'atelier, pas un contenu public.
 *
 * Ces encadrés disent au club ce qu'il reste à fournir (D11) — mais ils étaient publiés sur les sept pages
 * du site, jusque dans le pied de page : un visiteur y lisait « horaires officiels à confirmer ». Ils ne
 * s'affichent plus qu'à ceux qui gèrent le contenu (`spp-can-see-todo`, capability `edit_theme_options`) — pas
 * à un joueur connecté (revue du 19/10, lot 7) — et restent listés dans Apparence → Site South Padel.
 * Le contenu reste dans la page : rien n'est perdu, rien n'est inventé.
 */
body:not(.spp-can-see-todo) .spp-todo {
  display: none;
}

.spp-todo {
  display: block;
  margin-block: var(--spp-space-4);
  padding: var(--spp-space-3) var(--spp-space-4);
  border-left: var(--spp-border-thick) solid var(--spp-color-sand);
  background-color: var(--spp-bg-muted);
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

.spp-todo::before {
  content: "À compléter — ";
  font-weight: 600;
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg);
}

/* ================================================================== Hero et médias */

/*
 * Le hero est une photo plein écran surmontée d'un voile sombre. Le voile est un dégradé : c'est la seule
 * exception à l'interdit de D10, et elle est fonctionnelle — sans lui, le texte clair posé sur une photo
 * n'atteint aucun rapport de contraste garanti. Le dégradé ne colore rien, il assombrit.
 */
.spp-hero {
  display: flex;
  flex-direction: column;
  background-color: var(--spp-color-night);
  color: var(--spp-color-chalk);
  isolation: isolate;
}

/*
 * Le hero fendu (D44) : un aplat noir à gauche, la photo à droite, une diagonale entre les deux.
 *
 * Ce qu'il résout. Le texte était posé sur la photo ; pour qu'il se lise il fallait un voile, et plus le
 * voile montait, moins la photo existait — mesuré, le titre tombait à 1,53:1 sur un téléphone avec un voile
 * déjà lourd. Ici il n'y a **plus un pixel de texte sur l'image** : le contraste est celui du blanc sur le
 * noir, 19,8:1, et la photo garde toute sa couleur. Le compromis disparaît au lieu d'être arbitré.
 */
.spp-hero__stage {
  position: relative;
  display: flex;
  align-items: stretch;
  min-height: min(88vh, 820px);
  overflow: hidden;
}

/* La photo occupe tout le plateau ; c'est le panneau qui vient la recouvrir à gauche. */
.spp-hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 45%;
}

.spp-hero__panel {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: none;
  width: 100%;
  padding-block: calc(var(--spp-header-h) + var(--spp-space-7)) var(--spp-space-7);
  padding-inline: var(--spp-gutter);
  background-color: var(--spp-color-night);
}

@media (min-width: 900px) {
  .spp-hero__panel {
    width: min(58%, 820px);
    /* La diagonale, celle des sections (D38). Le panneau mord la photo, pas l'inverse. */
    clip-path: polygon(0 0, 100% 0, calc(100% - var(--spp-slant)) 100%, 0 100%);
    /* À gauche, on s'aligne sur la colonne de contenu du site ; à droite, on laisse passer la diagonale. */
    padding-inline: max(var(--spp-gutter), calc((100vw - var(--spp-layout-max)) / 2))
      calc(var(--spp-slant) + var(--spp-space-6));
  }
}

/*
 * Très grand écran : la marge gauche grandit, le panneau grandit avec elle et garde sa colonne de 650 px. À
 * 820 px fixes, il n'en restait que 396 à 1920 px, et le titre passait sur trois lignes (mesuré le 02/11/2026).
 */
@media (min-width: 1440px) {
  .spp-hero__panel {
    width: calc(
      max(var(--spp-gutter), (100vw - var(--spp-layout-max)) / 2) + 650px + var(--spp-slant) + var(--spp-space-6)
    );
  }
}

/*
 * Écran étroit : la photo passe au-dessus, le panneau en dessous. La diagonale bascule à l'horizontale —
 * elle reste le même geste, et le panneau mord toujours l'image.
 */
@media (max-width: 899px) {
  .spp-hero__stage {
    flex-direction: column;
    min-height: 0;
  }

  .spp-hero__media {
    position: relative;
    height: auto;
    aspect-ratio: 4 / 3;
  }

  .spp-hero__panel {
    margin-top: calc(var(--spp-slant) * -1);
    padding-block: calc(var(--spp-slant) + var(--spp-space-6)) var(--spp-space-7);
    clip-path: polygon(0 var(--spp-slant), 100% 0, 100% 100%, 0 100%);
  }
}

/*
 * Le panneau donne déjà la mesure : lui remettre une largeur maximale coupait le titre en quatre lignes et
 * empilait les deux boutons l'un sur l'autre. Seul le chapô garde une mesure, parce que c'est du texte
 * courant et qu'il se lit mal au-delà.
 */
.spp-hero__body {
  width: 100%;
  container-type: inline-size;
}

.spp-hero__kicker {
  color: var(--spp-color-chalk);
  opacity: 0.72;
}

/*
 * D64 : le titre est le sommet de la page, à la façon d'une affiche. Il faisait 88 px, moins que les titres de
 * section (92 px). Sa taille suit désormais la colonne : « jour et nuit. », sa ligne la plus longue, mesure
 * 4,98 em (mesuré le 02/11/2026), donc 19,6 % de la colonne la remplit presque sans jamais la dépasser, plafonnés à
 * 8 rem pour la tablette en portrait, où la colonne est la plus large. La coupure voulue — « Le padel, » puis « jour
 * et nuit. » — est écrite dans le motif, et reste la seule. Sans unité de conteneur, le navigateur garde la première
 * taille.
 */
.spp-hero__title {
  margin: 0 0 var(--spp-space-5);
  font-size: var(--spp-text-h1);
  font-size: min(19.6cqw, 8rem);
  text-wrap: balance;
}

.spp-hero__lead {
  max-width: 44ch;
  margin: 0 0 var(--spp-space-6);
  font-size: var(--spp-text-body-l);
  color: var(--spp-color-chalk);
  opacity: 0.86;
}

.spp-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-3);
}

/*
 * Le hero d'une page (D75) : un cran plus bas et plus petit que celui de l'accueil, qui reste le sommet du site.
 *
 * Les photos du club sont presque toutes en portrait, en 900 à 1200 px de large. Étirées sur toute la scène, elles
 * étaient agrandies jusqu'à ×1,6 (bandes de Contact et du Club house, relevé du 21/10/2026). Ici la photo n'occupe que
 * les 60 % de droite, le panneau recouvrant son bord : elle s'affiche à sa taille réelle, ou presque, jusqu'à 1920 px.
 *
 * Pas de bande noire sous la scène : le biseau de la jonction (base.css) coupe directement la photo et le panneau.
 */
.spp-hero--page .spp-hero__stage {
  min-height: min(66vh, 620px);
}

.spp-hero.spp-hero--page:has(+ .spp-section:not(.spp-section--dark)) {
  padding-bottom: 0;
}

.spp-hero--page .spp-hero__title {
  font-size: min(15cqw, 6rem);
}

@media (min-width: 900px) {
  .spp-hero--page .spp-hero__media {
    inset: 0 0 0 auto;
    width: 60%;
  }

  .spp-hero--page .spp-hero__panel {
    padding-block: var(--spp-space-8) calc(var(--spp-space-8) + var(--spp-slant));
  }
}

@media (max-width: 899px) {
  .spp-hero--page .spp-hero__panel {
    padding-bottom: calc(var(--spp-space-7) + var(--spp-slant));
  }
}

/* Bouton posé sur une photo : bordure claire, fond translucide, lisible sans assombrir davantage l'image. */
.spp-button--onphoto,
.spp-button--onphoto .wp-block-button__link {
  /*
   * La face n'est plus translucide : posée par-dessus la silhouette de trait, une couleur transparente se
   * teinterait de celle-ci au lieu de laisser voir le fond. Depuis le hero fendu (D44) ce bouton n'est
   * plus sur une photo mais sur l'aplat noir : la couleur de surface convient exactement.
   */
  --spp-button-fill: var(--spp-bg);
  --spp-button-line: rgb(237 235 230 / 55%);
  --spp-button-sweep: var(--spp-color-chalk);

  color: var(--spp-color-chalk);
}

.spp-button--onphoto:hover,
.spp-button--onphoto:focus-visible,
.spp-button--onphoto .wp-block-button__link:hover,
.spp-button--onphoto .wp-block-button__link:focus-visible {
  --spp-button-line: var(--spp-color-chalk);

  color: var(--spp-color-ink);
}

/* ---- Média éditorial : une photo qui occupe toute la largeur d'une section, sans cadre ni ombre. */
.spp-media {
  display: block;
}

.spp-media__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--spp-radius-none);
}

.spp-figure {
  margin: 0;
}

.spp-figure__caption {
  margin-top: var(--spp-space-3);
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

/* Bande photo pleine largeur entre deux sections : respiration visuelle, hauteur maîtrisée. */
.spp-band {
  position: relative;
  overflow: hidden;
  height: clamp(260px, 46vw, 560px);
}

.spp-band .spp-media__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Deux colonnes : une photo, un bloc de texte. S'empile sous 900 px, photo d'abord. */
.spp-split {
  display: grid;
  gap: var(--spp-space-6);
  align-items: center;
}

@media (min-width: 900px) {
  .spp-split {
    grid-template-columns: 1fr 1fr;
    gap: var(--spp-space-8);
  }

  .spp-split--reverse .spp-split__media {
    order: 2;
  }
}

.spp-split__media .spp-media__img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.spp-split--wide .spp-split__media .spp-media__img {
  aspect-ratio: 3 / 2;
}


/* Le formulaire de contact et ses renvois : le formulaire prend la place, les renvois suivent le fil de la lecture (D75). */
@media (min-width: 900px) {
  .spp-split--form {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
    align-items: start;
  }
}

/* Disposition en flux de WordPress : elle poserait une marge sur le second enfant, décalé de tout l'écart. */
.spp-split--form > * {
  margin-block: 0;
}

.spp-asides h3 {
  margin-top: 0;
  font-size: var(--spp-text-h4);
}

.spp-asides ul {
  display: grid;
  gap: var(--spp-space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * La vraie carte (D75) : OpenStreetMap, sans cookie. Ses couleurs seraient les seules de la page : le gris la range dans
 * le noir et blanc (D27). Plafonnée en hauteur pour qu'on puisse encore faire défiler la page à côté d'elle sur un
 * téléphone, où un doigt posé sur la carte la déplace, elle.
 */
.spp-map {
  margin: 0;
}

.spp-map__frame {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  max-height: 60vh;
  border: 0;
  background-color: var(--spp-bg-muted);
  filter: grayscale(1);
}

/* Les étapes d'une démarche, sans numéros (D73) : l'ordre de lecture suffit. */
.spp-steps {
  display: grid;
  gap: var(--spp-space-6);
  margin: 0 0 var(--spp-space-6);
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .spp-steps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.spp-steps__title {
  margin: 0 0 var(--spp-space-3);
  font-family: var(--spp-font-sport);
  font-size: clamp(1.5rem, 1.25rem + 0.8vw, 2rem);
  font-weight: 800;
  line-height: 1.05;
  text-transform: uppercase;
}

.spp-steps__item p {
  margin: 0;
}

/* ================================================================== Bande photo pleine largeur */

/*
 * Une photo bord à bord qui coupe le fil du texte : c'est le respirateur des pages éditoriales. Le format
 * est imposé (21/9 sur grand écran, 4/3 sur téléphone) pour que des originaux en portrait comme en paysage
 * tiennent la même ligne d'horizon.
 */

.spp-band {
  position: relative;
  margin: 0;
  overflow: hidden;
  background-color: var(--spp-color-night);
}

.spp-band .spp-media__img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: center 55%;
}

@media (min-width: 760px) {
  .spp-band .spp-media__img {
    aspect-ratio: 21 / 9;
  }
}

.spp-band figcaption {
  position: absolute;
  inset: auto 0 0;
  padding: var(--spp-space-7) var(--spp-gutter) var(--spp-space-4);
  background: linear-gradient(180deg, transparent, rgba(10, 10, 10, 0.8));
  color: var(--spp-color-chalk);
  font-size: var(--spp-text-small);
}

/* ================================================================== Galerie (/galerie/) */

/*
 * Une mosaïque plutôt qu'une grille régulière : la première photo prend toute la largeur, les suivantes
 * alternent deux colonnes. Les légendes se posent **sur** l'image, en bas, sur un voile — elles font partie
 * de la photo au lieu de flotter dessous en gris (D22).
 *
 * Pas de lightbox : elle ajouterait du JavaScript pour agrandir une image que le navigateur sait déjà
 * ouvrir, et casserait « ouvrir dans un nouvel onglet ».
 */

.spp-gallery {
  display: grid;
  gap: var(--spp-space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 760px) {
  .spp-gallery {
    grid-template-columns: 1fr 1fr;
  }

  .spp-gallery__item--wide {
    grid-column: 1 / -1;
  }
}

.spp-gallery figure {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--spp-radius-card);
  background-color: var(--spp-color-night);
}

.spp-gallery .spp-media__img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform var(--spp-duration-slow) var(--spp-easing);
}

.spp-gallery__item--wide .spp-media__img {
  aspect-ratio: 16 / 9;
}

.spp-gallery figure:hover .spp-media__img {
  transform: scale(1.03);
}

.spp-gallery figcaption {
  position: absolute;
  inset: auto 0 0;
  padding: var(--spp-space-6) var(--spp-space-4) var(--spp-space-3);
  background: linear-gradient(180deg, transparent, rgba(10, 10, 10, 0.85));
  color: var(--spp-color-chalk);
  font-size: var(--spp-text-small);
  line-height: 1.35;
}

@media (prefers-reduced-motion: reduce) {
  .spp-gallery .spp-media__img,
  .spp-gallery figure:hover .spp-media__img {
    transition: none;
    transform: none;
  }
}

/* ================================================================== Tournois : carte v2 (D23) */

/*
 * La carte de tournoi, croisement demandé par Damien le 15/09 entre la carte de référence du club (D16) et
 * les cartes de location SIXT : fond nuit en dégradé, lueur qui dit l'état, catégorie en très grand
 * capitales, pastilles translucides à icône, tampon diagonal quand il y a quelque chose à dire, tarif en
 * très grand, bandeau d'appel à l'action en pied. Un peu plus petite que la référence : 340–380 px.
 *
 * Toute la carte est un seul lien : un joueur qui vise avec le pouce n'a pas à chercher la bonne zone.
 */

.spp-tournaments {
  display: grid;
  /*
   * Damien a demandé des cartes « un peu plus petites » que sa référence (435 px) : on plafonne à 370 px.
   * `auto-fill` remplit la rangée, `start` garde l'alignement sur la colonne de texte de la page.
   */
  /* Sur téléphone, la carte prend toute la largeur : un plafond de 370 px y laisserait une bande vide. */
  grid-template-columns: 1fr;
  justify-content: start;
  gap: var(--spp-space-5);
  margin: 0 0 var(--spp-space-7);
  padding: 0;
  list-style: none;
}

@media (min-width: 720px) {
  .spp-tournaments {
    grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 370px));
  }
}

.spp-tcard {
  display: flex;
  border-radius: var(--spp-radius-card);
  overflow: hidden;
  isolation: isolate;
}

.spp-tcard__link {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 27rem;
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: var(--spp-radius-card);
  background-color: var(--spp-color-night);
  color: var(--spp-fg);
  text-decoration: none;
  transition:
    transform var(--spp-duration-base) var(--spp-easing),
    border-color var(--spp-duration-base) var(--spp-easing);
}

/*
 * D27 : plus de lueur colorée selon l'état. L'état se lit dans le libellé, le tampon et le bandeau de pied —
 * jamais dans une teinte.
 */
.spp-tcard__link:hover,
.spp-tcard__link:focus-visible {
  transform: translateY(-3px);
  border-color: var(--spp-fg);
}

/* Au survol, la photo se rapproche d'un cheveu : le seul mouvement de la carte avec son élévation. */
.spp-tcard__visual .spp-media__img,
.spp-tcard__thumbimg {
  transition: transform var(--spp-duration-slow) var(--spp-easing);
}

.spp-tcard__link:hover .spp-tcard__thumbimg {
  transform: scale(1.04);
}

.spp-tcard__link:focus-visible {
  outline: 2px solid var(--spp-focus);
  outline-offset: 3px;
}

/* --- Le visuel et son tampon ------------------------------------------------------------------ */

.spp-tcard__visual {
  position: relative;
  display: block;
  height: 8.5rem;
  overflow: hidden;
  background-color: var(--spp-color-charcoal);
}

.spp-tcard__visual .spp-media,
.spp-tcard__thumbimg {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 60%;
}

/* Voile : la photo porte le titre, elle ne doit pas lui disputer la lisibilité. */
.spp-tcard__visual::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 10, 10, 0.15) 0%, rgba(10, 10, 10, 0.85) 100%);
}

.spp-tcard--past .spp-tcard__visual .spp-media,
.spp-tcard--past .spp-tcard__thumbimg {
  filter: grayscale(1) contrast(0.9);
}

/*
 * Le tampon : un parallélogramme incliné au contour clair, posé sur le visuel. Le texte est redressé pour
 * rester lisible ; seul le cadre est penché.
 */
.spp-tcard__stamp {
  position: absolute;
  inset-block-start: var(--spp-space-3);
  inset-inline-end: var(--spp-space-3);
  z-index: 1;
  max-width: calc(100% - var(--spp-space-6));
  display: inline-block;
  padding: var(--spp-space-2) var(--spp-space-5);
  transform: rotate(-4deg);
  border: 2px solid var(--spp-color-chalk);
  background-color: rgba(10, 10, 10, 0.55);
  color: var(--spp-color-chalk);
  font-family: var(--spp-font-sport);
  font-size: var(--spp-text-h4);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.spp-tcard--open .spp-tcard__stamp {
  border-color: var(--spp-accent);
  color: var(--spp-accent);
}

/* --- Le corps ---------------------------------------------------------------------------------- */

.spp-tcard__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--spp-space-3);
  padding: var(--spp-space-4) var(--spp-space-5) var(--spp-space-5);
}

.spp-tcard__head {
  display: grid;
  gap: 2px;
}

.spp-tcard__cat {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h2) * 1.1);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--spp-color-chalk);
}

.spp-tcard__name {
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-small);
  font-weight: 500;
  color: rgba(255, 255, 255, 0.72);
}

/* --- Pastilles d'information ------------------------------------------------------------------- */

.spp-tcard__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.spp-tcard__chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 26px;
  padding: 0 10px;
  border-radius: 2px;
  background-color: rgba(255, 255, 255, 0.12);
  color: var(--spp-color-chalk);
  font-size: var(--spp-text-small);
  line-height: 1;
  white-space: nowrap;
}

.spp-tcard__chip svg {
  width: 1.15em;
  height: 1.15em;
  color: inherit;
}

/* Une seule pastille accentuée par carte : la date, ce que le joueur cherche en premier. */
.spp-tcard__chip--accent {
  background-color: var(--spp-accent);
  color: var(--spp-accent-fg);
  font-weight: 600;
}

/* --- Places et état ----------------------------------------------------------------------------- */

.spp-tcard__slots {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-3);
  margin-top: auto;
  min-width: 0;
}

.spp-slots {
  display: inline-flex;
  align-items: center;
}

.spp-slots__dot,
.spp-slots__more {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid var(--spp-color-night);
  background-color: var(--spp-accent);
}

.spp-slots__dot + .spp-slots__dot,
.spp-slots__dot + .spp-slots__more {
  margin-inline-start: -11px;
}

.spp-slots__dot--free {
  background-color: rgba(255, 255, 255, 0.16);
}

.spp-slots__more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: var(--spp-color-chalk);
  color: var(--spp-color-ink);
  font-size: 0.72rem;
  font-weight: 700;
}

/*
 * L'état reste un libellé, jamais une couleur seule (règle a11y conservée de D10). Certains libellés sont
 * longs (« Complet, liste d'attente ouverte ») : ils passent à la ligne au lieu de sortir de la carte.
 */
.spp-tcard__slots .spp-status {
  flex: 1;
  min-width: 0;
  text-align: end;
  color: rgba(255, 255, 255, 0.86);
  font-size: calc(var(--spp-text-label) * 0.95);
  line-height: 1.25;
  white-space: normal;
}

/* --- Tarif ------------------------------------------------------------------------------------- */

.spp-tcard__pricing {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--spp-space-2) var(--spp-space-3);
  padding-top: var(--spp-space-3);
  border-top: var(--spp-border-width) solid rgba(255, 255, 255, 0.14);
}

/*
 * Plus aucun montant (décision D26) : à la place du tarif géant, la carte dit ce qui se passera le jour du
 * tournoi. La place réservée reste la même — c'est le bas de carte, celui qu'on lit en dernier et qui
 * décide — mais elle porte une phrase, pas un chiffre.
 */
.spp-tcard__onsite {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h3) * 1.05);
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--spp-accent);
}

.spp-tcard--closed .spp-tcard__onsite,
.spp-tcard--past .spp-tcard__onsite,
.spp-tcard--muted .spp-tcard__onsite {
  color: var(--spp-color-chalk);
}

.spp-tcard__total {
  font-size: var(--spp-text-small);
  color: rgba(255, 255, 255, 0.66);
}

/* --- Bandeau d'appel à l'action ---------------------------------------------------------------- */

.spp-tcard__foot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--spp-space-2);
  min-height: 3rem;
  border-top: var(--spp-border-width) solid var(--spp-border);
  background-color: transparent;
  color: var(--spp-color-chalk);
  font-family: var(--spp-font-sport);
  font-size: var(--spp-text-h5, 1rem);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.spp-tcard--open .spp-tcard__foot {
  background-color: var(--spp-accent);
  color: var(--spp-accent-fg);
}

@media (prefers-reduced-motion: reduce) {
  .spp-tcard__link {
    transition: none;
  }

  .spp-tcard__link:hover,
  .spp-tcard__link:focus-visible {
    transform: none;
  }

  .spp-tcard__link:hover .spp-tcard__foot::after {
    transform: none;
  }
}


/* ================================================================== Calendrier des tournois (/tournois/) */

/*
 * Un calendrier de compétition se compose en typographie, pas en cartes. La date porte la page en display,
 * la catégorie et l'état passent en petites capitales, et des filets d'un pixel tiennent les colonnes.
 * Modèle mesuré : day one® Run (Awwwards HM) — grande date, colonnes date / titre / statut, deux valeurs
 * de couleur, aucune ombre. Les cartes dessinées restent à l'accueil (D15 §3), où chaque objet ne porte
 * que trois informations ; ici il y en a six, et la carte devient une fiche illisible.
 *
 * Cette vue est rendue par le plugin, hors du système de mise en page des blocs : les sections pleine
 * largeur annulent elles-mêmes le remplissage de racine (`--spp-gutter`) plutôt que d'employer `alignfull`,
 * qui n'a aucun effet ici. Pas de `100vw` : la barre de défilement provoquerait un débordement horizontal.
 */

.spp-calendar-intro {
  margin-inline: calc(var(--spp-gutter) * -1);
  padding-inline: var(--spp-gutter);
}

.spp-calendar-intro__inner {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

.spp-calendar-intro__title {
  margin: var(--spp-space-3) 0 var(--spp-space-4);
  /* Typographie : voir « Les titres de sport » dans base.css — une seule source. */
}

/* Le chapô garde une mesure de lecture : le bloc nocturne fait 1280 px de large, pas la phrase. */
.spp-calendar-intro .spp-page-lead {
  max-width: 62ch;
  margin: 0;
}

.spp-calendar {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

/*
 * Le mois sépare les rangées de cartes : il mérite d'être vu. Il passe dans la police de sport (voir
 * « Les titres de sport » dans base.css, une seule source) et gagne un filet volt qui court sous le mot.
 */
.spp-calendar__month {
  display: flex;
  align-items: center;
  gap: var(--spp-space-4);
  margin: var(--spp-space-8) 0 var(--spp-space-4);
  color: var(--spp-fg);
}

.spp-calendar__month::after {
  content: "";
  flex: 1;
  height: var(--spp-border-width);
  background: var(--spp-fg);
}

.spp-calendar__month:first-of-type {
  margin-top: 0;
}

.spp-calendar__list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-calendar__row {
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-calendar__empty {
  max-width: 46ch;
  margin: 0;
  font-size: var(--spp-text-body-l);
  color: var(--spp-fg-muted);
}

/*
 * Vue rendue par le thème (`spp-view--themed`) : la feuille du plugin s'est retirée, le thème reprend le
 * rythme vertical. Le retrait horizontal vient du remplissage de racine porté par `.wp-site-blocks`.
 */
.spp-view--themed .spp-main {
  padding-block: 0 var(--spp-space-8);
  /*
   * `useRootPaddingAwareAlignments` porte le retrait de racine sur les blocs `.has-global-padding`, pas sur
   * `.wp-site-blocks` : un `<main>` qui n'est pas un bloc n'en reçoit rien, et le contenu collerait au bord.
   */
  padding-inline: var(--spp-gutter);
}

/* ================================================================== Page d'un tournoi (/tournois/{annee}/{slug}/) */

/*
 * Même registre que le calendrier : bandeau nocturne pleine largeur, puis les faits en liste à filets.
 * La jauge de remplissage est le seul élément coloré de l'écran — un accent qui se compte (D10).
 */

/*
 * Le hero d'un tournoi porte désormais une photo du club, assombrie par un voile : c'est elle qui dit
 * « padel de nuit » avant qu'un mot soit lu (D22). Le contenu passe au-dessus par la pile z.
 */
.spp-tournament-hero,
.spp-calendar-intro {
  position: relative;
  isolation: isolate;
}

.spp-tournament-hero__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  display: block;
  overflow: hidden;
}

.spp-tournament-hero__media .spp-media,
.spp-tournament-hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
}

/* Le voile assombrit, il ne colore pas : le texte doit tenir son contraste sur n'importe quelle photo. */
.spp-tournament-hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(10, 10, 10, 0.72) 0%, rgba(10, 10, 10, 0.88) 60%, rgba(10, 10, 10, 0.96) 100%);
}

.spp-tournament-hero {
  margin-inline: calc(var(--spp-gutter) * -1);
  padding-inline: var(--spp-gutter);
}

.spp-tournament-hero__inner {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

.spp-tournament-hero__title {
  margin: var(--spp-space-3) 0 var(--spp-space-4);
  max-width: 20ch;
  /* Typographie : voir « Les titres de sport » dans base.css — une seule source. */
}

.spp-tournament-hero__when {
  margin: 0;
  font-size: var(--spp-text-body-l);
  color: var(--spp-fg-muted);
}

.spp-tournament-hero .spp-actions {
  margin-top: var(--spp-space-7);
}

/* Variante compacte du bandeau : le tunnel n'a pas de jauge, le titre n'a pas à occuper tout l'écran. */
.spp-tournament-hero--tight {
  padding-block: var(--spp-space-7);
}

.spp-tournament-hero__state {
  margin: var(--spp-space-4) 0 0;
}

/* Le formulaire garde une mesure de saisie : deux colonnes de champs, pas la largeur de la page. */
.spp-tunnel {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

.spp-tunnel .spp-form,
.spp-tunnel__main > .spp-note,
.spp-tunnel__main > .spp-actions,
.spp-tunnel__main > .spp-linkrow {
  max-width: 52rem;
}

/* ================================================================== Filtres du calendrier */

/*
 * Chaque filtre est un lien vers une page. Pas de JavaScript : un filtre doit être partageable, indexable
 * et utilisable au clavier, et sur un téléphone en 4G au bord d'une piste, un aller-retour serveur est
 * plus rapide qu'un script à charger. Les pastilles actives portent `aria-current`, pas seulement une
 * couleur — jamais d'information par la seule couleur (D10).
 */

.spp-filters {
  display: grid;
  gap: var(--spp-space-4);
  margin-bottom: var(--spp-space-6);
  padding-bottom: var(--spp-space-5);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-filters__group {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--spp-space-2);
}

.spp-filters__legend {
  flex: 0 0 6.5rem;
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  line-height: var(--spp-text-label-leading);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--spp-target-min); /* cible tactile : 44 px, au bord d'une piste on vise mal. */
  padding: 4px 16px;
  border: var(--spp-border-width) solid var(--spp-border);
  border-radius: 0;
  background-color: var(--spp-bg-elevated);
  font-size: var(--spp-text-small);
  font-weight: 500;
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
  transition:
    border-color var(--spp-duration-base) var(--spp-easing),
    background-color var(--spp-duration-base) var(--spp-easing),
    color var(--spp-duration-base) var(--spp-easing);
}

.spp-chip:hover {
  border-color: var(--spp-fg-muted);
  color: inherit;
}

/*
 * Pastille active : aplat volt à encre sombre (D22). Le contraste est franc et la couleur ne porte pas
 * seule l'information — `aria-current` reste posé par le gabarit.
 */
.spp-chip--on {
  background-color: var(--spp-accent);
  border-color: var(--spp-accent);
  color: var(--spp-accent-fg);
  font-weight: 700;
}

.spp-chip--on:hover {
  background-color: var(--spp-accent-hover);
  border-color: var(--spp-accent-hover);
  color: var(--spp-accent-fg);
}

.spp-filters__reset {
  margin: 0;
  font-size: var(--spp-text-small);
}

.spp-calendar__count {
  margin: 0 0 var(--spp-space-5);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

@media (max-width: 599px) {
  /* Sur téléphone, l'étiquette passe au-dessus : sept caractères de large volent la moitié de l'écran. */
  .spp-filters__group {
    display: block;
  }

  .spp-filters__legend {
    display: block;
    margin-bottom: var(--spp-space-2);
  }

  .spp-chip {
    margin: 0 var(--spp-space-2) var(--spp-space-2) 0;
  }
}

/* ================================================================== Attente : la balle qui rebondit */

/*
 * Le seul moment où le site fait patienter quelqu'un est l'envoi d'une inscription. Plutôt qu'un rond qui
 * tourne, une balle de padel qui rebondit : elle dit le sport et elle dit l'attente, en un objet de douze
 * pixels et sans une ligne de JavaScript.
 *
 * Elle s'accroche à l'état `pending` que `tunnel.js` pose déjà : aucun contrat nouveau entre le thème et
 * le plugin. Le texte (« Envoi en cours… ») porte seul l'information — la balle est un renfort, elle est
 * `aria-hidden` par construction puisqu'elle est un pseudo-élément.
 *
 * `prefers-reduced-motion` la fige : la balle reste, elle ne bouge plus. Rien ne se perd.
 * D10 interdit les animations d'entrée ; un indicateur d'attente n'en est pas une — il dit qu'il se passe
 * quelque chose, et il disparaît dès que c'est fini.
 */

@keyframes spp-ball-bounce {
  0% {
    transform: translateY(-9px) scale(1);
    animation-timing-function: cubic-bezier(0.6, 0, 1, 0.6);
  }

  /* Impact : la balle s'écrase légèrement, comme sur la vitre. */
  46% {
    transform: translateY(0) scale(1);
    animation-timing-function: linear;
  }

  52% {
    transform: translateY(1px) scale(1.18, 0.8);
    animation-timing-function: cubic-bezier(0, 0.4, 0.4, 1);
  }

  58% {
    transform: translateY(0) scale(1);
  }

  100% {
    transform: translateY(-9px) scale(1);
  }
}

@keyframes spp-ball-shadow {
  0%,
  100% {
    transform: scaleX(0.5);
    opacity: 0.18;
  }

  52% {
    transform: scaleX(1);
    opacity: 0.34;
  }
}

.spp-loader {
  position: relative;
  display: inline-block;
  width: 22px;
  height: 22px;
  vertical-align: -4px;
}

.spp-loader::before {
  content: "";
  position: absolute;
  left: 5px;
  bottom: 4px;
  width: 12px;
  height: 12px;
  border-radius: var(--spp-radius-pill);
  /* Volt du logo, avec un reflet en haut à gauche : à cette taille, c'est ce qui en fait une balle. */
  background:
    radial-gradient(circle at 32% 30%, rgb(255 255 255 / 55%), transparent 45%),
    var(--spp-accent);
  box-shadow: inset -1px -1px 0 rgb(20 21 23 / 18%);
  animation: spp-ball-bounce 720ms infinite;
}

/* L'ombre au sol : elle s'étale à l'impact et se resserre en l'air. C'est elle qui donne le poids. */
.spp-loader::after {
  content: "";
  position: absolute;
  left: 5px;
  bottom: 1px;
  width: 12px;
  height: 3px;
  border-radius: var(--spp-radius-pill);
  background-color: var(--spp-fg);
  animation: spp-ball-shadow 720ms infinite;
}

/* L'état d'attente du tunnel d'inscription porte la balle sans que le script ait à la connaître. */
.spp-form__status--pending::before {
  content: "";
  position: relative;
  top: 2px;
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-right: var(--spp-space-3);
  border-radius: var(--spp-radius-pill);
  background:
    radial-gradient(circle at 32% 30%, rgb(255 255 255 / 55%), transparent 45%),
    var(--spp-accent);
  box-shadow: inset -1px -1px 0 rgb(20 21 23 / 18%);
  animation: spp-ball-bounce 720ms infinite;
}

@media (prefers-reduced-motion: reduce) {
  .spp-loader::before,
  .spp-loader::after,
  .spp-form__status--pending::before {
    animation: none;
  }

  .spp-loader::before {
    transform: translateY(-4px);
  }
}


/* ================================================================== Jauge de remplissage */

/*
 * La part de paires inscrites, en une barre d'un pixel et demi. Elle illustre un nombre écrit juste à côté :
 * la couleur ne porte donc jamais l'information (WCAG 1.4.1), et en noir et blanc (D27) elle n'a plus qu'à
 * dire « beaucoup » ou « presque rien » d'un coup d'œil.
 */
.spp-gauge {
  display: block;
  width: 100%;
  height: 6px;
  overflow: hidden;
  background-color: var(--spp-bg-muted);
  border: var(--spp-border-width) solid var(--spp-border);
}

.spp-gauge__fill {
  display: block;
  height: 100%;
  background-color: var(--spp-fg);
  transition: width var(--spp-duration-slow) var(--spp-easing);
}

@media (prefers-reduced-motion: reduce) {
  .spp-gauge__fill {
    transition: none;
  }
}


/* ================================================================== Calendrier : rail de filtres (D30) */

/*
 * Les filtres passent à gauche, en colonne collante ; les résultats occupent le reste. Chaque option porte
 * le nombre de tournois qu'elle donnerait — calculé par le backend en tenant compte des autres filtres et
 * en ignorant le sien (`TournamentCatalog::calendar()`). Une option à zéro reste visible mais n'est pas un
 * lien : on voit ce qui existe sans jamais atterrir sur une page vide.
 *
 * Aucun JavaScript. Sur téléphone, le rail est replié et s'ouvre par ancre (`.spp-rail:target`) : un lien,
 * une cible, rien à charger. La hauteur de l'en-tête fixe est reportée ici pour que les ancres ne passent
 * pas dessous.
 */

:root {
  /* Mesurée sur `.spp-header` : 2 × 12 px de retrait + 34 px de logo + le filet (D44 : la barre a maigri). */
  --spp-header-h: 59px;
}

.spp-calendar__layout {
  display: block;
}

.spp-rail,
.spp-calendar__results {
  scroll-margin-top: calc(var(--spp-header-h) + var(--spp-space-4));
}

.spp-rail__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spp-space-4);
  margin: 0 0 var(--spp-space-5);
  padding-bottom: var(--spp-space-3);
  border-bottom: var(--spp-border-thick) solid var(--spp-fg);
}

.spp-rail__title {
  margin: 0;
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h3) * 1.05);
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1;
  text-transform: uppercase;
}

.spp-rail__reset,
.spp-rail__done {
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
}

.spp-rail__group + .spp-rail__group {
  margin-top: var(--spp-space-6);
}

.spp-rail__legend {
  margin: 0 0 var(--spp-space-2);
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  line-height: var(--spp-text-label-leading);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-rail__options {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-rail__option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-3);
  min-height: var(--spp-target-min);
  padding: var(--spp-space-2) var(--spp-space-3);
  /* Hauteur de ligne resserrée : voir la note sur le pointeur fin, plus bas. */
  border-bottom: var(--spp-border-width) solid var(--spp-border);
  font-size: var(--spp-text-small);
  color: inherit;
  text-decoration: none;
  transition:
    background-color var(--spp-duration-fast) var(--spp-easing),
    color var(--spp-duration-fast) var(--spp-easing);
}

a.spp-rail__option:hover {
  background-color: var(--spp-bg-muted);
  color: inherit;
}

/* Choisi : aplat d'encre, comme un onglet enfoncé. `aria-current` porte l'information, pas l'aplat. */
.spp-rail__option--on {
  background-color: var(--spp-accent);
  color: var(--spp-accent-fg);
  font-weight: 700;
}

a.spp-rail__option--on:hover {
  background-color: var(--spp-accent-hover);
  color: var(--spp-accent-fg);
}

.spp-rail__option--on .spp-rail__count {
  color: var(--spp-accent-fg);
  opacity: 0.75;
}

/* Sans résultat : gardée à sa place pour que la liste ne bouge pas, mais éteinte et non cliquable. */
.spp-rail__option--empty {
  color: var(--spp-fg-muted);
  cursor: default;
}

/* Focalisable (role="link" + aria-disabled) : l'anneau de focus doit rester visible. */
.spp-rail__option--empty:focus-visible {
  outline: var(--spp-border-thick) solid var(--spp-focus);
  outline-offset: -2px;
}

.spp-rail__text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.spp-rail__count {
  flex: none;
  font-size: var(--spp-text-caption);
  font-variant-numeric: tabular-nums;
  color: var(--spp-fg-muted);
}

.spp-rail__done {
  margin: var(--spp-space-5) 0 0;
}

/*
 * Souris ou pavé tactile : on peut resserrer les lignes sans nuire à la visée. La cible de 44 px reste
 * entière sur écran tactile (`pointer: coarse`), où elle a un sens — c'est la règle d'accessibilité du
 * projet. Ici, elle passe à 38 px et fait entrer deux groupes de plus dans le premier écran.
 */
@media (pointer: fine) {
  .spp-rail__option {
    min-height: 38px;
    padding-block: var(--spp-space-1);
  }

  .spp-rail__group + .spp-rail__group {
    margin-top: var(--spp-space-5);
  }
}

.spp-rail__done .spp-button {
  width: 100%;
}

/* La barre au-dessus des résultats : le décompte à gauche, le bouton « Filtrer » à droite (téléphone). */
.spp-calendar__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4);
  margin-bottom: var(--spp-space-4);
}

.spp-calendar__bar .spp-calendar__count {
  margin: 0;
}

.spp-calendar__filterlink {
  margin: 0;
}

.spp-filterbutton {
  display: inline-flex;
  align-items: center;
  gap: var(--spp-space-2);
  min-height: var(--spp-target-min);
  padding: var(--spp-space-2) var(--spp-space-4);
  border: var(--spp-border-width) solid var(--spp-fg);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  text-decoration: none;
  color: inherit;
}

.spp-filterbutton__n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.4em;
  height: 1.4em;
  padding-inline: 0.3em;
  background-color: var(--spp-fg);
  color: var(--spp-bg);
  font-variant-numeric: tabular-nums;
}

/* Ce qui est posé, et qui se retire d'un clic. */
.spp-activefilters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-2);
  margin: 0 0 var(--spp-space-5);
  padding: 0;
  list-style: none;
}

.spp-activefilter {
  display: inline-flex;
  align-items: center;
  gap: var(--spp-space-2);
  min-height: var(--spp-target-min);
  padding: 0 var(--spp-space-4);
  border: var(--spp-border-width) solid var(--spp-border);
  font-size: var(--spp-text-small);
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.spp-activefilter:hover {
  border-color: var(--spp-fg);
  color: inherit;
}

.spp-activefilter__x {
  font-size: 1.1em;
  line-height: 1;
  color: var(--spp-fg-muted);
}

.spp-activefilter--clear {
  border-style: dashed;
  font-size: var(--spp-text-label);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
}

/* Téléphone et tablette : le rail est replié, le bouton « Filtrer » l'ouvre par ancre. */
@media (max-width: 1179px) {
  .spp-rail__inner {
    display: none;
  }

  .spp-rail:target .spp-rail__inner {
    display: block;
    margin-bottom: var(--spp-space-7);
    padding-bottom: var(--spp-space-5);
    border-bottom: var(--spp-border-width) solid var(--spp-border);
  }
}

@media (min-width: 1180px) {
  /*
   * `:has(> .spp-rail)` : sans tournoi au calendrier le rail n'est pas rendu, et le seul enfant restant
   * — les résultats — atterrissait dans la colonne de 17 rem, message d'absence écrasé sur six lignes.
   */
  .spp-calendar--railed .spp-calendar__layout:has(> .spp-rail) {
    display: grid;
    grid-template-columns: 17rem minmax(0, 1fr);
    gap: var(--spp-space-8);
    align-items: start;
  }

  /*
   * Le rail s'étire sur toute la hauteur de la rangée, sinon son contenu collant n'a nulle part où
   * voyager : un élément `sticky` ne se déplace que dans la boîte de son parent, et un parent à la
   * hauteur de son contenu le fige sur place.
   */
  .spp-rail {
    align-self: stretch;
  }

  .spp-rail__inner {
    position: sticky;
    top: calc(var(--spp-header-h) + var(--spp-space-5));
    max-height: calc(100vh - var(--spp-header-h) - var(--spp-space-8));
    overflow-y: auto;
    /*
     * Le rail est plus haut qu'un écran : il défile à l'intérieur. Encore faut-il le voir — sans indice,
     * les deux derniers groupes passent pour absents (constaté le 23/09/2026 : Damien croyait les filtres
     * Hommes/Femmes/Mixte manquants). Un voile en bas dit qu'il reste quelque chose dessous ; il disparaît
     * dès qu'on atteint la fin, grâce à `background-attachment: local` sur le dégradé.
     */
    background:
      linear-gradient(to top, var(--spp-bg), rgba(255, 255, 255, 0)) bottom / 100% var(--spp-space-6) no-repeat local,
      linear-gradient(to top, rgba(10, 10, 10, 0.16), rgba(255, 255, 255, 0)) bottom / 100% var(--spp-space-3) no-repeat scroll;
    /* Le filet de séparation entre le rail et les résultats : la colonne, pas une boîte. */
    padding-right: var(--spp-space-5);
    border-right: var(--spp-border-width) solid var(--spp-border);
  }

  /* Sur grand écran, le rail est ouvert en permanence : ces deux repères n'ont plus rien à dire. */
  .spp-rail__done,
  .spp-calendar__filterlink {
    display: none;
  }
}


/* ================================================================== Fiche d'un tournoi (D29) */

/*
 * Structure reprise des pages d'événement de la FIP : hero-affiche, barre d'onglets collante, sommaire
 * ancré à gauche, blocs d'information à droite, bandeau d'action en bas d'écran sur téléphone. Le registre,
 * lui, reste le nôtre : noir et blanc, filets d'un pixel, titres de sport en capitales (D27).
 */

.spp-event-hero {
  position: relative;
  isolation: isolate;
  margin-inline: calc(var(--spp-gutter) * -1);
  padding-inline: var(--spp-gutter);
}

.spp-event-hero__inner {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

.spp-crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--spp-space-2);
  margin-bottom: var(--spp-space-5);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-crumbs a {
  color: inherit;
}

/*
 * La catégorie, très grande : c'est elle qu'un joueur cherche en premier, avant même le nom de l'épreuve.
 * Le tableau (Hommes, Femmes, Mixte) la suit, posé sur la ligne de base.
 */
.spp-event-hero__cat {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--spp-space-3);
  margin: 0;
}

.spp-event-hero__cat-main {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h1) * 0.9);
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 0.9;
  text-transform: uppercase;
}

.spp-event-hero__cat-sub {
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-event-hero__title {
  max-width: 22ch;
  margin: var(--spp-space-3) 0 var(--spp-space-6);
  font-size: calc(var(--spp-text-h2) * 1.1);
  /* Typographie : voir « Les titres de sport » dans base.css — une seule source. */
}

/* Les faits d'affiche : quatre colonnes séparées par des filets, comme un bandeau de compétition. */
.spp-event-hero__meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--spp-space-4) var(--spp-space-6);
  margin: 0 0 var(--spp-space-7);
  padding: var(--spp-space-4) 0;
  border-block: var(--spp-border-width) solid var(--spp-border);
  list-style: none;
}

.spp-event-hero__meta li {
  display: flex;
  flex-direction: column;
  gap: var(--spp-space-1);
  font-size: var(--spp-text-body);
}

.spp-event-hero__metalabel {
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-event-hero__capacity {
  max-width: 34rem;
}

.spp-event-hero__counts {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spp-space-3) var(--spp-space-5);
  margin: 0 0 var(--spp-space-3);
}

.spp-event-hero__teams {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h2) * 0.9);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.spp-event-hero__max {
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-small);
  font-weight: 400;
  color: var(--spp-fg-muted);
}

.spp-event-hero .spp-actions {
  margin-top: var(--spp-space-7);
}

.spp-event-hero__onsite {
  margin: var(--spp-space-4) 0 0;
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

/* ---- Le panneau de navigation, collant à gauche (D34). */

/*
 * Il flotte au-dessus des bandes, qui restent pleine largeur. Traversant des fonds noirs et blancs —
 * parfois à cheval sur les deux —, il est rendu en `mix-blend-mode: difference` avec du blanc : sur du
 * blanc il devient noir, sur du noir il reste blanc, et à la frontière chaque moitié reste lisible. Aucune
 * ligne de JavaScript pour ça, et aucune teinte intermédiaire illisible.
 *
 * Sous 1180 px il n'y a pas de place pour une colonne : le panneau redevient une rangée d'ancres, en haut
 * du contenu, sur le fond de la première bande.
 */

.spp-event-nav__title {
  margin: 0 0 var(--spp-space-4);
  padding-bottom: var(--spp-space-3);
  border-bottom: var(--spp-border-width) solid currentColor;
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  /*
   * `opacity` sur un élément en `mix-blend-mode` s'applique **après** le mélange et donne des teintes
   * boueuses ; une couleur semi-transparente, elle, se mélange proprement. Même raison plus bas.
   */
  color: rgba(255, 255, 255, 0.55);
}

.spp-event-nav__list {
  position: relative;
  margin: 0;
  padding: 0 0 0 var(--spp-space-5);
  list-style: none;
}

/* Le filet vertical qui relie les sections : c'est lui qui fait de la liste un parcours. */
.spp-event-nav__list::before {
  content: "";
  position: absolute;
  inset-block: 0.6em;
  inset-inline-start: 0;
  width: var(--spp-border-width);
  background-color: rgba(255, 255, 255, 0.28);
}

.spp-event-nav a {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: var(--spp-space-3);
  min-height: var(--spp-target-min);
  padding-block: var(--spp-space-3);
  color: rgba(255, 255, 255, 0.55);
  text-decoration: none;
  font-size: var(--spp-text-body);
  transition: color var(--spp-duration-fast) var(--spp-easing);
}

.spp-event-nav a:hover,
.spp-event-nav a:focus-visible {
  color: var(--spp-color-white);
}

/*
 * Section en cours de lecture (posée par assets/js/event.js). Le repère est une **marque sur le filet**,
 * pas un soulignement : il se lit d'un coup d'œil, il ne dépend pas de la graisse seule, et il ne bouge pas
 * la ligne de base. Sans JavaScript, rien n'est marqué et la liste reste une liste d'ancres.
 */
.spp-event-nav a.is-current {
  color: var(--spp-color-white);
  font-weight: 700;
}

.spp-event-nav a.is-current::before {
  content: "";
  position: absolute;
  inset-inline-start: calc(var(--spp-space-5) * -1);
  inset-block: var(--spp-space-3);
  width: var(--spp-border-thick);
  background-color: var(--spp-color-white);
}

.spp-event-nav__n {
  flex: none;
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-caption);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.16em;
}

@media (max-width: 1179px) {
  .spp-event-nav {
    max-width: var(--spp-layout-max);
    margin-inline: auto;
    padding-block: var(--spp-space-6) 0;
  }

  .spp-event-nav__title {
    display: none;
  }

  .spp-event-nav__list {
    display: flex;
    flex-wrap: wrap;
    gap: 0 var(--spp-space-5);
    padding-left: 0;
  }

  .spp-event-nav__list::before {
    display: none;
  }

  .spp-event-nav a.is-current::before {
    inset-inline: 0;
    inset-block: auto 0;
    width: auto;
    height: var(--spp-border-thick);
  }
}

@media (min-width: 1180px) {
  .spp-event-bands {
    position: relative;
  }

  /*
   * Flottant et collant : la navigation se place dans la marge gauche du conteneur centré et suit le
   * défilement, pendant que les bandes passent dessous en pleine largeur.
   *
   * `margin-top` aligne son premier repère sur le contenu de la première bande : sans lui, la navigation
   * commençait 64 px plus haut que le titre qu'elle désigne, et l'ensemble paraissait décroché.
   */
  .spp-event-nav {
    position: sticky;
    top: calc(var(--spp-header-h) + var(--spp-space-6));
    z-index: 2;
    float: left;
    width: 15rem;
    margin-top: var(--spp-space-8);
    margin-left: max(0px, calc((100% - var(--spp-layout-max)) / 2));
    color: var(--spp-color-white);
    mix-blend-mode: difference;
  }

  @supports not (mix-blend-mode: difference) {
    /* Repli : un panneau noir à texte clair, lisible sur les deux fonds faute d'inversion. */
    .spp-event-nav {
      mix-blend-mode: normal;
      padding: var(--spp-space-4);
      background-color: var(--spp-color-night);
    }
  }

  /* Le contenu des bandes laisse la place au panneau. */
  .spp-event-block__inner {
    padding-left: 18rem;
  }
}

/* ---- Les sections : bandes pleine largeur, noires et blanches en alternance (D27, D32). */

/*
 * Chaque section occupe toute la largeur et prend sa couleur à tour de rôle : blanche, noire, blanche…
 * L'alternance est décidée par le gabarit (une section « Déroulement » absente ne doit pas mettre deux
 * bandes de la même couleur côte à côte), le CSS ne fait qu'appliquer les jetons du thème correspondant.
 */

/* `--spp-slant` est déclaré dans base.css : le biseau sert tout le site, pas seulement la fiche. */

.spp-event-block {
  position: relative;
  margin-inline: calc(var(--spp-gutter) * -1);
  padding: var(--spp-space-8) var(--spp-gutter);
  background-color: var(--spp-bg);
  color: var(--spp-fg);
  scroll-margin-top: calc(var(--spp-header-h) + 60px);
}

/*
 * Le séparateur en biais.
 *
 * La bande remonte sur la précédente (`margin-top` négatif) puis se découpe en diagonale : comme un frère
 * postérieur se peint par-dessus, le triangle retiré laisse voir la bande du dessus — donc l'autre couleur.
 * Un dégradé ou une image auraient exigé de connaître les deux couleurs ; ici, la découpe suffit.
 */
.spp-event-block + .spp-event-block {
  margin-top: calc(var(--spp-slant) * -1);
  padding-top: calc(var(--spp-space-8) + var(--spp-slant));
  clip-path: polygon(0 var(--spp-slant), 100% 0, 100% 100%, 0 100%);
}

.spp-event-block__inner {
  max-width: var(--spp-layout-max);
  margin-inline: auto;
}

.spp-event-block__head {
  display: flex;
  align-items: baseline;
  gap: var(--spp-space-4);
  margin-bottom: var(--spp-space-5);
  padding-bottom: var(--spp-space-3);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-event-block__n {
  margin: 0;
  font-family: var(--spp-font-text);
  font-size: var(--spp-text-label);
  font-weight: 600;
  letter-spacing: 0.16em;
  line-height: 1;
  color: var(--spp-fg-muted);
  font-variant-numeric: tabular-nums;
}

.spp-event-block__title {
  margin: 0;
  font-size: calc(var(--spp-text-h2) * 0.95);
}

.spp-event-block__sub {
  margin: var(--spp-space-7) 0 var(--spp-space-4);
  font-size: var(--spp-text-h3);
}

.spp-event-block .spp-facts {
  margin-bottom: 0;
}

/* Les trois temps de l'inscription : un grand chiffre, une phrase en gras, une explication. */
.spp-steps {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-steps li {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: var(--spp-space-4);
  align-items: start;
  padding-block: var(--spp-space-4);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-steps__n {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h2) * 0.8);
  font-weight: 800;
  line-height: 0.85;
  color: var(--spp-fg-muted);
}

.spp-steps__body strong {
  display: block;
  margin-bottom: var(--spp-space-1);
}


/* ---- Le bandeau d'action, en bas d'écran, sur téléphone. */

.spp-event-bar {
  position: fixed;
  inset: auto 0 0;
  z-index: var(--spp-z-sticky);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--spp-space-4);
  padding: var(--spp-space-3) var(--spp-gutter);
  background-color: var(--spp-color-night);
  color: var(--spp-color-chalk);
  border-top: var(--spp-border-width) solid rgba(255, 255, 255, 0.16);
}

.spp-event-bar__state {
  display: flex;
  flex-direction: column;
  gap: var(--spp-space-1);
  margin: 0;
  min-width: 0;
}

/* Le libellé d'état est en `nowrap` : sans cela il pousse le bouton hors de l'écran sur un petit mobile. */
.spp-event-bar__state .spp-status {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
}

.spp-event-bar__teams {
  font-size: var(--spp-text-small);
  font-variant-numeric: tabular-nums;
  color: var(--spp-fg-muted);
}

.spp-event-bar .spp-button {
  flex: none;
  padding-inline: var(--spp-space-5);
}

/*
 * Le bandeau recouvre le bas de l'écran : la réserve de place va sur le document entier, pas sur
 * l'article — sinon c'est le pied de page, qui vient après, qui passe dessous.
 */
.spp-view--themed:has(.spp-event-bar) .wp-site-blocks {
  padding-bottom: calc(var(--spp-target-min) + var(--spp-space-6));
}

/*
 * Le bandeau reste à toutes les largeurs : depuis que les sections sont des bandes pleine largeur, il n'y a
 * plus de fiche d'action collante dans une colonne de gauche pour prendre le relais, et la fiche est longue.
 * L'inscription ne doit jamais se trouver à trois écrans de défilement.
 */


/* ================================================================== Tunnel d'inscription : récapitulatif */

/*
 * Le formulaire à gauche, le récapitulatif du tournoi à droite, collant : ce qu'on engage reste lisible
 * pendant qu'on saisit deux joueurs. Sous 1000 px, le récapitulatif passe **au-dessus** du formulaire —
 * on lit ce qu'on va faire avant de le faire, jamais après l'avoir fait.
 */

.spp-event-hero--tight {
  padding-block: var(--spp-space-7) var(--spp-space-6);
}

.spp-event-hero--tight .spp-event-hero__title {
  margin-bottom: var(--spp-space-3);
}

.spp-tunnel__layout {
  display: flex;
  flex-direction: column-reverse;
  gap: var(--spp-space-7);
}

.spp-recap {
  padding: var(--spp-space-5);
  background-color: var(--spp-color-night);
  color: var(--spp-color-chalk);
}

.spp-recap__title {
  margin: 0;
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h3) * 1.15);
  font-weight: 800;
  letter-spacing: 0.04em;
  line-height: 1;
  text-transform: uppercase;
}

.spp-recap__name {
  margin: var(--spp-space-1) 0 var(--spp-space-4);
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

.spp-recap__facts {
  margin: 0 0 var(--spp-space-4);
  padding: 0;
  border-top: var(--spp-border-width) solid var(--spp-border);
}

.spp-recap__facts > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--spp-space-4);
  padding-block: var(--spp-space-2);
  border-bottom: var(--spp-border-width) solid var(--spp-border);
}

.spp-recap__facts dt {
  margin: 0;
  flex: none;
  font-size: var(--spp-text-label);
  font-weight: var(--spp-text-label-weight);
  letter-spacing: var(--spp-text-label-tracking);
  text-transform: uppercase;
  color: var(--spp-fg-muted);
}

.spp-recap__facts dd {
  margin: 0;
  font-size: var(--spp-text-small);
  text-align: right;
}

.spp-recap__teams {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--spp-space-2) var(--spp-space-4);
  margin: 0 0 var(--spp-space-2);
}

/*
 * Le libellé d'état est en `nowrap` par défaut : dans une colonne de 20 rem, « Complet, liste d'attente (1) »
 * poussait le compteur **hors de la carte** — le « 4 » flottait dans le vide à droite (vu à l'image le
 * 22/09/2026). Ici, il a le droit de passer à la ligne.
 */
.spp-recap__teams .spp-status {
  min-width: 0;
  white-space: normal;
}

.spp-recap__count {
  font-family: var(--spp-font-sport);
  font-size: calc(var(--spp-text-h3) * 1.1);
  font-weight: 800;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.spp-recap__onsite {
  margin: var(--spp-space-4) 0 0;
  font-size: var(--spp-text-small);
  color: var(--spp-fg-muted);
}

@media (min-width: 1000px) {
  .spp-tunnel__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 20rem;
    gap: var(--spp-space-8);
    align-items: start;
  }

  .spp-tunnel__recap {
    position: sticky;
    top: calc(var(--spp-header-h) + var(--spp-space-5));
  }
}


/* ================================================================== Filtres dynamiques du calendrier (D31) */

/*
 * Pendant que le serveur renvoie la liste filtrée, les résultats s'estompent et un filet noir progresse en
 * haut de la colonne. Pas de roue qui tourne, pas de couleur : le seul mouvement de l'écran, et il dit
 * « ça arrive ». Sous `prefers-reduced-motion`, il ne reste que l'estompage.
 *
 * Tout ceci ne s'affiche que si le script est chargé : sans JavaScript, la classe `is-loading` n'existe
 * jamais et le calendrier navigue de page en page, comme avant.
 */

.spp-calendar__results {
  position: relative;
  transition: opacity var(--spp-duration-fast) var(--spp-easing);
  /*
   * L'ancrage de défilement de Chrome choisit un nœud repère dans cette zone ; comme on la remplace
   * entièrement à chaque filtre, il renonce et la page saute. On le désactive ici, et le script remet de
   * toute façon la position exacte.
   */
  overflow-anchor: none;
}

.is-loading .spp-calendar__results {
  opacity: 0.45;
  pointer-events: none;
}

.is-loading .spp-calendar__results::before {
  content: "";
  position: absolute;
  inset-block-start: calc(var(--spp-space-5) * -1);
  inset-inline: 0;
  height: var(--spp-border-thick);
  background-color: var(--spp-fg);
  transform-origin: left center;
  animation: spp-progress 900ms var(--spp-easing) infinite;
}

@keyframes spp-progress {
  0% { transform: scaleX(0); }
  60% { transform: scaleX(0.8); }
  100% { transform: scaleX(1); opacity: 0; }
}

/* L'option qu'on vient de choisir s'allume avant la réponse du serveur : le clic ne reste jamais sans effet. */
.is-loading .spp-rail__option--on {
  background-color: var(--spp-accent);
  color: var(--spp-accent-fg);
}

@media (prefers-reduced-motion: reduce) {
  .is-loading .spp-calendar__results::before {
    animation: none;
    transform: scaleX(1);
  }
}

/* ================================================================== Bouton de réservation fixe (D68) */

/*
 * Toujours en bas à droite, sur toutes les pages. Il traverse des bandes noires, des bandes blanches et des photos :
 * sa face noire ressort sur le blanc, son contour blanc sur le noir, sans ombre ni couleur (D27). Au survol, le
 * balayage habituel des boutons le retourne en blanc (D47).
 */
.spp-fab {
  --spp-button-fill: var(--spp-color-night);
  --spp-button-line: var(--spp-color-chalk);
  --spp-button-sweep: var(--spp-color-chalk);

  position: fixed;
  right: max(var(--spp-space-4), env(safe-area-inset-right));
  bottom: max(var(--spp-space-4), env(safe-area-inset-bottom));
  z-index: var(--spp-z-drawer);
  color: var(--spp-color-chalk);
}

.spp-fab:hover,
.spp-fab:focus-visible {
  color: var(--spp-color-night);
}

/* Sur la fiche d'un tournoi, le bandeau d'action occupe le bas de l'écran à toutes les largeurs : on passe au-dessus. */
body:has(.spp-event-bar) .spp-fab {
  bottom: calc(var(--spp-target-min) + var(--spp-space-6) + var(--spp-space-3));
}

/* Sur téléphone, le mot suffit : le bouton ne doit pas cacher ce qu'on lit. */
@media (max-width: 599px) {
  .spp-fab__more {
    display: none;
  }
}

@media print {
  .spp-fab {
    display: none;
  }
}

/* ================================================================== Apparition au défilement (D64) */

/*
 * Les titres et les lignes montent d'un cran en entrant à l'écran, en CSS seul : aucun script, aucun contenu masqué
 * pour qui ne la connaît pas, puisque la règle n'existe que si le navigateur sait la jouer. Hors `@media screen`,
 * un PDF ou une impression montreraient des titres transparents.
 */
@media screen and (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .spp-section .spp-sectionhead__title,
    .spp-agenda__item,
    .spp-pcard,
    .spp-main--front .spp-sectionhead__lead,
    .spp-main--front .spp-split,
    .spp-main--front .spp-review,
    .spp-main--front .spp-partners {
      animation: spp-rise linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 50%;
    }
  }
}

@keyframes spp-rise {
  from {
    opacity: 0;
    transform: translateY(var(--spp-space-5));
  }

  to {
    opacity: 1;
    transform: none;
  }
}
