/* =====================================================================
   CIMAISE — la feuille.
   =====================================================================
   Les jetons sont dans themes/cimaise/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 : le fond est un mur blanc, ce
   qu'on y accroche est grand, et tout le reste est un filet d'un pixel.

   TROIS CHOSES QU'ON NE TROUVERA PAS DANS CE FICHIER, et qu'il vaut
   mieux dire une fois pour toutes :

     — `border-radius` autre que zéro. Le jeton vaut 0 et rien ne le
       recalcule ;
     — `box-shadow`. Une ombre porte une carte ; ici il n'y a pas de
       cartes, il y a des cases dans une grille ;
     — un aplat de couleur au-delà d'un bouton et d'une date. Dans une
       salle d'exposition, la couleur appartient à ce qui est accroché.
   ===================================================================== */

/* ---------- 1. Polices auto-hébergées ------------------------------------
   Jost porte tout : une géométrique de la lignée Bauhaus, des cercles
   vrais et des jambages courts. C'est la grammaire typographique des
   lieux d'art contemporain, et c'est la seule des cinq familles du dépôt
   que ce thème emploie — aucun autre ne la touche, ce qui fait qu'on
   reconnaît ce site avant d'avoir lu une ligne.

   AUCUNE SERIF, AUCUNE ITALIQUE DÉCORATIVE. Une serif de titre ferait de
   ce lieu un magazine, et un magazine n'est pas un lieu. Les trois
   graisses de Jost portent toute la hiérarchie : 300 pour les grands
   titres, où la géométrie se voit le mieux ; 400 pour le texte ; 500
   pour les intitulés et les dates. */

