/* =====================================================================
   PERMANENCE — la feuille.
   =====================================================================
   Les jetons sont dans themes/permanence/css/tokens.css, et la direction
   y est expliquée. Ici : les composants, dans l'ordre de la page.

   LA RÈGLE DE CE THÈME, en une phrase : ce qu'on vient chercher — les
   horaires, l'adresse, les conditions — se lit AVANT tout récit, et se
   lit en gros.
   ===================================================================== */

/* ---------- 1. Polices auto-hébergées ------------------------------------
   Alegreya Sans porte tout : une humaniste d'origine calligraphique,
   dessinée pour la lecture longue. Sa chasse étroite fait tenir une
   adresse sur une ligne à 390 px — ce qui compte, ici, plus que
   partout ailleurs.

   AUCUNE SERIF, ET C'EST DÉLIBÉRÉ. Une serif de titre donnerait à ce
   site un air de rapport moral. Les trois graisses d'Alegreya Sans
   suffisent à toute la hiérarchie : 300 pour les grands titres, 400 pour
   le texte, 500 pour ce qui doit ressortir. */

@font-face {
  font-family: 'Alegreya Sans'; font-style: normal; font-weight: 300;
  font-display: swap; src: url('../../../assets/fonts/alegreyasans-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya Sans'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('../../../assets/fonts/alegreyasans-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Alegreya Sans'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('../../../assets/fonts/alegreyasans-500.woff2') format('woff2');
}

/* Repli métrique. LE DÉCALAGE DE MISE EN PAGE DE CE SOCLE EST À ZÉRO
   EXACT, et c'est cette règle qui le tient : sans elle, la substitution
   de police au chargement fait sauter chaque ligne de la page. */
@font-face {
  font-family: 'Alegreya Sans repli';
  src: local('Gill Sans'), local('Optima'), local('Helvetica Neue'), local('Arial');
  size-adjust: 96%; ascent-override: 98%; descent-override: 26%; line-gap-override: 0%;
}

/* ---------- 2. Jetons ----------------------------------------------------
   Déclarés dans themes/permanence/css/tokens.css — voir la note en tête. */

/* ---------- 3. Remise à plat --------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  interpolate-size: allow-keywords;
  /* Les deux noms du contrat d'ancrage sont ceux du socle : c'est
     tools/verifier-ancres.mjs qui les cherche, par leur nom. */
  --ancre-air: 14px;
  --ancre-haut: calc(var(--h-entete) + var(--ancre-air));
  scroll-padding-top: var(--ancre-haut);
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--fond);
  color: var(--encre);
  font-family: var(--texte);
  font-size: var(--t-body);
  /* L'INTERLIGNE EST LARGE, ET C'EST LE POINT. 1,72 là où un thème
     ordinaire met 1,55 : c'est ce qui rend un paragraphe abordable pour
     quelqu'un qui lit mal. */
  line-height: 1.8;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body.bloque { overflow: hidden; }

img, picture, svg, video { display: block; max-width: 100%; }
img { height: auto; }
ul, ol { list-style: none; padding: 0; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible { outline: 3px solid var(--ocre); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }
::selection { background: var(--vert); color: var(--encre-clair); }

.evitement {
  position: absolute; left: -9999px; top: 0; z-index: 300;
  background: var(--vert); color: var(--encre-clair);
  padding: 0.7em 1.1em; font-weight: 500;
}
.evitement:focus { left: 0; }

.hors-ecran {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.defs { display: none; }

/* ---------- 4. Rythme et enveloppes --------------------------------------
   LE SÉPARATEUR DE CE THÈME EST LE VIDE, ET IL N'Y EN A PAS D'AUTRE.

   `--section-y` monte ici à 156 px, contre 64 sur le club : c'est plus
   du double, à contenu identique. Ce n'est pas un réglage, c'est la
   direction — une porte ouverte ne se lit pas dans un tableau serré,
   elle se lit lentement, et le blanc autour d'un paragraphe est ce qui
   dit qu'on a le temps.

   Un gris une section sur deux, qu'on posait ici comme ailleurs, coupait
   ce blanc en tranches et rendait la page aussi compacte que les autres.
   Il est retiré. Le seul fond teinté restant est celui du bloc
   d'information encadré, qui est un objet, pas une bande.

   RESTE UNE EXCEPTION, ET ELLE EST NOMMÉE : la fin de page — adhérer,
   donner, aider — passe sur le vert très pâle. Le blanc a porté la
   lecture ; la couleur porte la demande. */

main > .sec--adhesion,
main > .sec--benevoles,
main > .sec--dons { background: var(--vert-pale); }

.sec {
  padding: var(--section-y) var(--gouttiere);
  --ancre-retrait: var(--section-y);
  scroll-margin-top: calc(0px - var(--ancre-retrait));
}
/* L'ACCUEIL EST DÉCRIT EN UN SEUL ENDROIT — partie 9, plus bas.
   Il l'était en deux : ce bloc-ci gardait la toute première version de
   la nuit, qui plaçait le texte avant la photo par `order`, et la partie 9
   déclarait l'inverse. Les deux se contredisaient à chaque rendu, et la
   dernière gagnait — c'est-à-dire que la moitié des règles écrites ici ne
   servaient plus qu'à égarer la relecture. */

.sec__entete { max-width: var(--large); margin: 0 auto clamp(22px, 3vw, 40px); }

/* LE TITRE DE SECTION. Léger — graisse 300 — et grand : un titre gras
   sur un site d'aide a l'air d'un avertissement. */
.sec__titre {
  font-weight: 300;
  font-size: var(--t-h2);
  line-height: 1.2;
  letter-spacing: -0.01em;
  max-width: 22ch;
  text-wrap: balance;
}
.sec__texte { max-width: var(--lecture); color: var(--encre-douce); }
.sec__texte + .sec__texte { margin-top: 0.9em; }
.sec__texte p + p, .corps p + p { margin-top: 0.9em; }

.sec__corps { max-width: var(--large); margin: 0 auto; }

.sec__intitule {
  font-weight: 500; font-size: var(--t-mention);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--vert);
  margin: 2em 0 0.8em;
}
.sec__intitule--passe { color: var(--encre-douce); }
.sec__categorie { font-weight: 500; font-size: var(--t-h3); margin: 1.6em 0 0.7em; }

/* L'AVIS. Encadré, pas coloré : ce thème dit les choses, il n'alarme
   personne. */
.sec__avis {
  max-width: var(--lecture);
  padding: 0.9em 1.1em;
  border: 1px solid var(--trait-fort); border-radius: var(--rayon);
  background: var(--fond);
}

.secours { margin-top: 1.4em; color: var(--encre-douce); font-size: var(--t-petit); }
.lien { color: var(--vert); text-underline-offset: 2px; }
.lien:hover { color: var(--vert-fonce); }

.mention-donnees {
  margin-top: 1em; padding: 0.8em 1em;
  background: var(--fond-creux); border-radius: var(--rayon);
  font-size: var(--t-petit); color: var(--encre-douce);
}
.mention-donnees__texte + .mention-donnees__texte { margin-top: 0.4em; }

h1, h2, h3, h4 { font-weight: 500; line-height: 1.28; }
.ital { font-style: italic; }

.sec__points { display: grid; gap: 0.6em; max-width: var(--lecture); }
.sec__points li { position: relative; padding-left: 1.4em; }
.sec__points li::before {
  content: ""; position: absolute; left: 0; top: 0.62em;
  width: 8px; height: 8px; border-radius: 50%; background: var(--vert);
}

/* ---------- 5. Boutons ---------------------------------------------------
   GRANDS, ET IL Y A UNE RAISON. 50 px de haut au lieu de 44 : ce site
   est ouvert au doigt, dehors, souvent en marchant. Six pixels de plus
   coûtent une ligne de CSS et évitent un appui raté. */

.bouton, .sec__bouton, .menu__action {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 50px; padding: 0.65em 1.4em;
  font-weight: 500; font-size: var(--t-body);
  text-decoration: none; cursor: pointer;
  border: 1px solid var(--vert); border-radius: var(--rayon);
  background: transparent; color: var(--vert);
  transition: background var(--survol) var(--ease), color var(--survol) var(--ease);
}
.bouton:hover, .sec__bouton:hover { background: var(--vert-pale); }

.menu__action, .bouton--action {
  background: var(--vert); border-color: var(--vert); color: var(--encre-clair);
}
.menu__action:hover, .bouton--action:hover {
  background: var(--vert-fonce); border-color: var(--vert-fonce); color: var(--encre-clair);
}

/* ---------- 6. Photos -----------------------------------------------------
   AUCUN EFFET DE COULEUR, ET AUCUN CADRAGE SERRÉ. Les photos d'une
   association d'aide montrent des gens ; un recadrage serré transforme
   une scène ordinaire en portrait de détresse, et ce n'est pas ce
   qu'elle veut dire d'elle. Le 4/3 laisse le contexte. */

.sec__agrandir { display: block; }
.sec__agrandir img { transition: opacity var(--survol) var(--ease); }
.sec__agrandir:hover img { opacity: 0.92; }
figure { margin: 0; }
figcaption { margin-top: 0.45em; font-size: var(--t-mention); color: var(--encre-douce); }

/* ---------- 7. En-tête ---------------------------------------------------- */

.entete {
  position: sticky; top: 0; z-index: 100;
  background: var(--fond);
  border-bottom: 1px solid var(--trait);
}
/* LA BARRE NE PASSE PAS À LA LIGNE. `--ancre-haut` se calcule depuis
   `--h-entete` ; une barre qui s'enroule mesure 100 px là où elle en
   déclare 80, et toutes les ancres déposent alors leur titre sous
   l'en-tête collée. Ce n'était vrai qu'à 900 px de large — la largeur la
   plus serrée où le menu de bureau paraît —, donc invisible à l'essai et
   parfaitement réel. Le menu se serre pour tenir la ligne. */
.entete__barre {
  min-height: var(--h-entete);
  max-width: var(--large); margin: 0 auto;
  padding: 0.4rem var(--gouttiere);
  display: flex; align-items: center; flex-wrap: nowrap; gap: 1rem;
}
/* LE NOM NE SE SERRE JAMAIS, ET LE MENU SE SERRE EN DERNIER.

   La barre tient une ligne — le contrat d'ancre l'exige, voir plus haut.
   Une ligne unique veut dire que quelque chose doit céder quand le menu
   est long, et il faut dire QUOI : sans `flex: none`, c'est le nom de
   l'association qui se comprimait, et il venait toucher la première
   entrée du menu. « L'Écho du PontACCUEIL », collés, sans un pixel entre
   eux. Le nom est ce qu'on ne peut pas abîmer. */
.entete__marque {
  flex: none; min-width: 0;
  display: inline-flex; align-items: center; gap: 0.6rem;
  text-decoration: none; font-weight: 500; font-size: 1.18rem; line-height: 1.15;
}
.entete__embleme { width: 28px; height: 28px; flex: none; color: var(--vert); }

.menu {
  margin-left: auto; min-width: 0;
  display: flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end;
  gap: clamp(0.55rem, 1.1vw, 1.1rem);
}
.menu__liste {
  min-width: 0;
  display: flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end;
  gap: clamp(0.5rem, 1vw, 1rem);
}
.menu__liste a {
  text-decoration: none; font-size: var(--t-petit);
  padding: 0.4em 0; border-bottom: 2px solid transparent; white-space: nowrap;
}
.menu__liste a:hover, .menu__liste a[aria-current] { border-bottom-color: var(--vert); }

/* LE BOUTON DU MENU REPREND SES MARGES, ET IL LUI FAUT DEUX CLASSES POUR
   CELA. « .menu__liste a » ci-dessus pèse plus qu'un « .menu__action »
   seul — une classe et un type contre une classe — et il passe après :
   la marge du bouton était donc écrasée par la sienne, horizontale à
   ZÉRO. Mesuré sur les cinq thèmes : quatorze pixels au-dessus et en
   dessous du texte, UN SEUL à gauche et à droite — les capitales
   touchaient le bord de l'aplat, et la hauteur ne venait même pas de la
   marge mais du « min-height ».
   La marge est maintenant la même sur les quatre côtés. La valeur est
   calculée pour que la hauteur du bouton ne bouge pas : c'est la largeur
   qui prend la différence. */
.menu__liste .menu__action { padding: 0.6em; }

.entete__bascule { display: none; }
.entete__trait2 { display: none; }

@media (max-width: 899px) {
  .entete__bascule {
    display: inline-flex; align-items: center; justify-content: center;
    width: 48px; height: 48px; margin-left: auto;
    background: none; border: 1px solid var(--trait-fort); border-radius: var(--rayon);
    cursor: pointer;
  }
    /* LE BOUTON PORTE DEUX <span>, ET UN SEUL DOIT DESSINER.

     Le gabarit du socle en émet deux — c'est l'héritage d'un burger à
     deux barres qui se croisaient, celui des thèmes hôteliers. Ces
     cinq-ci dessinent leurs trois traits avec UN span et ses deux
     pseudo-éléments ; le second span, visé par la même règle, posait un
     second burger par-dessus le premier et débordait de vingt pixels à
     droite du bouton. Sur les cinq thèmes, à 375 comme à 768.

     `.entete__trait2 { display: none }` plus haut ne suffisait pas :
     `.entete__bascule span` a une spécificité supérieure et gagnait. On
     vise donc le premier, et le second reste caché. */
  .entete__bascule span:first-child { display: block; width: 20px; height: 2px; background: var(--encre); position: relative; }
  .entete__bascule span:first-child::before, .entete__bascule span:first-child::after {
    content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: var(--encre);
    transition: transform 160ms var(--ease), top 160ms var(--ease);
  }
  .entete__bascule span:first-child::before { top: -6px; }
  .entete__bascule span:first-child::after  { top: 6px; }
  .entete[data-ouvert] .entete__bascule span:first-child { background: transparent; }
  .entete[data-ouvert] .entete__bascule span:first-child::before { top: 0; transform: rotate(45deg); }
  .entete[data-ouvert] .entete__bascule span:first-child::after  { top: 0; transform: rotate(-45deg); }

  .menu {
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--fond); border-bottom: 1px solid var(--trait);
    padding: 0 var(--gouttiere) 1.2rem;
    max-height: calc(100dvh - var(--h-entete)); overflow-y: auto;
    transform: translateY(-6px); opacity: 0; visibility: hidden;
    transition: opacity 160ms var(--ease), transform 160ms var(--ease), visibility 160ms;
  }
  .entete[data-ouvert] .menu { transform: none; opacity: 1; visibility: visible; }
  .menu__liste { flex-direction: column; align-items: stretch; gap: 0; }
  .menu__liste a { padding: 0.95em 0; border-bottom: 1px solid var(--trait); font-size: 1.08rem; }
  .menu__action { margin-top: 1.1rem; }
}

/* ---------- 8. Le bandeau d'information -----------------------------------
   VERT PLEIN, EN HAUT DE TOUT. C'est là qu'une association d'aide dit
   « fermé la semaine du 15 août » ou « collecte exceptionnelle
   samedi » — et c'est l'information qui coûte le plus cher à ne pas
   voir. */

.info {
  background: var(--vert); color: var(--encre-clair);
  padding: 0.7em var(--gouttiere);
  font-size: var(--t-petit); text-align: center;
}
.info__mot { display: inline; }
.info__lien { color: var(--encre-clair); text-underline-offset: 3px; margin-left: 0.5em; }

/* ---------- 9. L'accueil — LE TEXTE ET LA PHOTO, EN VIS-À-VIS ------------
   DANS LES MARGES DE LA PAGE, ET AVEC DE L'AIR AU-DESSUS.

   Cet accueil a été composé trois fois cette nuit, et les deux premières
   étaient mauvaises. La leçon de chacune est écrite ici, parce qu'elles
   ne se déduisent pas du résultat.

   1. LE TEXTE SEUL, PUIS LA PHOTO BORNÉE EN DESSOUS. L'intention se
      défendait — « on lit avant de voir » — et le résultat était un
      empilement : un titre, deux boutons, cent cinquante pixels de
      blanc, une photographie flottant au milieu avec du vide de chaque
      côté. Du blanc entre deux blocs qui se répondent les sépare ; du
      blanc autour d'un bloc qui se suffit le met en valeur. L'accueil est
      l'endroit où l'image et le texte DOIVENT se répondre.

   2. LA PHOTO À FOND PERDU À DROITE, collée sous l'en-tête. Elle mordait
      sur la barre de navigation sans marge, et sortait de la colonne où
      TOUT le reste de la page est aligné — la galerie, les activités,
      l'agenda. Une image d'accueil qui ignore la grille de la page ne
      fait pas une ouverture, elle fait une exception.

   CE QUI TIENT : les mêmes marges que le reste de la page, de l'air
   au-dessus pour décoller de l'en-tête, et deux colonnes de même hauteur
   — le texte à gauche, la photo à droite, alignées haut et bas.

   CE QUI LE DISTINGUE DE `plateau`, qui met aussi deux colonnes : là-bas
   l'affiche est en 3/4 sur un fond noir de salle, et le nom est à droite.
   Ici la photo est en paysage sur du blanc, à droite, et le texte tient
   la gauche — donc il se lit toujours en premier.

   SUR TÉLÉPHONE, LA PHOTO PASSE EN PREMIER : en dessous de 900 px il n'y
   a plus de vis-à-vis, et une photographie d'accueil placée sous un écran
   de texte n'accueille personne. L'ordre du DOCUMENT ne bouge pas — un
   lecteur d'écran entend toujours le texte d'abord ; c'est `order` qui
   inverse, et lui seul. */

.sec--hero {
  padding: 0 0 var(--section-y);
  background: var(--fond) !important;
  --ancre-retrait: 0px;
  display: flex; flex-direction: column;
}
.sec--hero__media { order: 1; }
.sec--hero__texte { order: 2; }

.sec--hero__texte {
  /* `width: 100%` N'EST PAS REDONDANT AVEC `margin: 0 auto`, IL LE
     RÉPARE. Sur un enfant de conteneur FLEX, une marge automatique
     absorbe tout l'espace libre de la ligne — et absorber l'espace libre,
     c'est précisément ce qui empêche l'étirement. L'élément retombe alors
     sur la largeur de son contenu et se centre dedans : mesuré à 436 px
     de large avec 132 px de marge de chaque côté sur une fenêtre de 700,
     alors que la photo juste au-dessus allait de bord à bord.
     En déclarant la largeur, il ne reste plus d'espace libre à absorber,
     et `auto` redevient ce qu'on lui demandait : un centrage, utile
     seulement au-delà de 1160 px. */
  width: 100%;
  max-width: var(--large);
  margin: 0 auto;
  padding: clamp(28px, 5vw, 48px) var(--gouttiere) 0;
}
.sec--hero--sobre .sec--hero__texte { padding-top: clamp(52px, 9vw, 128px); }

.sec--hero__surtitre {
  font-weight: 500; font-size: var(--t-mention);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--vert);
  margin-bottom: 0.9em;
}
.sec--hero__titre {
  font-weight: 300;
  font-size: var(--t-display);
  line-height: 1.1; letter-spacing: -0.015em;
  max-width: 17ch; text-wrap: balance;
}
.sec--hero__soustitre {
  margin-top: 0.7em; font-size: var(--t-lead);
  color: var(--encre-douce); max-width: 34ch;
}
.sec--hero__intro { margin-top: 1.2em; max-width: 36ch; }
.sec--hero__intro + .sec--hero__intro { margin-top: 0.9em; }
.sec--hero__actions { margin-top: 1.8em; display: flex; flex-wrap: wrap; gap: 0.8em; }

