/* ════════════════════════════════════════════════════════════════════
   FBI KLUB — saison 10
   Feuille de style unique. Aucune dépendance, aucun cadre.

   UNE SEULE POLICE (depuis le 13/09)
   · Manrope, en graisse variable 200 → 800, pour tout — titres, texte,
     étiquettes. Elle remplace le trio Archivo / Manrope / Space Grotesk :
     la référence (21tsi) n emploie qu une famille, et c est ce qui fait
     son unité. La hiérarchie vient de la taille et de la graisse.
     La variable : --police. Le détail des graisses : ameliorations.css.

   LES TAILLES SUIVENT LE NOMBRE D'OR (φ = 1,618)
   Chaque échelon vaut le précédent multiplié par √φ (1,272) : un échelon
   sur deux vaut donc exactement φ fois le précédent. Rien n'est choisi à
   la main, --t1 … --t11 en découlent. L'interlignage du texte vaut φ.

   LES ESPACEMENTS SUIVENT FIBONACCI (5 · 8 · 13 · 21 · 34 · 55 · 89 · 144),
   dont le rapport de deux termes tend vers φ.
   ════════════════════════════════════════════════════════════════════ */

:root {
  /* ── échelle typographique, base 16 px ── */
  /* 13/09 : les deux plus petits échelons remontent — la référence n a
     aucun texte sous 12 px, et le 13 px était la taille la plus fréquente
     du site. Mesuré : 21tsi 14 px ×45, 12 px ×4. */
  --t1:  0.75rem;    /*  12 px — micro étiquette  */
  --t2:  0.875rem;   /*  14 px — étiquette, nav   */
  --t3:  1rem;       /*  16.0 px — annexe, mentions */
  /* ⚠️ 20,4 px est le CORPS, pas une taille appuyée. Relevé sur la
     référence : sa taille la plus fréquente est 20 px, 167 fois — la
     mienne était 13. Un site qui parle fort commence par un corps qui
     se lit sans se pencher. */
  --t4:  1.272rem;   /*  20.4 px — texte appuyé     */
  --t5:  1.618rem;   /*  25.9 px — sous-titre       */
  --t6:  2.058rem;   /*  32.9 px                    */
  --t7:  2.618rem;   /*  41.9 px                    */
  --t8:  3.330rem;   /*  53.3 px                    */
  --t9:  4.236rem;   /*  67.8 px                    */
  --t10: 5.388rem;   /*  86.2 px                    */
  --t11: 6.854rem;   /* 109.7 px — display maximum  */
  /* UNE SEULE VOIX (13/09) — la référence n emploie qu une famille (Saans,
     290 textes sur 295). Le klub en mélangeait trois. Manrope était déjà
     chargée : c est la plus proche en esprit, et rien de neuf ne se charge. */
  --police: 'Manrope', system-ui, sans-serif;

  /* ── espacements : Fibonacci ── */
  --f1: 5px; --f2: 8px; --f3: 13px; --f4: 21px;
  --f5: 34px; --f6: 55px; --f7: 89px; --f8: 144px;

  --marge: clamp(21px, 5vw, 89px);
  /* Les deux largeurs sont DERIVEES, pas choisies : la bande du
     cartouche vaut la colonne de texte multipliee par racine de phi
     (1,272), soit un echelon de la meme echelle que la typographie.
     Avant : 1400 et 1760, deux nombres ronds dont le rapport tombait
     par hasard a 1,257 — presque la, mais pas la. */
  --colonne: 1400px;
  --haut: 100px;      /* hauteur du cartouche */
  --sommet: 24px;     /* ce qui le sépare du haut de la page */
  --large: 1781px;    /* = --colonne x 1,272 (racine de phi) */
  --gout: cubic-bezier(.16,1,.3,1);

  /* ── ambiance Nuit ── */
  --noir:      #0A0908;
  --ivoire:    #F4EFEA;
  --sourd:     #F4EFEA;   /* 13/09 : blanc plein, comme la référence (293 textes sur 295) */
  --faible:    rgba(244,239,234,.62);
  --terra:     #E2705C;
  --filet:     rgba(244,239,234,.30);
  --filet-vif: rgba(244,239,234,.44);
  --voile:     rgba(10,9,8,.40);   /* 13/09 : .56 → .40, les photos respirent */
  --ecran-fort: rgba(10,9,8,.80);
  --ecran-doux: rgba(10,9,8,.48);
  --sur-terra: #150B08;
}

html[data-ambiance="jour"] {
  --noir:      #F4EFEA;
  --ivoire:    #14100E;
  --sourd:     #14100E;
  --faible:    rgba(20,16,14,.68);
  --terra:     #A61E22;
  --filet:     rgba(20,16,14,.32);
  --filet-vif: rgba(20,16,14,.44);
  --voile:     rgba(244,239,234,.54);
  --ecran-fort: rgba(244,239,234,.88);
  --ecran-doux: rgba(244,239,234,.54);
  --sur-terra: #FFF6F2;
}

html[data-ambiance="sienne"] {
  --noir:      #3E120A;
  --ivoire:    #FFF3EC;
  --sourd:     #FFF3EC;
  --faible:    rgba(255,243,236,.72);
  --terra:     #F0876F;
  --filet:     rgba(255,243,236,.34);
  --filet-vif: rgba(255,243,236,.50);
  --voile:     rgba(62,18,10,.46);
  --ecran-fort: rgba(62,18,10,.84);
  --ecran-doux: rgba(62,18,10,.46);
  --sur-terra: #2A0A05;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }

html { scroll-behavior: smooth; scrollbar-width: none; }
::-webkit-scrollbar { width: 0; height: 0; }

body {
  background: var(--noir);
  color: var(--ivoire);
  font: 300 var(--t3)/1.5 var(--police);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  transition: background .8s var(--gout), color .8s var(--gout);
}

::selection { background: var(--terra); color: var(--sur-terra); }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
img, video { display: block; max-width: 100%; }
:focus-visible { outline: 2px solid var(--terra); outline-offset: 4px;
  /* sans ca, tabuler amene la cible SOUS le cartouche fixe */
  scroll-margin-top: calc(var(--sommet) + var(--haut) + var(--f4)); }


/* ════ TYPOGRAPHIE ═══════════════════════════════════════════════ */

.titre {
  font-family: var(--police);
  font-weight: 400;
  font-size: clamp(var(--t7), 6.6vw, var(--t10));
  line-height: .99;
  letter-spacing: -.018em;
  text-transform: uppercase;
  color: var(--ivoire);
}
/* le gras attire l'œil : un mot par titre, jamais deux idées */
.titre b { font-weight: 800; color: var(--terra); }
/* ⚠️ CE QUI CRÉAIT DES TAILLES PRESQUE IDENTIQUES — et ce n'était pas
   le nombre d'échelons.
   Relevé sur la page : 26, 27, 29 et 31 px cohabitaient. J'avais d'abord
   accusé l'échelle (11 échelons à ×1,272). Faux. 26 px est un VRAI
   échelon (--t5, utilisé 33 fois) ; 27, 29 et 31 sont des « clamp() » dont
   le terme en « vw » atterrit ENTRE deux échelons. Une taille fluide ne
   tombe jamais sur l'échelle : elle la traverse.
   Les rôles d'AFFICHAGE sont donc posés sur des échelons FIXES, un sur
   deux — soit un rapport de φ (1,618) et non plus √φ (1,272) :

       12,6  ·  16  ·  25,9  ·  41,9  ·  67,8  ·  109,7

   C'est le « très gros, moyen, petit » demandé : il lui fallait des
   TROUS, pas un continuum. Le fluide est gardé là où il sert vraiment —
   le titre géant, qui doit tenir dans la largeur quelle qu'elle soit. */
.titre--geant { font-size: clamp(var(--t8), 8.2vw, var(--t11)); }
.titre--moyen { font-size: var(--t9); }
.titre--petit { font-size: var(--t7); letter-spacing: -.01em; }

.sous {
  font-family: var(--police); font-weight: 600;
  font-size: var(--t7);
  line-height: 1.12; letter-spacing: -.01em; text-transform: uppercase;
}

.oeillet {
  display: inline-flex; align-items: center; gap: var(--f3);
  font: 700 var(--t1)/1 var(--police);
  letter-spacing: .26em; text-transform: uppercase; color: var(--terra);
}
.oeillet::after { content: ''; width: var(--f6); height: 1px; background: var(--filet); }

.micro {
  font: 500 var(--t2)/1.618 var(--police);
  letter-spacing: .1em; text-transform: uppercase; color: var(--sourd);
  font-variant-numeric: tabular-nums;
}
.micro--vif { color: var(--terra); font-weight: 700; }
.micro--clair { color: var(--sourd); }

.texte { font-size: var(--t4); line-height: 1.6; color: var(--sourd); max-width: 44ch; }
.texte--grand { font-size: var(--t5); line-height: 1.32; max-width: 26ch; color: var(--ivoire); font-weight: 300; }
.texte b { font-weight: 700; color: var(--ivoire); }

.filet { height: 1px; background: var(--filet); border: 0; }


/* ════ LE RAIL — la ligne fine au-dessus du cartouche ════════════
   Elle ne bouge jamais. Seule sa part remplie avance avec la slide. */

/* Elle occupe la première rangée du cartouche, au-dessus du sigle et des
   rubriques seulement : elle ne passe pas au-dessus des pastilles. */
/* LE RAIL EST UNE COMMANDE, PAS UN VOYANT.
   Il montrait l avancement sans permettre d y aller — une information
   qu on regarde et qu on ne peut pas utiliser, à l endroit exact où la
   main se pose. Il est maintenant cliquable, glissable et pilotable au
   clavier.
   ⚠️ La ligne fait 1 px de haut : viser 1 px à la souris est impossible,
   et au doigt c est hors de question. `::before` lui donne une zone
   d attrape de 30 px, invisible, centrée sur la ligne — la règle des
   cibles de 24 px minimum (WCAG 2.5.8) est tenue sans épaissir le trait. */
/* ⚠️ --filet (30 % d opacité) ne donne que 2,5:1 sur le fond : la piste
   VIDE de la glissière serait sous le seuil de 3:1 exigé pour la limite
   visuelle d une commande (WCAG 1.4.11). --filet-vif la porte à 4,1:1. */
#rail {
  grid-column: 1 / 3; grid-row: 1;
  height: 1px; background: var(--filet-vif);
  position: relative; cursor: pointer; touch-action: none;
}
#rail::before { content: ''; position: absolute; inset: -15px 0; }
#rail i { display: block; height: 100%; background: var(--terra);
  transform-origin: left center; transform: scaleX(0); }