@font-face {
  font-family: 'Jost'; font-style: normal; font-weight: 300;
  font-display: swap; src: url('../../../assets/fonts/jost-300.woff2') format('woff2');
}
@font-face {
  font-family: 'Jost'; font-style: normal; font-weight: 400;
  font-display: swap; src: url('../../../assets/fonts/jost-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Jost'; font-style: normal; font-weight: 500;
  font-display: swap; src: url('../../../assets/fonts/jost-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. Jost est
   étroite et à grand œil ; Century Gothic et Futura sont ses replis
   naturels, et la chasse est ramenée dans leur rapport. */
@font-face {
  font-family: 'Jost repli';
  src: local('Century Gothic'), local('Futura'), local('Avenir Next'), local('Helvetica Neue'), local('Arial');
  size-adjust: 92%; ascent-override: 104%; descent-override: 27%; line-gap-override: 0%;
}

/* ---------- 2. Jetons ----------------------------------------------------
   Déclarés dans themes/cimaise/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.7;
  -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(--signal); outline-offset: 2px; }
:focus:not(:focus-visible) { outline: none; }
::selection { background: var(--signal); color: var(--encre-clair); }

.evitement {
  position: absolute; left: -9999px; top: 0; z-index: 300;
  background: var(--signal); 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 -------------------------------------- */

/* PAS DE BANDE ALTERNÉE, ET C'EST LA PREMIÈRE DÉCISION DU THÈME.

   Les trois autres thèmes rythment la page en alternant deux fonds.
   Celui-ci ne le fait pas : un mur d'exposition est d'une seule valeur,
   et une salle ne change pas de couleur d'une cloison à l'autre. Ce qui
   sépare deux sections est un FILET, comme dans une salle où deux
   cimaises se rencontrent.

   Le gris ne sert donc qu'à deux endroits nommés — la programmation et
   les informations pratiques —, et l'aplat sombre à un seul : le pied. */
main > .sec + .sec { border-top: var(--filet) solid var(--trait); }

.sec {
  padding: var(--section-y) var(--gouttiere);
  --ancre-retrait: var(--section-y);
  scroll-margin-top: calc(0px - var(--ancre-retrait));
}
/* L'ACCUEIL EST UNE AFFICHE, ET ELLE SE LIT DANS CET ORDRE : l'image
   pleine largeur, puis le nom en grand, puis ce qui est visible en ce
   moment. C'est la façade d'un lieu : on voit d'abord ce qu'il y a
   dedans.

   AUCUN TEXTE POSÉ SUR LA PHOTO. Un titre en surimpression oblige à
   assombrir l'image, donc à abîmer ce qu'on montre ; et il devient
   illisible dès qu'une association dépose une photo claire. Le titre est
   dessous, sur le mur blanc. */
.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__entete { max-width: var(--large); margin: 0 auto clamp(22px, 3vw, 40px); }

/* LE TITRE DE SECTION. Léger, grand, et posé sur un filet qui traverse
   toute la largeur : c'est le cartel d'une salle. Aucun trait de
   couleur, aucune bande — la ligne suffit à séparer, et c'est elle qui
   fait la grille. */
.sec__titre {
  font-weight: 300;
  font-size: var(--t-h2);
  line-height: 1.12;
  letter-spacing: -0.02em;
  max-width: 20ch;
  text-wrap: balance;
}
.sec__entete { position: relative; padding-top: 1.1rem; }
.sec__entete::before {
  content: ""; position: absolute; inset: 0 0 auto 0;
  height: var(--filet); background: var(--encre);
}
.sec--hero .sec__entete::before { display: none; }
.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; }

/* LES INTITULÉS sont des étiquettes de salle : petites capitales
   espacées, encre douce, jamais colorées. La couleur est réservée aux
   dates et au bouton, et une exception la userait. */
.sec__intitule {
  font-weight: 500; font-size: var(--t-mention);
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--encre-douce);
  margin: 2.4em 0 0.9em;
  padding-bottom: 0.5em;
  border-bottom: var(--filet) solid var(--trait);
}
.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(--signal); text-underline-offset: 2px; }
.lien:hover { color: var(--signal-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; }
/* UN TIRET, PAS UN ROND. Un disque de couleur devant chaque ligne est
   une décoration ; une barre d'encre est une ponctuation. */
.sec__points li::before {
  content: ""; position: absolute; left: 0; top: 0.72em;
  width: 12px; height: 2px; background: var(--encre);
}

/* ---------- 5. Boutons ---------------------------------------------------
   RECTANGULAIRES, D'ENCRE, ET SANS ARRONDI. Le bouton ordinaire est un
   filet d'encre sur le mur : c'est le même vocabulaire que le reste de
   la page. Le seul bouton de couleur est l'appel à l'action, et il n'y
   en a qu'un par écran.

   L'ÉCART DE POIDS FAIT LA HIÉRARCHIE, pas la taille : les deux font
   48 px, l'un est plein et l'autre non. Deux tailles différentes
   diraient qu'un des deux est moins sérieux. */

.bouton, .sec__bouton, .menu__action {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 0.6em 1.4em;
  font-weight: 500; font-size: var(--t-petit);
  letter-spacing: 0.05em; text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  border: var(--filet) solid var(--encre); border-radius: 0;
  background: transparent; color: var(--encre);
  transition: background var(--survol) var(--ease), color var(--survol) var(--ease);
}
.bouton:hover, .sec__bouton:hover { background: var(--encre); color: var(--encre-clair); }

.menu__action, .bouton--action {
  background: var(--signal); border-color: var(--signal); color: var(--encre-clair);
}
/* Dans la barre, le bouton est plus court : il n'a pas à peser autant
   qu'un bouton de page, et la barre tient une ligne. */
.menu__action { min-height: 40px; font-size: var(--t-mention); }
.menu__action:hover, .bouton--action:hover {
  background: var(--signal-fonce); border-color: var(--signal-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 ----------------------------------------------------
   UNE RÈGLE, ET RIEN D'AUTRE. L'en-tête n'a ni fond teinté, ni ombre, ni
   volume : elle est du mur, et un filet d'encre la sépare de la page.
   C'est le même filet que celui des sections, et c'est ce qui fait la
   grille du thème. */

.entete {
  position: sticky; top: 0; z-index: 100;
  background: var(--fond);
  border-bottom: var(--filet) solid var(--encre);
}
/* 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. */
/* LE NOM EN CAPITALES ESPACÉES : c'est l'enseigne d'un lieu, pas une
   marque. Aucune graisse forte, aucune serif — la géométrie de Jost fait
   tout le travail. */
.entete__marque {
  flex: none; min-width: 0;
  display: inline-flex; align-items: center; gap: 0.7rem;
  text-decoration: none; font-weight: 500; font-size: 0.98rem; line-height: 1.15;
  letter-spacing: 0.06em; text-transform: uppercase;
}
.entete__embleme { width: 26px; height: 26px; flex: none; color: var(--encre); }

.menu {
  margin-left: auto; min-width: 0;
  display: flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end;
  gap: clamp(0.5rem, 0.9vw, 0.95rem);
}
.menu__liste {
  min-width: 0;
  display: flex; align-items: center; flex-wrap: nowrap; justify-content: flex-end;
  gap: clamp(0.45rem, 0.85vw, 0.9rem);
}
/* LE MENU EN CAPITALES COÛTE DE LA PLACE, ET LA BARRE TIENT UNE LIGNE.
   À 0,8125 rem et 0,08 em d'interlettrage, sept entrées plus le nom du
   lieu — lui aussi en capitales — venaient se toucher à 900 et 1024 px.
   Les capitales sont la voix du thème ; on les garde et on serre. */
.menu__liste a {
  text-decoration: none; font-size: 0.75rem;
  letter-spacing: 0.045em; text-transform: uppercase;
  padding: 0.4em 0; border-bottom: var(--filet) solid transparent; white-space: nowrap;
}
.menu__liste a:hover, .menu__liste a[aria-current] { border-bottom-color: var(--encre); }

/* 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.73em; }

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

/* LE MENU DE BUREAU N'APPARAÎT QU'À 1000 PX, ET NON À 900.

   Ce thème compose son menu ET son enseigne en capitales espacées :
   c'est sa voix, et elle coûte de la place. À 900 px, sept entrées plus
   le nom du lieu se touchaient — mesuré. Le contrat d'ancre interdit une
   barre qui s'enroule, et serrer davantage l'interlettrage aurait retiré
   au thème ce qui le fait reconnaître.

   Le burger tient donc jusqu'à 999 px. C'est un réglage de THÈME, pas du
   socle : les quatre autres gardent 900, parce que leurs menus tiennent. */
@media (max-width: 999px) {
  .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 -----------------------------------
   ENCRE PLEINE, ET LE LIEN EN MAGENTA. Une bande magenta pleine largeur
   dépenserait l'accent avant qu'on ait vu une seule date : le magenta
   est réservé aux dates et au bouton, et le bandeau n'est ni l'un ni
   l'autre. Il est noir, il se voit autant, et il ne coûte rien à la
   hiérarchie. */

.info {
  background: var(--fond-encre); color: var(--encre-clair);
  padding: 0.75em var(--gouttiere);
  font-size: var(--t-petit); text-align: center;
  letter-spacing: 0.01em;
}
.info__mot { display: inline; }
.info__lien { color: var(--encre-clair); text-underline-offset: 3px; margin-left: 0.6em; font-weight: 500; }

/* ---------- 9. L'accueil --------------------------------------------------
   L'AFFICHE : l'image d'abord, pleine largeur et sans marge, puis le nom
   du lieu en très grand sur le mur blanc. C'est la façade — on voit ce
   qu'il y a dedans avant de lire l'enseigne.

   L'IMAGE N'EST PAS RECADRÉE EN BANDEAU. 3/2 sur grand écran plutôt que
   21/9 : une œuvre ou une vue de salle perd son sujet dans une fente. Ce
   thème est le seul des quatre à ne pas couper sa photo d'ouverture, et
   c'est cohérent avec ce qu'il montre. */

.sec--hero__texte {
  max-width: var(--large);
  margin: 0 auto;
  padding: clamp(34px, 5vw, 68px) var(--gouttiere) clamp(24px, 3.5vw, 48px);
}
.sec--hero--sobre .sec--hero__texte { padding-bottom: clamp(36px, 6vw, 80px); }

.sec--hero__surtitre {
  font-weight: 500; font-size: var(--t-mention);
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--encre-douce);
  margin-bottom: 1.1em;
  padding-bottom: 0.7em;
  border-bottom: var(--filet) solid var(--trait);
}
/* LE NOM DU LIEU, EN TRÈS GRAND ET EN MAIGRE. Jusqu'à 4,6 rem : c'est
   le seul endroit du dépôt où un titre monte aussi haut, et c'est ce qui
   fait la différence entre un site d'association et un lieu qui
   programme. La graisse 300 empêche que ce soit un cri.

   LA PHOTO EST PLEINE LARGEUR, ET ELLE L'EST REDEVENUE.
   Elle a été décalée d'un tiers pendant une heure cette nuit, au motif
   qu'un centre d'art laisse du mur autour de ce qu'il accroche. L'idée
   se défend et le résultat ne tenait pas : la marge de gauche restait
   VIDE — aucun texte, aucun cartel, rien —, et l'illustration, dont la
   composition est centrée, se retrouvait coupée en son milieu. Un
   décalage qui ne se lit pas comme voulu se lit comme une erreur de mise
   en page, et c'est ce qui est arrivé.

   La règle qu'on en tire : une asymétrie ne vaut que si la marge qu'elle
   ouvre PORTE quelque chose. Ici il n'y avait rien à y mettre — le nom
   du lieu vient après, et il a besoin de toute la largeur.

   Ce thème se distingue ailleurs, et de façon plus solide : la largeur
   de page (1360 px, la plus grande des cinq), la planche contact à six
   colonnes, les cartels sans boîte ni fond, et les filets d'un pixel qui
   remplacent partout les bordures. */
.sec--hero__titre {
  font-weight: 300;
  font-size: var(--t-display);
  line-height: 0.96; letter-spacing: -0.04em;
  max-width: 15ch; text-wrap: balance;
}
.sec--hero__soustitre { margin-top: 0.7em; font-size: var(--t-lead); color: var(--encre-douce); max-width: 38ch; }
.sec--hero__intro { margin-top: 1em; max-width: var(--lecture); }
.sec--hero__intro + .sec--hero__intro { margin-top: 0.8em; }
.sec--hero__actions { margin-top: 1.8em; display: flex; flex-wrap: wrap; gap: 0.8em; }

.sec--hero__media { width: 100%; aspect-ratio: 4 / 3; overflow: hidden; }
.sec--hero__media img { width: 100%; height: 100%; object-fit: cover; }
@media (min-width: 620px) { .sec--hero__media { aspect-ratio: 3 / 2; } }

@media (min-width: 1000px) {
  .sec--hero__media { aspect-ratio: 2 / 1; }
  .sec--hero__texte {
    max-width: var(--large);
    margin: clamp(36px, 4vw, 64px) auto 0;
    padding: 0 var(--gouttiere);
    display: grid;
    grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
    column-gap: clamp(32px, 5vw, 80px);
    align-items: start;
  }
  .sec--hero__surtitre { grid-column: 1; }
  .sec--hero__titre    { grid-column: 1; }
  .sec--hero__soustitre{ grid-column: 1; }
  /* Une classe posée par riche() ne reçoit jamais de placement par
     élément : elle peut sortir en plusieurs paragraphes, et deux
     paragraphes dans la même case se superposeraient. On place le
     PREMIER, les suivants suivent. */
  .sec--hero__intro    { grid-column: 2; grid-row: 1 / span 3; margin-top: 0.4em; }
  .sec--hero__intro + .sec--hero__intro { grid-row: auto; margin-top: 0.8em; }
  .sec--hero__actions  { grid-column: 1; }

  /* SANS PHOTO, IL N'Y A PLUS DE MARGE D'ACCROCHAGE À TENIR. */
  .sec--hero--sobre .sec--hero__texte { margin-top: clamp(48px, 8vw, 112px); }
}

/* ---------- 10. L'association --------------------------------------------
   LES CHIFFRES SONT UNE RANGÉE, PAS DES CARTES. Quatre colonnes séparées
   par un filet vertical, sans fond et sans bordure extérieure : c'est un
   tableau de salle, et c'est le composant le plus institutionnel du
   thème. */

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

.sec__chiffres {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  border-top: var(--filet) solid var(--encre);
  border-bottom: var(--filet) solid var(--trait);
}
.sec__chiffres > * {
  padding: 1.4rem clamp(0.9rem, 2vw, 1.6rem);
  border-left: var(--filet) solid var(--trait);
  background: transparent;
}
.sec__chiffres > *:first-child { border-left: 0; }
/* UN CHIFFRE NE SE COUPE JAMAIS. « 1 840 » passait à la ligne entre le
   1 et le 840 : à quatre rem, cinq signes et une espace demandent plus
   de place qu'une colonne de deux cents pixels n'en offre une fois son
   padding retiré. Un nombre coupé en deux n'est plus un nombre, c'est
   une erreur de rendu — et c'est le composant signature du thème.

   Deux règles, et il faut les deux : la colonne s'élargit assez pour
   tenir un nombre de cinq signes, et le nombre lui-même refuse la
   coupure quoi qu'il arrive. La seconde protège la première le jour où
   une association écrira « 18 400 ». */
.sec__chiffres dt, .sec__chiffres .valeur {
  white-space: nowrap;
  font-size: var(--t-nombre); font-weight: 500; line-height: 1;
  letter-spacing: -0.02em; color: var(--signal);
  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; }


/* L'ACCROCHAGE — LES TROIS PHOTOS PARTENT DU MÊME BORD GAUCHE, ET LE
   MUR EST À DROITE. La grande garde exactement sa largeur — neuf
   colonnes sur douze —, elle a seulement changé de côté : le vide qui
   traînait à sa gauche cassait l'alignement avec les deux petites
   posées dessous, et un alignement rompu se lit comme un défaut, pas
   comme une composition. C'est le même geste que l'accueil de ce
   thème : on laisse du mur autour, et le vide fait partie de la
   composition. Aucun des quatre autres thèmes ne le fait ; c'est ce qui
   rend celui-ci reconnaissable deux sections plus bas que son accueil.

   Douze colonnes pour pouvoir décaler d'un quart sans approximation.
   Formats natifs — 3/2 et 4/3 —, aucun recadrage : dans un lieu
   d'exposition, ce qu'on coupe d'une image est une décision, pas un
   effet de bord. */
.sec__medias {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.sec__medias li:first-child { grid-column: 1 / -1; }
.sec__medias li:first-child img { aspect-ratio: 3 / 2; }
.sec__medias img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
@media (min-width: 1000px) {
  .sec__medias { grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 16px; }
  .sec__medias li:first-child { grid-column: 1 / span 9; }
  .sec__medias li:nth-child(2) { grid-column: 1 / span 4; }
  .sec__medias li:nth-child(3) { grid-column: 5 / span 4; }
}
/* ---------- 11. Les activités — LE CARTEL -------------------------------
   L'ŒUVRE, PUIS SON CARTEL. AUCUNE BOÎTE, AUCUN FOND, UN FILET.

   Les cinq thèmes posaient ici la même grille de cartes de 260 à 300 px.
   Celui-ci garde trois colonnes — c'est le thème le plus large du socle,
   1360 px, il peut se le permettre — mais il ne pose plus de CARTES : la
   photo en 4/5, un filet d'un pixel dessous, le nom, puis les détails en
   petit. C'est ce qu'on lit à côté d'une pièce accrochée, et c'est le
   seul composant du socle qui ne dessine ni bord ni fond.

   LE 4/5 EST LE FORMAT DU THÈME — celui de sa galerie, celui de ses
   portraits. Un lieu d'exposition cadre en portrait ; c'est ce qui fait
   qu'on reconnaît sa page trois sections plus bas.

   PAS DE GABARIT DE THÈME : une colonne par fiche, donc aucune rangée
   partagée entre deux colonnes, donc aucun des défauts d'alignement qui
   obligent `club`, `plateau` et `tribune` à écrire le leur. */

.sec__grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(36px, 4vw, 64px) clamp(24px, 3vw, 52px);
  max-width: var(--large);
  margin: 0 auto;
}
@media (min-width: 620px)  { .sec__grille { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .sec__grille { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.carte {
  background: transparent;
  border: 0; border-radius: 0;
  display: flex; flex-direction: column; gap: 0.35rem;
  scroll-margin-top: var(--ancre-air);
}
.carte__photo { margin-bottom: 0.6rem; }
.carte__photo img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }

/* LE FILET DU CARTEL : un pixel sous la photo, au-dessus du nom. C'est
   le seul séparateur du thème, et il est partout — sections, titres,
   fiches. */
.carte__nom {
  font-size: var(--t-h3); font-weight: 300; line-height: 1.2;
  padding-top: 0.6rem;
  border-top: 1px solid var(--encre);
}
.carte__accroche { color: var(--encre-douce); font-size: var(--t-petit); }
.carte__resume, .carte__texte { color: var(--encre-douce); font-size: var(--t-petit); }
.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.14em; text-transform: uppercase;
  color: var(--encre-douce); margin-top: 0.6rem;
}

/* Les faits, l'un sous l'autre sur un filet clair : c'est la fiche
   technique d'un cartel — durée, lieu, public. */
.carte__faits { display: grid; font-size: var(--t-petit); color: var(--encre-douce); }
.carte__faits li { padding: 0.35em 0; border-bottom: 1px solid var(--trait); }
.carte__faits li:first-child { border-top: 1px solid var(--trait); }

.carte__equipements {
  display: flex; flex-wrap: wrap; gap: 0.2em 1em;
  font-size: var(--t-petit); color: var(--encre-douce);
}
.carte__prix { display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.4rem; }
.carte__montant { font-size: var(--t-h3); font-weight: 300; font-variant-numeric: tabular-nums; white-space: nowrap; }
.carte__mention { font-size: var(--t-petit); color: var(--encre-douce); }
.carte__action { margin-top: 0.6rem; }

/* DEUX COLONNES FRANCHES, en 4/5 comme le reste. Elles tenaient
   `auto-fill, minmax(64px, 1fr)` : dans une colonne large, huit pistes
   pour deux photos, donc deux vignettes de soixante-quatre pixels et
   six colonnes de vide. Même défaut que celui corrigé dans la galerie. */
.carte__vues { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; margin-top: 0.3rem; }
.carte__vues img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.carte__vues figcaption { font-size: var(--t-mention); color: var(--encre-douce); margin-top: 0.25em; }

/* ---------- 12. Les appels du moment --------------------------------------
   « À l'affiche » : ce qui est visible en ce moment, et jusqu'à quand.
   Un aplat sombre, et un seul par page : c'est la seule surface pleine
   du thème avec le pied, et c'est ce qui la fait remarquer sans qu'elle
   crie. */

.appels { display: grid; gap: clamp(16px, 2vw, 28px); max-width: var(--large); margin: 0 auto; }
.appel {
  display: grid;
  border: 0; border-radius: 0;
  background: var(--fond-encre); color: var(--encre-clair); overflow: hidden;
}
.appel .lien, .appel__nom { color: var(--encre-clair); }
/* Sous 760 px la photo est posée au-dessus du texte : elle garde son
   rapport, rien ne la contraint en hauteur. */
.appel__photo img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
@media (min-width: 760px) {
  .appel { grid-template-columns: minmax(0, 280px) minmax(0, 1fr); }
  .appel__photo { grid-row: 1 / span 6; }
  /* LA PHOTO PREND TOUTE LA HAUTEUR DE L'APLAT, ET SA LARGEUR NE BOUGE
     PAS : elle devient une bande à gauche, et c'est le recadrage qui
     absorbe la différence.

     Les trois hauteurs ci-dessous ne sont pas du zèle. Sans elles, le
     « height: 100% » de l'image tombe dans le vide — <picture> est un
     élément en ligne, sa hauteur est indéfinie, la valeur en pourcentage
     est donc ignorée et le rapport 4/3 reprend la main. La photo
     s'arrêtait aux deux tiers de l'aplat et le reste du noir restait nu.
     C'est le même montage que .galerie-mosaique, pour la même raison. */
  .appel__photo,
  .appel__photo .sec__agrandir,
  .appel__photo picture { display: block; height: 100%; }
  .appel__photo img { aspect-ratio: auto; }
}
.appel__nom { padding: 1.3rem 1.5rem 0; font-size: var(--t-h2); font-weight: 300; line-height: 1.1; letter-spacing: -0.02em; }
.appel__accroche {
  padding: 1.3rem 1.5rem 0; color: var(--signal-clair); font-weight: 500;
  font-size: var(--t-mention); letter-spacing: 0.14em; text-transform: uppercase;
}
.appel__mots { padding: 0.7rem 1.5rem 0; color: rgba(255, 255, 255, 0.76); max-width: 46ch; }
.appel__chiffre { padding: 0.9rem 1.5rem 0; display: flex; align-items: baseline; gap: 0.5rem; }
.appel__nombre {
  font-size: var(--t-nombre); font-weight: 300; line-height: 1;
  color: var(--encre-clair); font-variant-numeric: tabular-nums;
}
.appel__mention { font-size: var(--t-petit); color: rgba(255, 255, 255, 0.72); }
/* LA DATE DE FIN EN MAGENTA : c'est le seul mot coloré d'un aplat
   sombre, et c'est celui qu'on vient chercher. */
.appel__validite {
  padding: 0.8rem 1.5rem 0; font-size: var(--t-date); font-weight: 500;
  letter-spacing: -0.01em; text-transform: none; color: var(--signal-clair);
  font-variant-numeric: tabular-nums;
}
.appel__action { padding: 1.2rem 1.5rem 1.5rem; }
.appel .bouton, .appel .sec__bouton {
  border-color: var(--encre-clair); color: var(--encre-clair);
}
.appel .bouton:hover, .appel .sec__bouton:hover {
  background: var(--encre-clair); color: var(--encre);
}

/* ---------- 13. L'agenda ---------------------------------------------------
   LA PROGRAMMATION EST LE CŒUR DU THÈME, et elle se lit comme un tableau
   d'affichage : une ligne par date, un filet entre chaque, la date en
   magenta et en grand À GAUCHE, le titre à côté.

   AUCUN ENCADRÉ. Douze événements encadrés font douze boîtes ; douze
   événements sur des filets font un programme. C'est la seule
   disposition qui reste lisible quand une saison en compte trente. */

.sec--evenements { background: var(--fond-bande); }
.sec--evenements .sec__corps { max-width: var(--large); }
.agenda__liste { display: grid; gap: 0; border-top: var(--filet) solid var(--encre); }
.evenement {
  display: grid; gap: 0.2rem 1.6rem;
  padding: 1.1rem 0;
  border: 0; border-bottom: var(--filet) solid var(--trait); border-radius: 0;
}
@media (min-width: 700px) {
  .evenement { grid-template-columns: minmax(0, 15rem) 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; }
}
/* LA DATE EN GRAND, ET C'EST LA SIGNATURE DU THÈME. Presque la taille
   d'un titre de section : dans un lieu qui programme, la date est
   l'information, et le titre vient après elle. */
.evenement__quand {
  font-weight: 500; font-size: var(--t-date); line-height: 1.1;
  letter-spacing: -0.015em;
  color: var(--signal); font-variant-numeric: tabular-nums;
}
.evenement__nom { font-size: var(--t-h3); font-weight: 400; }
.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(--signal); }
.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 PLANCHE CONTACT. Des vues serrées, jointives à quatre pixels, en
   4/5 : le format d'une œuvre plutôt que celui d'un paysage. C'est la
   galerie la plus dense des quatre thèmes, et c'est voulu — un lieu
   d'exposition montre beaucoup d'images. */

/* 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. */
/* La planche contact d'un lieu d'exposition : six colonnes serrées, quatre
   pixels d'écart, cadrage en 4/5. On voit l'ensemble d'un coup d'œil, et
   c'est la vue à laquelle sert une planche contact. */
.galerie-mosaique {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 4px; max-width: var(--large); margin: 0 auto;
}
@media (min-width: 640px)  { .galerie-mosaique { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .galerie-mosaique { grid-template-columns: repeat(6, 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 / 5; }
.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: 0; }
.galerie-mosaique figcaption { display: none; }
.sec--gallery__couverture { margin-bottom: 4px; }
.sec--gallery__couverture img { width: 100%; aspect-ratio: 2 / 1; object-fit: cover; border-radius: 0; }

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

.sec__services {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 0 clamp(20px, 3vw, 48px); 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 0; border: 0; border-top: var(--filet) solid var(--trait); border-radius: 0;
}
.service__pictogramme { width: 1.5em; height: 1.5em; grid-column: 1; grid-row: 1 / span 2; color: var(--encre); }
.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: 0; border-top: var(--filet) solid var(--encre); border-radius: 0; 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: 1.2rem 0 0 clamp(0px, 2vw, 28px); font-size: var(--t-h3); font-weight: 500; }
.atelier__pour, .atelier__categorie {
  padding: 0.25rem 0 0 clamp(0px, 2vw, 28px); color: var(--encre-douce);
  font-weight: 500; font-size: var(--t-mention);
  letter-spacing: 0.12em; text-transform: uppercase;
}
.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(--encre); 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: 0; }

/* ---------- 18. Les informations pratiques --------------------------------
   HORAIRES, TARIFS, ACCESSIBILITÉ. Une liste dépliable sur toute la
   largeur, filets d'encre : c'est le panneau d'entrée d'un lieu, pas une
   foire aux questions. La section porte le gris de mur pour se détacher
   du blanc, comme la programmation. */

.sec--infos_pratiques { background: var(--fond-bande); }
.sec__rubriques { max-width: var(--large); margin: 0 auto; border-top: var(--filet) solid var(--encre); }
.rubrique { border-bottom: var(--filet) 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(--encre), var(--encre)) center / 100% 2px no-repeat,
    linear-gradient(var(--encre), var(--encre)) center / 2px 100% no-repeat;
}
.rubrique[open] .rubrique__ligne::after {
  background: linear-gradient(var(--encre), var(--encre)) center / 100% 2px no-repeat;
}
.rubrique__detail { padding-bottom: 1.4em; color: var(--encre-douce); max-width: var(--lecture); }

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

.sec--about .sec__corps { display: grid; gap: clamp(22px, 3vw, 44px); }
/* LE PORTRAIT EST UN RECTANGLE, ET IL EST EN 4/5. Aucun rond nulle part
   dans ce thème : un portrait rond est une convention de réseau social,
   et ce lieu-ci accroche des images rectangulaires sur un mur. */
.sec--about__portrait { max-width: 260px; }
.sec--about__portrait img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 0; }
.sec--about__portrait .sec__agrandir { border-radius: 0; overflow: hidden; }
.sec--about__signature { color: var(--encre); 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(150px, 45%), 1fr)); gap: clamp(14px, 2vw, 24px); max-width: var(--large); margin: 0 auto; }
.membre__photo img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 0; }
.membre__nom { font-weight: 500; margin-top: 0.7em; padding-top: 0.6em; border-top: var(--filet) solid var(--encre); }
.membre__role { font-size: var(--t-mention); letter-spacing: 0.1em; text-transform: uppercase; color: var(--encre-douce); }
.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.2rem 0 0; border: 0; border-top: var(--filet) solid var(--encre); border-radius: 0; background: transparent; }
.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: 52px; height: 64px; object-fit: cover; border-radius: 0; margin-bottom: 0.7em; }

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