.sec--hero__media {
  width: 100%;
  max-width: calc(var(--large) - 2 * var(--gouttiere));
  margin: clamp(20px, 3vw, 32px) auto 0;
  aspect-ratio: 3 / 2; overflow: hidden;
}
.sec--hero__media img {
  width: 100%; height: 100%; object-fit: cover; border-radius: var(--rayon);
}

@media (min-width: 900px) {
  /* LA SECTION DEVIENT LA GRILLE, bornée à la largeur de page comme tout
     le reste. `align-items: stretch` — la valeur par défaut, rappelée ici
     parce que c'est elle qui fait descendre la photo jusqu'au bas du
     texte : sans elle la figure garde sa hauteur propre et laisse un vide
     blanc sous elle, ce qui était le défaut de la version précédente. */
  .sec--hero {
    display: grid;
    /* LA PHOTO PREND PLUS DE PLACE QUE LE TEXTE, ET CELA NE COÛTE RIEN
       À LA HAUTEUR. Le partage était de moitié-moitié ; il est
       maintenant de 37/63 en faveur de l'image.

       Ce qui rend l'opération gratuite : le contenu du bloc de texte est
       déjà borné en SIGNES et non par sa colonne — le titre à 17 ch, le
       sous-titre à 34, les paragraphes à 36. À 18 px, cela fait environ
       320 px de texte réellement occupés. Tant que la colonne reste plus
       large que ça, la resserrer ne rajoute pas une seule ligne, donc
       n'ajoute pas un pixel de hauteur. Le `minmax(340px, …)` garde cette
       promesse : en dessous, le texte se remettrait à couler. */
    grid-template-columns: minmax(340px, 0.58fr) minmax(0, 1fr);
    align-items: stretch;
    column-gap: clamp(28px, 4vw, 56px);
    /* LA MÊME COLONNE QUE TOUT LE RESTE DE LA PAGE, ET C'EST MESURÉ.
       Les sections ont `padding: … var(--gouttiere)` PUIS leur contenu
       borné à `--large` : sur 1440 px, la galerie commence donc à 140.
       En donnant au hero une gouttière EN PLUS de sa largeur maximale,
       il commençait à 212 — soixante-douze pixels plus à droite que tout
       ce qui le suit. La largeur maximale suffit : le centrage fait le
       reste, et les deux colonnes tombent au même endroit. */
    /* LA GOUTTIÈRE EST RENDUE, ET LA LARGEUR MAXIMALE LA COMPENSE.
       Elle avait été retirée pour aligner le hero sur la galerie — et
       c'était juste à 1440, faux en dessous : entre 900 et 1160 px de
       fenêtre, `max-width` ne mordait plus, il n'y avait donc plus rien
       pour écarter le texte du bord, et il s'y collait. Mesuré à 900 et
       à 1100 : x = 0.

       En bornant à `--large PLUS deux gouttières`, la boîte reprend une
       marge à toutes les largeurs, et son CONTENU tombe exactement où
       tombe celui des autres sections — qui font, elles, `padding:
       gouttière` puis contenu borné à `--large`. Vérifié : 140 px à
       1440, 380 à 1920, la gouttière en dessous de 1304. */
    max-width: calc(var(--large) + 2 * var(--gouttiere));
    margin: 0 auto;
    padding: clamp(32px, 4.5vw, 64px) var(--gouttiere) var(--section-y);
  }
  .sec--hero__texte {
    order: 1; grid-column: 1;
    max-width: none; margin: 0; padding: 0;
    align-self: center;
  }
  .sec--hero__media {
    order: 2; grid-column: 2;
    max-width: none; margin: 0;
    /* Le rapport cède : c'est la colonne de texte qui décide de la
       hauteur, et la photo la remplit. Un minimum garde une ouverture
       présentable quand le texte est court. */
    aspect-ratio: auto;
    min-height: clamp(320px, 42vh, 460px);
    height: 100%;
  }
  /* LA HAUTEUR DOIT TRAVERSER TOUTE LA CHAÎNE, et c'est le piège.
     `pic_agrandissable()` emboîte figure > a > picture > img : poser
     `height: 100%` sur l'image seule ne sert à rien, parce que le lien et
     le <picture> entre les deux n'ont, eux, aucune hauteur à remplir.
     L'image retombait donc sur son rapport naturel et s'arrêtait deux
     cents pixels au-dessus du bas du texte. C'est le même emboîtement que
     la galerie, qui déclare déjà les trois maillons. */
  .sec--hero__media .sec__agrandir,
  .sec--hero__media picture { display: block; height: 100%; }
  .sec--hero--sobre { display: block; }
  .sec--hero--sobre .sec--hero__texte {
    max-width: var(--large); margin: 0 auto;
    padding: clamp(52px, 9vw, 128px) var(--gouttiere) 0;
  }
}