#rail:hover, #rail:focus-visible, #rail.rail--tire { background: var(--ivoire); }
#rail:focus-visible { outline: 2px solid var(--terra); outline-offset: 8px; }

/* les six écrans en repères : le site a une fin, et on la voit */
.rail-reperes { position: absolute; inset: 0; pointer-events: none; }
.rail-reperes b { position: absolute; top: -3px; width: 1px; height: 7px;
  background: var(--filet-vif); }
#rail:hover .rail-reperes b, #rail.rail--tire .rail-reperes b { background: var(--terra); }


/* ════ LE CARTOUCHE — partout, immobile ══════════════════════════ */

#cartouche {
  position: fixed; top: 0; left: 0; right: 0; z-index: 99;
  height: calc(var(--sommet) + var(--haut)); padding: var(--sommet) var(--marge) 0;
}
/* pas de barre, mais un fondu : sans lui, le texte de la page passe
   derrière la navigation et les deux deviennent illisibles. */
#cartouche::before {
  content: ''; position: absolute; inset: calc(-1px - var(--sommet)) 0 auto 0; z-index: -1;
  height: calc(var(--sommet) + var(--haut) + var(--f5));
  background: linear-gradient(to bottom, var(--noir) 12%, transparent 100%);
  opacity: .92; pointer-events: none;
}
/* la meme colonne que le contenu : le sigle et les pastilles tombent
   exactement sur les bords du texte, a toutes les largeurs. */
.cartouche-dedans {
  width: 100%; max-width: var(--large); height: 100%; margin: 0 auto;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: auto 1fr;
  align-items: center;
  column-gap: clamp(var(--f6), 6vw, var(--f8));   /* les trois groupes respirent */
  row-gap: var(--f4);
}
.marque    { grid-column: 1; grid-row: 2; }
#nav       { grid-column: 2; grid-row: 2; }
.pastilles { grid-column: 3; grid-row: 1 / 3; align-self: center; }

.marque { display: inline-flex; align-items: center; gap: var(--f2); min-height: 24px; }
.marque-pt { width: 6px; height: 6px; border-radius: 50%; background: var(--terra); }
.marque-nom { font-family: var(--police); font-weight: 800; font-size: var(--t4); letter-spacing: .1em; text-transform: uppercase; line-height: 1; }
.marque-s { font: 400 var(--t1)/1 var(--police); letter-spacing: .18em; color: var(--faible); }

/* les rubriques se répartissent sur toute la largeur disponible */
#nav { display: flex; justify-content: space-between; align-items: center; gap: var(--f4); }
#nav::-webkit-scrollbar { height: 0; }
/* Pas de barre sous le mot : le libellé lui-même remonte et laisse la
   place à sa copie. Un point marque l écran en cours — un repère de
   forme, pas seulement de couleur. */
/* min-height 24 px : la piste ne fait que 1,3 em, soit ~21 px — sous le
   minimum WCAG 2.5.8 pour une cible. Elle est centrée, rien ne bouge. */
.lien {
  position: relative; flex: none; min-height: 24px;
  display: inline-flex; align-items: center;
  font-family: var(--police); font-weight: 700; font-size: var(--t3);
  letter-spacing: .085em; text-transform: uppercase;
  color: var(--sourd); transition: color .45s var(--gout);
}
/* ⚠️ WCAG 1.4.12 « Text Spacing ». La hauteur de la piste était figée à
   1,3 em alors que le critère autorise une feuille utilisateur à forcer
   un interligne de 1,5 : les libellés de navigation auraient été rognés.
   Piste et copies passent donc à 1,5 em, comme le translate qui les fait
   défiler — les trois valeurs doivent rester identiques. */
.lien .piste {
  display: flex; flex-direction: column; overflow: hidden;
  height: 1.5em;
}
.lien .piste > span {
  flex: none; height: 1.5em; line-height: 1.5;
  transition: transform .55s var(--gout);
}
.lien:hover .piste > span { transform: translateY(-1.5em); }
.lien:focus-visible .piste > span { transform: translateY(-1.5em); }
.lien:hover { color: var(--ivoire); }
/* l écran en cours : terracotta ET plus gras — pour que ce ne soit pas
   la couleur seule qui le distingue. */
.lien.ici { color: var(--terra); font-weight: 800; }
/* le point de l écran en cours. Il était rogné par overflow-x sur #nav,
   retiré depuis : un conteneur de défilement coupe ce qui dépasse. */
.lien::before {
  content: ""; position: absolute; left: -16px; top: 50%;
  width: 5px; height: 5px; margin-top: -3px; border-radius: 50%;
  background: var(--terra); opacity: 0; transform: scale(.3);
  transition: opacity .45s var(--gout), transform .45s var(--gout);
}
.lien.ici::before { opacity: 1; transform: none; }

.pastilles { display: inline-flex; align-items: center; gap: var(--f3); }
.pastille {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--f2);
  min-height: 44px; padding: 0 var(--f4);
  border: 1px solid var(--filet); border-radius: 999px;
  font-family: var(--police); font-weight: 700; font-size: var(--t2);
  letter-spacing: .11em; text-transform: uppercase; line-height: 1; color: var(--sourd);
  transition: border-color .45s var(--gout), color .45s var(--gout);
}
.pastille:hover { border-color: var(--terra); color: var(--terra); }
.pastille i { font-style: normal; font-size: var(--t4); line-height: 1; }
.pastille em { font-style: normal; color: var(--faible); }
.pastille .fleche { transition: transform .5s var(--gout); }
.pastille:hover .fleche { transform: translate(3px, -3px); }
/* la langue montre les deux, celle en cours en clair */
#p-langue b { font-weight: 700; color: var(--faible); transition: color .4s var(--gout); }
#p-langue b.active { color: var(--ivoire); }
#p-langue:hover b.active { color: var(--terra); }

/* 18/09 : 1100 → 1260 px — mesuré, sur une seule rangée « REJOINDRE » recouvrait
   encore les pastilles jusqu à 1240 px (outils/banc-cartouche.js) */
@media (max-width: 1260px) {
  :root { --haut: 136px; }   /* deux rangs : pastilles larges + rubriques */
  #cartouche { height: auto; padding-top: var(--f2); padding-bottom: var(--f2); }
  .cartouche-dedans { grid-template-columns: auto auto; justify-content: space-between; align-content: center; gap: var(--f3) var(--f4); }
  #nav { order: 3; grid-column: 1 / -1; justify-content: flex-start; overflow-x: auto; padding-left: var(--f3); }
}


/* ════ LES FONDS — un par slide, tous fixes ══════════════════════ */

#fond { position: fixed; inset: 0; z-index: 0; overflow: hidden; background: var(--noir); }
.couche { position: absolute; inset: -9%; opacity: 0; will-change: transform, opacity; }
.couche:first-child { opacity: 1; }
.couche > * { width: 100%; height: 100%; object-fit: cover; }
/* Le premier fond est un portrait sur noir : plein cadre on n en verrait
   qu une bande de torse. On le montre entier — son propre fond se confond
   avec celui de la page — décalé à droite pour laisser le texte respirer. */
#voile { position: absolute; inset: 0; background: var(--voile); transition: background .8s var(--gout); }
/* UNE TRAÎNÉE D AIR — une vraie réfraction, pas un flou.

   `#refraction` est une COPIE EXACTE de la pile de photos, posée par
   `monteRefraction()` et tenue au pixel près sur l originale par la boucle
   de rendu. Un filtre SVG la déforme (feTurbulence + feDisplacementMap),
   et un masque ne laisse voir cette copie déformée que le long de la
   traînée. Aucune couleur, aucune lumière : rien que du déplacement.

   Elle est au-dessus des photos mais SOUS les voiles : la traînée déforme
   l image, pas la trame de lisibilité posée pour le texte.

   `display` est piloté par le script : à l arrêt la couche est retirée,
   pas rendue transparente — un élément à opacity:0 reste composé et son
   filtre continuerait d être calculé sur tout l écran, à chaque image. */