.documents { max-width: var(--large); margin: 0 auto; display: grid; gap: 0; border-bottom: var(--filet) solid var(--trait); }
.document { display: grid; gap: 0.2rem 1rem; padding: 1rem 0; border: 0; border-top: var(--filet) solid var(--trait); border-radius: 0; }
@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 ----------------------------------------------------
   L'adresse en grand, sans cadre : elle est posée sur un filet d'encre,
   comme un cartel. Les repères d'accès suivent, en deux colonnes sur
   grand écran. */

.sec--access .sec__corps { display: grid; gap: 1.4em; max-width: var(--large); }
.sec--access__adresse {
  font-size: var(--t-h3); font-weight: 400; line-height: 1.4;
  padding: 1.1rem 0 0; border-top: var(--filet) solid var(--encre);
  background: transparent; border-radius: 0; max-width: 34ch;
}
.sec--access__reperes {
  display: grid; gap: 0.9em clamp(20px, 3vw, 48px);
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
}
.sec--access__reperes dt {
  font-weight: 500; color: var(--encre-douce);
  font-size: var(--t-mention); letter-spacing: 0.12em; text-transform: uppercase;
}
.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 0 0; border: 0; border-top: var(--filet) solid var(--encre); border-radius: 0; }
.formule__nom { font-size: var(--t-h3); font-weight: 500; }
.formule__mention { color: var(--encre-douce); font-weight: 400; 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); }