/* LA PROSE EN DEUX COLONNES, ET LA MENTION EN NOTE.

   Le corps de cette section tenait dans une colonne de 34 rem sur une
   page de 960 : un tiers de la largeur restait vide à droite, sur toute
   la hauteur du texte. Élargir la colonne aurait allongé la ligne
   au-delà de ce qui se relit bien — c'est le thème de la lecture, on ne
   lui fait pas ça. Deux colonnes occupent la largeur SANS toucher à la
   longueur de ligne, et c'est ce que fait la presse depuis toujours.

   `break-inside: avoid` empêche qu'un paragraphe se coupe d'une colonne
   à l'autre : une phrase qui saute par-dessus la gouttière se relit deux
   fois. Et en dessous de 700 px, une seule colonne — deux colonnes de
   quarante signes ne sont plus de la lecture. */
.sec--association .sec__prose { max-width: var(--large); }
.sec--association .sec__prose .sec__texte { max-width: none; }
.sec--association .sec__prose .sec__texte + .sec__texte { margin-top: 1em; }

@media (min-width: 700px) {
  .sec--association .sec__prose {
    columns: 2;
    column-gap: clamp(32px, 5vw, 72px);
  }
  .sec--association .sec__prose .sec__texte {
    break-inside: avoid;
    /* Le premier paragraphe de la seconde colonne ne doit pas hériter de
       la marge haute qui le séparait du précédent dans la première. */
    margin-top: 0;
  }
  .sec--association .sec__prose .sec__texte + .sec__texte { margin-top: 1em; }
}