#refraction {
  position: absolute; inset: 0; pointer-events: none;
  display: none;
  filter: url(#air);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
@media (prefers-reduced-motion: reduce) { #refraction { display: none !important; } }
/* Le voile de lisibilité épouse la zone de texte de l étape en cours.
   Deux arrêts durs puis un fondu de 14 % : le bord ne doit pas se voir
   comme un trait, mais la photo doit redevenir nette vite. */
#lisibilite { position: absolute; inset: 0;
  background: linear-gradient(90deg, var(--ecran-fort) 0%, var(--ecran-doux) 45%, transparent 62%);
  transition: background .9s var(--gout); }
/* LE PANNEAU FLOU — la règle de la référence (21tsi, `.panel`), relevée le
   13/09. Une colonne verticale de texte ne se pose pas sur la photo nue :
   elle se pose sur un panneau fixe, pleine hauteur, qui FLOUTE ce qui passe
   derrière (20 px) sous une teinte à peine posée. Il glisse depuis le bord
   droit (1,2 s, leur courbe) puis RESTE, constant, tant que la colonne est
   affichée — il ne suit pas le défilement. 44 vw : leur largeur ; la
   colonne de texte démarre à 63 %, soit 7 % à l intérieur du panneau. */
#panneau {
  position: absolute; top: 0; bottom: 0; right: 0; width: 44vw;
  background: color-mix(in srgb, var(--noir) 14%, transparent);
  -webkit-backdrop-filter: blur(20px); backdrop-filter: blur(20px);
  clip-path: polygon(100% 0, 100% 0, 100% 100%, 100% 100%);
  transition: clip-path 1.2s cubic-bezier(0.19, 1, 0.22, 1);
  will-change: clip-path; pointer-events: none;
}
#panneau.actif { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
@media (prefers-reduced-motion: reduce) { #panneau { transition: none; } }

/* Le contenu se pose DANS sa zone. Les trois places sont celles de la
   référence, toutes tirées de la section dorée. */
/* ⚠️ Les DEUX marges, toujours. La règle de base pose `margin: 0 auto` ;
   n en redéfinir qu une laisse l autre sur `auto`, et deux marges
   automatiques recentrent le bloc. Mesuré : la zone « droite » démarrait
   à 40 % au lieu de 61,8 %. */
.etape[data-zone="gauche"] > .dedans { max-width: min(var(--colonne), 58%); margin-left: 0; margin-right: auto; }
.etape[data-zone="droite"] > .dedans { max-width: min(var(--colonne), 36%); margin-left: auto; margin-right: 0; }
/* Le texte est TOUJOURS aligné à gauche, colonne de droite comprise —
   comme sur la référence (287 textes « start » sur 295). La colonne
   étroite de gauche est retirée : elle rendait la page trop verticale. */
.etape > .dedans { text-align: left; }
/* une etape qui porte deja sa mise en page en largeur garde la colonne */
.etape[data-zone="large"] > .dedans { max-width: var(--colonne); margin: 0 auto; }
@media (max-width: 1000px) {
  .etape[data-zone] > .dedans { max-width: var(--colonne); margin: 0 auto; }
  #lisibilite { background: var(--ecran-doux) !important; }
  #panneau { display: none; }
}


/* ════ LES SLIDES ET LEURS ÉTAPES ════════════════════════════════
   Une slide dure (nombre d'étapes + 1) hauteurs d'écran. La scène
   reste collée : ce sont les étapes qui se succèdent dedans, chacune
   entrant par son côté et sortant par l'opposé. */

main { position: relative; z-index: 1; }

.slide { position: relative; height: calc((var(--n) + 1) * 100vh); }
.scene { position: sticky; top: 0; height: 100vh; overflow: hidden; }

/* ⚠️ LE NOMBRE D OR NE SERVAIT QUE LA TYPOGRAPHIE. Il commande aussi
   la MISE EN PAGE ici : le contenu ne se cale plus au milieu, il se cale
   à la SECTION DOREE — l espace au-dessus vaut 0,382, celui du dessous
   0,618, leur rapport est phi. C est la règle classique de composition,
   et elle donne un bloc qui pèse plus haut que le centre géométrique :
   l œil le lit comme posé, pas comme flottant.
   Une grille de trois rangées l exprime exactement, sans calcul à la main. */
.etape {
  position: absolute; inset: 0;
  display: grid;
  grid-template-rows: 0.382fr auto 0.618fr;
  padding: calc(var(--sommet) + var(--haut) + var(--f5)) var(--marge) var(--f6);
  pointer-events: none;
}
.etape > .dedans { grid-row: 2; }
.etape > .dedans { width: 100%; max-width: var(--colonne); margin: 0 auto; }
.etape.ouverte { pointer-events: auto; }

/* Le texte ne se deplace qu a la verticale, et TOUJOURS du bas vers le
   haut : chaque element monte a sa place. L horizontale est reservee aux
   images, plus bas : [data-img]. Seule la sortie de l etape entiere garde
   son sens propre (--sy), pour qu on sente d ou l on vient. */
.etape[data-sens="haut"] { --ay: 0.9em; --sy: -58px; }
.etape[data-sens="bas"]  { --ay: 0.9em; --sy:  58px; }

/* Sans JavaScript, rien ne s'anime et tout reste lisible : ces règles
   n'entrent en jeu que si le script a posé la classe sur <html>. */
html.anime .etape {
  opacity: var(--o, 0);
  transform: translate3d(0, calc(var(--sy, 0px) * var(--x, 0)), 0);
  will-change: opacity, transform;
}
/* UN ÉLÉMENT À LA FOIS. --e avance avec le doigt, --d est le rang de
   l élément, --p la pente (l inverse de sa durée) : les deux sont posés
   par `cadence()` d après le NOMBRE réel d éléments de l étape.
   --s adoucit le résultat (3s² − 2s³) : --e reste linéaire pour coller au
   défilement, et c est chaque élément qui arrondit son propre départ. */
/* L ENTRÉE, RÉGLÉE SUR DES RÈGLES ÉCRITES, PAS AU JUGÉ.
   Le « motion cookbook » distillé du travail d Emil Kowalski, Jakub Krehel
   et Jhey Tompkins donne l entrée de référence : opacité 0→1, montée
   d environ 8 px, ET un flou de 4 px qui se lève. Le flou est le détail
   qui manquait — il fait qu un élément semble se former plutôt que
   d apparaître, et c est ce qui distingue une entrée soignée d un simple
   fondu. Trois corrections en découlent :

   1 · LE FLOU. 4 px qui tombent à 0, pilotés par la même avancée.

   2 · LA COURBE EST SORTANTE, pas symétrique. La règle est nette :
   `ease-out` pour ce qui arrive, `ease-in` pour ce qui part. Le
   smoothstep employé avant (3s² − 2s³) est symétrique : il démarrait
   aussi mollement qu il finissait, et l élément avait l air de peiner.
   `1 − (1 − s)³` part vif et se pose — c est un ease-out cubique.

   3 · LA DISTANCE EST PROPORTIONNÉE. 52 px pour tout le monde, c était
   trop : la référence dit 8 px. Un titre de 110 px peut se permettre une
   grande montée, une ligne de 10 px non — sur elle, 52 px ne se lisent
   pas comme une arrivée mais comme un saut. La distance suit donc la
   taille du texte (`--ay` en em), bornée pour rester tenue. */
html.anime .etape [data-d] {
  --ei: clamp(0, calc((var(--e, 0) - var(--d, 0)) * var(--p, 3)), 1);
  --r: calc(1 - var(--ei));
  --s: calc(1 - var(--r) * var(--r) * var(--r));
  --reste: calc(1 - var(--s));
  opacity: var(--s);
  transform: translate3d(0, clamp(8px, calc(var(--ay, 0.9em) * var(--reste)), 56px), 0);
}
/* ⚠️ LE FLOU N EST POSÉ QUE PENDANT LE MOUVEMENT.
   Un filtre non nul force une couche composée, même à blur(0). Laissé
   en permanence sur la centaine d éléments animés du site, ça fait cent
   couches qui ne servent à rien une fois tout posé. La classe « bouge »
   n est mise sur une étape que pendant sa transition. */
html.anime .etape.bouge [data-d] { filter: blur(calc(var(--reste) * 4px)); }

/* les mots d'un titre montent sous leur propre ligne, légèrement inclinés */
.lgn { display: block; overflow: clip; padding: .1em 0 .07em; margin-top: -.1em; }
.mot { display: inline-block; }
html.anime .mot {
  --ew: clamp(0, calc((var(--e, 0) - var(--d, 0)) * var(--pm, 5)), 1);
  --sw: calc(var(--ew) * var(--ew) * (3 - 2 * var(--ew)));
  opacity: var(--sw);
  transform: translateY(calc((1 - var(--sw)) * 104%)) rotate(calc((1 - var(--sw)) * 1.7deg));
}


/* ════ ÉCRAN DE CHARGEMENT ═══════════════════════════════════════ */

#chargement {
  position: fixed; inset: 0; z-index: 200;
  display: grid; grid-template-rows: 1fr auto; padding: var(--marge);
  background: #0A0908; color: #F4EFEA;
  transition: opacity .9s var(--gout), visibility .9s;
}
/* le décompte, au centre de la PAGE — pas de l espace qui reste */
.ch-compte { position: absolute; inset: 0; display: grid; place-items: center; pointer-events: none; }
#ch-nombre {
  display: block; color: #F4EFEA;
  font-family: var(--police); font-weight: 200;
  font-size: clamp(96px, 21vw, 300px); line-height: .9;
  letter-spacing: -.05em; font-variant-numeric: tabular-nums;
  color: var(--ivoire);
}
#chargement.parti { opacity: 0; visibility: hidden; pointer-events: none; }
.ch-bloc { grid-row: 2; width: 100%; max-width: var(--large); margin: 0 auto; align-self: end; }
.ch-sigle {
  font-family: var(--police); font-weight: 800;
  font-size: clamp(var(--t8), 11vw, var(--t11)); line-height: .9;
  letter-spacing: -.025em; text-transform: uppercase;
}
.ch-sigle i { font-style: normal; color: var(--terra); }
.ch-piste { position: relative; height: 1px; margin: var(--f5) 0 var(--f3); background: var(--filet); }
.ch-piste i { position: absolute; inset: 0; background: var(--terra); transform: scaleX(0); transform-origin: left; transition: transform .3s linear; }
.ch-bas { display: flex; justify-content: space-between; align-items: baseline; }


/* ════ PIÈCES COMMUNES ═══════════════════════════════════════════ */

.bouton {
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; gap: var(--f3);
  height: 56px; padding: 0 var(--f5);
  border: 1px solid var(--filet); border-radius: 999px;
  font-family: var(--police); font-weight: 700; font-size: var(--t2);
  letter-spacing: .16em; text-transform: uppercase; color: var(--sourd);
  transition: color .45s var(--gout), border-color .45s var(--gout);
}
.bouton::before {
  content: ''; position: absolute; inset: 0; z-index: -1; background: var(--terra);
  transform: scaleX(0); transform-origin: left center; transition: transform .55s var(--gout);
}
.bouton:hover { color: var(--sur-terra); border-color: var(--terra); }
.bouton:hover::before { transform: scaleX(1); }
.bouton--plein { color: var(--sur-terra); border-color: var(--terra); }
.bouton--plein::before { transform: scaleX(1); }
.bouton--plein:hover::before { opacity: .78; }
.bouton .fleche { transition: transform .5s var(--gout); }
.bouton:hover .fleche { transform: translateX(6px); }

.rangee { display: flex; flex-wrap: wrap; gap: var(--f3); }
/* Deux colonnes a parts egales, c est le reglage par defaut de tout le
   monde et ca ne dit rien. Elles suivent desormais phi : 1 contre 1,618.
   En dessous de 860 px il n y a plus la place pour deux colonnes, elles
   s empilent — une proportion juste sur 300 px de large ne sert a rien. */
.duo { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.618fr);
  gap: var(--f6); align-items: center; }
.duo--or { grid-template-columns: minmax(0, 1.618fr) minmax(0, 1fr); }
@media (max-width: 860px) { .duo, .duo--or { grid-template-columns: 1fr; gap: var(--f5); } }
.pile { display: grid; gap: var(--f4); }

/* ⚠️ PLUS DE FILET AUTOUR DES IMAGES.
   Le trait d un pixel faisait ressembler chaque photo à une vignette
   posée dans une grille. Sans lui, l image occupe son bloc et c est la
   composition qui la tient — c est la règle de la référence, où aucune
   image n est encadrée. */
.cadre { position: relative; overflow: hidden; border: 0; }
.cadre > img, .cadre > video { width: 100%; height: 100%; object-fit: cover; transition: transform 1.4s var(--gout); }
.cadre:hover > img, .cadre:hover > video { transform: scale(1.05); }
.cadre-note { position: absolute; left: var(--f3); bottom: var(--f3); padding: 5px 9px; background: var(--ecran-fort); color: var(--ivoire); }