/* LE CHAMP EST UNE LIGNE, PAS UNE BOÎTE. Un seul filet, en bas : c'est
   le formulaire d'un lieu qui n'a rien à encadrer. Le fond gris à la
   saisie remplace l'encadré : il dit où l'on est sans ajouter un trait. */
.controle {
  width: 100%; min-height: 48px; padding: 0.6em 0.1em;
  background: transparent; color: var(--encre);
  border: 0; border-bottom: var(--filet) solid var(--trait-champ); border-radius: 0;
  font-size: var(--t-body);
}
.controle--zone { min-height: auto; resize: vertical; padding: 0.6em 0.6em; background: var(--fond-bande); }
.controle:focus-visible {
  outline: 2px solid var(--encre); outline-offset: 2px;
  border-color: var(--encre); background: var(--fond-bande);
}
.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(--encre); border-radius: 0; }
.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.3rem 0 0; border: 0; border-top: 3px solid var(--oui); border-radius: 0; background: transparent; }
.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: 0 clamp(20px, 3vw, 48px); 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 0; border: 0; border-top: var(--filet) solid var(--trait); border-radius: 0;
}
.mission__pictogramme { width: 1.5em; height: 1.5em; grid-column: 1; grid-row: 1 / span 2; color: var(--encre); }
.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 ---------------------------------------------------
   Le chiffre en grand et en maigre, la phrase dessous, sur un filet
   d'encre. Aucun cadre : c'est la même rangée que les chiffres clés, et
   les deux composants doivent se ressembler. */