/* LA MENTION. Une note de bas de page : petite, grise, détachée, et hors
   des colonnes — dans la prose, elle tombait au pied de l'une des deux
   et se lisait comme la suite du propos. */
.sec__mention {
  margin-top: 1.6em;
  max-width: var(--lecture);
  font-size: var(--t-petit);
  font-style: italic;
  color: var(--encre-douce);
}

/* LE CHAPÔ PREND TOUTE LA LARGEUR DE PAGE, hors marges, ET TIENT SUR UNE
   LIGNE.

   Il sort en `.sec__intro` et non en `.sec__texte` — c'est ce qui avait
   fait échouer la première tentative, qui visait la mauvaise classe et
   n'a donc rien changé du tout.

   Une phrase d'annonce n'est pas un paragraphe de lecture : la borner à
   la colonne de 34 rem la cassait en deux lignes courtes au-dessus de
   deux colonnes qui, elles, vont jusqu'au bord — le chapô flottait dans
   son coin. Il couvre maintenant la même largeur que ce qu'il annonce.
   C'est aussi la raison pour laquelle la page de ce thème est passée de
   960 à 1160 px : à 960, cette phrase-là ne tenait pas sur une ligne à
   une taille lisible. */
.sec--association .sec__entete .sec__intro {
  max-width: none;
  /* `pretty` évite qu'un mot seul finisse la dernière ligne ; il ne
     force pas la ligne unique, c'est la largeur de page qui la permet. */
  text-wrap: pretty;
}

/* LES ACCENTS DU TEXTE. Le gras porte ce qui fait la position de
   l'association — « on vend, on ne donne pas » —, l'italique porte
   l'opposition qu'elle nomme. Les deux sont rares : trois accents dans
   toute la section. Un texte où tout est important n'a plus rien
   d'important. */
.sec__prose strong { font-weight: 500; color: var(--encre); }
.sec__prose em { font-style: italic; }

/* ---------- 10. L'association --------------------------------------------
   LES CHIFFRES CLÉS DANS DES CADRES. Ce sont les seuls chiffres d'une
   association d'aide qui aient le droit d'être gros : combien de
   familles, combien de bénévoles, depuis quand. Ils disent la mesure de
   ce qui se fait, pas une performance. */

.sec--association .sec__corps { display: grid; gap: clamp(22px, 3vw, 44px); }

.sec__chiffres {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
}
.sec__chiffres > * {
  padding: 1.1rem 1.2rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
  background: var(--fond);
}
.sec__chiffres dt, .sec__chiffres .valeur {
  font-size: var(--t-nombre); font-weight: 500; line-height: 1;
  letter-spacing: -0.02em; color: var(--vert);
  font-variant-numeric: tabular-nums;
}
.sec__chiffres dd, .sec__chiffres .mot {
  margin: 0.45rem 0 0; font-size: var(--t-petit); color: var(--encre-douce); line-height: 1.4;
}
/* LA CELLULE D'UN CHIFFRE — le couple « nombre + mot », enveloppé par le
   gabarit du socle depuis qu'un « 31 » s'est retrouvé en fin de ligne et
   son « bénévoles » seul à la ligne suivante. La grille place ce
   conteneur ; elle ne peut plus séparer ce qu'il contient.
   La règle est nommée, et pas seulement héritée d'un `> *` :
   tools/verifier-styles.php exige qu'une classe émise soit visée. */
.sec__chiffres .chiffre { min-width: 0; }


/* DEUX COLONNES INÉGALES — la grande à gauche, les deux autres empilées
   à droite. Les quatre autres thèmes posent la grande AU-DESSUS ; ici
   elle est À CÔTÉ, et la composition tient sur une seule hauteur au lieu
   de deux. Sur le thème le plus aéré du socle, c'est ce qui évite qu'une
   section de photos occupe deux écrans à elle seule.

   Les formats sont ceux des sources — 3/2 et 4/3 — pour ne rien
   recadrer : ce thème montre des lieux où l'on entre, et le bord d'une
   photo de lieu porte l'information. */