/* ════ 00 · ACCUEIL ══════════════════════════════════════════════ */

.faits { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); border-top: 1px solid var(--filet); }
.fait { padding: var(--f4) var(--f4) 0 0; }
.fait b { display: block; font-family: var(--police); font-weight: 700; font-size: clamp(var(--t5), 2.1vw, var(--t6)); line-height: 1.05; letter-spacing: -.022em; text-transform: uppercase; }
.fait span { display: block; margin-top: var(--f2); }

.prix { display: inline-flex; align-items: baseline; gap: var(--f3); }
.prix b { font-family: var(--police); font-weight: 800; font-size: clamp(var(--t6), 3.4vw, var(--t8)); line-height: 1; color: var(--terra); }

.defiler { display: inline-flex; align-items: center; gap: var(--f3); }
.defiler-piste { position: relative; width: 1px; height: 34px; background: var(--filet); overflow: hidden; }
.defiler-piste i { position: absolute; left: 0; width: 1px; height: 13px; background: var(--terra); animation: glisse 2.1s var(--gout) infinite; }
@keyframes glisse { 0% { transform: translateY(-16px); } 100% { transform: translateY(36px); } }


/* ════ 01 · LE KLUB ══════════════════════════════════════════════ */

.devise {
  padding-left: var(--f4); border-left: 1px solid var(--terra);
  font-family: var(--police); font-weight: 400;
  font-size: clamp(var(--t4), 2.4vw, var(--t6)); line-height: 1.2;
  letter-spacing: -.012em; text-transform: uppercase; color: var(--ivoire);
}

.chiffres { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); border-top: 1px solid var(--filet); }
.chiffre { padding: var(--f4) var(--f4) 0 0; }
.chiffre b { display: block; white-space: nowrap; font-family: var(--police); font-weight: 800; font-size: clamp(var(--t7), 4.6vw, var(--t9)); line-height: .92; letter-spacing: -.035em; color: var(--terra); }
.chiffre span { display: block; margin-top: var(--f3); }

.vie { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); border-top: 1px solid var(--filet); }
.vie > div { padding: var(--f4) var(--f4) var(--f4) 0; border-bottom: 1px solid var(--filet); }
.vie b { display: block; font-family: var(--police); font-weight: 700; font-size: var(--t5); line-height: 1.08; letter-spacing: -.018em; text-transform: uppercase; }
/* ⚠️ LE SITE PARLAIT À VOIX BASSE, ET ÇA SE MESURE.
   Relevé sur la page rendue : la taille de texte la plus fréquente était
   13 px (164 occurrences) et la couleur la plus fréquente l'ivoire à 80 %
   (141 occurrences, devant l'ivoire plein à 129). Autrement dit, la voix
   dominante du site était une ÉTIQUETTE atténuée.
   Sur 21tsi, pris en référence : une seule couleur (blanc pur, 352 fois)
   et un corps à 20 px (167 fois). La hiérarchie y vient de la TAILLE et
   de l'ESPACE, jamais d'un texte qu'on éteint.
   Huit règles de texte de LECTURE — pas des étiquettes — étaient réglées
   à --t2 (12,6 px) et --sourd. Elles passent à --t3 (16 px) et à l'ivoire
   plein, avec un interligne resserré à 1,5 : c'était le « moyen » qui
   manquait entre le titre de 105 px et l'étiquette de 13. */
.vie p { margin-top: var(--f2); font-size: var(--t4); line-height: 1.5; color: var(--ivoire); }


/* ════ 02 · LES COURS ════════════════════════════════════════════ */

.familles-geant { border-top: 1px solid var(--filet); }
.famille-geant { display: flex; align-items: baseline; gap: var(--f4); padding: var(--f3) 0; border-bottom: 1px solid var(--filet); }
.famille-geant b { font-family: var(--police); font-weight: 700; font-size: clamp(var(--t6), 4.4vw, var(--t8)); line-height: 1.05; letter-spacing: -.028em; text-transform: uppercase; }
/* le numero reste a gauche, largeur fixe : les noms s alignent tous */
.famille-geant > .micro:first-child { flex: none; width: var(--f5); text-align: left; }
.famille-geant > .micro:last-child { margin-left: auto; text-align: right; }

.maitre { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: var(--f6); margin-top: var(--f5); }
.familles { border-top: 1px solid var(--filet); }
.famille {
  display: flex; align-items: center; gap: var(--f4); width: 100%;
  padding: var(--f4) 0; border-bottom: 1px solid var(--filet); text-align: left;
  transition: padding-left .5s var(--gout);
}
.famille:hover, .famille.ici { padding-left: var(--f3); }
.famille-nom { font-family: var(--police); font-weight: 700; font-size: var(--t5); letter-spacing: -.018em; text-transform: uppercase; transition: color .4s var(--gout); }
.famille-tiret { margin-left: auto; width: 21px; height: 1px; background: var(--filet-vif); transition: width .5s var(--gout), background .4s; }
.famille.ici .famille-nom { color: var(--terra); }
.famille.ici .famille-tiret { width: 55px; background: var(--terra); }

.detail-tete { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--f3); padding-bottom: var(--f3); border-bottom: 1px solid var(--filet); }
.liste-cours {
  max-height: min(42vh, 400px); overflow: hidden auto; padding-bottom: var(--f5);
  mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 55px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 55px), transparent 100%);
  scrollbar-width: thin; scrollbar-color: var(--filet-vif) transparent;
}
.liste-cours::-webkit-scrollbar { width: 2px; }
.liste-cours::-webkit-scrollbar-thumb { background: var(--filet-vif); }
.cours { padding: var(--f4) 0; border-bottom: 1px solid var(--filet); transition: padding-left .45s var(--gout); }
.cours:hover { padding-left: var(--f2); }
.cours-tete { display: flex; align-items: baseline; gap: var(--f3); }
.cours-tete h4 { font-family: var(--police); font-weight: 700; font-size: var(--t5); letter-spacing: -.012em; text-transform: uppercase; }
.cours-quand { margin: var(--f2) 0; }
.cours-quand b { color: var(--terra); font-weight: 700; }
.cours p { font-size: var(--t4); line-height: 1.5; color: var(--ivoire); max-width: 54ch; }
.niveau { margin-left: auto; flex: none; padding: 4px 11px; border: 1px solid var(--filet); border-radius: 999px; font: 400 var(--t1)/1.5 var(--police); letter-spacing: .12em; text-transform: uppercase; color: var(--faible); }
.niveau[data-n="Intense"] { border-color: var(--terra); color: var(--terra); }


/* ════ 03 · LA SEMAINE ═══════════════════════════════════════════ */

.salles { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr)); gap: var(--f6); border-top: 1px solid var(--filet); padding-top: var(--f4); }
.salle b { display: block; font-family: var(--police); font-weight: 800; font-size: clamp(var(--t5), 3.2vw, var(--t7)); line-height: 1.04; letter-spacing: -.025em; text-transform: uppercase; }
.salle .micro { display: block; margin: var(--f3) 0; }

.jours { display: flex; flex-wrap: wrap; gap: var(--f2); margin: var(--f4) 0 var(--f5); }
.jour {
  position: relative; isolation: isolate; overflow: hidden;
  padding: 11px var(--f4); border: 1px solid var(--filet); border-radius: 999px;
  font-family: var(--police); font-weight: 700; font-size: var(--t2);
  letter-spacing: .14em; text-transform: uppercase; color: var(--sourd);
  transition: color .4s var(--gout), border-color .4s var(--gout);
}
.jour::before { content: ''; position: absolute; inset: 0; z-index: -1; background: var(--terra); transform: scaleX(0); transform-origin: left; transition: transform .5s var(--gout); }
.jour:hover { color: var(--ivoire); border-color: var(--filet-vif); }
.jour.ici { color: var(--sur-terra); border-color: var(--terra); }
.jour.ici::before { transform: scaleX(1); }

.jour-tete { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--f3); padding-bottom: var(--f3); border-bottom: 1px solid var(--filet); }
.creneau { display: flex; align-items: baseline; gap: var(--f4); padding: var(--f3) 0; border-bottom: 1px solid var(--filet); transition: padding-left .45s var(--gout); }
.creneau:hover { padding-left: var(--f2); }
.creneau-h { flex: none; min-width: 150px; font: 700 var(--t2)/1.5 var(--police); letter-spacing: .03em; color: var(--terra); font-variant-numeric: tabular-nums; }
.creneau-nom { font-family: var(--police); font-weight: 600; font-size: var(--t3); letter-spacing: .015em; text-transform: uppercase; }
.creneau-note { margin-left: auto; }

.trousseau { display: grid; grid-template-columns: 1fr 1.618fr; border: 1px solid var(--filet); align-items: stretch; }
.trousseau .cadre { aspect-ratio: 4 / 5; height: 100%; }
.trousseau > div:last-child { padding: var(--f4); }


/* ════ 04 · L'ÉQUIPE ═════════════════════════════════════════════ */

.equipe { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); gap: var(--f3); }
.coach { border: 1px solid var(--filet); transition: border-color .45s var(--gout); }
.coach:hover { border-color: var(--filet-vif); }
.coach-corps { padding: var(--f4); }
.coach-corps h3 { font-family: var(--police); font-weight: 700; font-size: var(--t5); letter-spacing: -.015em; text-transform: uppercase; }
.coach-corps .micro { margin: var(--f2) 0 var(--f3); color: var(--terra); }
.coach-corps p { font-size: var(--t4); line-height: 1.5; color: var(--ivoire); }

.fente {
  position: relative; aspect-ratio: 1/1; overflow: hidden; background: #14100F;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.fente-lettre {
  font-family: var(--police); font-weight: 800;
  font-size: clamp(var(--t9), 9vw, var(--t11)); line-height: 1;
  letter-spacing: -.035em; color: #F4EFEA; opacity: .13;
  pointer-events: none; transition: opacity .5s var(--gout);
}
.fente-aide { position: absolute; left: 0; right: 0; bottom: var(--f3); text-align: center; pointer-events: none; transition: opacity .4s; }
.fente img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* La boîte porte la position et l état ; le label porte le dessin.
   Le focus vient du VRAI champ, invisible mais tabulable — pas d un faux
   état posé à la main. */