.dons__emplois {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 0; margin: 1.5rem 0;
  border-top: var(--filet) solid var(--encre); border-bottom: var(--filet) solid var(--trait);
}
.dons__emplois > * {
  padding: 1.3rem clamp(0.9rem, 2vw, 1.6rem);
  border: 0; border-left: var(--filet) solid var(--trait); border-radius: 0;
}
.dons__emplois > *:first-child { border-left: 0; }
.dons__emplois dt {
  white-space: nowrap; font-size: var(--t-nombre); font-weight: 300; line-height: 1; color: var(--encre); 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 -------------------------------------------
   L'APLAT SOMBRE. C'est la seule grande surface pleine du site avec le
   bloc « à l'affiche », et elle ferme la page comme une salle se ferme :
   on sort du blanc. */

.pied {
  border-top: 0;
  background: var(--fond-encre); color: var(--encre-clair);
  padding: clamp(40px, 5vw, 76px) var(--gouttiere);
  font-size: var(--t-petit);
}
.pied a { color: var(--encre-clair); }
.pied__devise, .pied__adresse, .pied__contacts, .pied__mention { color: rgba(255, 255, 255, 0.72); }
.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__intitule {
  font-weight: 500; color: rgba(255, 255, 255, 0.62); margin-bottom: 0.7em;
  font-size: var(--t-mention); letter-spacing: 0.14em; text-transform: uppercase;
}
.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 rgba(255, 255, 255, 0.18);
  display: flex; flex-wrap: wrap; gap: 0.6em 1.2em;
  color: rgba(255, 255, 255, 0.66); 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(--signal); color: var(--encre-clair); border-color: var(--signal); }