.sec__medias {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(14px, 2vw, 24px);
}
.sec__medias img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--rayon); }
.sec__medias li:first-child img { aspect-ratio: 3 / 2; }
@media (min-width: 760px) {
  .sec__medias { grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr); }
  .sec__medias li:first-child { grid-column: 1; grid-row: 1 / span 2; }
  .sec__medias li:first-child img { aspect-ratio: 4 / 5; height: 100%; }
}
/* ---------- 11. Les activités — UN BLOC PLEINE LARGEUR PAR ACTIVITÉ ------
   AUCUNE COLONNE, ET C'EST LE PARTI PRIS.

   Les cinq thèmes posaient ici la même grille de cartes de 260 à 300 px.
   Celui-ci n'en pose plus du tout : une activité occupe toute la
   largeur, sa photo en tête, son texte dans la colonne de lecture, et
   la suivante arrive bien plus bas. Deux activités ne se regardent
   jamais côte à côte.

   C'est cohérent avec tout le reste du thème — c'est le plus aéré des
   cinq, 156 px entre deux sections, corps à 18 px. Une grille de cartes
   serrées au milieu d'une page qui respire aurait été le seul endroit
   dense du site, et on l'aurait vu.

   PAS DE GABARIT DE THÈME ICI, et c'est délibéré : une seule colonne
   veut dire aucune rangée partagée entre deux colonnes, donc aucun des
   défauts d'alignement qui obligent `club`, `plateau` et `tribune` à
   écrire le leur. Le balisage du socle suffit, et c'est autant de copie
   en moins à maintenir. */

.sec__grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(48px, 7vw, 104px);
  max-width: var(--large);
  margin: 0 auto;
}

.carte {
  background: transparent;
  border: 0; border-radius: 0; overflow: visible;
  display: flex; flex-direction: column; gap: 0.55rem;
  scroll-margin-top: var(--ancre-air);
}
.carte__photo { margin-bottom: 0.5rem; }
/* UNE BANDE, PAS UN PAVÉ. En 16/9 sur une page de 960 px, chaque photo
   faisait 540 px de haut ; à quatre activités, cela mettait deux mille
   pixels de photographie dans une seule section, et le thème le plus
   aéré du socle devenait le plus long à parcourir. L'air doit être
   autour du texte, pas dans les images. */
.carte__photo img { width: 100%; aspect-ratio: 21 / 9; object-fit: cover; border-radius: var(--rayon); }
@media (max-width: 599px) { .carte__photo img { aspect-ratio: 3 / 2; } }

.carte__nom { font-size: var(--t-h2); font-weight: 300; line-height: 1.2; letter-spacing: -0.01em; }
.carte__accroche { color: var(--vert); font-weight: 500; }
.carte__resume, .carte__texte { color: var(--encre-douce); max-width: var(--lecture); }
.carte__texte + .carte__texte { margin-top: 0.2rem; }
.carte__type, .carte__depuis, .carte__categorie { font-size: var(--t-petit); color: var(--encre-douce); }
.carte__intitule {
  font-size: var(--t-mention); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--vert); font-weight: 500; margin-top: 0.7rem;
}

/* LES HORAIRES EN TÊTE, ENCADRÉS. C'est l'information numéro un d'un
   lieu où l'on passe sans rendez-vous, et le seul bloc coloré de la
   fiche. */
.carte__faits {
  display: flex; flex-wrap: wrap; gap: 0.3em 1.4em;
  background: var(--vert-pale);
  border-radius: var(--rayon);
  padding: 0.7em 0.9em;
  max-width: var(--lecture);
  font-size: var(--t-petit);
  order: -1;
}
.carte__equipements {
  display: flex; flex-wrap: wrap; gap: 0.25em 1.2em;
  font-size: var(--t-petit); color: var(--encre-douce);
}
.carte__equipements li { position: relative; padding-left: 1em; }
.carte__equipements li::before {
  content: ""; position: absolute; left: 0; top: 0.5em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--vert);
}
.carte__prix {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.5rem;
  margin-top: 0.3rem;
}
.carte__montant { font-size: var(--t-nombre); font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums; white-space: nowrap; }
.carte__mention { font-size: var(--t-petit); color: var(--encre-douce); }
.carte__action { margin-top: 0.5rem; }

/* DEUX COLONNES FRANCHES pour les autres vues : ce thème montre peu de
   photos et les montre grandes, comme sa galerie. */
.carte__vues {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px;
  max-width: var(--lecture);
}
.carte__vues img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--rayon); }
.carte__vues figcaption { font-size: var(--t-petit); color: var(--encre-douce); margin-top: 0.3em; }

/* PAS DE SECONDE COLONNE, MÊME SUR GRAND ÉCRAN — et j'ai failli en
   remettre une. Passer la photo à côté du texte demanderait de la faire
   couvrir toutes les rangées (`grid-row: 1 / span 30`), et une grille
   compte l'écart de CHAQUE rangée couverte, vides comprises : deux cent
   cinquante pixels de blanc fantôme en bas de chaque fiche. C'est
   exactement le défaut relevé sur `club`, et le contourner demanderait
   d'écrire ici un gabarit de thème.

   On ne le fait pas, parce qu'on n'en veut pas : ce thème a annoncé
   qu'une activité occupe toute la largeur et que deux activités ne se
   regardent jamais côte à côte. Une seule colonne, c'est aussi zéro
   rangée partagée — donc aucun de ces défauts, et aucune copie de
   gabarit à maintenir. */

/* ---------- 12. Les appels du moment --------------------------------------
   « Ce dont on a besoin maintenant » : trois rayons vides, dix couvertures,
   un chauffeur le mardi. Encadré ocre — la seule couleur d'urgence de ce
   thème, et elle ne sert qu'ici. */

.appels { display: grid; gap: clamp(14px, 2vw, 24px); max-width: var(--large); margin: 0 auto; }
.appel {
  display: grid;
  border: 1px solid var(--ocre); border-radius: var(--rayon);
  background: var(--fond); overflow: hidden;
}
@media (min-width: 760px) {
  .appel { grid-template-columns: minmax(0, 280px) minmax(0, 1fr); }
  .appel__photo { grid-row: 1 / span 6; }
}
.appel__photo img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.appel__nom { padding: 1rem 1.1rem 0; font-size: var(--t-h3); font-weight: 500; }
.appel__accroche { padding: 0.2rem 1.1rem 0; color: var(--ocre); font-weight: 500; font-size: var(--t-petit); }
.appel__mots { padding: 0.6rem 1.1rem 0; color: var(--encre-douce); }
.appel__chiffre { padding: 0.8rem 1.1rem 0; display: flex; align-items: baseline; gap: 0.5rem; }
.appel__nombre {
  font-size: var(--t-nombre); font-weight: 500; line-height: 1;
  color: var(--ocre); font-variant-numeric: tabular-nums;
}
.appel__mention { font-size: var(--t-petit); color: var(--encre-douce); }
.appel__validite { padding: 0.6rem 1.1rem 0; font-size: var(--t-mention); letter-spacing: 0.08em; text-transform: uppercase; color: var(--encre-douce); }
.appel__action { padding: 0.9rem 1.1rem 1.1rem; }

/* ---------- 13. L'agenda --------------------------------------------------- */

.sec--evenements .sec__corps { max-width: var(--large); }
.agenda__liste { display: grid; gap: 10px; }
.evenement {
  display: grid; gap: 0.2rem 1.2rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
}
@media (min-width: 700px) {
  .evenement { grid-template-columns: minmax(0, 12rem) minmax(0, 1fr) auto; align-items: baseline; }
  /* Chaque morceau dit sa colonne : le lien arrive en dernier dans le
     balisage et prendrait sinon la case de la date. */
  .evenement__quand     { grid-column: 1; grid-row: 1; }
  .evenement__lieu      { grid-column: 1; grid-row: 2; }
  .evenement__nom       { grid-column: 2; grid-row: 1; }
  .evenement__texte     { grid-column: 2; }
  .evenement__categorie { grid-column: 3; grid-row: 1; text-align: right; }
  .evenement__action    { grid-column: 3; grid-row: 2; text-align: right; }
}
.evenement__quand { font-weight: 500; color: var(--vert); font-variant-numeric: tabular-nums; }
.evenement__nom { font-size: var(--t-h3); font-weight: 500; }
.evenement__lieu, .evenement__categorie, .evenement__texte { font-size: var(--t-petit); color: var(--encre-douce); }
.agenda__liste--passe .evenement { opacity: 0.7; }
.agenda__vide { color: var(--encre-douce); padding: 1rem 0; }