.fente-boite { position: relative; }
.fente-boite.remplie .fente-lettre, .fente-boite.remplie .fente-aide { opacity: 0; }
.fente-boite:focus-within .fente { outline: 2px solid var(--terra); outline-offset: 3px; }
.fente-boite.survol .fente { outline: 1px solid var(--terra); outline-offset: -1px; }
.fente-vider {
  position: absolute; top: var(--f2); right: var(--f2); z-index: 2;
  width: 28px; height: 28px; border: 1px solid var(--filet-vif); border-radius: 50%;
  color: #F4EFEA; background: rgba(10,9,8,.6); line-height: 1; opacity: 0; transition: opacity .35s;
}
.fente-boite.remplie:hover .fente-vider, .fente-vider:focus-visible { opacity: 1; }
/* ⚠️ opacity:0 RESTE TABULABLE. Tant qu aucune photo n a été déposée, le
   bouton « retirer » était invisible mais on tombait dessus à la
   tabulation, et il ne faisait rien. `visibility` le retire vraiment —
   et elle n est PAS dans la transition, sinon elle bloquerait le retour. */
.fente-boite:not(.remplie) .fente-vider { visibility: hidden; pointer-events: none; }


/* ════ 05 · REJOINDRE ════════════════════════════════════════════ */

.tarif-geant { display: flex; align-items: baseline; gap: var(--f4); flex-wrap: wrap; }
.tarif-geant b { font-family: var(--police); font-weight: 800; font-size: clamp(var(--t9), 12vw, var(--t11)); line-height: .88; letter-spacing: -.045em; color: var(--terra); }
.compris { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); border-top: 1px solid var(--filet); margin-top: var(--f5); }
.compris > div { padding: var(--f4) var(--f4) var(--f4) 0; border-bottom: 1px solid var(--filet); font-family: var(--police); font-weight: 600; font-size: var(--t4); line-height: 1.15; letter-spacing: -.01em; text-transform: uppercase; }

.suite { position: relative; padding: calc(var(--sommet) + var(--f7)) var(--marge) 0; }
/* Chaque page de la suite occupe sa hauteur d écran et cale son contenu
   à la section dorée, comme les étapes : le rythme de lecture ne change
   pas quand on quitte la mise en scène pour le formulaire. */
.suite-page {
  min-height: 100vh;
  display: grid; grid-template-rows: 0.382fr auto 0.618fr;
  padding-bottom: var(--f7);
}
.suite-page > * { grid-row: 2; }

/* ⚠️ LA MONTÉE SE FAIT EN TRANSITION, PAS EN ANIMATION PILOTÉE.
   Ces pages sont dans le flux normal : il n y a pas d avancement de
   défilement à lire, donc rien à recalculer à chaque image. Une classe
   posée une fois, une transition CSS, et le navigateur fait le reste.
   Le vocabulaire est celui des étapes — opacité, montée, flou de 4 px
   qui se lève — pour que le rythme ne change pas en cours de page. */
html.anime .suite-page [data-monte] {
  opacity: 0;
  transform: translate3d(0, 28px, 0);
  filter: blur(4px);
  transition: opacity .55s var(--gout) var(--montee, 0s),
              transform .55s var(--gout) var(--montee, 0s),
              filter .55s var(--gout) var(--montee, 0s);
}
html.anime .suite-page [data-monte].monte {
  opacity: 1; transform: none; filter: none;
}
@media (prefers-reduced-motion: reduce) {
  html.anime .suite-page [data-monte] { opacity: 1; transform: none; filter: none; transition: none; }
}
@media (max-height: 620px), (prefers-reduced-motion: reduce) {
  .suite-page { min-height: 0; display: block; padding-bottom: var(--f6); }
}
.suite-dedans { width: 100%; max-width: var(--colonne); margin: 0 auto; }

.questions { border-top: 1px solid var(--filet); }
.question { padding: var(--f4) 0; border-bottom: 1px solid var(--filet); }
/* les questions sont des h3 depuis la reprise de la hiérarchie des titres */
.question h3 { font-family: var(--police); font-weight: 700; font-size: var(--t5); letter-spacing: -.005em; text-transform: uppercase; }
.question p { margin-top: var(--f3); font-size: var(--t4); line-height: 1.5; color: var(--ivoire); max-width: 58ch; }
.contacts { display: flex; flex-wrap: wrap; gap: var(--f2); margin-top: var(--f4); }
.contacts .bouton { height: 44px; padding: 0 var(--f4); }

.fiche { border: 1px solid var(--filet); padding: clamp(var(--f4), 3vw, var(--f6)); }
.fiche h3 { margin-top: var(--f3); }
.fiche > p { margin-top: var(--f3); font-size: var(--t4); line-height: 1.5; color: var(--ivoire); }
.champs { display: grid; gap: var(--f4); margin-top: var(--f5); }
.paire { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr)); gap: var(--f4); }
.champ { display: flex; flex-direction: column; gap: var(--f2); }
.champ > span { font: 400 var(--t1)/1 var(--police); letter-spacing: .16em; text-transform: uppercase; color: var(--faible); }
.champ > span em { font-style: normal; color: var(--terra); }
/* le trait du bas est la SEULE chose qui dit « ici, un champ » : il lui
   faut 3:1 (WCAG 1.4.11). --filet plafonnait à 2,5:1, --filet-vif tient 4,1:1. */
.champ input, .champ select, .champ textarea {
  width: 100%; padding: var(--f3) 0; border: 0; border-bottom: 1px solid var(--filet-vif);
  background: none; color: var(--ivoire);
  font: 300 var(--t3)/1.5 var(--police); border-radius: 0;
  transition: border-color .4s var(--gout);
}
.champ textarea { resize: vertical; }
.champ ::placeholder { color: var(--faible); }
.champ input:focus, .champ select:focus, .champ textarea:focus { border-bottom-color: var(--terra); }
.champ select option { background: var(--noir); color: var(--ivoire); }

.accord { display: flex; align-items: flex-start; gap: var(--f3); font-size: var(--t3); line-height: 1.5; color: var(--ivoire); cursor: pointer; }
.accord input { flex: none; width: 16px; height: 16px; margin-top: 3px; accent-color: var(--terra); cursor: pointer; }

.avis { padding: var(--f3) var(--f4); border: 1px solid var(--terra); font-size: var(--t2); line-height: 1.618; color: var(--ivoire); }
.avis a { color: var(--terra); border-bottom: 1px solid var(--filet); }

.recu { display: flex; flex-direction: column; gap: var(--f4); padding: clamp(var(--f4), 3vw, var(--f6)); border: 1px solid var(--terra); }
.recu p { font-size: var(--t3); line-height: 1.618; color: var(--sourd); }

details#mentions { margin-top: var(--f6); border-top: 1px solid var(--filet); }
details#mentions summary { display: flex; align-items: center; justify-content: space-between; gap: var(--f4); padding: var(--f4) 0; cursor: pointer; list-style: none; }
details#mentions summary::-webkit-details-marker { display: none; }
details#mentions summary .plus { font-size: var(--t4); color: var(--terra); transition: transform .4s var(--gout); }
details#mentions[open] summary .plus { transform: rotate(45deg); }
.mentions-grille { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr)); gap: var(--f5); padding-bottom: var(--f5); }
.mentions-grille h4 { font: 700 var(--t1)/1 var(--police); letter-spacing: .18em; text-transform: uppercase; color: var(--terra); margin-bottom: var(--f3); }
.mentions-grille p { font-size: var(--t3); line-height: 1.55; color: var(--sourd); }
.mentions-grille b { font-weight: 700; color: var(--ivoire); }
.mentions-grille a { color: var(--terra); }
.avoir { color: var(--terra); font-style: normal; }

.pied { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--f3) var(--f5); padding: var(--f4) 0 var(--f6); border-top: 1px solid var(--filet); }


/* ════ MOUVEMENT RÉDUIT ══════════════════════════════════════════ */

/* ════ MOUVEMENT RÉDUIT, ET ÉCRANS TROP COURTS ═══════════════════
   Dans les deux cas la mise en scène est abandonnée : les étapes
   reprennent leur place dans le flux, rien ne se superpose, rien ne
   peut être rogné. C est la seule façon de ne perdre aucun contenu à
   200 % de zoom ou sur un portable en paysage. */
/* LA VUE SIMPLE. La classe html.vue-simple declenche le meme bloc que
   le média : une seule mise en page dégradée, pas deux à tenir en accord.
   Le sélecteur est dupliqué au lieu du bloc — c est la seule façon en CSS
   de faire entrer une classe dans une requête média sans tout recopier. */
html.vue-simple { scroll-behavior: auto; }
html.vue-simple .slide { height: auto; }
html.vue-simple .scene { position: static; height: auto; overflow: visible; }
html.vue-simple .etape { position: static; inset: auto; min-height: 100vh;
  pointer-events: auto; opacity: 1 !important; transform: none !important; }
html.vue-simple .mot,
html.vue-simple .etape [data-d] { opacity: 1 !important; transform: none !important; filter: none !important; }
html.vue-simple .etape [data-img] { clip-path: none !important; opacity: 1 !important; transform: none !important; }
html.vue-simple .etape [data-img] > img { transform: none !important; }
html.vue-simple #cartouche { position: absolute; }
html.vue-simple #refraction { display: none !important; }

@media (prefers-reduced-motion: reduce), (max-height: 620px) {
  /* un cartouche fixe de 160 px sur une fenêtre de 256 px, ce n est plus
     une navigation, c est un bandeau : il redevient un en-tête qui défile. */
  #cartouche { position: absolute; }
  html { scroll-behavior: auto; }
  .slide { height: auto; }
  .scene { position: static; height: auto; overflow: visible; }
  .etape {
    position: static; inset: auto; min-height: 100vh;
    pointer-events: auto; opacity: 1 !important; transform: none !important;
  }
  html.anime .mot,
  html.anime .etape [data-d] { opacity: 1 !important; transform: none !important; }
  /* le cadre porte desormais lui aussi une translation : on la neutralise */
  html.anime .etape [data-img] { clip-path: none !important; opacity: 1 !important; transform: none !important; }
  html.anime .etape [data-img] > img { transform: none !important; }
  .defiler-piste i { animation: none; }
  *, *::before, *::after { transition-duration: .01ms !important; }
}
/* ════ LES IMAGES — la seule chose qui se déplace à l'horizontale ══

   Elles ARRIVENT PAR LA DROITE, une par une, au rythme du défilement.
   Le cadre entier glisse depuis la droite ; le voile se retire du bord
   droit vers le bord gauche ; et le contenu glisse un peu en sens inverse
   à l intérieur — c'est ce décalage qui donne la douceur plutôt qu un
   simple bloc qui se déplace.

   Elles partagent la cadence du texte (--d, --p) : une image est un
   élément de la file comme un autre, elle ne double personne. */