/* ---------- 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: var(--filet) solid var(--trait); border-radius: 0; padding: 0.9rem; background: var(--fond); }
.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.6rem 1.5rem 0; color: rgba(255, 255, 255, 0.76); max-width: 46ch; }
.actu__texte { padding: 0.5rem 0 0; color: var(--encre-douce); }
.atelier__texte { padding: 0.5rem 0 0 clamp(0px, 2vw, 28px); 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 0 0; border-top: var(--filet) solid var(--trait); background: transparent;
  font-size: var(--t-petit); color: var(--encre-douce);
}
.sec--access__lieu { color: var(--encre-douce); }
.pied__mot { color: rgba(255, 255, 255, 0.72); }

/* 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 0 0;
  border: 0; border-top: var(--filet) solid var(--encre); border-radius: 0;
}

/* LE PREMIER BOUTON DE L'ACCUEIL EST L'ACTION, et c'est le seul aplat
   magenta de la page d'accueil. Le second bouton reste un filet d'encre :
   deux boutons pleins côte à côte ne disent plus lequel compte. */
.sec--hero .sec__bouton:not(.sec__bouton--doux) {
  background: var(--signal); border-color: var(--signal); color: var(--encre-clair);
}
.sec--hero .sec__bouton:not(.sec__bouton--doux):hover {
  background: var(--signal-fonce); border-color: var(--signal-fonce); color: var(--encre-clair);
}