/* ---------- 14. Les actualités -------------------------------------------- */

.actus { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: clamp(14px, 2vw, 24px); max-width: var(--large); margin: 0 auto; }
.actu { border: 1px solid var(--trait); border-radius: var(--rayon); overflow: hidden; display: flex; flex-direction: column; }
.actu__photo img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.actu__date { padding: 0.9rem 1.1rem 0; font-size: var(--t-mention); letter-spacing: 0.08em; text-transform: uppercase; color: var(--vert); }
.actu__nom { padding: 0.2rem 1.1rem 0; font-size: var(--t-h3); font-weight: 500; }
.actu__mots { padding: 0.5rem 1.1rem 0; color: var(--encre-douce); }
.actu__action { padding: 0.9rem 1.1rem 1.1rem; margin-top: auto; }

/* ---------- 15. La galerie ------------------------------------------------ */

/* LA GALERIE A UN NOMBRE DE COLONNES CHOISI, PAS CALCULÉ.

   Elle tenait un `repeat(auto-fill, minmax(...))`, et c'était faux deux
   fois. `auto-fill` fabrique toutes les colonnes que la largeur permet
   PUIS y range ce qu'il y a : une série de trois photos dans une grille
   qui en tient sept sortait en trois vignettes minuscules serrées à
   gauche, avec quatre colonnes de vide à droite. Et comme le gabarit
   découpe la galerie en séries titrées dès qu'il y a des catégories, le
   cas n'était pas rare, c'était le cas COURANT.

   `auto-fit` réparait l'orphelin et en fabriquait un autre : les
   colonnes vides se replient, donc une série de deux photos les affiche
   à 586 px quand une série de quatre les affiche à 289. La taille d'une
   vignette dépendait du nombre de photos de sa catégorie, c'est-à-dire
   de rien.

   Un nombre FRANC de colonnes règle les deux : toutes les vignettes de
   la page ont la même taille, et une série courte laisse un vide en fin
   de ligne — ce qui se lit comme une ligne incomplète, pas comme une
   erreur. C'est aussi une décision de thème : chacun choisit sa trame et
   son cadrage, et c'est ce qui distingue une planche contact d'un mur
   d'affiches. */
/* Trois colonnes seulement, seize pixels d'écart, cadrage en 4/3. Ce thème
   montre PEU de photos et il les montre GRANDES : c'est le thème le plus
   aéré du socle, une planche contact le contredirait. */
.galerie-mosaique {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px; max-width: var(--large); margin: 0 auto;
}
@media (min-width: 640px)  { .galerie-mosaique { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .galerie-mosaique { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Le rapport se pose sur la case, pas sur la photo : « aspect-ratio »
   sur un <img> qui porte ses attributs se fait doubler par le rapport
   intrinsèque du fichier dans WebKit. */
.galerie-mosaique > li { aspect-ratio: 4 / 3; }
.galerie-mosaique > li > figure,
.galerie-mosaique .sec__agrandir,
.galerie-mosaique picture { display: block; height: 100%; }
.galerie-mosaique img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--rayon); }
.galerie-mosaique figcaption { display: none; }
.sec--gallery__couverture { margin-bottom: 12px; }
.sec--gallery__couverture img { width: 100%; aspect-ratio: 21 / 9; object-fit: cover; border-radius: var(--rayon); }

/* ---------- 16. Les services ---------------------------------------------- */

.sec__services { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 12px; max-width: var(--large); margin: 0 auto; }
/* LE PICTOGRAMME EST FACULTATIF, ET LA GRILLE DOIT LE SAVOIR.
   Le gabarit ne l'émet que si une icône est choisie ; sans lui, le nom
   tombe dans la PREMIÈRE colonne, qui est en « auto » — donc à la
   largeur de son contenu, donc sans rétrécissement possible. Une
   mission un peu longue débordait alors de sa carte, et la page avec.
   Chaque morceau déclare donc sa colonne, et la colonne de texte
   déclare qu'elle peut rétrécir. */
.sec__services > li {
  display: grid; grid-template-columns: 1.5em minmax(0, 1fr); gap: 0.25em 0.8em;
  padding: 1rem 1.1rem; border: 1px solid var(--trait); border-radius: var(--rayon);
}
.service__pictogramme { width: 1.5em; height: 1.5em; grid-column: 1; grid-row: 1 / span 2; color: var(--vert); }
.service__nom { grid-column: 2; min-width: 0; font-weight: 500; overflow-wrap: anywhere; }
.service__detail { grid-column: 2; min-width: 0; font-size: var(--t-petit); color: var(--encre-douce); overflow-wrap: anywhere; }

/* ---------- 17. Les ateliers ---------------------------------------------- */

.ateliers { display: grid; gap: clamp(14px, 2vw, 24px); max-width: var(--large); margin: 0 auto; }
.atelier { display: grid; border: 1px solid var(--trait); border-radius: var(--rayon); overflow: hidden; }
@media (min-width: 760px) {
  .atelier { grid-template-columns: minmax(0, 280px) minmax(0, 1fr); }
  .atelier__photo { grid-row: 1 / span 8; }
}
.atelier__photo img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.atelier__nom { padding: 1rem 1.1rem 0; font-size: var(--t-h3); font-weight: 500; }
.atelier__pour, .atelier__categorie { padding: 0.2rem 1.1rem 0; color: var(--vert); font-weight: 500; font-size: var(--t-petit); }
.atelier__mots { padding: 0.6rem 1.1rem 0; color: var(--encre-douce); }
.atelier__intitule { padding: 0.8rem 1.1rem 0.2rem; font-size: var(--t-mention); letter-spacing: 0.09em; text-transform: uppercase; color: var(--encre-douce); font-weight: 500; }
.atelier__suite { padding: 0 1.1rem; display: grid; gap: 0.3em; font-size: var(--t-petit); color: var(--encre-douce); }
.atelier__suite li { position: relative; padding-left: 0.9em; }
.atelier__suite li::before { content: "·"; position: absolute; left: 0.1em; }
.atelier__prix { padding: 0.9rem 1.1rem 1.1rem; display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap; }
.atelier__montant { font-size: var(--t-h3); font-weight: 500; color: var(--vert); font-variant-numeric: tabular-nums; }
.atelier__mention, .atelier__compte, .atelier__releve { font-size: var(--t-petit); color: var(--encre-douce); }
.atelier__compte { padding: 0 1.1rem 0.8rem; }
.atelier__releve { padding: 0 1.1rem 0.8rem; }
.atelier__groupe { padding: 0 1.1rem; }
.atelier__serie, .atelier__vues { padding: 0 1.1rem 0.9rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 6px; }
.atelier__vues img, .atelier__serie img { aspect-ratio: 1; object-fit: cover; border-radius: var(--rayon); }

/* ---------- 18. Les informations pratiques --------------------------------
   DÉPLIÉES PAR DÉFAUT ? NON — mais grandes, et avec une cible de 52 px.
   Ce sont les questions qu'on n'ose pas poser : « faut-il être adhérent »,
   « qu'est-ce que je dois apporter », « est-ce que c'est pour moi ». */

.sec__rubriques { max-width: var(--lecture); margin: 0 auto; border-top: 1px solid var(--trait); }
.rubrique { border-bottom: 1px solid var(--trait); }
.rubrique__ligne {
  display: flex; align-items: center; justify-content: space-between; gap: 1em;
  padding: 1.05em 0; min-height: 52px; cursor: pointer; list-style: none;
}
.rubrique__ligne::-webkit-details-marker { display: none; }
.rubrique__nom { font-weight: 500; font-size: var(--t-body); }
.rubrique__ligne::after {
  content: ""; flex: none; width: 14px; height: 14px;
  background:
    linear-gradient(var(--vert), var(--vert)) center / 100% 2px no-repeat,
    linear-gradient(var(--vert), var(--vert)) center / 2px 100% no-repeat;
}
.rubrique[open] .rubrique__ligne::after {
  background: linear-gradient(var(--vert), var(--vert)) center / 100% 2px no-repeat;
}
.rubrique__detail { padding-bottom: 1.2em; color: var(--encre-douce); }

/* ---------- 19. Le mot de la présidence ----------------------------------- */

.sec--about .sec__corps { display: grid; gap: clamp(22px, 3vw, 44px); }
/* LE PORTRAIT EST ROND. C'est le seul geste rond de ce thème, et il ne
   sert qu'aux VISAGES : un carré fait une photo d'identité, un rond fait
   quelqu'un. */
.sec--about__portrait { max-width: 240px; }
.sec--about__portrait img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 50%; }
.sec--about__portrait .sec__agrandir { border-radius: 50%; overflow: hidden; }
.sec--about__signature { color: var(--vert); font-weight: 500; }
.sec--about__histoire { max-width: var(--lecture); color: var(--encre-douce); }
@media (min-width: 900px) {
  .sec--about .sec__corps { grid-template-columns: auto minmax(0, 1fr); column-gap: clamp(26px, 3.5vw, 52px); align-items: start; }
  .sec--about__portrait { grid-row: 1 / span 4; width: 200px; }
}