html.anime .etape [data-img] {
  --ei: clamp(0, calc((var(--e, 0) - var(--d, 0)) * var(--p, 3)), 1);
  --s: calc(var(--ei) * var(--ei) * (3 - 2 * var(--ei)));
  opacity: clamp(0, calc(var(--s) * 3), 1);
  clip-path: inset(0 0 0 calc((1 - var(--s)) * 101%));
  transform: translate3d(calc((1 - var(--s)) * 9%), 0, 0);
}
html.anime .etape [data-img] > img,
html.anime .etape [data-img] > video {
  transform: translateX(calc((1 - var(--s)) * -7%));
}
/* ⚠️ Le cadrage par défaut coupait les têtes : la photo des agents est
   en 4/3 dans un cadre de 220 à 440 px de haut, et « cover » centré
   retire autant en haut qu en bas. Le sujet est dans le tiers haut. */
.photo-large { width: 100%; }
.photo-large .cadre > img { object-position: 50% 0; }
/* le bandeau de groupe : très large, il garde tout son monde */
/* la photo de groupe, cadrée sur les visages : ils sont à 52 % de la
   hauteur, la moitié basse n est que du sable */
.photo-large--groupe .cadre > img { object-position: 50% 52%; }
.photo-large--groupe .cadre { height: clamp(260px, 44vh, 520px); }
.photo-large .cadre { width: 100%; height: clamp(220px, 40vh, 440px); }
.photo-debout { width: 100%; max-width: min(34vw, 400px); justify-self: end; }
/* Le portrait de Karine prend la largeur de la colonne dorée : c est lui
   qu on vient voir, le parcours se lit à côté. */
.photo-karine { max-width: none; justify-self: stretch; }
.photo-karine .cadre { width: 100%; height: clamp(340px, 62vh, 640px); }
.photo-karine .cadre > img { object-position: 62% 22%; }
.parcours-ligne { display: grid; grid-template-columns: 10ch 1fr;
  gap: var(--f2) var(--f4); padding: var(--f3) 0;
  border-bottom: 1px solid var(--filet); }
.parcours-ligne b { font-family: var(--police); font-weight: 700; font-size: var(--t3); }
.parcours-ligne span:last-child { grid-column: 2; font-size: var(--t3); color: var(--sourd); }
.photo-debout .cadre { width: 100%; height: clamp(300px, 54vh, 580px); }
/* un document se montre ENTIER : on ne recadre pas un planning. */
/* ⚠️ UN DOCUMENT SE MONTRE EN ENTIER, SANS CADRE.
   Trois affiches du klub sont affichées sur le site : le planning papier,
   le trousseau et l affiche de la saison. Elles portent des informations
   qu on doit pouvoir lire — un recadrage en coupe forcément une partie,
   et le filet de 1 px les fait passer pour des vignettes décoratives
   alors que ce sont des pièces à consulter.
   Le trousseau, lui, était en plus enfermé dans un ratio 4/3 alors qu il
   est en 1024 × 1536 : le tiers du bas était perdu. */
.cadre--doc { border: 0; }
.cadre--doc > img { object-fit: contain; background: transparent; }
.cadre--doc:hover > img { transform: none; }   /* on ne zoome pas un document */
.trousseau .cadre--doc { height: auto; }
.trousseau .cadre--doc > img { height: auto; max-height: 62vh; }

/* ════ LES DISCIPLINES QUI TOURNENT ══════════════════════════════ */

.etiquettes { display: flex; flex-wrap: wrap; gap: var(--f2); }
.etiquette {
  padding: 10px var(--f4); border: 1px solid var(--filet); border-radius: 999px;
  font-family: var(--police); font-weight: 600; font-size: var(--t2);
  letter-spacing: .09em; text-transform: uppercase; color: var(--sourd);
  transition: border-color .45s var(--gout), color .45s var(--gout);
}
.etiquette:hover { border-color: var(--terra); color: var(--terra); }

/* ════ LA SEMAINE D'UN COUP D'ŒIL ════════════════════════════════ */

.grille-semaine { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 190px), 1fr)); gap: 0; border-top: 1px solid var(--filet); }
.grille-jour { padding: var(--f4) var(--f4) var(--f4) 0; border-bottom: 1px solid var(--filet); }
.grille-jour > b {
  display: block; font-family: var(--police); font-weight: 800;
  font-size: var(--t5); letter-spacing: -.01em; text-transform: uppercase;
}
.grille-jour > .micro { display: block; margin: var(--f2) 0 var(--f3); }
.grille-jour ul { list-style: none; display: grid; gap: var(--f2); }
.grille-jour li { display: grid; gap: 2px; }
.grille-jour li em { font-style: normal; font: 700 var(--t2)/1.4 var(--police); letter-spacing: .02em; color: var(--terra); font-variant-numeric: tabular-nums; }
.grille-jour li span { font-size: var(--t3); line-height: 1.45; color: var(--sourd); }

/* ════ COMMENT ÇA SE PASSE ═══════════════════════════════════════ */

.marches { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: 0; border-top: 1px solid var(--filet); }
.marche { padding: var(--f5) var(--f5) var(--f5) 0; border-bottom: 1px solid var(--filet); }
.marche > .micro {
  display: block; font-family: var(--police); font-weight: 200;
  font-size: clamp(var(--t7), 5.5vw, var(--t9)); line-height: .9;
  letter-spacing: -.04em; color: var(--terra);
}
.marche > b {
  display: block; margin: var(--f4) 0 var(--f3);
  font-family: var(--police); font-weight: 700; font-size: var(--t5);
  line-height: 1.15; letter-spacing: -.01em; text-transform: uppercase;
}
.marche > p { font-size: var(--t4); line-height: 1.5; color: var(--ivoire); }


/* ════ LIEN D'ÉVITEMENT ET REPLI SANS JAVASCRIPT ═════════════════ */

.saut {
  position: fixed; top: 0; left: 0; z-index: 300;
  padding: var(--f3) var(--f4); background: var(--terra); color: var(--sur-terra);
  font: 700 var(--t2)/1 var(--police); letter-spacing: .1em; text-transform: uppercase;
  transform: translateY(-120%); transition: transform .3s var(--gout);
}
.saut:focus { transform: none; }

.repli { max-width: 760px; margin: 0 auto; padding: var(--f7) var(--marge); }
.repli h1 { font-family: var(--police); font-weight: 800; font-size: var(--t6); line-height: 1.05; text-transform: uppercase; }
.repli h2 { margin: var(--f6) 0 var(--f3); font-family: var(--police); font-weight: 700; font-size: var(--t4); text-transform: uppercase; color: var(--terra); }
.repli p { margin-top: var(--f3); color: var(--sourd); }
.repli b { color: var(--ivoire); font-weight: 700; }
.repli ul { list-style: none; display: grid; gap: var(--f3); }
.repli li { padding-bottom: var(--f3); border-bottom: 1px solid var(--filet); color: var(--sourd); }
.repli a { color: var(--terra); }

/* le pied de page, hors de <main> */
.pied-page { position: relative; z-index: 1; padding: 0 var(--marge); }


/* ════ LES TROIS DOSSIERS PORTFOLIO ═══════════════════════════════
   Des cartes à ouvrir, pas des photos à regarder : elles doivent se
   lire comme des dossiers fermés. D où le cadre fin, le nom en gros,
   le décompte en petit, et la mention d ouverture en bas — les mêmes
   codes que le reste du site, rien de neuf à apprendre. */

/* ⚠️ auto-fit créait une QUATRIÈME piste pour trois cartes : elle est
   bien réduite à 0 px, mais la gouttière qui la précède reste comptée —
   33 px de débordement mesurés. Il y a exactement trois dossiers : on le
   dit, au lieu de laisser la grille le deviner. */
.dossiers {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--f4);
}
@media (max-width: 900px) { .dossiers { grid-template-columns: 1fr; } }
.dossier {
  display: flex; flex-direction: column; gap: 0;
  padding: 0; text-align: left; cursor: pointer;
  background: none; color: inherit; font: inherit;
  border: 1px solid var(--filet);
  transition: border-color .45s var(--gout), transform .45s var(--gout);
}
.dossier:hover, .dossier:focus-visible { border-color: var(--terra); }
.dossier:hover { transform: translateY(-3px); }
.dossier[aria-disabled="true"] { opacity: .45; cursor: not-allowed; }

.dossier-vue { position: relative; display: block; height: clamp(180px, 26vh, 300px); overflow: hidden; }
.dossier-vue img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .7s var(--gout); }
.dossier:hover .dossier-vue img { transform: scale(1.045); }
.dossier-voile { position: absolute; inset: 0;
  background: linear-gradient(to top, var(--ecran-fort) 0%, transparent 62%); }

.dossier-bas { display: flex; flex-direction: column; gap: var(--f1); padding: var(--f3); }
.dossier-nom { font-family: var(--police); font-weight: 700; font-size: var(--t5); line-height: 1.05;
  letter-spacing: -.01em; color: var(--ivoire); }
.dossier-compte { color: var(--terra); }
.dossier-texte { font-size: var(--t1); line-height: 1.5; color: var(--sourd); }
.dossier-ouvrir { margin-top: var(--f2); color: var(--ivoire); }


/* ════ LA GALERIE ═════════════════════════════════════════════════
   Un <dialog> natif : il apporte le piège à tabulation, Échap, le
   retour du focus et l inertie du reste de la page. Les réécrire à la
   main, c est le genre de chose qu on rate sans s en apercevoir. */

.galerie {
  width: 100vw; max-width: 100vw; height: 100vh; max-height: 100vh;
  margin: 0; padding: 0; border: 0;
  background: var(--noir); color: var(--ivoire);
  display: flex; flex-direction: column; overflow: hidden;
}
.galerie::backdrop { background: rgba(6,5,5,.92); }

.gal-tete {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--f4);
  padding: var(--f4) var(--marge) var(--f3);
  border-bottom: 1px solid var(--filet); flex: 0 0 auto;
}
.gal-nom { font-family: var(--police); font-weight: 700; font-size: var(--t6); line-height: 1; letter-spacing: -.015em; }
.gal-compte { margin-top: var(--f1); color: var(--terra); }
.gal-fermer { flex: 0 0 auto; }