/* ---------- 20. Le bureau -------------------------------------------------- */

.bureau { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(160px, 45%), 1fr)); gap: clamp(18px, 2.4vw, 32px); max-width: var(--large); margin: 0 auto; }
.membre__photo img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 50%; }
.membre__nom { font-weight: 500; margin-top: 0.6em; }
.membre__role { font-size: var(--t-petit); color: var(--vert); }
.membre__depuis { font-size: var(--t-mention); color: var(--encre-douce); }

/* ---------- 21. Les témoignages ------------------------------------------- */

.sec__temoignages { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); gap: clamp(14px, 2vw, 24px); max-width: var(--large); margin: 0 auto; }
.temoignage { padding: 1.1rem 1.2rem; border: 1px solid var(--trait); border-radius: var(--rayon); background: var(--fond); }
.temoignage__texte p::before { content: "\00AB\00A0"; }
.temoignage__texte p::after { content: "\00A0\00BB"; }
.temoignage__auteur { margin-top: 0.8em; font-weight: 500; }
.temoignage__qualite, .temoignage__source, .temoignage__date { font-size: var(--t-petit); color: var(--encre-douce); }
.temoignage__photo img { width: 48px; height: 48px; object-fit: cover; border-radius: 50%; margin-bottom: 0.6em; }

/* ---------- 22. Les documents --------------------------------------------- */

.documents { max-width: var(--large); margin: 0 auto; display: grid; gap: 10px; }
.document { display: grid; gap: 0.2rem 1rem; padding: 0.9rem 1.1rem; border: 1px solid var(--trait); border-radius: var(--rayon); }
@media (min-width: 700px) { .document { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; } }
.document__nom { font-weight: 500; }
.document__nature, .document__faits { font-size: var(--t-petit); color: var(--encre-douce); }

/* ---------- 23. L'accès ----------------------------------------------------
   ENCADRÉ, ET EN GRAND. L'adresse et les horaires sont l'information la
   plus consultée de tout le site : ils sont posés dans un cadre vert
   pâle, en corps de lecture, avec des repères d'accès en dessous. */

.sec--access .sec__corps { display: grid; gap: 1.2em; max-width: var(--lecture); }
.sec--access__adresse {
  font-size: var(--t-lead); font-weight: 500;
  padding: 1rem 1.2rem; background: var(--fond-creux); border-radius: var(--rayon);
}
.sec--access__reperes { display: grid; gap: 0.9em; }
.sec--access__reperes dt { font-weight: 500; color: var(--vert); }
.sec--access__reperes dd { margin: 0.15em 0 0; color: var(--encre-douce); }
.sec--access__carte { margin-top: 0.4em; }

/* ---------- 24. Adhérer ----------------------------------------------------
   LE BARÈME EN CADRES, ET LE MONTANT LIBRE ASSUMÉ. Beaucoup
   d'associations d'aide ont une adhésion à montant libre : le cadre doit
   rester lisible même quand il n'y a pas de chiffre à montrer. */

.formules { max-width: var(--large); margin: 0 auto 2rem; display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); }
.formule { padding: 1.1rem 1.2rem; border: 1px solid var(--trait); border-radius: var(--rayon); }
.formule__nom { font-size: var(--t-h3); font-weight: 500; }
.formule__mention { color: var(--vert); font-weight: 500; margin-top: 0.15em; }
.formule__texte { color: var(--encre-douce); font-size: var(--t-petit); margin-top: 0.4em; }

.formulaire { max-width: 44rem; }
.champs { display: grid; gap: 1rem; }
@media (min-width: 700px) { .champs { grid-template-columns: 1fr 1fr; } }
.champ { display: grid; gap: 0.3em; grid-column: 1 / -1; }
.champ--moitie { grid-column: span 1; }
@media (max-width: 699px) { .champ--moitie { grid-column: 1 / -1; } }
.etiquette { font-weight: 500; }
.etiquette__note { font-weight: 400; color: var(--encre-douce); }

.controle {
  width: 100%; min-height: 50px; padding: 0.6em 0.8em;
  background: var(--fond); color: var(--encre);
  border: 1px solid var(--trait-champ); border-radius: var(--rayon);
  font-size: var(--t-body);
}
.controle--zone { min-height: auto; resize: vertical; }
.controle:focus-visible { outline: 3px solid var(--ocre); outline-offset: 0; border-color: var(--ocre); }
.controle[aria-invalid="true"] { border-color: var(--alerte); border-width: 2px; }

.champ--case { grid-template-columns: auto minmax(0, 1fr); align-items: start; gap: 0.7rem; }
.case { width: 26px; height: 26px; margin-top: 2px; accent-color: var(--vert); }
.case__etiquette { color: var(--encre-douce); }
.champ--case .erreur { grid-column: 2; }

.erreur { color: var(--alerte); font-size: var(--t-petit); }
.erreur--visible { min-height: 1.3em; }
.indication { font-size: var(--t-petit); color: var(--encre-douce); }
.indication--visible { display: block; }
.appat { position: absolute; left: -9999px; }
.envoi { margin-top: 1.3rem; }

.confirme { padding: 1.2rem 1.3rem; border: 1px solid var(--oui); border-radius: var(--rayon); background: var(--fond-creux); }
.confirme__titre { font-size: var(--t-h3); font-weight: 500; }
.confirme__actions { margin-top: 1em; display: flex; flex-wrap: wrap; gap: 0.8em; }

/* ---------- 25. Les bénévoles --------------------------------------------- */

.missions { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 12px; max-width: var(--large); margin: 1.5rem auto; }
.mission {
  display: grid; grid-template-columns: 1.5em minmax(0, 1fr); gap: 0.25em 0.8em;
  padding: 1rem 1.1rem; border: 1px solid var(--trait); border-radius: var(--rayon);
}
.mission__pictogramme { width: 1.5em; height: 1.5em; grid-column: 1; grid-row: 1 / span 2; color: var(--vert); }
.mission__nom { grid-column: 2; min-width: 0; font-weight: 500; overflow-wrap: anywhere; }
.mission__detail { grid-column: 2; min-width: 0; font-size: var(--t-petit); color: var(--encre-douce); overflow-wrap: anywhere; }

/* ---------- 26. Les dons ---------------------------------------------------
   « 30 € financent une sortie » : le chiffre en ocre, la phrase dessous,
   dans un cadre. C'est un engagement, et un engagement se cadre. */

.dons__emplois { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr)); gap: 12px; margin: 1.5rem 0; }
.dons__emplois > * { padding: 1.1rem 1.2rem; border: 1px solid var(--ocre); border-radius: var(--rayon); }
.dons__emplois dt { font-size: var(--t-nombre); font-weight: 500; line-height: 1; color: var(--ocre); font-variant-numeric: tabular-nums; }
.dons__emplois dd { margin: 0.45rem 0 0; font-size: var(--t-petit); color: var(--encre-douce); line-height: 1.45; }
/* LE COUPLE « montant + phrase », enveloppé par le gabarit du socle :
   la grille place ce conteneur, elle ne peut plus séparer ce qu'il
   contient. Règle nommée, et pas seulement héritée du `> *` :
   tools/verifier-styles.php exige qu'une classe émise soit visée. */
.dons__emplois .emploi { min-width: 0; }

/* ---------- 27. Le pied de page ------------------------------------------- */

.pied {
  border-top: 1px solid var(--trait);
  background: var(--fond-bande);
  padding: clamp(30px, 4vw, 52px) var(--gouttiere);
  font-size: var(--t-petit);
}
.pied__grille { max-width: var(--large); margin: 0 auto; display: grid; gap: clamp(20px, 3vw, 38px); grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr)); }
.pied__nom { font-size: var(--t-h3); font-weight: 500; }
.pied__devise, .pied__adresse, .pied__contacts, .pied__mention { color: var(--encre-douce); }
.pied__intitule { font-weight: 500; color: var(--vert); margin-bottom: 0.4em; }
.pied a { color: var(--encre); }
.pied__reseaux, .pied__legal { display: flex; flex-wrap: wrap; gap: 0.8em; }
.pied__signature {
  max-width: var(--large); margin: clamp(20px, 3vw, 34px) auto 0;
  padding-top: 1rem; border-top: 1px solid var(--trait);
  display: flex; flex-wrap: wrap; gap: 0.6em 1.2em;
  color: var(--encre-douce); font-size: var(--t-mention);
}
.pied__annee { white-space: nowrap; }

/* ---------- 28. Le sélecteur de langue ------------------------------------ */

.langues { margin-left: 0.6rem; }
.langues__liste { display: flex; gap: 0.4em; }
.langues__lien {
  text-decoration: none; font-size: var(--t-mention); text-transform: uppercase;
  padding: 0.35em 0.5em; border: 1px solid var(--trait); border-radius: var(--rayon);
}
.langues__lien[aria-current] { background: var(--vert); color: var(--encre-clair); border-color: var(--vert); }

/* ---------- 29. Les pages légales ------------------------------------------ */

.sec--legal .sec__corps { max-width: var(--lecture); }
.sec--legal__mentions h2 { font-size: var(--t-h3); margin-top: 1.6em; }
.sec--legal__retour { margin-top: 2em; }

/* ---------- 30. Apparition au défilement ----------------------------------- */

.reveal { opacity: 0; transition: opacity var(--apparition) var(--ease); }
.reveal--vu { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transition: none; }
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}

/* ---------- 31. La visionneuse ---------------------------------------------
   ELLE N'EST PLUS HABILLÉE ICI, ET C'EST UNE CORRECTION.

   Son balisage est fabriqué par assets/js/commun.js, pas par un
   gabarit : sept parties, dont ce thème n'en habillait que trois. Le
   <dialog> restait rétracté au milieu de l'écran — l'agent utilisateur
   le pose en « width: fit-content » —, le bouton de fermeture n'avait
   pas de croix, et les deux chevrons s'empilaient sous l'image. Elle
   était inutilisable sur les trois thèmes à la fois, ce qui est le signe
   qu'une règle recopiée trois fois n'était à sa place nulle part.

   Elle vit maintenant dans assets/css/visionneuse.css, du socle, servie
   uniquement quand la page porte un lien agrandissable. Une photo
   agrandie se regarde sur du noir, quel que soit le site : cette
   feuille-là n'a aucune raison d'appartenir à un thème. */

/* ---------- 32. Le calendrier partagé -------------------------------------- */

.calendrier { max-width: var(--large); margin: 0 auto; }
.calendrier--agenda { border: 1px solid var(--trait); border-radius: var(--rayon); padding: 0.9rem; }
.calendrier__etat { font-size: var(--t-petit); color: var(--encre-douce); }
.apercu-section { display: block; }
/* `.serie` NE REÇOIT AUCUNE RÈGLE, ET C'EST VOULU.

   C'est un repère de script — assets/js/commun.js s'en sert pour
   composer le groupe que la visionneuse feuillette — et il est TOUJOURS
   posé à côté d'une classe qui, elle, habille : `galerie-mosaique
   serie`, `carte serie`, `sec__grille serie`. verifier-styles.php garde
   les LISTES de classes et n'exige une règle que pour la liste ; aucune
   ne sort donc nue à cause de lui.

   Il a porté un moment `display: block`, et cette ligne a coûté cher :
   posée après `.galerie-mosaique { display: grid }`, à spécificité
   égale, elle gagnait — la mosaïque tombait en colonne unique sur les
   trois thèmes, à toutes les largeurs, et chaque photo occupait la
   pleine largeur du cadre. Une règle écrite pour satisfaire un contrôle
   qui ne la demandait pas. */

/* ---------- 33. Ce que riche() classe, et qu'on oublie ---------------------
   riche() pose SA classe sur chaque paragraphe qu'elle produit : chacune
   doit avoir sa règle, sinon la section sort avec des blocs nus.
   tools/verifier-styles.php les relève sur le rendu ET sur les gabarits. */

.sec__intro { max-width: var(--lecture); color: var(--encre-douce); margin-top: 0.5em; }
.sec__intro + .sec__intro { margin-top: 0.8em; }

.appel__texte { padding: 0.5rem 1.1rem 0; color: var(--encre-douce); }
.actu__texte { padding: 0.5rem 1.1rem 0; color: var(--encre-douce); }
.atelier__texte { padding: 0.5rem 1.1rem 0; color: var(--encre-douce); }
.document__texte { font-size: var(--t-petit); color: var(--encre-douce); }
.membre__texte { font-size: var(--t-petit); color: var(--encre-douce); margin-top: 0.3em; }
.dons__moyens { max-width: var(--lecture); margin-top: 1.2rem; }
.dons__fiscal {
  max-width: var(--lecture); margin-top: 1.2rem;
  padding: 0.9em 1.1em; background: var(--fond-creux); border-radius: var(--rayon);
  font-size: var(--t-petit); color: var(--encre-douce);
}
.sec--access__lieu { color: var(--encre-douce); }
.pied__mot { color: var(--encre-douce); }

/* UNE FICHE DE MEMBRE SANS PHOTO N'EST PAS UNE FICHE VIDE. Le bureau
   d'une association d'aide compte toujours quelqu'un qui ne veut pas de
   sa photo en ligne, et c'est son droit. On lui rend un cadre plutôt
   qu'un trou. */
.membre { display: block; }
.membre--sans-photo {
  padding: 0.9rem 1rem;
  border: 1px solid var(--trait); border-radius: var(--rayon);
}

/* LE PREMIER BOUTON DE L'ACCUEIL EST L'ACTION — voir la note du thème
   club. Ici c'est le vert plein : « faire un don » ou « nous
   rejoindre », selon ce que l'association met en premier. */
.sec--hero .sec__bouton:not(.sec__bouton--doux) {
  background: var(--vert); border-color: var(--vert); color: var(--encre-clair);
}
.sec--hero .sec__bouton:not(.sec__bouton--doux):hover {
  background: var(--vert-fonce); border-color: var(--vert-fonce); color: var(--encre-clair);
}