.gal-corps { flex: 1 1 auto; overflow-y: auto; padding: var(--f4) var(--marge) var(--f6);
  overscroll-behavior: contain; }
.gal-groupe { font-family: var(--police); font-weight: 700; font-size: var(--t3); letter-spacing: .06em;
  text-transform: uppercase; color: var(--sourd);
  margin: var(--f5) 0 var(--f3); padding-bottom: var(--f1);
  border-bottom: 1px solid var(--filet); }
.gal-groupe:first-child { margin-top: 0; }

.gal-grille {
  display: grid; gap: var(--f2);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 190px), 1fr));
}
.tuile { position: relative; display: block; padding: 0; border: 0; cursor: pointer;
  background: var(--noir); aspect-ratio: 1; overflow: hidden;
  /* Un filet fin sur chaque tuile. Sans lui, une vignette pas encore
     chargee est INVISIBLE : le fond de la tuile et celui de la galerie
     sont la meme couleur, et la grille parait trouee le temps que les
     images arrivent — vu a l ecran, ca ressemble a une panne. */
  outline: 1px solid var(--filet); outline-offset: -1px; }
.tuile img { width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform .6s var(--gout), opacity .4s var(--gout); opacity: .86; }
.tuile:hover img, .tuile:focus-visible img { transform: scale(1.06); opacity: 1; }
/* ⚠️ LA TUILE N AVAIT AUCUN FOCUS VISIBLE, et ça ne se voyait pas dans le
   code : `:focus-visible` (règle globale, plus haut) et `.tuile` ont la
   MÊME spécificité — c est donc la dernière écrite qui gagne, et c est
   l outline décoratif de 1 px de la tuile. Au clavier, on traversait toute
   la galerie sans savoir où l on était (WCAG 2.4.7). Il faut une règle
   plus spécifique. Offset négatif : la gouttière ne fait que 8 px. */
.tuile:focus-visible {
  outline: 3px solid var(--terra); outline-offset: -3px;
  box-shadow: inset 0 0 0 5px rgba(10, 9, 8, .75);
}
.tuile-jouer { position: absolute; inset: 0; display: grid; place-items: center;
  font-size: var(--t4); color: var(--ivoire); text-shadow: 0 1px 12px rgba(0,0,0,.6);
  pointer-events: none; }
.tuile-duree { position: absolute; left: 6px; bottom: 6px; padding: 2px 6px;
  background: var(--ecran-fort); color: var(--ivoire); pointer-events: none; }

/* ── le plein écran, par-dessus la grille ── */
/* CHAQUE PIÈCE EST PLACÉE EXPLICITEMENT. Une première version laissait
   la grille placer toute seule : les deux flèches se retrouvaient côte
   à côte dans les colonnes 1 et 2, et la vidéo était poussée dans la
   colonne 3 — qui, étant en `auto`, ne la contraignait pas et la
   laissait déborder de l écran. Vu à la capture. */
.gal-vue {
  position: absolute; inset: 0; z-index: 2;
  display: grid; align-items: center;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: var(--f3); padding: var(--f4) var(--f3) var(--f5);
  background: var(--noir);
}
.gal-scene { grid-column: 2; grid-row: 1;
  display: grid; place-items: center; width: 100%; height: 100%; min-width: 0; min-height: 0; }
.gal-scene img, .gal-scene video {
  max-width: 100%; max-height: 100%; width: auto; height: auto; display: block; background: #000;
}
/* Les rediffusions sont en 360 p natif : laissées à leur taille réelle
   elles font un timbre-poste au milieu d un écran de 1920. On les laisse
   grandir, plafonnées — au-delà de ~1180 px la source ne suit plus. */
.gal-scene video { width: min(100%, 1180px); }
.gal-nav { align-self: center; width: 52px; height: 52px;
  display: grid; place-items: center; cursor: pointer;
  background: none; color: var(--ivoire); font-size: var(--t3);
  border: 1px solid var(--filet); border-radius: 50%;
  transition: border-color .35s var(--gout), background .35s var(--gout); }
.gal-prec { grid-column: 1; grid-row: 1; }
.gal-suiv { grid-column: 3; grid-row: 1; }
.gal-nav:hover, .gal-nav:focus-visible { border-color: var(--terra); background: var(--noir); }
.gal-legende { grid-column: 1 / -1; grid-row: 2; text-align: center; color: var(--sourd); }

@media (max-width: 720px) {
  .gal-tete { padding: var(--f3) var(--f3) var(--f2); }
  .gal-nom { font-size: var(--t4); }
  .gal-corps { padding: var(--f3) var(--f3) var(--f5); }
  .gal-grille { grid-template-columns: repeat(auto-fill, minmax(min(100%, 128px), 1fr)); gap: 6px; }
  .gal-vue { grid-template-columns: 1fr; grid-template-rows: minmax(0,1fr) auto auto;
    padding: var(--f2); }
  /* Sur téléphone la colonne unique impose de tout replacer : les deux
     flèches partagent la rangée 2, l une calée à gauche, l autre à droite. */
  .gal-scene { grid-column: 1; grid-row: 1; }
  .gal-nav { width: 46px; height: 46px; }
  .gal-prec { grid-column: 1; grid-row: 2; justify-self: start; }
  .gal-suiv { grid-column: 1; grid-row: 2; justify-self: end; }
  .gal-legende { grid-column: 1; grid-row: 3; }
  .gal-retour   { grid-column: 1; grid-row: 4; }
  .gal-vue { grid-template-rows: minmax(0,1fr) auto auto auto; }
}


/* ════ DIT MAIS PAS MONTRÉ ════════════════════════════════════════
   Pour ce qu un lecteur d écran doit entendre sans que ça occupe la
   page. On ne se sert PAS de `display:none` ni de `visibility:hidden`,
   qui retirent aussi le texte de l arbre d accessibilité : il faut
   qu il reste là, simplement hors du champ. */
.invisible {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}


/* ════ LES RACCOURCIS ═════════════════════════════════════════════
   Ouverts par « ? », la convention GitHub. Même dialogue natif que la
   galerie : piège à tabulation, Échap et retour du focus sont donnés. */
.aide {
  border: 1px solid var(--filet); background: var(--noir); color: var(--ivoire);
  padding: var(--f6); max-width: 520px; width: calc(100vw - var(--f5));
}
.aide::backdrop { background: rgba(6,5,5,.86); }
.aide h2 { font-family: var(--police); font-weight: 700;
  font-size: var(--t5); letter-spacing: -.01em; margin-bottom: var(--f4); }
.aide-liste { display: grid; gap: var(--f3); }
.aide-liste div { display: grid; grid-template-columns: 1fr 1.618fr;
  gap: var(--f4); align-items: baseline; }
.aide kbd { font: 500 var(--t2)/1.4 var(--police);
  color: var(--ivoire); letter-spacing: .04em; }
.aide-liste span { font-size: var(--t2); color: var(--sourd); }
.aide-fermer { margin-top: var(--f5); }

/* le repère qui rend la touche découvrable.
   min-height + padding : le texte fait 10 px de haut, la cible en faisait
   autant. 24 px, c est le minimum WCAG 2.5.8 — obtenu sans rien déplacer,
   les pastilles voisines faisant déjà 44 px. */
.cle-aide { background: none; border: 0; padding: 0 4px; cursor: pointer;
  display: inline-flex; align-items: center; min-height: 24px;
  font: 500 var(--t1)/1 var(--police);
  color: var(--faible); letter-spacing: .1em; text-transform: uppercase;
  transition: color .35s var(--gout); }
.cle-aide:hover, .cle-aide:focus-visible { color: var(--terra); }
/* ⚠️ Mesuré à 1278 px : le repère chevauchait « REJOINDRE ». Le
   cartouche tient le sigle, six rubriques et trois pastilles — il n y a
   pas de place pour un quatrième bloc en dessous de ~1400 px. Le
   raccourci « ? » continue de fonctionner sans lui, et c est justement
   au clavier qu on le cherche. */
@media (max-width: 1400px) { .cle-aide { display: none; } }

/* le décompte, à droite de l'étiquette de groupe : on sait ce qu'il y a
   sous la section avant d'avoir fait défiler */
.gal-groupe { display: flex; align-items: baseline; justify-content: space-between; gap: var(--f4); }
.gal-compte-groupe { font: 500 var(--t1)/1 var(--police);
  letter-spacing: .1em; color: var(--terra); text-transform: none; flex: 0 0 auto; }

/* le retour à la grille, visible : Échap n'est écrit nulle part */
.gal-retour { grid-column: 1 / -1; grid-row: 3; justify-self: center; }
.gal-vue { grid-template-rows: minmax(0, 1fr) auto auto; }

.aide-mot { font-size: var(--t1); line-height: 1.55; color: var(--faible);
  margin: var(--f5) 0 var(--f3); }
.aide-simple { margin-right: var(--f2); }
.aide-simple[aria-pressed="true"] { border-color: var(--terra); color: var(--terra); }

/* ════ L'AFFICHE, MOT POUR MOT ════════════════════════════════════
   Tout ce que porte l'affiche papier, en texte lisible : par un lecteur
   d'écran, par un moteur de recherche, et sur un téléphone où l'image
   fait trois centimètres de haut. Les deux colonnes suivent φ comme le
   reste du site — ici à parts égales, parce que les deux salles pèsent
   pareil et qu'une hiérarchie inventée serait fausse. */
.affiche-clair {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--f6); margin-top: var(--f5);
}
.affiche-salle { border-top: 1px solid var(--filet); padding-top: var(--f3); }
.affiche-ville { font-family: var(--police); font-weight: 700;
  font-size: var(--t5); color: var(--terra); letter-spacing: -.01em; }
.affiche-lieu { display: block; margin-top: 2px; color: var(--faible); }
.affiche-jour { margin-top: var(--f4); }
.affiche-jour b { display: block; font-family: var(--police); font-weight: 700;
  font-size: var(--t5); letter-spacing: -.005em; }
.affiche-jour span { display: block; margin-top: 3px; font-size: var(--t3);
  color: var(--sourd); }

.affiche-pied {
  display: grid; grid-template-columns: 1fr auto; gap: var(--f5);
  align-items: end; margin-top: var(--f6);
  border-top: 1px solid var(--filet); padding-top: var(--f4);
}
.affiche-dates b { display: block; font-family: var(--police); font-weight: 700;
  font-size: var(--t5); }
.affiche-dates .micro { display: block; margin-top: 3px; color: var(--faible); }
.affiche-essai { display: inline-block; margin-top: var(--f3);
  padding: 7px 14px; background: var(--terra); color: var(--sur-terra);
  font: 700 var(--t2)/1 var(--police); letter-spacing: .06em;
  text-transform: uppercase; }
.affiche-tel { grid-column: 1; }
.affiche-tel .micro { display: block; color: var(--faible); }
.affiche-tel a { font-family: var(--police);
  font-size: var(--t4); letter-spacing: .02em; }

/* les QR codes. 16/09 : régénérés depuis les vrais liens (Facebook, Instagram)
   et relus — décodés en machine — avant d être posés ; voir LIRE-MOI.md.
   Le fond reste un blanc FIXE (jamais var(--ivoire), qui s inverse en
   ambiance jour) : un QR se scanne au contraste, pas à la mode du site. Le
   filet terracotta est ce qui le relie à la DA. */
.affiche-codes { grid-column: 2; grid-row: 1 / 3; display: grid;
  grid-template-columns: auto auto; gap: var(--f3); align-items: end; justify-items: center; }
.affiche-suivez { grid-column: 1 / -1; color: var(--faible); justify-self: end; }
.qr { display: grid; justify-items: center; gap: 5px; }
.qr img { width: 88px; height: 88px; display: block; background: #fff; padding: 5px;
  border: 1.5px solid var(--terra); border-radius: 3px;
  image-rendering: pixelated;              /* un QR ne se lisse pas */
  transition: transform .4s var(--gout), border-color .4s var(--gout); }
.qr:hover img, .qr:focus-visible img { transform: scale(1.06); }
.qr .micro { color: var(--faible); }

.affiche-devise { margin-top: var(--f5);
  font: 700 var(--t5)/1.1 var(--police); color: var(--terra);
  letter-spacing: -.01em; }

@media (max-width: 760px) {
  .affiche-pied { grid-template-columns: 1fr; }
  .affiche-codes { grid-column: 1; grid-row: auto; justify-content: start; justify-items: start; }
  .affiche-suivez { justify-self: start; }
}

/* ════ LA FICHE DE RECRUTEMENT ════════════════════════════════════
   Elle était juste et laide : des champs empilés et une liste
   déroulante. Trois changements, tous dans la langue déjà posée du
   site — pastilles à contour fin, filets d'un pixel, terracotta. */

/* ── la jauge : quatre champs, et rien ne disait où on en était ── */
.fiche-jauge { position: relative; margin-top: var(--f4); height: 1px;
  background: var(--filet); }
.fiche-jauge i { display: block; height: 100%; background: var(--terra);
  transform-origin: left center; transform: scaleX(0);
  transition: transform .55s var(--gout); }
.fiche-jauge span { position: absolute; right: 0; top: var(--f2);
  color: var(--faible); transition: color .4s var(--gout); }
.fiche--paree .fiche-jauge span { color: var(--terra); }

/* ── le choix devient tactile ──────────────────────────────────────
   C'était le seul endroit du site qui gardait un <select>, la commande
   la plus pauvre du web sur téléphone. Des radios natives : le clavier,
   les flèches et le lecteur d'écran marchent sans une ligne de script. */
.champ--choix { border: 0; padding: 0; margin: 0; min-width: 0; }
.champ--choix legend { padding: 0; font: 500 var(--t1)/1 var(--police);
  letter-spacing: .12em; text-transform: uppercase; color: var(--faible); }
.choix-lot { display: flex; flex-wrap: wrap; gap: var(--f2); margin-top: var(--f3); }
.choix { position: relative; }
.choix input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.choix span { display: block; padding: 9px 15px; min-height: 24px;
  border: 1px solid var(--filet); border-radius: 999px;
  font-size: var(--t2); color: var(--sourd); cursor: pointer;
  transition: border-color .35s var(--gout), color .35s var(--gout),
              background .35s var(--gout); }
.choix input:hover + span { border-color: var(--filet-vif); color: var(--ivoire); }
.choix input:checked + span { border-color: var(--terra); color: var(--terra); }
/* le focus vient du vrai <input>, pas d'un faux état : il suit le clavier */
.choix input:focus-visible + span { outline: 2px solid var(--terra); outline-offset: 3px; }

/* ── le bouton dit qu'on y est ──────────────────────────────────────
   On n'a PAS désactivé l'envoi tant que la fiche est incomplète : un
   bouton grisé ne dit jamais POURQUOI il l'est. Il change seulement
   d'allure, et la validation garde le droit d'expliquer. */
.fiche--paree .bouton--plein { box-shadow: 0 0 0 4px rgba(226,112,92,.18); }

/* le matériel en usage, sous la liste du trousseau */
/* Écran « la semaine » : les images n y portent ni légende ni cadre.
   Le planning et le trousseau sont des documents qu on lit, la photo est
   une respiration — aucun des trois n a besoin d être encadré ni titré. */
.trousseau-usage { margin-top: var(--f4); width: 100%; height: clamp(180px, 26vh, 300px); border: 0; }
.trousseau-usage > img { object-position: 50% 22%; }

/* ════ LES CIBLES AU DOIGT ════════════════════════════════════════
   Règle tirée du skill ui-ux-pro-max (priorité 2, « Touch & Interaction ») :
   44 × 44 px minimum. WCAG 2.5.8 n'exige que 24 px, et le site les tient
   déjà — mais 24 px suffisent à une souris, pas à un pouce.

   Mesuré : 18 commandes sous 44 px, dont les six rubriques de navigation
   (24 px de haut) et les champs du formulaire (40 px).

   ⚠️ On n'élargit PAS tout le monde partout : des boutons de 44 px sur
   un écran de bureau casseraient le dessin fin et aéré qui fait ce site.
   `pointer: coarse` ne s'applique qu'aux pointeurs imprécis — doigt,
   stylet. À la souris, rien ne bouge. */
@media (pointer: coarse) {
  .lien, .marque, .cle-aide, .pastille { min-height: 44px; }
  .lien, .marque { display: inline-flex; align-items: center; }
  /* la zone d'attrape du rail passe de 31 à 45 px */
  #rail::before { inset: -22px 0; }
  .tuile { min-height: 44px; }
  .choix span { padding: 12px 18px; }
}

/* Les champs, eux, gagnent leurs 44 px PARTOUT : un formulaire est
   l'endroit où une frappe manquée coûte le plus cher, et 4 px de plus
   ne se voient pas. */
.champ input, .champ select, .champ textarea { min-height: 44px; }
.saut { min-height: 44px; display: inline-flex; align-items: center; }

/* La case RGPD est obligatoire pour envoyer la fiche, et c'était la plus
   petite cible du site : 598 × 20 px. Le label entier est cliquable —
   c'est donc LUI qu'il faut rendre atteignable, pas la case. */
.accord { min-height: 44px; align-items: center; padding: var(--f2) 0; }
.accord input { width: 20px; height: 20px; flex: 0 0 auto; accent-color: var(--terra); }

/* Le mail et le téléphone du pied de page : deux liens de 17 px, et ce
   sont précisément ceux qu'on vise au doigt pour appeler le klub.
   `inline-block` + padding les porte au-dessus du plancher sans changer
   la ligne de texte qui les contient. */
.pied-page a[href^="mailto:"], .pied-page a[href^="tel:"] {
  display: inline-block; padding: 4px 0; min-height: 24px;
}
@media (pointer: coarse) {
  .pied-page a[href^="mailto:"], .pied-page a[href^="tel:"] { padding: 12px 0; min-height: 44px; }
}

/* Le décompte de la jauge est posé en absolu à droite ; la ligne des
   champs obligatoires passait dessous. On lui réserve la place. */
/* ⚠️  ne suffisait pas : le rembourrage est DANS la
   boîte, donc le bloc gardait toute sa largeur et passait sous le
   décompte. Mesuré : la ligne allait jusqu à 1175 px, le décompte
   commençait à 1004. Il faut réduire la largeur, pas l intérieur. */
.fiche > p.micro { width: max-content; max-width: calc(100% - 19ch); }
@media (max-width: 620px) {
  .fiche-jauge span { position: static; display: block; margin-top: var(--f2); }
  .fiche > p.micro { padding-right: 0; }
}

/* Le suffixe « + » tombait à la ligne sous le 80, ce qui décalait son
   libellé et cassait l'alignement de la rangée de chiffres. Un nombre et
   son suffixe sont un seul mot. */
/* ⚠️ Ce n était PAS un retour à la ligne : le span du compteur est en
   display:block, donc le « + » tombait SOUS le 80 — le libellé de la
   première colonne descendait de 54 px et la rangée se désalignait.
    n y pouvait rien ; il fallait remettre le span en ligne. */
.chiffre b { white-space: nowrap; }
.chiffre b [data-compteur] { display: inline; }

/* ════ LA LARGEUR DE LECTURE ══════════════════════════════════════
   Relevé sur la page rendue : deux blocs de texte faisaient 183 et
   134 caractères de large. Au-delà d'environ 70, l'œil perd la ligne
   en revenant à la marge gauche — on relit la même, ou on en saute une.
   Sur 21tsi, quatre largeurs seulement, et la plus grande vaut 62 ch.
   On borne donc TOUT texte suivi, sans avoir à le prévoir cas par cas :
   `max-width` en `ch` suit la taille de la police, contrairement à une
   valeur en pixels qui se périme dès qu'on change le corps. */
.suite-page p,
.fiche > p,
.etape p:not([class]),
.micro:not(.tuile-duree):not(.cadre-note):not(.dossier-compte) { max-width: 62ch; }
/* la consigne de dépôt de photo est une phrase, pas une étiquette */
.coachs-mot { max-width: 62ch; }

/* ════ LA LISEUSE ═════════════════════════════════════════════════
   Dans la copie envoyée, les 40 rediffusions gardent leur affiche mais
   pas leur fichier — 6,1 Go ne s'envoient pas. La tuile le dit : une
   commande qui ne mène nulle part sans prévenir, c'est une panne. */
.tuile--absente img { opacity: .5; }
.tuile-absente { position: absolute; inset: auto 6px 6px 6px; text-align: center;
  padding: 4px 6px; background: var(--ecran-fort); color: var(--sourd); }
.tuile--absente .tuile-duree { display: none; }
.vue-absente { display: grid; place-items: center; gap: var(--f4); text-align: center; }
.vue-absente img { max-width: min(100%, 640px); opacity: .6; }
.vue-absente p { max-width: 44ch; color: var(--sourd); }
