/* Thème « sobre ». Premier thème de XXVII : il prouve la chaîne adresse →
   entrée → gabarit, pas une direction artistique.

   Il ne fixe aucune couleur, police ni mesure en dur : il lit les variables
   de l'Apparence (--site-…), placées dans la page avant cette feuille
   (noyau/apparence.php). Le clair et le sombre y sont déjà résolus. */
:root {
  --fond: var(--site-fond, #FBFBFA);
  --encre: var(--site-texte, #1A1A1D);
  --gris: var(--site-secondaire, #6B6B73);
  --filet: var(--site-filet, #E4E4E7);
  --lien: var(--site-lien, #3F3AB8);
  --accent: var(--site-accent, #3F3AB8);
  --sur-accent: var(--site-sur-accent, #FFFFFF);
  --arrondi: var(--site-arrondi, 6px);
  --arrondi-boutons: var(--site-arrondi-boutons, 6px);
  --arrondi-images: var(--site-arrondi-images, 4px);
  --marges: var(--site-marges, 20px);
  --gouttiere: var(--site-gouttiere, 20px);
  --mesure: 42rem;
}
*, *::before, *::after { box-sizing: border-box; }
/* [hidden] vaut display:none dans la feuille du navigateur — mais toute classe
   qui fixe un display l'emporte sur elle. Sans ce rappel, masquer par [hidden]
   ne fait RIEN : le menu du téléphone et la visionneuse s'étaient déjà chacun
   payé leur rustine, et le bandeau des contenus extérieurs ne se fermait pas.
   La règle est posée une fois, pour tout le thème. */
[hidden] { display: none !important; }
body {
  margin: 0; min-height: 100vh; display: flex; flex-direction: column; overflow-x: clip;
  background: var(--fond); color: var(--encre);
  font-family: var(--site-police-texte, ui-sans-serif, system-ui, sans-serif);
  font-size: var(--site-taille, 17px); font-weight: var(--site-graisse-texte, 400); line-height: 1.65;
}
h1, h2, h3, .marque, .selection-tete h2 {
  font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 700);
  text-transform: var(--site-casse-titres, none); letter-spacing: var(--site-interlettre-titres, -.01em);
}
a { color: var(--lien); text-decoration-color: var(--accent); text-underline-offset: .18em; }
/* L'en-tête et le pied prennent la largeur réglée ; le texte garde sa mesure. */
.page, .pied { width: 100%; max-width: var(--site-largeur, var(--mesure)); margin: 0 auto; padding: 0 var(--marges); }
.page > * { max-width: var(--mesure); margin-left: auto; margin-right: auto; }
/* ── En-tête (Apparence → En-tête) ──────────────────────────────────────
   Le fond va d'un bord à l'autre ; son contenu s'aligne sur le site ou va
   aux marges. entete.js le fait vivre : est-defile (on a défilé), est-reduit,
   est-cache, est-sur-sombre ; --entete-h (sa hauteur mesurée) sur la racine. */
:root { --entete-h: 5.5rem; }
.entete { --entete-cran: calc(var(--marges) * .5); --entete-pad: calc(var(--entete-cran) * var(--entete-crans, 3)); position: relative; z-index: 30; width: 100%; color: var(--encre);
  background: var(--site-entete-fond, var(--fond)); border-bottom: 1px solid transparent;
  transition: background-color .3s ease, color .3s ease, border-color .3s ease, box-shadow .3s ease, transform .35s cubic-bezier(.16, 1, .3, 1); }
.entete-in { position: relative; display: flex; align-items: center; gap: 1rem 2rem; flex-wrap: wrap; padding: var(--entete-pad) var(--marges);
  transition: padding .3s cubic-bezier(.16, 1, .3, 1); }
.entete.largeur-alignee .entete-in { max-width: var(--site-largeur, var(--mesure)); margin: 0 auto; }
.entete.largeur-bord .entete-in { padding-left: calc(var(--entete-cran) * var(--entete-crans-cote, 2)); padding-right: calc(var(--entete-cran) * var(--entete-crans-cote, 2)); }
.entete .nav { margin-left: auto; }
.entete-cote { display: flex; align-items: center; gap: 1rem 1.4rem; }
.entete-reseaux { display: flex; gap: .8rem; list-style: none; margin: 0; padding: 0; }
.entete-reseaux a { display: grid; color: inherit; opacity: .85; }
.entete-reseaux a:hover { opacity: 1; }
.entete .bouton { font-size: .9rem; padding-top: .5rem; padding-bottom: .5rem; }
.entete .bouton-souligne, .entete .bouton-fleche { padding-top: 0; padding-bottom: 0; }
/* Au défilement : il reste en haut (toujours visible, se cache, se réduit). */
.entete-fixe, .entete-cache, .entete-reduit { position: sticky; top: 0; }
.entete-cache.est-cache { transform: translateY(-100%); }
.entete-reduit.est-reduit { --entete-pad: calc(var(--entete-cran) * var(--entete-crans-reduit, 1)); }
/* Ombre portée : jamais, une fois qu'on a défilé, ou toujours ; sa densité
   va de 1 à 6 crans (--entete-ombre-f, 4 % par cran). */
.entete.ombre-toujours, .entete.ombre-defile.est-defile { box-shadow: 0 6px 24px rgb(0 0 0 / calc(var(--entete-ombre-f, 2) * 4%)); }
.entete-reduit .marque .logo { transition: height .3s cubic-bezier(.16, 1, .3, 1), opacity .2s, transform .2s; }
.entete-reduit.est-reduit .marque .logo { height: min(var(--site-logo-hauteur, 2.2rem), 2rem); }
/* Fond flouté, quand il passe sur le contenu. */
.entete.avec-flou:is(.entete-fixe, .entete-cache, .entete-reduit) { backdrop-filter: saturate(1.4) blur(14px); -webkit-backdrop-filter: saturate(1.4) blur(14px); }
/* Filet, éventuellement seulement une fois qu'on a défilé. */
.entete.avec-filet { border-bottom-color: var(--site-entete-filet, var(--filet)); }
.entete.avec-filet.filet-au-defilement:not(.est-defile) { border-bottom-color: transparent; }
/* Transparent en haut de page (réglage, ou ouverture sous l'en-tête). */
:is(.entete.est-transparent, .entete-transparent .entete):not(.est-defile) { background: transparent; backdrop-filter: none; -webkit-backdrop-filter: none; box-shadow: none; }
/* Sur SON fond (Apparence → Couleur du fond) : texte et logo lisibles,
   décidés par le noyau (entete_ton) ; tant qu'il est transparent en haut de
   page, son fond ne compte pas. */
.entete { color: var(--site-entete-texte, var(--encre)); }
.entete .logo-sur-sombre { display: none; }
.entete .marque:has(.logo-sur-sombre) .marque-normale { display: var(--site-entete-logo-n, inline); }
.entete .marque .logo-sur-sombre { display: var(--site-entete-logo-c, none); }
.entete .marque-normale img { filter: var(--site-entete-logo-f, none); }
.entete .marque:not(:has(.logo-sur-sombre)) .marque-normale img { filter: var(--site-entete-logo-fi, none); }
:is(.entete.est-transparent, .entete-transparent .entete):not(.est-defile) { --site-entete-texte: var(--encre); --site-entete-logo-n: inline;
  --site-entete-logo-c: none; --site-entete-logo-f: none; --site-entete-logo-fi: none; }
/* Posé sur une ouverture au texte clair : le logo suit ce texte (version
   claire, ou silhouette blanche) — toujours raccord. */
.entete-transparent .entete.ouverture-claire:not(.est-defile) { --site-entete-logo-n: none; --site-entete-logo-c: block; --site-entete-logo-fi: brightness(0) invert(1); }
/* Sur une zone sombre : texte blanc, logo en version claire (s'il y en a une).
   ⚠ Plus précis que « .marque .logo » (display: block), qui suit. */
.entete.est-sur-sombre { color: #fff; }
.entete.est-sur-sombre .marque:has(.logo-sur-sombre) .marque-normale { display: none; }
.entete.est-sur-sombre .marque .logo-sur-sombre { display: block; }
.entete.est-sur-sombre .marque-normale img { filter: none; }
/* Pas de version claire fournie : le logo passe en blanc (silhouette). */
.entete.est-sur-sombre .marque:not(:has(.logo-sur-sombre)) .marque-normale img { filter: brightness(0) invert(1); }
/* Au survol d'une entrée du menu (Apparence → En-tête → Menu) : la couleur
   du lien (d'origine), la couleur d'accent, un trait qui se déploie depuis la
   gauche et se retire vers la droite, ou un badge à l'accent. La page en
   cours porte le même signe, en permanence. */
/* Les entrées de la barre ont toutes la même boîte — avec ou sans sous-menu :
   sinon le souligné ne tombe pas à la même hauteur. */
.entete .nav-barre > .nav-el > :is(a, .nav-parent) { display: inline-flex; align-items: center; gap: .3em; padding-block: .4rem;
  position: relative; transition: color .15s ease; }
/* Le menu en capitales, si on le veut — dans la barre comme sur téléphone. */
:is(.entete, .menu-mobile).menu-majuscules .nav-barre { text-transform: uppercase; letter-spacing: .05em; }
/* Le chevron d'un sous-menu, si on le veut (Apparence → En-tête → Menu). */
.entete.sans-chevron .nav-barre > .nav-el > .nav-parent::after { display: none; }
/* Souligné ou badge : la couleur du texte ne bouge pas (le signe suffit). */
.entete:is(.survol-souligne, .survol-badge, .survol-roule, .survol-special, .survol-wave) .nav-barre > .nav-el > :is(a:hover, a:focus-visible, a[aria-current="page"]) { color: inherit; }
.entete.survol-accent .nav-barre > .nav-el > :is(a:hover, a:focus-visible, a[aria-current="page"]) { color: var(--lien); }
/* « Spécial » : le libellé se peint d'un dégradé — accent aux deux bouts, un
   ton clair entre les deux — qui traverse le mot tant qu'on reste dessus ; sur
   une zone sombre, c'est l'inverse (un ton sombre). Le dégradé est peint DANS
   le texte (background-clip) ; le remplissage devient transparent.
   ⚠ Ce ton ne peut pas être currentColor : le remplissage étant transparent,
   ces lettres-là disparaîtraient. */
.entete.survol-special .nav-barre > .nav-el > :is(a, .nav-parent) .nav-texte {
  --melange: var(--site-entete-fond, var(--fond));
  background-image: linear-gradient(90deg, var(--lien) 0%, var(--melange) 25%, var(--lien) 50%, var(--melange) 75%, var(--lien) 100%);
  background-size: 200% 100%; background-position: 100% 0; background-repeat: repeat-x;
  -webkit-background-clip: text; background-clip: text; }
.entete.survol-special .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-texte,
.entete.survol-special .nav-barre > .nav-el > a[aria-current="page"] .nav-texte {
  -webkit-text-fill-color: transparent; animation: sobre-degrade 2.2s linear infinite; }
@keyframes sobre-degrade { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) {
  .entete.survol-special .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-texte { animation: none; background-position: 50% 0; }
}
/* Le trait court sous le TEXTE (.nav-texte), jamais sous une pastille. */
.entete.survol-souligne .nav-barre > .nav-el > :is(a, .nav-parent) .nav-texte { position: relative; }
.entete.survol-souligne .nav-barre > .nav-el > :is(a, .nav-parent) .nav-texte::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px; background: currentColor;
  transform: scaleX(0); transform-origin: right center; transition: transform .3s; }
.entete.survol-souligne .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-texte::after,
.entete.survol-souligne .nav-barre > .nav-el > a[aria-current="page"] .nav-texte::after { transform: scaleX(1); transform-origin: left center; }
.entete.survol-badge .nav-barre > .nav-el > :is(a, .nav-parent) { padding: .55em 1.1em; border-radius: 999px; transition: background-color .15s ease, color .15s ease; }
.entete.survol-badge .nav-barre { gap: .25rem .6rem; }
.entete.survol-badge .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent),
.entete.survol-badge .nav-barre > .nav-el > a[aria-current="page"] { background: var(--accent); color: var(--sur-accent); }
.entete.survol-badge .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .mn-label,
.entete.survol-badge .nav-barre > .nav-el > a[aria-current="page"] .mn-label { background: var(--sur-accent); color: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .entete .nav-barre > .nav-el > :is(a, .nav-parent)::after, .entete.survol-badge .nav-barre > .nav-el > :is(a, .nav-parent) { transition: none; }
}
/* « Le texte roule » (repris de quidu.fr) : le libellé remonte et sa copie
   arrive par le bas, dans une boîte qui coupe. Ailleurs, la boîte ne change
   rien du tout. */
.nav-roule { display: contents; }
/* Deux emplois pour la même recette : la barre quand l'Apparence choisit
   « reveal », et TOUJOURS les liens d'un panneau — pastilles comme rangées. */
.entete.survol-roule .nav-barre > .nav-el > :is(a, .nav-parent) .nav-roule,
.nav-col li > :is(a, span) .nav-roule { display: block; overflow: hidden; line-height: 1.3; }
.entete.survol-roule .nav-barre > .nav-el > :is(a, .nav-parent) .nav-roule > span,
.nav-col li > :is(a, span) .nav-roule > span { display: block; position: relative; transition: transform .55s cubic-bezier(.25, 1, .33, 1); }
.entete.survol-roule .nav-barre > .nav-el > :is(a, .nav-parent) .nav-roule > span::after,
.nav-col li > :is(a, span) .nav-roule > span::after {
  content: attr(data-texte); position: absolute; left: 0; bottom: -120%; transition: transform .55s cubic-bezier(.25, 1, .33, 1); }
.entete.survol-roule .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-roule > span,
.nav-col li > a:is(:hover, :focus-visible) .nav-roule > span { transform: translateY(-100%); }
.entete.survol-roule .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-roule > span::after,
.nav-col li > a:is(:hover, :focus-visible) .nav-roule > span::after { transform: translateY(-20%); }
@media (prefers-reduced-motion: reduce) {
  .entete.survol-roule .nav-barre > .nav-el > :is(a, .nav-parent) .nav-roule > span, .entete.survol-roule .nav-barre > .nav-el > :is(a, .nav-parent) .nav-roule > span::after,
  .nav-col li > :is(a, span) .nav-roule > span, .nav-col li > :is(a, span) .nav-roule > span::after { transition: none; }
}
/* Le logo aussi peut onduler (Apparence → Logo → Au survol). Une image se
   filtre telle quelle : pas de copie à fondre, c'est l'amplitude qui monte
   (entete.js) ; sans script, elle ondule d'emblée. */
.entete.logo-onde .marque:hover .logo, .entete.logo-onde .marque:focus-visible .logo { filter: url(#xxvii-onde); }
@media (prefers-reduced-motion: reduce) { .entete.logo-onde .marque:hover .logo { filter: none; } }
/* « Wave » (repris de codefronts.com) : une copie du libellé, posée dessus,
   ondule sous un filtre SVG ; elle se fond au survol.
   ⚠ filter: url() ne se transitionne jamais — d'où la copie et son fondu. Le
   filtre n'est posé qu'au survol : ailleurs, rien à recalculer. */
.entete.survol-wave .nav-barre > .nav-el > :is(a, .nav-parent) .nav-texte { position: relative; display: inline-block; }
.entete.survol-wave .nav-net { display: block; transition: opacity .45s ease; }
.entete.survol-wave .nav-onde { position: absolute; inset: 0; opacity: 0; white-space: nowrap;
  pointer-events: none; user-select: none; transition: opacity .45s ease; }
.entete.survol-wave .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-net { opacity: 0; }
.entete.survol-wave .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-onde { opacity: 1; filter: url(#xxvii-onde); }
@media (prefers-reduced-motion: reduce) {
  .entete.survol-wave .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-net { opacity: 1; }
  .entete.survol-wave .nav-barre > .nav-el:is(:hover, :focus-within) > :is(a, .nav-parent) .nav-onde { opacity: 0; filter: none; }
}
/* Sur une zone sombre, l'accent se lirait mal : le texte reste clair, et le
   dégradé de « spécial » ne se peint pas. */
.entete.est-sur-sombre.survol-accent .nav-barre > .nav-el > :is(a:hover, a:focus-visible, a[aria-current="page"]) { color: inherit; opacity: .8; }
.entete.est-sur-sombre.survol-special .nav-barre > .nav-el > :is(a, .nav-parent) .nav-texte { --melange: var(--encre); }
.entete.est-sur-sombre .nav a:hover { color: inherit; opacity: .8; }
/* Téléphone : le menu se range derrière le bouton (avec le script ; sans,
   il reste déplié, sur plusieurs lignes). */
.entete-burger { display: none; margin-left: auto; padding: .55rem .35rem; border: 0; background: none; color: inherit; cursor: pointer; }
@media (max-width: 48rem) {
  .js .entete .nav, .js .entete-cote { display: none; }
  .js .entete-burger { display: grid; }
}
/* ☰ en trois traits : au survol, ceux du haut et du bas pivotent et se
   rejoignent au milieu — le bouton devient un +. */
.entete-burger .traits { position: relative; display: block; width: 22px; height: 16px; }
.entete-burger .traits i, .menu-mobile-fermer .croix i { position: absolute; left: 0; width: 100%; height: 2px; border-radius: 2px; background: currentColor; transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
.entete-burger .traits i:nth-child(1) { top: 0; }
.entete-burger .traits i:nth-child(2) { top: 7px; }
.entete-burger .traits i:nth-child(3) { top: 14px; }
.entete-burger:is(:hover, :focus-visible) .traits i:nth-child(1) { transform: translateY(7px) rotate(90deg); }
.entete-burger:is(:hover, :focus-visible) .traits i:nth-child(3) { transform: translateY(-7px) rotate(90deg); }
/* Le menu : un voile noir (70 %) et un panneau qui glisse de la droite ;
   il repart par le même chemin (entete.js attend la fin avant de le masquer). */
.menu-mobile { position: fixed; inset: 0; z-index: 1001; }
.menu-mobile-voile { position: absolute; inset: 0; background: rgb(0 0 0 / .7); opacity: 0; transition: opacity .35s ease; }
.menu-mobile-panneau { position: absolute; top: 0; right: 0; bottom: 0; width: 80%; display: flex; flex-direction: column; gap: 1.6rem;
  padding: 5rem var(--marges) 2rem; overflow-y: auto; overscroll-behavior: contain; background: var(--fond); color: var(--encre);
  transform: translateX(100%); transition: transform .3s cubic-bezier(.7, 0, .84, 0); }
.menu-mobile-plein .menu-mobile-panneau { width: 100%; }
.menu-mobile.est-ouvert .menu-mobile-voile { opacity: 1; }
.menu-mobile.est-ouvert .menu-mobile-panneau { transform: none; transition: transform .5s cubic-bezier(.16, 1, .3, 1); }
.menu-mobile .nav-barre { flex-direction: column; align-items: flex-start; gap: .9rem; font-size: 1.3rem; }
.menu-mobile .nav-deroulant, .menu-mobile .nav-panneau { position: static; visibility: visible; opacity: 1; border: 0; box-shadow: none; padding: .4rem 0 0 1rem; background: none; }
.menu-mobile .nav-panneau img, .menu-mobile .nav-voile { display: none; }
.menu-mobile .nav-colonnes { flex-direction: column; gap: .6rem; }
/* ✕ à la place exacte du ☰ (--burger-* mesurés à l'ouverture) ; au survol,
   la croix fait un quart de tour. */
.menu-mobile-fermer { position: fixed; z-index: 1; top: var(--burger-haut, 1rem); right: var(--burger-droite, 1rem); width: var(--burger-l, 2.5rem); height: var(--burger-h, 2.5rem);
  display: grid; place-items: center; padding: 0; border: 0; background: none; color: var(--encre); cursor: pointer; opacity: 0; transition: opacity .25s ease; }
.menu-mobile.est-ouvert .menu-mobile-fermer { opacity: 1; transition-delay: .15s; }
.menu-mobile-fermer .croix { position: relative; display: block; width: 22px; height: 22px; transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
.menu-mobile-fermer .croix i { top: 10px; }
.menu-mobile-fermer .croix i:nth-child(1) { transform: rotate(45deg); }
.menu-mobile-fermer .croix i:nth-child(2) { transform: rotate(-45deg); }
.menu-mobile-fermer:is(:hover, :focus-visible) .croix { transform: rotate(90deg); }
@media (prefers-reduced-motion: reduce) {
  .menu-mobile-voile, .menu-mobile-panneau, .menu-mobile-fermer, .entete-burger .traits i, .menu-mobile-fermer .croix { transition: none !important; }
}
@media (prefers-reduced-motion: reduce) { .entete, .entete-in { transition: none; } }
.marque { color: var(--encre); text-decoration: none; font-size: 1.15rem; }
.page { flex: 1; }
.entree h1, .liste h1 { font-size: clamp(calc(var(--site-h1, 2.75rem) * .62), 7vw, var(--site-h1, 2.75rem)); line-height: 1.08; margin: 1rem auto calc(var(--marges) * 1.2); }
.corps p { margin: 0 0 1.1em; }
/* Un lien dans le texte : un filet de 1 px sous le mot, qui se retire quand
   on y passe — le mot prend alors la couleur d'accent — et se retrace en
   partant. ⚠ Le fond d'un élément en ligne est rogné sur sa boîte : un filet
   posé SOUS elle (calc(100% + 3px)) ne se voit pas. C'est le padding du bas
   qui le descend. */
.corps a:not(.bouton, .media-agrandir) { color: inherit; text-decoration: none; padding-bottom: 3px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%; background-size: 100% 1px;
  transition: background-size .35s cubic-bezier(.16, 1, .3, 1), color .2s ease; }
.corps a:not(.bouton, .media-agrandir):is(:hover, :focus-visible) { color: var(--accent); background-size: 0 1px; }
/* ⚠ Un corps ne contient pas que de la prose : un champ Sélection ou Blocs y
   met des cartes, des galeries, des « Tout voir », une liste de lieux — tout
   cela porte ses propres gestes, et le filet leur barrerait le bas. Le filet
   ne vaut donc que pour un lien de texte courant. */
.corps :is(.cartes, .galerie, .media, .selection-tete, .selection-pied, .carte-lieux, .bloc-grille, .filtres) a,
.corps a:has(img) { padding-bottom: 0; background-image: none; }
/* Le titre d'une ligne de programme prend le geste inverse : rien, puis le
   filet se trace. */
.style-agenda .carte-titre { background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 calc(100% + 3px); background-size: 0 1px;
  transition: background-size .35s cubic-bezier(.16, 1, .3, 1); }
.style-agenda .carte-entree a:is(:hover, :focus-visible) .carte-titre { background-size: 100% 1px; text-decoration: none; }
@media (prefers-reduced-motion: reduce) { .corps a:not(.bouton) { transition: none; } }
.champ { color: var(--gris); }
.pied { padding-top: calc(var(--marges) * 2.4); padding-bottom: 2rem; color: var(--gris); font-size: .875rem; border-top: 1px solid var(--filet); margin-top: calc(var(--marges) * 3.2); }
.vide { color: var(--gris); }
.fiche { display: grid; gap: .35rem 1.5rem; grid-template-columns: max-content 1fr; margin: 0 0 1.5rem; }
.fiche > div { display: contents; }
.fiche dt { color: var(--gris); }
.fiche dd { margin: 0; }
.intertitre { font-size: .8rem; text-transform: uppercase; letter-spacing: .08em; color: var(--gris); margin: 2rem 0 .75rem; }

/* Texte riche : la structure vient du contenu, l'apparence d'ici. */
.corps h2 { font-size: var(--site-h2, 1.5rem); line-height: 1.2; margin: calc(var(--marges) * 1.76) 0 .8rem; }
.corps h3 { font-size: var(--site-h3, 1.2rem); line-height: 1.3; margin: calc(var(--marges) * 1.44) 0 .6rem; }
.corps ul, .corps ol { padding-left: 1.4rem; margin: 0 0 1.1em; }
.corps li + li { margin-top: .3em; }
.corps blockquote { margin: 1.6rem 0; padding-left: 1.2rem; border-left: 3px solid var(--accent); color: var(--gris); font-size: 1.1rem; }
.corps blockquote p:last-child { margin-bottom: 0; }
.corps code { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: .9em; background: var(--filet); padding: .1em .35em; border-radius: 4px; }
.corps pre { background: var(--encre); color: var(--fond); padding: 1rem 1.2rem; border-radius: var(--arrondi); overflow-x: auto; font-size: .9rem; }

/* Images : la largeur de la colonne, le poids servi par srcset. */
.media { margin: 2rem 0; }
.media img { display: block; width: 100%; height: auto; border-radius: var(--arrondi-images); }
.media figcaption { margin-top: .5rem; font-size: .85rem; color: var(--gris); }

/* ── Menus ─────────────────────────────────────────────────────────────── */
.nav ul { list-style: none; margin: 0; padding: 0; }
/* ⚠ Pas la pastille : elle garde sa couleur, calculée sur l'accent. */
.nav a, .nav span:not(.mn-label) { color: inherit; text-decoration: none; }
.nav a:hover, .nav a[aria-current="page"] { color: var(--lien); }
.nav-barre { display: flex; flex-wrap: wrap; gap: .25rem 1.4rem; align-items: center; }
.nav-el { position: static; }
.nav-parent { display: inline-flex; align-items: center; gap: .3rem; padding: .4rem 0; }
.nav-parent::after { content: ""; width: .35em; height: .35em; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg) translateY(-2px); opacity: .6; }
.nav-sep { width: 1px; height: 1.1em; background: var(--filet); }
.nav-deroulant ul, .nav-col ul .nav-sep { margin-left: .8rem; }
.nav-deroulant .nav-sep, .nav-col .nav-sep { width: auto; height: 1px; margin: .4rem 0; }
/* Fermés par défaut, ouverts au survol comme au clavier. */
.nav-deroulant, .nav-panneau { visibility: hidden; opacity: 0; transition: opacity .15s ease, visibility .15s; z-index: 10; }
.nav-el:hover > .nav-deroulant, .nav-el:focus-within > .nav-deroulant,
.nav-el:hover > .nav-panneau, .nav-el:focus-within > .nav-panneau,
.nav-el.est-ouvert > .nav-deroulant, .nav-el.est-ouvert > .nav-panneau { visibility: visible; opacity: 1; }
.avec-deroulant { position: relative; }
.nav-deroulant { position: absolute; top: 100%; left: -1rem; min-width: 14rem; padding: .6rem 1rem; background: var(--fond); border: 1px solid var(--filet); border-radius: 6px; box-shadow: 0 10px 30px rgb(0 0 0 / .08); }
.nav-deroulant li { padding: .25rem 0; }
/* Le panneau d'un menu en colonnes, en DEUX boîtes.

   · .nav-panneau place, et ne se voit pas. Son conteneur est toujours l'en-tête
     (.nav-el reste statique) : les deux accroches partent donc exactement de la
     même hauteur. Sa gouttière haute descend la carte sous la barre — et comme
     cette gouttière lui appartient, la survoler c'est encore le survoler : pas
     de zone morte entre l'entrée et la carte.
   · .nav-colonnes est la carte : fond, arrondi, et l'ombre qu'on lui demande.
     Pas de filet — l'ombre suffit à la détacher, et sans ombre le panneau se
     pose franchement sur la page.

   Largeur : « pleine » va de bord à bord, « du site » prend --site-largeur,
   « libre » la valeur choisie (--pan-l), toujours ramenée entre les marges.
   Accroche : « milieu » centre sur la page ; « entrée » aligne le bord droit du
   panneau sur celui de l'entrée, et entete.js pose --nav-x (mesuré depuis
   l'en-tête) pour qu'il ne sorte jamais de la page. */
/* La gouttière se dit en crans de 5 px. Positive, elle descend la carte sans
   creuser de vide : elle est le rembourrage du panneau, donc survolée comme
   lui. Négative, il n'y a rien à survoler — le panneau mord sur la barre. */
.nav-panneau { position: absolute; left: 0; right: 0; --pan-g: calc(var(--pan-gout, 1) * 5px);
  top: calc(100% + min(var(--pan-g), 0px)); padding-top: max(var(--pan-g), 0px); }
.nav-el:is(.pan-site, .pan-libre) .nav-panneau {
  right: auto; width: min(var(--pan-l, var(--site-largeur, 100%)), calc(100vw - var(--marges) * 2));
}
.nav-el:is(.pan-site, .pan-libre).ancre-milieu .nav-panneau { left: 50%; translate: -50% 0; }
.nav-el:is(.pan-site, .pan-libre).ancre-entree .nav-panneau { left: var(--nav-x, 0px); }
.nav-panneau.avec-fond { color: #fff; }
.nav-panneau.avec-fond a:hover { color: #fff; text-decoration: underline; }
.nav-fond { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Un fond vidéo occupe exactement la place d'un fond image, partout. */
.ouverture-fond video, .appel-fond video, video.nav-fond, video.nav-col-fond { width: 100%; height: 100%; object-fit: cover; display: block; }
.nav-voile { position: absolute; inset: 0; background: #000; }
.nav-colonnes { position: relative; display: flex; gap: 1.5rem; align-items: stretch;
  padding: 1.5rem; background: var(--fond); border-radius: var(--arrondi); overflow: hidden; }
/* L'ombre se dose en crans, comme celle de l'en-tête : 4 % par cran. */
.nav-panneau.avec-ombre .nav-colonnes { box-shadow: 0 16px 40px rgb(0 0 0 / calc(var(--pan-ombre, 3) * 4%)); }
.nav-col { min-width: 0; position: relative; display: flex; flex-direction: column; }
.nav-col-in { position: relative; display: flex; flex-direction: column; gap: .4rem; height: 100%; }
.nav-titre { font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; opacity: .7; }
.nav-col li { padding: .15rem 0; }
.nav-visuel { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--arrondi-images); }

/* ── Colonne : la taille de son titre ──────────────────────────────────── */
/* « Grand » : une phrase, pas un intertitre — la police des titres du site,
   sans capitales forcées ni opacité. */
.nav-col.est-titre-grand .nav-titre { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 600);
  font-size: var(--site-h3, 1.5rem); line-height: 1.15; text-transform: none; letter-spacing: -.01em; opacity: 1; margin-bottom: .6rem; }

/* ── Colonne : la forme de ses liens ───────────────────────────────────── */
.nav-col.est-cartes li > a, .nav-col.est-cartes li > span { display: block; padding: .6rem .8rem; border: 1px solid var(--filet); border-radius: 6px; }
/* ⚠ Ces règles habillent l'entrée elle-même : son enfant DIRECT, jamais ses
   entrailles. Depuis que le « reveal » met des <span> DANS les liens, un
   sélecteur « li span » les attraperait aussi — et l'on se retrouverait avec
   trois rembourrages emboîtés (vu à l'écran le 25/09). */
/* Pastilles : elles passent à la ligne, d'où la liste en flex. */
.nav-col.est-pastilles ul { display: flex; flex-wrap: wrap; gap: .5rem; }
.nav-col.est-pastilles li { padding: 0; }
.nav-col.est-pastilles li > a, .nav-col.est-pastilles li > span {
  display: inline-block; padding: .5rem 1rem; border-radius: 999px;
  background: var(--fond); color: var(--encre); border: 1px solid var(--filet); line-height: 1.2;
}
.nav-col.est-pastilles li > a:hover, .nav-col.est-pastilles li > a:focus-visible {
  background: var(--accent); color: var(--sur-accent); border-color: transparent; text-decoration: none;
}
/* Rangées : des lignes hautes séparées d'un filet, que le survol remplit de la
   couleur d'accent. La colonne mange le rembourrage du panneau du côté où elle
   touche le bord, pour que les rangées aillent d'un bord à l'autre — et elle
   garde sa propre encre, même posée sur un panneau à fond sombre. */
.nav-col.est-rangees { background: var(--fond); color: var(--encre); }
.nav-col.est-rangees .nav-col-in { gap: 0; }
.nav-col.est-rangees ul { display: flex; flex-direction: column; height: 100%; }
.nav-col.est-rangees li { flex: 1; padding: 0; display: flex; }
.nav-col.est-rangees li + li { border-top: 1px solid var(--filet); }
.nav-col.est-rangees li > a, .nav-col.est-rangees li > span {
  flex: 1; display: flex; align-items: center; justify-content: center; text-align: center;
  padding: 1.6rem 1.2rem; font-size: .8rem; text-transform: uppercase; letter-spacing: .08em; color: var(--encre);
}
.nav-col.est-rangees li > a:hover, .nav-col.est-rangees li > a:focus-visible {
  background: var(--accent); color: var(--sur-accent); text-decoration: none;
}
.nav-col.est-rangees .nav-titre:not(.titre-masque) { padding: 1.2rem 1.2rem 0; }

/* Une colonne qui porte sa propre surface — fond d'image, ou rangées — va d'un
   bord à l'autre du panneau : elle mange le rembourrage du panneau du côté où
   elle touche le bord, et la gouttière quand sa voisine est du même bois (deux
   surfaces qui se touchent, comme chez Or Bleu). Une voisine en simple liste
   garde sa gouttière : du texte ne colle pas à une photo. */
.nav-col:is(.est-hab-fond, .est-rangees) { margin-block: -1.5rem; }
.nav-col:is(.est-hab-fond, .est-rangees):first-child { margin-left: -1.5rem; }
.nav-col:is(.est-hab-fond, .est-rangees):last-child { margin-right: -1.5rem; }
.nav-col:is(.est-hab-fond, .est-rangees) + .nav-col:is(.est-hab-fond, .est-rangees) { margin-left: -1.5rem; }

/* ── Colonne : ce qui l'habille ────────────────────────────────────────── */
/* Un fond de colonne porte son propre voile, comme celui du panneau : la
   lisibilité ne dépend pas de l'image qu'on y met. */
/* Sans image, un fond de colonne reste un fond : la couleur d'accent, et
   l'encre que le produit garantit lisible dessus. On peut donc composer le
   panneau d'abord et poser la photo ensuite, sans passage par un état illisible. */
.nav-col.est-hab-fond { background: var(--accent); color: var(--sur-accent); }
.nav-col.est-hab-fond.avec-image { background: none; color: #fff; }
.nav-col.est-hab-fond .nav-col-in { padding: 1.5rem; }
.nav-col.est-hab-fond > .nav-col-fond { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Sur un fond d'image, le titre et le lien de bas de colonne passent au blanc,
   fût-ce des liens : la couleur d'accent ne se lit pas sur une photo. */
.nav-col.est-hab-fond .nav-titre, .nav-col.est-hab-fond .nav-col-lien { color: inherit; opacity: 1; }
.nav-col.est-hab-fond .nav-col-lien { opacity: .85; }
.nav-col.est-hab-fond.est-pastilles li > a, .nav-col.est-hab-fond.est-pastilles li > span { background: #fff; color: #111; border-color: transparent; }
/* Le lien de bas de colonne : discret, poussé en bas, et souligné d'un trait
   qui se déploie depuis la gauche puis se retire vers la droite — la même
   recette que le survol « souligné » de la barre. */
.nav-col-lien { margin-top: auto; padding-top: .8rem; font-size: .75rem; text-transform: uppercase; letter-spacing: .08em; opacity: .85; align-self: flex-start; }
.nav-col-lien > span { position: relative; }
.nav-col-lien > span::after { content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 1px;
  background: currentColor; transform: scaleX(0); transform-origin: right center; transition: transform .3s; }
.nav-col-lien:is(:hover, :focus-visible) { opacity: 1; text-decoration: none; }
.nav-col-lien:is(:hover, :focus-visible) > span::after { transform: scaleX(1); transform-origin: left center; }
@media (prefers-reduced-motion: reduce) { .nav-col-lien > span::after { transition: none; } }

/* ── Le panneau sur téléphone ──────────────────────────────────────────── */
/* Il y redevient une liste : plus de colonnes, donc plus de surface propre —
   ni débord, ni fond, ni hauteur imposée, ni capitales. Ces règles viennent
   APRÈS celles des colonnes : c'est l'ordre qui les fait gagner, sans avoir à
   gonfler leur spécificité. */
/* La géométrie du panneau voyage sur son entrée, et l'entrée est dupliquée
   dans le tiroir : sans ce rappel, le menu du téléphone hériterait d'une
   largeur de bureau et déborderait du tiroir. */
.menu-mobile .nav-el .nav-panneau { width: auto; left: auto; translate: none; padding-top: 0; }
/* La carte n'en est plus une dans le tiroir : ni fond, ni arrondi, ni ombre. */
.menu-mobile .nav-panneau .nav-colonnes { padding: 0; background: none; border-radius: 0; box-shadow: none; }
.menu-mobile .nav-panneau .nav-col { margin: 0; background: none; color: inherit; }
/* Même forme de sélecteur que la règle de débord, pour la battre par l'ordre. */
.menu-mobile .nav-panneau .nav-col:is(.est-hab-fond, .est-rangees) { margin: 0; }
.menu-mobile .nav-panneau .nav-col :is(.nav-titre, .nav-col-lien) { color: inherit; }
.menu-mobile .nav-panneau .nav-col-in { padding: 0; height: auto; }
.menu-mobile .nav-panneau .nav-col ul { display: block; height: auto; }
.menu-mobile .nav-panneau .nav-col li { flex: none; display: list-item; border: 0; padding: 0; }
.menu-mobile .nav-panneau .nav-col li > :is(a, span) {
  display: block; padding: .2rem 0; border: 0; border-radius: 0; background: none;
  text-align: left; text-transform: none; letter-spacing: 0; font-size: inherit; color: inherit;
}
/* Labels : pastille, devant, exposant, indice, point. */
/* Pastille d'un lien de menu : assez grande pour se lire (le chiffre est
   petit par nature) ; sa couleur de texte est calculée sur l'accent. */
.mn-label { display: inline-flex; align-items: center; justify-content: center; margin-left: .35em; font-size: .8em; font-weight: 600; line-height: 1; letter-spacing: .01em; background: var(--accent); color: var(--sur-accent); border-radius: 999px; }
.mn-label.est-pastille, .mn-label.est-avant { min-width: 1.7em; height: 1.7em; padding: 0 .45em; }
.mn-label.est-avant { margin: 0 .3em 0 0; }
.mn-label.est-exposant { vertical-align: super; padding: .1em .35em; border-radius: 3px; }
.mn-label.est-indice { vertical-align: sub; padding: .1em .35em; border-radius: 3px; }
.mn-label.est-point { width: .45em; height: .45em; padding: 0; vertical-align: super; }
.pied { display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.pied .nav-barre { gap: .25rem 1rem; }
@media (prefers-reduced-motion: reduce) { .nav-deroulant, .nav-panneau { transition: none; } }

/* ── Contenus extérieurs : le bandeau et son rappel ────────────────────── */
/* Rendu caché, montré par tiers.js seulement si le visiteur n'a pas encore
   choisi : sans script, il ne gêne personne — et il n'aurait rien à commander,
   puisque sans script aucun contenu extérieur ne se charge. */
.tiers { position: fixed; z-index: 60; display: flex; gap: 1rem var(--gouttiere); align-items: center; flex-wrap: wrap;
  padding: 1.1rem 1.4rem; background: var(--fond); color: var(--encre);
  border: 1px solid var(--filet); border-radius: var(--arrondi); box-shadow: 0 16px 40px rgb(0 0 0 / .14); }
.tiers-bas { left: var(--marges); right: var(--marges); bottom: var(--marges); }
.tiers-coin { left: var(--marges); bottom: var(--marges); max-width: 26rem; }
.tiers-centre { left: 50%; top: 50%; translate: -50% -50%; width: min(34rem, calc(100vw - var(--marges) * 2)); }
.tiers-dit { flex: 1; min-width: min(20rem, 100%); }
.tiers-dit b { display: block; margin-bottom: .25rem; }
.tiers-dit p { margin: 0; font-size: .9rem; color: var(--gris); }
.tiers-choix { display: flex; gap: .6rem; flex-wrap: wrap; }
/* Le détail, rubrique par rubrique : il ne paraît qu'à la demande, et prend
   toute la largeur du bandeau pour rester lisible. */
.tiers-rubriques { flex: 1 0 100%; display: flex; flex-direction: column; gap: .5rem; margin: 0; padding: .8rem 0 0; list-style: none; border-top: 1px solid var(--filet); }
.tiers-rubrique { display: flex; align-items: flex-start; gap: .6rem; font-size: .9rem; cursor: pointer; }
.tiers-rubrique input { margin-top: .2rem; flex: none; }
.tiers-rubrique b { display: block; font-weight: 600; }
.tiers-rubrique span span { display: block; color: var(--gris); font-size: .85rem; }
.tiers-choix .bouton { padding: .5rem 1.1rem; font-size: .9rem; }
.pied-tiers { padding: 0; border: 0; background: none; color: var(--gris); font: inherit; font-size: .85rem;
  /* Sans opacity : à .7 le texte tombait à 2,84:1. La couleur seule donne 5,10:1. */
  cursor: pointer; text-decoration: underline; text-underline-offset: .18em; }
.pied-tiers:hover { color: var(--encre); }

/* ── Réglages rendus par le thème ──────────────────────────────────────── */
.marque .logo { display: block; height: var(--site-logo-hauteur, 2.2rem); width: auto; max-width: 20rem; object-fit: contain; }
/* Le logo mène à l'accueil : l'effet de survol réglé dans l'Apparence. */
.marque .logo, .marque { transition: opacity .2s ease, transform .2s ease; transform-origin: left center; }
.marque:hover .logo, .marque:focus-visible .logo { opacity: var(--site-logo-survol-opacite, 1); transform: scale(var(--site-logo-survol-echelle, 1)); }
.marque:not(:has(.logo)):hover { opacity: var(--site-logo-survol-opacite, 1); }
@media (max-width: 40rem) { .marque .logo { height: min(var(--site-logo-hauteur, 2.2rem), 3rem); } }
@media (prefers-reduced-motion: reduce) { .marque .logo, .marque { transition: none; } .marque:hover .logo { transform: none; } }
.visuellement-cache { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.bandeau-maintenance { padding: .5rem 1.25rem; background: #FFF3CD; color: #5C4400; font-size: .85rem; text-align: center; }
.apercu-flottant { position: fixed; top: 1rem; right: 1rem; z-index: 1000; display: flex; align-items: flex-start; gap: .75rem; max-width: min(24rem, calc(100vw - 2rem));
  padding: .75rem .75rem .75rem 1rem; border-radius: 8px; background: #FFF3CD; color: #5C4400; font: 400 .85rem/1.45 system-ui, sans-serif;
  box-shadow: 0 8px 30px rgb(0 0 0 / .18); animation: sobre-note .35s cubic-bezier(.16, 1, .3, 1) both; }
.apercu-flottant:has(.apercu-fermer-case:checked) { display: none; }
.apercu-fermer-case { position: absolute; top: .5rem; right: .5rem; width: 1.75rem; height: 1.75rem; margin: 0; opacity: 0; cursor: pointer; }
.apercu-flottant label { flex: none; display: grid; place-items: center; width: 1.75rem; height: 1.75rem; margin: -.25rem -.25rem 0 0; border-radius: 50%; font-size: 1.2rem; line-height: 1; cursor: pointer; }
.apercu-fermer-case:hover + span + label, .apercu-fermer-case:focus-visible + span + label { background: rgb(92 68 0 / .12); }
.apercu-fermer-case:focus-visible + span + label { outline: 2px solid #5C4400; }
@keyframes sobre-note { from { opacity: 0; transform: translateY(-8px); } }
@media (prefers-reduced-motion: reduce) { .apercu-flottant { animation: none; } }
.coordonnees { display: flex; flex-direction: column; gap: .25rem; }
.coordonnees address { font-style: normal; }
.coordonnees a { color: inherit; }
.reseaux { list-style: none; margin: .25rem 0 0; padding: 0; display: flex; gap: .8rem; flex-wrap: wrap; }

/* Sélecteur de langue : les codes, dans leur propre langue au survol. */
.langues ul { list-style: none; margin: 0 0 0 auto; padding: 0; display: flex; gap: .6rem; font-size: .8rem; letter-spacing: .06em; }
.langues a { color: var(--gris); text-decoration: none; }
.langues a:hover { color: var(--lien); }
.langues [aria-current] { font-weight: 700; }

/* Galerie, dates, fichier, entrées liées, filtres de liste. */
.galerie { display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: var(--gouttiere); margin: 0 0 1.5rem; }
.galerie .media { margin: 0; }
.galerie img { width: 100%; height: auto; }

/* ── La visionneuse en page (disposition « Visionneuse ») ──────────────────
   Une grande image, sa légende, ses vignettes. La hauteur de la scène est
   celle réglée dans le bloc, en pourcentage de la hauteur d'écran (--vision-h).

   ⚠ SANS SCRIPT, les vues restent empilées et tout se lit : c'est scene.js qui
   pose « est-vive », et c'est cette classe SEULE qui autorise à n'en montrer
   qu'une. Masquer d'abord et espérer le script ensuite laisserait une page
   vide à qui ne l'exécute pas. */
.galerie.est-visionneuse { display: flex; flex-direction: column; gap: .75rem; }
.est-visionneuse .scene { position: relative; }
.est-visionneuse .scene-vues { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--gouttiere); }
.est-visionneuse .scene-vue { margin: 0; }
.est-visionneuse .scene-vue .media { margin: 0; }
.est-visionneuse.est-vive .scene-vues { display: block; }
.est-visionneuse.est-vive .scene-vue { display: none; }
.est-visionneuse.est-vive .scene-vue.est-courant { display: block; }
/* « contain » et non « cover » : ces photos sont des pièces entières, on ne
   coupe pas un pied de chaise pour remplir un cadre. */
/* ⚠ LA HAUTEUR RÉGLÉE VAUT POUR LE BLOC ENTIER, pas pour la seule image :
   légende et vignettes comprises. La scène prend ce qu'elles laissent
   (flex: 1), et l'image s'y loge en entier. Régler « la hauteur de l'image »
   sans compter la bande de vignettes donnait un bloc plus haut que demandé,
   d'autant plus faux que les vignettes sont grandes. */
.est-visionneuse.est-vive { height: var(--vision-h, 60vh); }
.est-visionneuse.est-vive .scene { flex: 1; min-height: 0; }
.est-visionneuse.est-vive :is(.scene-vues, .scene-vue, .scene-vue .media, .scene-vue .media-cadre, .scene-vue .media-agrandir) { height: 100%; }
/* « contain » : ces photos sont des pièces entières, on ne coupe pas un pied
   de chaise pour remplir un cadre. */
.est-visionneuse.est-vive .scene-vue img { width: 100%; height: 100%; object-fit: contain; }
/* ⚠ L'ASPECT DE CES COMMANDES EST ÉCRIT UNE SEULE FOIS, plus bas, avec celles
   de la fenêtre d'agrandissement (« .scene-nav, .visionneuse button ») : deux
   flèches et une croix, le même geste dans toutes les galeries — il n'avait pas
   à être dessiné deux fois, avec deux tailles et deux fonds qui divergeaient.
   Ici, seulement leur PLACE. */
.est-visionneuse .scene-nav { top: 50%; translate: 0 -50%; }
.est-visionneuse .scene-prec { left: .5rem; }
.est-visionneuse .scene-suiv { right: .5rem; }
.est-visionneuse .scene-compteur { position: absolute; right: .75rem; bottom: .75rem; z-index: 2;
  margin: 0; padding: .15rem .55rem; border-radius: 99px; font-size: .8rem;
  background: color-mix(in oklab, var(--fond) 78%, transparent); color: var(--texte-doux, var(--texte)); }
/* Le fer des textes : réglé sur le bloc, il vaut pour les trois lignes. */
.est-visionneuse .scene-legende { display: flex; flex-direction: column; gap: .15rem; min-height: 2.75rem; }
.est-visionneuse.fer-centre .scene-legende { align-items: center; text-align: center; }
.est-visionneuse.fer-droite .scene-legende { align-items: flex-end; text-align: right; }
.est-visionneuse .scene-titre { font-weight: 600; }
.est-visionneuse .scene-texte { color: var(--texte-doux, var(--texte)); font-size: .925rem; }
/* ⚠ LA BANDE DES VIGNETTES A DU RESPIRE, et ce n'est pas cosmétique : le
   liseré de la vignette choisie est un « outline » posé à 2 px du bouton. Sans
   marge intérieure, « overflow » le rogne en haut et en bas — on voyait les
   côtés du cadre, pas ses arêtes. La barre de défilement est masquée (même
   geste que .presentation-defilant) et la vignette choisie se ramène au
   CENTRE : la bande se lit alors comme un ruban, sans ascenseur à pousser.
   ⚠ Pas de fondu aux bords : le thème l'a tranché pour ses bandes défilantes
   (« bord à bord, sans barre ni fondu »), et un cliquet de fumée l'interdit
   dans toute la feuille. Une même feuille, une même réponse. */
/* ⚠ LE BANDEAU VA D'UN BORD À L'AUTRE de la page — le motif du thème, celui
   de .est-pleine — et masque ce qui dépasse. La PISTE, à l'intérieur, est ce
   que le script fait tourner par translation.

   ⚠ PLUS DE DÉFILEMENT NATIF. Le boucler demanderait de replacer scrollLeft
   d'une largeur de jeu à chaque bord franchi, et ce saut se bat avec le
   défilement doux : la bande part à l'envers ou se fige. Une translation n'a
   aucun bord à franchir. Contrepartie assumée : on ne fait plus glisser la
   bande au doigt ; le geste reste sur la scène, qui l'écoute déjà.

   ⚠ LE VIDE AUX DEUX BOUTS EST PARTI (0.9.142). Il existait parce que la
   première et la dernière vignette butaient. Rien ne bute plus. */
.est-visionneuse .scene-vignettes { width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw);
  overflow: hidden; padding: 5px 0; }
.est-visionneuse .scene-piste { list-style: none; margin: 0; padding: 0; display: flex;
  width: max-content; gap: var(--ecart-vignettes, .5rem); }
/* L'écart du bloc commande l'espace entre les vignettes. */
.ecart-serre .est-visionneuse .scene-piste { --ecart-vignettes: .25rem; }
.ecart-normal .est-visionneuse .scene-piste { --ecart-vignettes: .5rem; }
.ecart-large .est-visionneuse .scene-piste { --ecart-vignettes: 1rem; }
.est-visionneuse .scene-piste li { flex: none; }
.est-visionneuse .scene-vignettes button { display: block; padding: 0; border: 0; cursor: pointer; background: none;
  border-radius: var(--rayon, 4px); overflow: hidden; opacity: .55;
  transition: opacity var(--dur, .2s) ease, outline-color var(--dur, .2s) ease;
  outline: 2px solid transparent; outline-offset: 2px; }
.est-visionneuse .scene-vignettes img { display: block; width: 4.5rem; height: 5.5rem; object-fit: cover; }
.est-visionneuse .scene-vignettes button:is(:hover, :focus-visible) { opacity: .85; }
.est-visionneuse .scene-vignettes button.est-courant { opacity: 1; outline-color: var(--accent); }
@media (max-width: 48rem) {
  /* ⚠ SUR TÉLÉPHONE, LA HAUTEUR RÉGLÉE NE S'APPLIQUE PAS. Une part d'écran
     choisie devant un grand moniteur ne veut plus rien dire sur un portrait de
     poche : le bloc reprend sa hauteur naturelle et l'image se borne à 60 %
     de l'écran, pour qu'il reste de la place aux vignettes et au texte. */
  .est-visionneuse.est-vive { height: auto; }
  .est-visionneuse.est-vive .scene { flex: none; }
  .est-visionneuse.est-vive :is(.scene-vues, .scene-vue, .scene-vue .media, .scene-vue .media-cadre, .scene-vue .media-agrandir) { height: auto; }
  .est-visionneuse.est-vive .scene-vue img { height: 60vh; }
  .est-visionneuse .scene-vignettes img { width: 3.5rem; height: 4.25rem; }
}
@media (prefers-reduced-motion: reduce) {
  .est-visionneuse .scene-vignettes button { transition: none; }
  /* La piste ne glisse plus : scene.js coupe lui-même sa transition. */
  .est-visionneuse .scene-piste { transition: none !important; }
}
.dates { list-style: none; padding: 0; margin: 0; }
.fichier span { color: var(--gris); }
/* La puce ne vaut que pour la liste de simples liens : une suite de cartes
   apporte sa propre mise en page, et ce retrait décalerait ses filets. */
.liees ul:not(.cartes) { padding-left: 1.2rem; }
/* La barre des filtres : les champs à choix en onglets, à gauche ; une
   relation, qui ouvre souvent beaucoup de valeurs, en liste déroulante, à
   droite. Les deux marchent sans script (liens, puis formulaire). */
.filtres-barre { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 2rem; margin: 0 0 2rem; }
.filtres ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 1.4rem; }
.filtres a { display: inline-block; padding: .2rem 0; color: var(--gris); text-decoration: none; font-size: .95rem;
  transition: color .2s ease; }
.filtres a sup { font-size: .68em; margin-left: .25em; vertical-align: super; }
/* Seul le mot porte le filet, jamais le nombre — et il se trace, comme un
   lien de texte. */
.filtres a b { font-weight: inherit; padding-bottom: 3px;
  background-image: linear-gradient(var(--accent), var(--accent));
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px;
  transition: background-size .35s cubic-bezier(.16, 1, .3, 1); }
.filtres a:is(:hover, :focus-visible), .filtres a[aria-current] { color: var(--encre); }
.filtres a:is(:hover, :focus-visible) b, .filtres a[aria-current] b { background-size: 100% 1px; }
/* La liste déroulante prend la forme d'une pilule ; son bouton ne sert qu'à
   ceux qui n'ont pas de script (liste.js le retire). */
.filtres { order: 0; }
.filtre-liste { order: 1; display: flex; align-items: center; gap: .6rem; margin-left: auto; }
.filtre-select { appearance: none; padding: .55rem 2.4rem .55rem 1.1rem; font: inherit; font-size: .95rem;
  color: inherit; background: transparent; border: 1px solid var(--filet); border-radius: 999px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 1.15rem) 1.15em, calc(100% - .9rem) 1.15em; background-size: 5px 5px; background-repeat: no-repeat;
  transition: border-color .2s ease; }
.filtre-select:is(:hover, :focus-visible) { border-color: var(--gris); }
/* Les vignettes se remplacent sans recharger la page : le temps de l'aller
   et retour, la grille s'estompe. */
.cartes.est-en-route { opacity: .35; transition: opacity .2s ease; }
@media (prefers-reduced-motion: reduce) { .filtres a, .filtres a b, .filtre-select, .cartes.est-en-route { transition: none; } }
/* ── La fiche d'une entrée (entree.php) ─────────────────────────────────
   Une ouverture qui porte la couverture, les pastilles, le titre au centre et
   le sous-titre dessous ; puis le texte à sa mesure, la galerie et les
   contenus liés à la largeur du site, et le passage à la fiche voisine. */
.page > .entree.avec-ouverture { max-width: none; }
.entree.avec-ouverture > .fiche-ouverture { width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.fiche-ouverture { position: relative; display: grid; place-items: center; text-align: center; overflow: clip;
  padding: calc(var(--marges) * 3) var(--marges); }
.fiche-ouverture.avec-image { color: #fff; }
.fiche-ouverture.ouverture-pleine { min-height: 100vh; min-height: 100svh; }
.fiche-ouverture.ouverture-bandeau { min-height: 60vh; min-height: 60svh; }
.fiche-ouverture .ouverture-texte { max-width: 50rem; }
.fiche-ouverture h1 { margin: 0; }
/* L'affiche posée à côté du titre : deux moitiés égales, l'affiche à gauche,
   le texte à droite ; la couverture reste le fond. Le texte se range à gauche
   — centré, il flotterait au milieu d'une demi-largeur. */
/* ⚠ Les deux ouvertures — celle d'une fiche et le bloc Ouverture — partagent
   cette composition. `:is()` prend la force de son membre le plus fort, mais
   ici les deux sont une classe : la règle pèse autant qu'avant. */
:is(.fiche-ouverture, .bloc-ouverture).avec-affiche { text-align: left; }
.ouverture-compo { position: relative; z-index: 2; width: 100%; max-width: var(--site-largeur, var(--mesure));
  margin: 0 auto; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 5vw, 72px); align-items: center; }
.ouverture-affiche { display: flex; justify-content: center; }
/* ⚠ Bornée en MAX, jamais `width: 100%` avec un `max-height` : la boîte
   prendrait toute la colonne alors qu'une affiche verticale n'en peint qu'une
   part — et l'ombre portée, dessinée autour de la BOÎTE, flotterait à distance
   du papier. Ainsi bornée, la boîte épouse l'image quel que soit son format. */
.ouverture-affiche img { max-width: min(100%, 32rem); max-height: 72svh; width: auto; height: auto;
  display: block; border-radius: var(--arrondi-images); box-shadow: 0 26px 60px rgb(0 0 0 / .45); }
:is(.fiche-ouverture, .bloc-ouverture).avec-affiche .ouverture-texte { max-width: none; }
:is(.fiche-ouverture, .bloc-ouverture).avec-affiche :is(.fiche-pastilles, .ouverture-boutons) { justify-content: flex-start; }
.fiche-texte { margin: .9rem 0 0; max-width: 46ch; opacity: .88; }
.fiche-texte p { margin: .5rem 0 0; }
.fiche-texte p:first-child { margin-top: 0; }
.fiche-ouverture:not(.avec-affiche) .fiche-texte { margin-left: auto; margin-right: auto; }
@media (max-width: 56rem) {
  .ouverture-compo { grid-template-columns: 1fr; gap: clamp(20px, 5vw, 40px); }
  .ouverture-affiche img { max-height: 42svh; }
}
.fiche-sous-titre { margin: .9rem 0 0; font-size: clamp(1rem, 2.2vw, 1.35rem); line-height: 1.35; opacity: .9; }
.fiche-bouton { margin: 1.6rem 0 0; }
.fiche-pastilles { display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem; margin: 0 0 1.3rem; }
.pastille { display: inline-block; padding: .3rem .85rem; border: 1px solid currentColor; border-radius: 999px;
  font-size: .75rem; text-transform: uppercase; letter-spacing: .07em; text-decoration: none; color: inherit; opacity: .85;
  transition: background .2s ease, color .2s ease, border-color .2s ease, opacity .2s ease; }
/* La pastille d'état n'est pas un lien : elle est pleine, pour se distinguer
   de celles qui mènent quelque part. Sur une photo, elle s'inverse. */
.pastille-etat { background: var(--encre); border-color: var(--encre); color: var(--fond); opacity: 1; }
/* ⚠ Sur une photo, la pastille d'état n'est PAS blanche : elle serait plus
   criante que le titre. Le gris profond translucide d'Or Bleu la pose sans
   la faire crier, et le flou derrière la tient lisible sur n'importe quelle
   image. */
.fiche-ouverture.avec-image .pastille-etat { background: rgb(18 18 20 / .62); border-color: transparent; color: #fff;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.fiche-ouverture.avec-image a.pastille:is(:hover, :focus-visible) { background: #fff; border-color: #fff; color: #111; opacity: 1; }
.fiche-ouverture:not(.avec-image) a.pastille:is(:hover, :focus-visible) { background: var(--accent); border-color: var(--accent); color: var(--sur-accent); opacity: 1; }
.fiche-suite { padding-top: calc(var(--marges) * 4); }
.entree.avec-ouverture .fiche-suite > * { max-width: var(--mesure); margin-left: auto; margin-right: auto; }
.entree.avec-ouverture .fiche-suite > .carte { max-width: var(--site-largeur, var(--mesure)); }
.entree.avec-ouverture .fiche-suite > .liees { margin-top: calc(var(--marges) * 3); }
/* Le titre d'une suite de contenus liés : une étiquette, pas un titre de
   chapitre — il annonce « Au programme », il ne concurrence pas le nom. */
.liees > .intertitre { font-family: inherit; font-size: .8rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .12em; color: var(--accent); text-align: center; margin: 0 0 1.2rem; }
.style-agenda :is(.carte-titre, .carte-entree time) { font-weight: 400; }
/* Plus fort que « les enfants de la suite tiennent la mesure » : sinon les
   marges automatiques recentrent la bande et la décalent d'une demi-page. */
.entree.avec-ouverture .fiche-suite > .fiche-nav { max-width: none; width: 100vw;
  margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); margin-bottom: 0; }
/* La bande vient buter contre le pied de page : c'est l'écart du pied qu'il
   faut retirer, pas celui de la bande — la page n'en avait aucun. */
.page:has(.fiche-nav) + .pied { margin-top: 0; }
/* La galerie sort de la mesure du texte pour prendre celle du site — sans
   aller bord à bord : ce sont des vignettes, pas une ouverture. */
.entree.avec-ouverture .fiche-suite .corps > .galerie-justifiee {
  width: min(var(--site-largeur, 100%), calc(100vw - var(--marges) * 2)); margin-left: 50%; translate: -50%; }
/* La galerie d'une fiche : des rangées justifiées comme la médiathèque —
   chaque image garde ses proportions (--r) et pousse à partir d'une hauteur
   cible ; la rangée a donc une seule hauteur et remplit la largeur. La
   dernière ne s'étire pas (le pseudo-élément prend le reste). */
.galerie-justifiee { display: flex; flex-wrap: wrap; gap: calc(var(--gouttiere) * .5);
  margin: calc(var(--marges) * 3) 0; --rangee-h: 260px; }
.galerie-justifiee::after { content: ""; flex: 999 1 0; }
.galerie-justifiee .media-agrandir { display: block; position: relative; overflow: hidden;
  flex: var(--r, 1.5) var(--r, 1.5) calc(var(--r, 1.5) * var(--rangee-h)); min-width: 0;
  aspect-ratio: var(--r, 1.5); border-radius: var(--arrondi-images); background: var(--filet); }
.galerie-justifiee img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit;
  transition: scale .5s cubic-bezier(.16, 1, .3, 1); }
.galerie-justifiee .media-agrandir:is(:hover, :focus-visible) img { scale: 1.04; }
@media (max-width: 48rem) { .galerie-justifiee { --rangee-h: 150px; } }
/* D'une fiche à l'autre : une bande bord à bord, deux moitiés et le retour à
   la liste au milieu. Survoler une moitié y découvre la couverture de la
   voisine — l'image est là, sous un voile, et le voile s'écarte. */
.fiche-nav { display: grid; grid-template-columns: 1fr auto 1fr; align-items: stretch;
  margin-top: calc(var(--marges) * 2.5); border-top: 1px solid var(--filet); border-bottom: 1px solid var(--filet);
  width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.fiche-nav-cote { position: relative; display: grid; align-items: center; overflow: clip;
  min-height: 15rem; padding: calc(var(--marges) * 1.5) calc(var(--marges) * 2.5); color: inherit; text-decoration: none; }
.fiche-nav-prec { justify-items: end; text-align: right; }
.fiche-nav-suiv { justify-items: start; }
.fiche-nav-fond { position: absolute; inset: 0; opacity: 0; transition: opacity .45s ease; }
.fiche-nav-fond img { width: 100%; height: 100%; object-fit: cover; display: block;
  scale: 1; transition: scale .8s cubic-bezier(.16, 1, .3, 1); }
.fiche-nav-cote:is(:hover, :focus-visible) .fiche-nav-fond img { scale: 1.08; }
.fiche-nav-fond::after { content: ""; position: absolute; inset: 0; background: rgb(0 0 0 / .45); }
.fiche-nav-cote:is(:hover, :focus-visible) .fiche-nav-fond { opacity: 1; }
.fiche-nav-cote.avec-image:is(:hover, :focus-visible) { color: #fff; }
.fiche-nav-texte { position: relative; display: grid; gap: .3rem; }
.fiche-nav-sens { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: var(--gris);
  transition: color .3s ease; }
.fiche-nav-cote.avec-image:is(:hover, :focus-visible) .fiche-nav-sens { color: rgb(255 255 255 / .8); }
.fiche-nav-prec .fiche-nav-sens::before { content: "\2039\00a0\00a0"; }
.fiche-nav-suiv .fiche-nav-sens::after { content: "\00a0\00a0\203a"; }
.fiche-nav-titre { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 600);
  font-size: clamp(1.2rem, 2.4vw, 1.9rem); line-height: 1.15; }
/* Le retour à la liste, entre les deux, dans sa gouttière. */
.fiche-nav-toutes { display: grid; justify-items: center; align-content: center; gap: .5rem;
  padding: var(--marges) calc(var(--marges) * 1.6); color: var(--gris); text-decoration: none;
  border-left: 1px solid var(--filet); border-right: 1px solid var(--filet); transition: color .2s ease; }
.fiche-nav-toutes span { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; }
.fiche-nav-toutes:is(:hover, :focus-visible) { color: var(--encre); }
.fiche-nav-cote.est-vide { min-height: 0; }
@media (max-width: 48rem) {
  .fiche-nav { grid-template-columns: 1fr; }
  .fiche-nav-cote { min-height: 9rem; justify-items: start; text-align: left; }
  .fiche-nav-toutes { border: 0; border-top: 1px solid var(--filet); border-bottom: 1px solid var(--filet); }
}
@media (prefers-reduced-motion: reduce) { .fiche-nav-fond, .fiche-nav-sens, .fiche-nav-fond img { transition: none; } }
@media (prefers-reduced-motion: reduce) { .galerie-justifiee img, .pastille { transition: none; } }

.entree-liste { padding: 1.5rem 0; border-top: 1px solid var(--filet); }
.entree-liste h2 { font-size: 1.25rem; margin: 0 0 .75rem; }
.intro { margin-bottom: 2rem; }

/* Carte des lieux (_carte.php) : un cadre qui attend le clic, puis la carte ;
   la liste numérotée reste dessous, avec ou sans carte. */
.carte { margin: 2.5rem 0 0; }
.carte-cadre { position: relative; border: 1px solid var(--filet); border-radius: var(--arrondi); padding: 2rem 1.25rem; text-align: center; background: color-mix(in srgb, var(--encre) 3%, var(--fond)); }
.carte-cadre.est-ouvert { padding: 0; overflow: hidden; }
.carte-cadre.est-ouvert .carte-bouton, .carte-cadre.est-ouvert .carte-note { display: none; }
.carte-bouton { font: inherit; font-weight: 600; padding: .6rem 1.1rem; border-radius: var(--arrondi-boutons); border: 1px solid var(--accent); background: var(--accent); color: var(--sur-accent); cursor: pointer; }
.carte-bouton:disabled { opacity: .6; cursor: progress; }
.carte-note { color: var(--gris); font-size: .8rem; margin: .75rem 0 0; }
.carte-toile { height: var(--carte-hauteur, min(28rem, 70vh)); }
/* En attendant le clic : le schéma des lieux, à la hauteur de la carte. */
.carte-cadre:not(.est-ouvert) { min-height: var(--carte-hauteur, 16rem); display: flex; flex-direction: column; align-items: center; justify-content: flex-end; padding-bottom: 1.25rem; }
.carte-cadre > :not(.carte-schema) { position: relative; }
.carte-schema { position: absolute; inset: 0; width: 100%; height: 100%; }
.carte-cadre.est-ouvert .carte-schema { display: none; }
.carte-trame { fill: none; stroke: var(--filet); stroke-width: 1; }
.carte-schema circle { fill: var(--carte-repere, var(--accent)); stroke: var(--fond); stroke-width: 3; }
.carte-schema text { fill: var(--sur-accent); font: 600 20px/1 system-ui, sans-serif; text-anchor: middle; }
.carte-schema .est-loin { opacity: .45; }
/* Liste à côté de la carte. */
.carte.liste-cote { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); column-gap: var(--gouttiere); align-items: start; }
.carte.liste-cote > h2 { grid-column: 1 / -1; }
.carte.liste-cote .carte-lieux { margin-top: 0; max-height: var(--carte-hauteur, 28rem); overflow-y: auto; }
@media (max-width: 48rem) { .carte.liste-cote { grid-template-columns: minmax(0, 1fr); } .carte.liste-cote .carte-lieux { margin-top: 1rem; max-height: none; } }
.carte-repere { display: grid; place-items: center; border-radius: 50%; background: var(--carte-repere, var(--accent)); color: var(--sur-accent); font: 600 12px/1 system-ui, sans-serif; border: 2px solid #fff; box-shadow: 0 1px 4px rgb(0 0 0 / .35); }
.carte-lieux { counter-reset: lieu; list-style: none; padding: 0; margin: 1rem 0 0; display: grid; gap: .9rem; }
.carte-lieux > li { counter-increment: lieu; display: grid; grid-template-columns: 1.75rem 1fr; column-gap: .6rem; }
.carte-lieux > li::before { content: counter(lieu); grid-row: span 3; width: 1.6rem; height: 1.6rem; border-radius: 50%; background: var(--carte-repere, var(--accent)); color: var(--sur-accent); display: grid; place-items: center; font-size: .75rem; font-weight: 600; }
.carte-nom { font-weight: 600; }
.carte-adresse { color: var(--gris); font-size: .9rem; }
.carte-lieux ul { list-style: none; padding: 0; margin: .3rem 0 0; font-size: .9rem; }

/* Page de liste : ses cartes prennent la largeur du site ; le titre, l'intro
   et les filtres gardent la mesure du texte. Sa mise en page se règle dans le
   type (largeur, marges, écart entre les vignettes, apparition). */
.page > .liste { max-width: var(--site-largeur, var(--mesure)); padding: calc(var(--marges) * var(--bloc-marges, 0)); }
/* Le titre d'une page de liste peut se taire : il reste lu par les lecteurs
   d'écran, et l'introduction prend l'air qu'on lui donne. */
/* Un titre masqué : hors du regard, jamais hors du document. */
.titre-masque, .liste.titre-cache > h1 { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
/* La composition d'une page de liste (son introduction, et demain le reste)
   garde l'air qu'avait l'introduction avant de devenir un bloc.
   ⚠ Un bloc est un conteneur FLEX : les marges de son dernier paragraphe ne
   s'échappent plus de la boîte comme elles le faisaient d'un simple <div>.
   Sans les annuler, le bloc gagne la hauteur de cette marge et tout ce qui
   suit remonte d'autant. */
/* ⚠ L'air se compte sur le BLOC de texte, pas sur la composition entière :
   c'est l'introduction qui le portait, et depuis que les entrées sont un bloc
   à sa suite, une marge posée sur la composition tomberait après elles au lieu
   de les précéder — la barre de filtres remontait de 32 px. */
.liste > .blocs > .bloc-texte { margin-bottom: 2rem; }
/* ⚠ Une page de liste qui s'ouvre par une Ouverture ne garde pas son air du
   haut : l'image doit toucher l'en-tête, comme sur une fiche. La composition
   perd alors sa marge basse, que le premier bloc d'après pose lui-même. */
.liste.avec-ouverture { padding-top: 0; }
.liste.avec-ouverture > .blocs > .bloc-ouverture:first-child { margin-bottom: 0; }
/* ⚠ L'air d'une introduction se comptait VERTICALEMENT seulement : la page de
   liste posait déjà ses marges latérales. Un bloc, lui, applique ses marges
   des quatre côtés — laissées telles quelles, elles rétrécissaient le texte de
   1080 à 840 px. Dans une page de liste, l'horizontale revient à la page. */
.liste > .blocs > .bloc { padding-inline: 0; }
/* ⚠ Et le bloc redevient un conteneur ORDINAIRE, pas flex : c'est le flex qui
   empêchait les marges du dernier paragraphe de s'échapper de la boîte, comme
   elles le faisaient d'une introduction. Les annuler à la main tombait juste
   sans marges et 19 px trop haut avec — le collapse, lui, tombe juste dans les
   deux cas, puisque c'est exactement ce qui avait lieu avant. */
.liste > .blocs > .bloc-texte { display: block; }
.liste > :is(h1, .intro, .filtres, .vide, .entree-liste) { max-width: var(--mesure); }
/* L'introduction peut sortir de la mesure du texte et prendre toute la
   largeur de la page ; son titre la suit. */
/* « Introduction sur toute la largeur » vaut aussi pour le titre. L'ancien
   `.intro` a disparu du sélecteur : c'est un bloc maintenant, et c'est sa
   propre largeur de texte qui décide. */
.liste.intro-pleine > h1 { max-width: none; }
.page > .liste.est-pleine { max-width: none; width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.ecart-serre .cartes { gap: calc(var(--gouttiere) * .3); }
.ecart-large .cartes { gap: calc(var(--gouttiere) * 2); }

/* Sélections : des cartes (image, titre, date), « Tout voir » vers la liste. */
.selection { margin: calc(var(--marges) * 2) auto; }
.selection-tete { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
.selection-tete h2 { margin: 0; font-size: 1.35rem; }
.selection-tete a { font-size: .9rem; white-space: nowrap; }
.cartes { list-style: none; padding: 0; margin: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(12rem, 1fr)); gap: var(--gouttiere); }
.carte-entree a { display: block; color: inherit; text-decoration: none; }
.carte-entree a:hover .carte-titre { text-decoration: underline; }
.carte-image { display: block; position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--arrondi-images); background: var(--filet); margin-bottom: .6rem; }
/* L'image reprend l'arrondi de son cadre : le seul rognage du cadre lâche
   quand la carte s'anime (elle passe sur sa propre couche, et le coin du haut
   se rematérialise carré — vu sur Vitrine au survol). */
.carte-image img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; }
.carte-titre { display: block; font-weight: 600; line-height: 1.3; }
.carte-entree time { display: block; color: var(--gris); font-size: .85rem; margin-top: .2rem; }
/* Présentations d'une sélection (bloc) : grille à N colonnes, liste façon
   agenda (la date à gauche), bande qui défile ; formats des images. */
/* Autant de colonnes que demandé quand il y a la place ; en dessous d'une
   vignette de 8 rem, la grille en reprend d'elle-même — c'est ce qui permet
   d'aller jusqu'à 6 sans écraser les petits écrans. */
.presentation-grille .cartes { grid-template-columns: repeat(auto-fit,
  minmax(max(8rem, calc((100% - (var(--cartes, 3) - 1) * var(--gouttiere)) / var(--cartes, 3))), 1fr)); }
.format-portrait .carte-image { aspect-ratio: 4 / 5; }
.format-carre .carte-image { aspect-ratio: 1; }
.presentation-liste .cartes { grid-template-columns: minmax(0, 1fr); gap: 0; border-top: 1px solid var(--filet); }
.presentation-liste .carte-entree > :is(a, span) { display: grid; grid-template-columns: minmax(8rem, 12rem) minmax(0, 1fr); column-gap: var(--gouttiere); align-items: baseline;
  padding: .9rem 0; border-bottom: 1px solid var(--filet); }
.presentation-liste .carte-image { display: none; }
.presentation-liste .carte-entree time { grid-column: 1; grid-row: 1 / span 4; margin: 0; color: inherit; }
.presentation-liste .carte-entree > :is(a, span) > :not(time) { grid-column: 2; }
/* La barre de défilement s'efface : c'est la vignette coupée au bord qui dit
   qu'il y en a d'autres. Le défilement à la molette, au doigt et au clavier
   marche toujours. */
.presentation-defilant .cartes { display: grid; grid-auto-flow: column; grid-template-columns: none;
  grid-auto-columns: calc((100% - (var(--cartes, 3) - 1) * var(--gouttiere)) / var(--cartes, 3) - 1.5rem);
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; padding-bottom: .6rem;
  scrollbar-width: none; }
.presentation-defilant .cartes::-webkit-scrollbar { display: none; }
.presentation-defilant .carte-entree { scroll-snap-align: start; }
/* Une bande bord à bord court d'un bord à l'autre de l'écran, mais ne commence
   pas collée : la première vignette s'aligne sur la marge du site, et l'aimant
   du défilement s'y recale (scroll-padding) pour ne pas la coller au bord. Les
   marges intérieures du bloc sont annulées de chaque côté, sinon « bord à
   bord » n'irait pas jusqu'au bord. */
:is(.liste, .bloc-selection.est-pleine .selection).presentation-defilant.est-pleine .cartes,
.bloc-selection.est-pleine .selection.presentation-defilant .cartes {
  padding-inline: var(--marges); scroll-padding-inline: var(--marges);
  margin-inline: calc(var(--marges) * var(--bloc-marges, 0) * -1); }
/* Titre posé sur la photo : le nom en grand sur un dégradé ; au survol, la
   photo avance, une flèche et « Voir » paraissent, le nom se souligne. */
.titre-pose .carte-image { position: relative; margin-bottom: 0; container-type: inline-size; }
.titre-pose .carte-image img { transition: scale .5s cubic-bezier(.16, 1, .3, 1); }
.titre-pose .carte-entree a:is(:hover, :focus-visible) .carte-image img { scale: 1.05; }
/* Un voile uniforme sur toute la vignette, qui se fait plus dense au survol —
   pas un dégradé : le nom se lit où qu'il soit, et la photo garde ses valeurs. */
.titre-pose .carte-image::after { content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--carte-voile, rgb(0 0 0 / .22)); transition: background .35s ease; }
.titre-pose .carte-entree a:is(:hover, :focus-visible) .carte-image::after { background: var(--carte-voile-survol, rgb(0 0 0 / .5)); }
.carte-pose { position: absolute; inset: auto 0 0 0; z-index: 2; display: block; padding: 1.4rem 5cqw 4cqw; color: #fff; }
.carte-pose .carte-titre { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 600); line-height: 1.15;
  font-size: clamp(1rem, 7.5cqw, 2.2rem); text-shadow: 0 1px 4px rgb(0 0 0 / .4);
  text-decoration: underline 1px transparent; text-underline-offset: .18em; transition: text-decoration-color .3s ease; }
.titre-pose .carte-entree a:is(:hover, :focus-visible) .carte-titre { text-decoration-color: currentColor; }
.carte-pose .carte-extrait { color: rgb(255 255 255 / .85); font-size: .85rem; margin-top: .35rem;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
/* Une information peut attendre le survol — posée seulement : dessous, elle
   ferait sauter la mise en page. Deux façons d'arriver : un fondu, ou un
   fondu qui monte. */
/* Une information qui attend le survol ne prend aucune place tant qu'elle
   n'est pas là : c'est en la prenant qu'elle fait remonter le titre, posé au
   bas de la vignette. */
.carte-revele { opacity: 0; max-height: 0; overflow: hidden;
  transition: opacity .3s ease, max-height .45s cubic-bezier(.16, 1, .3, 1), translate .4s cubic-bezier(.16, 1, .3, 1); }
.revele-glisse .carte-revele { translate: 0 .6rem; }
.carte-entree a:is(:hover, :focus-visible) .carte-revele { opacity: 1; max-height: 6rem; translate: 0 0; }
/* L'alignement des informations, posées ou dessous (jamais en lignes : là, la
   date tient sa colonne). */
.infos-centre:not(.presentation-liste) .carte-entree > :is(a, span) { text-align: center; }
.infos-droite:not(.presentation-liste) .carte-entree > :is(a, span) { text-align: right; }
/* La flèche, en haut à droite ; la pastille « Voir », au milieu. */
.carte-fleche { position: absolute; z-index: 2; top: .9rem; right: .9rem; width: 1.5rem; height: 1.5rem; color: #fff; opacity: 0;
  filter: drop-shadow(0 1px 3px rgb(0 0 0 / .5)); translate: -.4rem .4rem; transition: opacity .3s ease, translate .4s cubic-bezier(.16, 1, .3, 1); }
.carte-entree a:is(:hover, :focus-visible) .carte-fleche { opacity: 1; translate: 0 0; }
.titre-pose .carte-entree time, .titre-pose .carte-lieu { margin-top: .4rem; }
@media (prefers-reduced-motion: reduce) {
  .titre-pose :is(.carte-image img, .carte-titre, .carte-extrait) { transition: none; }
  :is(.carte-fleche, .carte-revele) { transition: none; translate: none; }
}
/* Légende (en grille) : le texte se lit sous l'image comme la légende d'une
   photo — la catégorie au-dessus du nom, et un filet qui se trace sous le nom
   au survol plutôt qu'un souligné qui s'allume d'un coup. */
.style-legende .carte-image { margin-bottom: .7rem; }
.style-legende .carte-categorie { margin-bottom: .15rem; }
.style-legende .carte-titre { display: inline; background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 100%; background-size: 0 1px;
  transition: background-size .4s cubic-bezier(.16, 1, .3, 1); }
.style-legende .carte-entree a:is(:hover, :focus-visible) .carte-titre { background-size: 100% 1px; text-decoration: none; }
.style-legende .carte-entree time { font-variant-numeric: tabular-nums; }
/* Couverture (en grille) : une une de magazine — le nom repose au bas de
   l'image et monte d'un cran au survol, quand le voile se fait plus dense. */
.style-couverture .carte-image { --carte-voile: rgb(0 0 0 / .28); --carte-voile-survol: rgb(0 0 0 / .58); }
.style-couverture .carte-pose .carte-titre { transition: translate .4s cubic-bezier(.16, 1, .3, 1), text-decoration-color .3s ease; }
.style-couverture .carte-entree a:is(:hover, :focus-visible) .carte-pose .carte-titre { translate: 0 -.25rem; }
/* Agenda (en lignes) : la date tient sa colonne, en couleur d'accent, et la
   ligne qu'on survole s'éclaire sur toute sa largeur. */
.style-agenda .carte-entree time { color: var(--accent); }
.style-agenda .carte-entree > :is(a, span) { padding-inline: 1.1rem; transition: background .2s ease; }
.style-agenda .carte-entree > a:is(:hover, :focus-visible) { background: var(--site-surface, var(--filet)); }
/* Ruban (en bande) : des cartes côte à côte, qui filent vers le bord ; la
   photo s'avance dans son cadre quand on la regarde. */
.style-ruban .carte-image img { transition: scale .5s cubic-bezier(.16, 1, .3, 1); }
.style-ruban .carte-entree a:is(:hover, :focus-visible) .carte-image img { scale: 1.05; }
/* Vitrine (en bande) : de grandes cartes qui se soulèvent au survol. */
.style-vitrine .carte-entree > :is(a, span) { display: block; transition: translate .35s cubic-bezier(.16, 1, .3, 1); }
.style-vitrine .carte-entree > a:is(:hover, :focus-visible) { translate: 0 -.4rem; }
/* Fiches (en lignes) : la vignette s'avance quand on lit la ligne. */
.style-fiches .carte-image img { transition: scale .5s cubic-bezier(.16, 1, .3, 1); }
.style-fiches .carte-entree a:is(:hover, :focus-visible) .carte-image img { scale: 1.06; }
@media (prefers-reduced-motion: reduce) {
  .style-legende .carte-titre, .style-couverture :is(.carte-pose, .carte-pose .carte-titre),
  .style-agenda .carte-entree > :is(a, span), .style-vitrine .carte-entree > :is(a, span),
  .style-fiches .carte-image img, .style-planche .carte-image img, .style-ruban .carte-image img { transition: none; }
}

/* Sommaire (en lignes) : une table des matières — le titre en grand, la date
   menue au bout, la ligne qui avance et prend l'accent au survol. */
.presentation-liste.style-sommaire .carte-entree > :is(a, span) { grid-template-columns: minmax(0, 1fr) auto; align-items: baseline; padding: 1.1rem 0;
  transition: padding-inline-start .3s cubic-bezier(.16, 1, .3, 1), color .2s ease; }
.presentation-liste.style-sommaire .carte-entree > a:is(:hover, :focus-visible) { padding-inline-start: .8rem; color: var(--accent); }
.presentation-liste.style-sommaire .carte-entree > :is(a, span) > :not(time) { grid-column: 1; }
.presentation-liste.style-sommaire .carte-entree time { grid-column: 2; grid-row: auto; margin: 0; font-weight: 400; font-size: .85rem; color: var(--gris); }
.presentation-liste.style-sommaire .carte-titre { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 600);
  font-size: clamp(1.1rem, 2.6vw, 1.8rem); line-height: 1.2; }
.presentation-liste.style-sommaire .carte-entree a:is(:hover, :focus-visible) .carte-titre { text-decoration: none; }
/* Fiches (en lignes) : la vignette revient à gauche, le texte à droite — des
   lignes qui respirent, pour ce qu'on lit avant de cliquer. */
.presentation-liste.style-fiches .carte-entree > :is(a, span) { grid-template-columns: minmax(7rem, 11rem) minmax(0, 1fr); align-items: start; padding: 1.1rem 0; }
.presentation-liste.style-fiches .carte-image { display: block; grid-column: 1; grid-row: 1 / span 5; width: 100%; margin: 0; }
.presentation-liste.style-fiches .carte-entree > :is(a, span) > :not(.carte-image) { grid-column: 2; }
.presentation-liste.style-fiches .carte-entree time { grid-column: 2; grid-row: auto; margin: .2rem 0 0; font-weight: 400; color: var(--gris); }
.presentation-liste.style-fiches .carte-titre { font-size: 1.15rem; }
/* Affiches (en bande) : des affiches serrées ; en survoler une estompe ses
   voisines — c'est la bande qui recule, pas celle qu'on regarde. */
.presentation-defilant.style-affiches .carte-entree { transition: opacity .3s ease; }
.presentation-defilant.style-affiches .cartes:is(:hover, :focus-within) .carte-entree { opacity: .5; }
.presentation-defilant.style-affiches .cartes .carte-entree:is(:hover, :focus-within) { opacity: 1; }
/* Vitrine (en bande) : de grandes cartes, deux à l'écran, le texte dessous —
   un carrousel éditorial. */
.presentation-defilant.style-vitrine .carte-titre { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 600);
  font-size: clamp(1.05rem, 2vw, 1.45rem); line-height: 1.2; margin-top: .3rem; }
.presentation-defilant.style-vitrine .carte-extrait { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
  font-size: .95rem; color: var(--gris); margin-top: .35rem; }
@media (prefers-reduced-motion: reduce) {
  .presentation-liste.style-sommaire .carte-entree > :is(a, span), .presentation-defilant.style-affiches .carte-entree { transition: none; }
}

/* Le curseur qui suit la souris (curseur.js) : une pastille ronde portant un
   mot, qui remplace le pointeur dans les zones qui la demandent. Elle se
   place par son centre — le script lui donne la position de la souris, la
   marge négative fait le reste. Sous l'en-tête (30) et sous le menu du
   téléphone : une pastille ne doit pas passer par-dessus une navigation. */
.curseur-suiveur { position: fixed; top: 0; left: 0; z-index: 25; pointer-events: none;
  width: var(--site-curseur-taille, 72px); height: var(--site-curseur-taille, 72px);
  margin: calc(var(--site-curseur-taille, 72px) / -2);
  display: grid; place-items: center; border-radius: 50%; text-align: center; padding: .4em;
  background: var(--site-curseur-fond, var(--accent)); color: var(--site-curseur-encre, var(--sur-accent));
  font-size: .9rem; line-height: 1.1; opacity: 0; scale: .4;
  transition: opacity .2s ease, scale .3s cubic-bezier(.16, 1, .3, 1); }
.curseur-suiveur.est-la { opacity: 1; scale: 1; }
@media (pointer: fine) { .avec-curseur .cartes, .avec-curseur .cartes * { cursor: none; } }
@media (prefers-reduced-motion: reduce) { .curseur-suiveur { transition: opacity .2s ease; } }

/* Planche : une planche contact — des carrés serrés, les noms en petites
   capitales, et les vignettes en noir et blanc : la couleur ne revient que sur
   celle qu'on regarde. */
.style-planche .carte-image { margin-bottom: .5rem; }
.style-planche .carte-image img { filter: grayscale(1); transition: filter .5s ease, scale .6s cubic-bezier(.16, 1, .3, 1); }
.style-planche .carte-entree a:is(:hover, :focus-visible) .carte-image img { filter: none; scale: 1.04; }
.style-planche .carte-titre { font-size: .8rem; font-weight: 500; text-transform: uppercase; letter-spacing: .09em; }
.style-planche .carte-entree a:is(:hover, :focus-visible) .carte-titre { text-decoration: none; color: var(--accent); }
.style-planche :is(.carte-extrait, .carte-lieu) { font-size: .8rem; color: var(--gris); }
@media (prefers-reduced-motion: reduce) { .style-planche .carte-image img { transition: none; } }
.carte-categorie { display: block; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--gris); margin-bottom: .25rem; }
.carte-lieu, .carte-extrait { display: block; color: var(--gris); font-size: .85rem; margin-top: .2rem; }
.selection-pied { margin: 1.5rem 0 0; }
.selection-vide { color: var(--gris); margin: 0; }
.bloc-selection.tete-centre :is(.selection-tete, .selection-pied) { justify-content: center; text-align: center; }
.bloc-selection.tete-centre .selection-tete { flex-direction: column; align-items: center; }
.bloc-selection.avec-couleur :is(.carte-entree time, .carte-lieu, .carte-extrait, .carte-categorie, .selection-vide) { color: inherit; opacity: .8; }
@media (max-width: 48rem) {
  .presentation-defilant .cartes { grid-auto-columns: 70%; }
  .presentation-liste .carte-entree > :is(a, span) { grid-template-columns: minmax(0, 1fr); }
  .presentation-liste .carte-entree time, .presentation-liste .carte-entree > :is(a, span) > :not(time) { grid-column: 1; grid-row: auto; }
}

/* Blocs (noyau/blocs.php) : une page composée. Le texte garde sa mesure ;
   les autres blocs prennent la largeur réglée du site. */
.page > .entree-composee { max-width: none; }
.entree-composee > * { max-width: var(--mesure); margin-left: auto; margin-right: auto; }
.entree-composee > .blocs { max-width: none; }
/* Les blocs se touchent : l'espace appartient à chaque bloc (ses marges
   intérieures), jamais à l'entre-deux — un fond coloré va jusqu'au suivant.
   Les blocs sans réglage de mise en page gardent leur respiration dedans. */
.bloc { margin: 0 auto; }
.bloc:not(.bloc-ouverture, .bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-appel, .bloc-selection, .bloc-media, .bloc-carte) { padding-block: calc(var(--marges) * 1.2); }
/* Texte et colonnes : réglables comme une ouverture (largeur, hauteur — auto
   par défaut —, marges, placement, couleurs). Le texte garde sa mesure ; les
   colonnes prennent la largeur et s'alignent dedans. */
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte) { display: flex; flex-direction: column; max-width: none;
  min-height: calc(var(--bloc-hauteur, 0) * var(--xxvii-vh, 1vh)); min-height: calc(var(--bloc-hauteur, 0) * var(--xxvii-vh, 1svh));
  padding: calc(var(--marges) * var(--bloc-marges, 0)); background: var(--bloc-fond, transparent); color: var(--bloc-texte, inherit); }
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte).avec-fond { border-radius: var(--arrondi); }
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte).contenu-haut { justify-content: flex-start; }
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte).contenu-milieu { justify-content: center; }
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte).contenu-bas { justify-content: flex-end; }
:is(.bloc-texte, .bloc-colonnes, .bloc-chiffres, .bloc-selection, .bloc-media, .bloc-carte).est-pleine { width: 100vw; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.bloc-texte > .corps { width: 100%; max-width: var(--mesure); }
/* Le texte court sur toute la largeur de sa boîte : une introduction, un
   chapeau. C'est ce que faisait l'introduction d'une page de liste réglée
   « sur toute la largeur », avant de devenir un bloc. */
.bloc-texte > .corps-large { max-width: none; }
.bloc-texte.tete-gauche { align-items: flex-start; } .bloc-texte.tete-centre { align-items: center; } .bloc-texte.tete-droite { align-items: flex-end; }
.bloc-colonnes.tete-gauche { text-align: left; } .bloc-colonnes.tete-centre { text-align: center; } .bloc-colonnes.tete-droite { text-align: right; }
:is(.bloc-colonnes, .bloc-chiffres).est-pleine > .bloc-grille { width: 100%; max-width: var(--site-largeur, 70rem); margin: 0 auto; }
.bloc-chiffres.tete-gauche li { text-align: left; } .bloc-chiffres.tete-centre li { text-align: center; } .bloc-chiffres.tete-droite li { text-align: right; }
/* Une couleur de texte choisie vaut aussi pour ses liens et ses citations. */
.bloc.avec-couleur .corps a, .bloc.avec-couleur .corps blockquote { color: inherit; }
/* Boutons : pilule (l'accent), pilule vide, souligné, flèche. */
.bouton { display: inline-block; padding: .65rem 1.3rem; border: 1px solid var(--accent); border-radius: var(--arrondi-boutons); background: var(--accent); color: var(--sur-accent); text-decoration: none; font-weight: 600; line-height: 1.3; }
.bouton:hover { filter: brightness(1.08); }
.bouton-pill-transparent { background: transparent; border-color: currentColor; color: inherit; }
/* Souligné — le geste de Blok : filet discret au repos, second filet tracé
   depuis la gauche au survol, libellé qui roule pour laisser sa copie
   (data-texte) prendre sa place. Aucune marge verticale : la copie se pose à
   top:100% et dépasserait sous le bouton. */
.bouton-souligne { position: relative; display: inline-block; vertical-align: middle; padding: 0; border: 0; border-radius: 0;
  background: none; color: inherit; clip-path: inset(0 0 -4px 0); }
.bouton-souligne::before, .bouton-souligne::after { content: ""; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px; background: currentColor; }
.bouton-souligne::before { opacity: .35; }
.bouton-souligne::after { transform: scaleX(0); transform-origin: right center; transition: transform .3s ease; }
.bouton-souligne:hover::after, .bouton-souligne:focus-visible::after { transform: scaleX(1); transform-origin: left center; }
.bouton-t { display: block; position: relative; transition: transform .55s cubic-bezier(.25, 1, .33, 1); }
.bouton-t::after { content: attr(data-texte); position: absolute; top: 100%; left: 0; white-space: nowrap; }
.bouton-souligne:hover .bouton-t, .bouton-souligne:focus-visible .bouton-t { transform: translateY(-100%); }
/* Flèche — au survol, le libellé glisse et la flèche apparaît à sa gauche
   pendant que celle de droite se referme. Le mouvement passe par la LARGEUR
   des deux traits (0 ↔ 22 px) : le bouton garde sa largeur, ses voisins ne
   bougent pas. */
.bouton-fleche { display: inline-flex; align-items: center; gap: 0; padding: .35em 0; border: 0; border-radius: 0; background: none; color: inherit; }
.bouton-trait { flex: none; display: inline-block; position: relative; width: 22px; height: 1px; background: currentColor;
  transition: width .42s cubic-bezier(.16, 1, .3, 1), margin .42s cubic-bezier(.16, 1, .3, 1), opacity .26s ease, transform .42s cubic-bezier(.16, 1, .3, 1); }
.bouton-trait::after { content: ""; position: absolute; right: 0; top: 50%; width: 7px; height: 7px;
  border-top: 1px solid currentColor; border-right: 1px solid currentColor; transform: translateY(-50%) rotate(45deg); }
.bouton-fleche .trait-g { width: 0; opacity: 0; margin-right: 0; transform: translateX(-8px); }
.bouton-fleche .trait-d { margin-left: .55em; }
.bouton-fleche:hover .trait-g, .bouton-fleche:focus-visible .trait-g { width: 22px; opacity: 1; margin-right: .55em; transform: none; }
.bouton-fleche:hover .trait-d, .bouton-fleche:focus-visible .trait-d { width: 0; opacity: 0; margin-left: 0; transform: translateX(10px); }
.bouton-souligne:hover, .bouton-fleche:hover { filter: none; }
@media (prefers-reduced-motion: reduce) { .bouton-t, .bouton-souligne::after, .bouton-trait { transition: none; } }

/* Ouverture : ses réglages arrivent en variables (noyau/blocs.php) et en
   classes (placement, largeur) ; ce thème en fixe les défauts (theme.json). */
.bloc-ouverture { position: relative; display: flex; flex-direction: column; overflow: clip;
  /* --xxvii-vh : 1 % de l'écran ; l'aperçu de composition le fixe (son cadre a la hauteur de la page). */
  min-height: calc(var(--bloc-hauteur, 60) * var(--xxvii-vh, 1vh)); min-height: calc(var(--bloc-hauteur, 60) * var(--xxvii-vh, 1svh));
  padding: calc(var(--marges) * var(--bloc-marges, 3));
  background: var(--bloc-fond, color-mix(in srgb, var(--encre) 5%, var(--fond)));
  color: var(--bloc-texte, var(--encre)); border-radius: var(--arrondi-images); }
.bloc-ouverture.avec-image { color: var(--bloc-texte, #fff); }
.bloc-ouverture.est-pleine { width: 100vw; max-width: none; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
.bloc-ouverture.tete-gauche { align-items: flex-start; text-align: left; }
.bloc-ouverture.tete-centre { align-items: center; text-align: center; }
.bloc-ouverture.tete-droite { align-items: flex-end; text-align: right; }
.bloc-ouverture.contenu-haut { justify-content: flex-start; }
.bloc-ouverture.contenu-milieu { justify-content: center; }
.bloc-ouverture.contenu-bas { justify-content: flex-end; }
.bloc-ouverture h1 { font-size: clamp(calc(var(--site-h1, 2.75rem) * .7), 8vw, calc(var(--site-h1, 2.75rem) * 1.3)); line-height: 1.04; margin: 0; }
.ouverture-texte { position: relative; max-width: 50rem; }
/* Taille, casse et approche sont réglables : voir la section « typographie
   fine » en fin de feuille. Ici ne reste que ce qu'elle ne gouverne pas. */
.ouverture-surtitre { opacity: .75; margin: 0 0 1rem; }
.ouverture-chapo { opacity: .85; margin: 1.2rem 0 0; max-width: 36rem; }
.tete-centre .ouverture-chapo { margin-left: auto; margin-right: auto; }
.tete-droite .ouverture-chapo { margin-left: auto; }
.ouverture-boutons { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.4rem; margin-top: 1.6rem; }
.tete-centre .ouverture-boutons { justify-content: center; }
.tete-droite .ouverture-boutons { justify-content: flex-end; }
.ouverture-fond { position: absolute; inset: 0; overflow: clip; }
.ouverture-fond img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ouverture-fond::after { content: ""; position: absolute; inset: 0; background: var(--ouverture-voile, rgb(0 0 0 / .35)); }
/* Quand c'est terminé, la photo de fond passe presque en noir et blanc : la
   page se lit au premier coup d'œil comme une archive. */
.fiche-ouverture.est-passee .ouverture-fond img { filter: grayscale(.88) contrast(.96); }
/* Invitation à défiler — le trait de Blok (3.176 → 3.197) : il se remplit par
   le haut, puis se vide par le bas ; il évoque un écoulement plutôt qu'une
   flèche. Au survol, un chevron se dessine au bout et c'est l'OUVERTURE qui
   répond : son contenu se soulève, la photo respire (propriété `scale` :
   la parallaxe se sert de `translate`, les deux se composent). */
@keyframes sobre-defiler {
   0% { transform: scaleY(0); transform-origin: top; }
  45% { transform: scaleY(1); transform-origin: top; }
  55% { transform: scaleY(1); transform-origin: bottom; }
 100% { transform: scaleY(0); transform-origin: bottom; }
}
.ouverture-defiler { position: absolute; left: 50%; bottom: calc(var(--marges) * 1.6); z-index: 3; display: block;
  width: 26px; height: 52px; transform: translateX(-50%); color: inherit; transition: transform .35s cubic-bezier(.16, 1, .3, 1); }
/* Le rail : l'atténuation est DANS sa couleur, jamais en opacité (elle
   gagnerait le remplissage, qui perdrait son contraste). */
.ouverture-defiler i { position: absolute; left: 50%; top: 0; width: 1px; height: 100%; overflow: hidden;
  transform: translateX(-50%); background: color-mix(in srgb, currentColor 35%, transparent); }
.ouverture-defiler b { position: absolute; inset: 0; background: currentColor; animation: sobre-defiler 2.4s cubic-bezier(.65, 0, .35, 1) infinite; }
/* Zone de survol élargie, invisible : le trait fait un pixel de large. */
.ouverture-defiler::before { content: ""; position: absolute; left: 50%; top: 50%; width: 120px; height: 84px; transform: translate(-50%, -50%); }
/* Le chevron touche le trait, comme la pointe d'une flèche sa hampe. */
.ouverture-defiler::after { content: ""; position: absolute; left: 50%; bottom: 2px; width: 9px; height: 9px;
  border-right: 1px solid currentColor; border-bottom: 1px solid currentColor; opacity: 0;
  transform: translate(-50%, 6px) rotate(45deg); transition: opacity .3s ease, transform .35s cubic-bezier(.16, 1, .3, 1); }
.ouverture-defiler:hover, .ouverture-defiler:focus-visible { transform: translateX(-50%) translateY(4px); }
.ouverture-defiler:hover::after, .ouverture-defiler:focus-visible::after { opacity: 1; transform: translate(-50%, 0) rotate(45deg); }
.ouverture-texte { transition: transform .45s cubic-bezier(.16, 1, .3, 1); }
.ouverture-fond img { transition: scale .6s cubic-bezier(.16, 1, .3, 1); }
.bloc-ouverture:has(.ouverture-defiler:is(:hover, :focus-visible)) .ouverture-texte { transform: translateY(-12px); }
.bloc-ouverture:has(.ouverture-defiler:is(:hover, :focus-visible)) .ouverture-fond img { scale: 1.04; }
@media (prefers-reduced-motion: reduce) {
  .ouverture-defiler b { animation: none; }
  .ouverture-defiler, .ouverture-defiler::after, .ouverture-texte, .ouverture-fond img { transition: none; }
}
/* En-tête transparent : il se pose sur l'ouverture qui ouvre la page (sa
   hauteur, --entete-h, est rendue par le bas de l'en-tête). */
.entete-transparent .entete { margin-bottom: calc(-1 * var(--entete-h)); }
.entete-transparent .entete:not(.est-defile):not(.est-sur-sombre) { color: var(--entete-texte, inherit); }
.entete .marque { color: inherit; }
:is(.entete) :is(.nav-deroulant, .nav-panneau:not(.avec-fond)) { color: var(--encre); }
.bloc-ouverture.sous-entete { padding-top: calc(var(--marges) * var(--bloc-marges, 3) + var(--entete-h)); }
/* Avec l'invitation à défiler, le contenu remonte : il laisse la place au trait. */
.bloc-ouverture.avec-defiler { padding-bottom: calc(var(--marges) * var(--bloc-marges, 3) + 5rem); }
.entete-transparent .page > .entree-composee:first-child > .blocs:first-child > .bloc-ouverture:first-child { margin-top: 0; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
/* Une ancre atteinte sans script (adresse avec « #… ») : elle s'arrête sous
   l'en-tête quand celui-ci reste en haut. Avec le script, entete.js recale. */
html:has(:is(.entete-fixe, .entete-cache, .entete-reduit)) { scroll-padding-top: var(--entete-h); }
/* Parallaxe — reprise de Blok (3.176 → 3.196) : pilotée par le DÉFILEMENT
   (animation-timeline: view()), sans script là où le navigateur sait faire.
   ⚠ `overflow: hidden` ferait du bloc un conteneur de défilement : view()
   mesurerait l'image dans un cadre qui ne défile jamais, et rien ne
   bougerait. D'où `overflow: clip` (plus haut) et clip-path.
   ⚠ On anime `translate`, pas `transform` : les deux se composent.
   ⚠ Sens : l'image RETIENT (de -a % à +a %), elle ne devance pas la page.
   La réserve (--parallaxe-h, --parallaxe-t) vient du serveur, selon la force. */
@keyframes sobre-parallaxe { from { translate: 0 calc(var(--parallaxe-a, 10) * -1%); } to { translate: 0 calc(var(--parallaxe-a, 10) * 1%); } }
@media (prefers-reduced-motion: no-preference) {
  .avec-parallaxe.parallaxe-js, .avec-parallaxe .parallaxe-js-img { will-change: translate; }
  .avec-parallaxe.parallaxe-js { clip-path: inset(0 round var(--arrondi-images)); }
  .avec-parallaxe .parallaxe-js-img { height: calc(var(--parallaxe-h, 128) * 1%); top: calc(var(--parallaxe-t, -14) * 1%); position: absolute; }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .bloc-ouverture.avec-parallaxe { clip-path: inset(0 round var(--arrondi-images)); }
    .avec-parallaxe .ouverture-fond img { position: absolute; left: 0; width: 100%;
      height: calc(var(--parallaxe-h, 128) * 1%); top: calc(var(--parallaxe-t, -14) * 1%);
      animation: sobre-parallaxe linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
  }
}
.bloc-grille { display: grid; grid-template-columns: repeat(var(--colonnes, 3), minmax(0, 1fr)); gap: var(--gouttiere); list-style: none; padding: 0; margin: 0; }
.bloc-colonne h2 { font-size: 1.1rem; margin: 0 0 .4rem; }
.bloc-colonne p { margin: 0; color: var(--gris); }
.bloc-colonnes.avec-couleur .bloc-colonne p { color: inherit; opacity: .85; }
/* L'icône d'une colonne : au-dessus de son titre, à l'accent. */
.colonne-icone { display: block; width: 2rem; height: 2rem; margin: 0 0 .75rem; color: var(--accent); }
.bloc-colonnes.avec-couleur .colonne-icone { color: inherit; }
.tete-centre .colonne-icone { margin-left: auto; margin-right: auto; }
.tete-droite .colonne-icone { margin-left: auto; }
/* Chiffres clés : deux filets tant qu'il n'a pas de fond. */
.bloc-chiffres:not(.avec-fond) { border-top: 1px solid var(--filet); border-bottom: 1px solid var(--filet); }
.bloc-chiffres li { display: flex; flex-direction: column; gap: .3rem; }
.bloc-chiffres strong { font-family: var(--site-police-titres, inherit); font-weight: var(--site-graisse-titres, 700); font-size: clamp(1.8rem, 5vw, 2.6rem); line-height: 1; }
.bloc-chiffres span { color: var(--gris); font-size: .85rem; }
.bloc-chiffres.avec-couleur span { color: inherit; opacity: .8; }
.bloc .selection, .bloc .carte { margin: 0; }
/* Image ou galerie. Le cadre porte le recadrage (--media-ratio, l'image
   garde son point focal) ; un clic l'agrandit (visionneuse.js). */
.bloc-media .media { position: relative; margin: 0; }
.media-cadre { display: block; position: relative; overflow: clip; border-radius: var(--arrondi-images); }
.media-cadre img { display: block; width: 100%; height: auto; }
.est-recadre .media-cadre { aspect-ratio: var(--media-ratio); }
.est-recadre .media-cadre img { height: 100%; object-fit: cover; }
/* ⚠ Le lien « agrandir » enveloppe l'image : sans hauteur, l'image recadrée
   (height: 100 %) n'avait rien à remplir et gardait son format. */
.est-recadre .media-agrandir { height: 100%; }
.media-agrandir { display: block; cursor: zoom-in; }
.media-agrandir img { transition: scale .6s cubic-bezier(.16, 1, .3, 1); }
.media-agrandir:hover img { scale: 1.02; }
.bloc-media figcaption, .bloc-legende { color: var(--gris); font-size: .85rem; margin: .5rem 0 0; }
.bloc-media.avec-couleur :is(figcaption, .bloc-legende) { color: inherit; opacity: .8; }
.bloc-media.est-seule.taille-texte .media { width: 100%; max-width: var(--mesure); }
.bloc-media.est-seule.tete-centre { align-items: center; } .bloc-media.est-seule.tete-droite { align-items: flex-end; }
.bloc-media.est-seule .media { width: 100%; }
/* Légende sur l'image : en bas, sur un dégradé qui la rend lisible. */
.bloc-media.legende-sur figcaption { position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: 2.5rem 1rem .8rem; color: #fff; opacity: 1;
  background: linear-gradient(to top, rgb(0 0 0 / .65), transparent); border-radius: 0 0 var(--arrondi-images) var(--arrondi-images); pointer-events: none; }
/* Parallaxe d'une image recadrée : la même que l'ouverture. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .bloc-media.avec-parallaxe .media-cadre img { position: absolute; left: 0; width: 100%;
      height: calc(var(--parallaxe-h, 128) * 1%); top: calc(var(--parallaxe-t, -14) * 1%);
      animation: sobre-parallaxe linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
  }
}
/* Galerie : grille, mosaïque (formats d'origine), bande défilante ; écart. */
.bloc-media .galerie { width: 100%; margin: 0; gap: var(--gouttiere); }
/* Grille justifiée (celle de la médiathèque, en CSS) : chaque image pousse
   selon son format (--r) à partir d'une hauteur cible (--rangee-h) ; une
   rangée a donc une seule hauteur et remplit la largeur. La dernière ne
   s'étire pas (le pseudo-élément prend le reste). Les légendes passent sur
   l'image : dessous, elles désaligneraient les rangées. */
.bloc-media.disposition-grille .galerie { display: flex; flex-wrap: wrap; }
.bloc-media.disposition-grille .galerie::after { content: ""; flex: 999 1 0; }
.bloc-media.disposition-grille .media { flex: var(--r, 1.5) var(--r, 1.5) calc(var(--r, 1.5) * var(--rangee-h, 280px)); min-width: 0; }
.bloc-media.disposition-grille .media-cadre { aspect-ratio: var(--r, 1.5); }
.bloc-media.disposition-grille .media-cadre img, .bloc-media.disposition-grille .media-agrandir { width: 100%; height: 100%; object-fit: cover; }
.bloc-media.disposition-grille .media figcaption { position: absolute; left: 0; right: 0; bottom: 0; margin: 0; padding: 1.8rem .7rem .5rem; color: #fff; opacity: 0;
  font-size: .78rem; background: linear-gradient(to top, rgb(0 0 0 / .65), transparent); border-radius: 0 0 var(--arrondi-images) var(--arrondi-images);
  pointer-events: none; transition: opacity .25s ease; }
.bloc-media.disposition-grille .media:is(:hover, :focus-within) figcaption { opacity: 1; }
@media (hover: none) { .bloc-media.disposition-grille .media figcaption { opacity: 1; } }
.bloc-media.disposition-mosaique .galerie { display: block; columns: var(--cartes, 3); column-gap: var(--gouttiere); }
.bloc-media.disposition-mosaique .media { break-inside: avoid; margin-bottom: var(--gouttiere); }
.bloc-media.disposition-mosaique .media-cadre { aspect-ratio: auto; }
.bloc-media.disposition-mosaique .media-cadre img { height: auto; }
/* Défilante : toutes les images à la hauteur choisie (--bande-h) ; chacune
   prend la largeur de son format (--r : le sien, ou celui du recadrage).
   ⚠ La galerie commune (.galerie) pose des colonnes EXPLICITES de 12rem, qui
   passaient avant les pistes implicites : annulées (grid-template-columns). */
.bloc-media.disposition-defilant .galerie { display: grid; grid-auto-flow: column; grid-template-columns: none; grid-auto-columns: max-content;
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; padding-bottom: .6rem; }
.bloc-media.disposition-defilant .media { scroll-snap-align: start; }
.bloc-media.disposition-defilant .media-cadre { height: min(var(--bande-h, 320px), 60vw); aspect-ratio: var(--r, 4 / 3); width: auto; }
.bloc-media.disposition-defilant .media-cadre img, .bloc-media.disposition-defilant .media-agrandir { width: 100%; height: 100%; object-fit: cover; }
/* La légende ne doit pas élargir sa photo. */
.bloc-media.disposition-defilant figcaption { width: 0; min-width: 100%; }
.bloc-media.ecart-serre .galerie { gap: calc(var(--gouttiere) * .3); column-gap: calc(var(--gouttiere) * .3); }
.bloc-media.ecart-serre.disposition-mosaique .media { margin-bottom: calc(var(--gouttiere) * .3); }
.bloc-media.ecart-large .galerie { gap: calc(var(--gouttiere) * 2); column-gap: calc(var(--gouttiere) * 2); }
.bloc-media.ecart-large.disposition-mosaique .media { margin-bottom: calc(var(--gouttiere) * 2); }
@media (max-width: 48rem) {
  .bloc-media.disposition-grille .galerie { --rangee-h: 140px; }
  .bloc-media.disposition-grille .media { flex-basis: calc(var(--r, 1.5) * 140px); }
  .bloc-media.disposition-mosaique .galerie { columns: 2; }
}
/* La visionneuse (visionneuse.js) : l'image en grand, sa légende, ← →. */
.visionneuse { width: 100vw; height: 100vh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: rgb(10 10 12 / .94); color: #fff; }
.visionneuse::backdrop { background: transparent; }
.visionneuse[open] { display: grid; grid-template-rows: 1fr auto; place-items: center; }
.visionneuse img { max-width: calc(100vw - 8rem); max-height: calc(100vh - 7rem); object-fit: contain; user-select: none; }
.visionneuse p { margin: 0 0 1.2rem; padding: 0 1rem; font-size: .9rem; opacity: .85; text-align: center; min-height: 1.4em; }
/* ── Les commandes de TOUTES les galeries, écrites une seule fois ──────────
   La visionneuse EN PAGE et la fenêtre d'agrandissement portent les mêmes
   commandes : deux flèches, une croix. Elles avaient deux tailles (2,75 et
   3 rem), deux fonds et une bordure d'un seul côté — un seul geste, dessiné
   deux fois, qui dérivait.

   ⚠ UNE ICÔNE SVG SE DIMENSIONNE, elle ne se règle pas en « font-size » : la
   taille ci-dessous est celle du dessin, pas d'un caractère.
   ⚠ PLUS DE PASTILLE RONDE. Le bouton garde sa surface (2,75 rem : la cible
   reste atteignable au doigt), il ne montre plus que son icône. Contrepartie
   assumée du cercle retiré : au-dessus d'une photo, l'icône ne compte plus que
   sur son ombre portée.
   ⚠ IL LUI FAUT DONC UN AUTRE SIGNE DE FOYER. Le fond qui s'éclaircissait
   servait aussi au clavier, et l'ancienne règle éteignait l'outline : sans
   fond, « outline: none » aurait laissé le foyer invisible. */
.scene-nav, .visionneuse button { position: absolute; z-index: 2; display: grid; place-items: center;
  width: 2.75rem; height: 2.75rem; padding: 0; cursor: pointer;
  border: 0; border-radius: 0; background: none;
  /* Pour les seuls signes de repli de visionneuse.js (× ‹ ›), si le gabarit ne
     lui passait pas les icônes du jeu. */
  font: 400 1.4rem/1 system-ui, sans-serif; }
.scene-nav { color: var(--texte); }
.visionneuse button { color: #fff; }
.scene-nav:focus-visible, .visionneuse button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.scene-nav-icone, .visionneuse-icone { display: block; width: 1.75rem; height: 1.75rem;
  filter: drop-shadow(0 1px 2px rgb(0 0 0 / .4));
  transition: rotate .45s cubic-bezier(.16, 1, .3, 1); }
/* Le survol des flèches : celle qu'on quitte SORT du côté où elle emmène, et
   la suivante ENTRE par le bord opposé. Une seule icône dans le balisage —
   elle traverse en étant invisible, entre 45 et 55 % du parcours. Deux
   exemplaires empilés auraient dit la même chose en doublant le balisage.
   ⚠ LES 30 % SONT CEUX DE L'ICÔNE (1,75 rem), pas du bouton : la flèche ne
   parcourt que 8 px, et ne sort ni du bouton ni même de son propre cadre.
   L'amplitude ne sert donc pas à la faire disparaître — c'est l'opacité,
   tombée à zéro AVANT le saut, qui s'en charge, et la course ne fait
   qu'indiquer le sens. */
@keyframes galerie-fleche-suiv {
  45% { translate: 30% 0; opacity: 0; }
  55% { translate: -30% 0; opacity: 0; }
  100% { translate: 0 0; opacity: 1; } }
@keyframes galerie-fleche-prec {
  45% { translate: -30% 0; opacity: 0; }
  55% { translate: 30% 0; opacity: 0; }
  100% { translate: 0 0; opacity: 1; } }
:is(.scene-suiv, .visionneuse-suiv):hover :is(.scene-nav-icone, .visionneuse-icone) { animation: galerie-fleche-suiv .35s cubic-bezier(.16, 1, .3, 1); }
:is(.scene-prec, .visionneuse-prec):hover :is(.scene-nav-icone, .visionneuse-icone) { animation: galerie-fleche-prec .35s cubic-bezier(.16, 1, .3, 1); }
/* ⚠ SURVOL SEUL, PAS LE FOYER CLAVIER. visionneuse.js donne le foyer à la
   croix dès l'ouverture : avec « :focus-visible », la fenêtre s'ouvrait sur une
   croix qui tourne toute seule — mesuré à 180° sans que personne l'ait
   survolée. Et l'octroi du « focus-visible » à un foyer donné par script varie
   d'un navigateur à l'autre : le geste aurait été différent selon le
   navigateur. Au clavier, c'est le liseré de foyer qui répond, pas le
   mouvement.
   La croix fait un demi-tour sur elle-même. Le signe étant symétrique, il
   retombe sur lui-même : seul le mouvement se voit, à l'aller comme au
   retour — aucun à-coup à rattraper. */
.visionneuse-fermer:hover .visionneuse-icone { rotate: 180deg; }
/* ⚠ MÊME SÉLECTEUR, PLUS BAS : c'est l'ordre du fichier qui l'emporte, pas un
   « !important ». */
@media (prefers-reduced-motion: reduce) {
  .scene-nav-icone, .visionneuse-icone { transition: none; }
  :is(.scene-suiv, .visionneuse-suiv):hover :is(.scene-nav-icone, .visionneuse-icone),
  :is(.scene-prec, .visionneuse-prec):hover :is(.scene-nav-icone, .visionneuse-icone) { animation: none; }
  .visionneuse-fermer:hover .visionneuse-icone { rotate: 0deg; } }
.visionneuse .visionneuse-fermer { top: 1rem; right: 1rem; }
.visionneuse .visionneuse-prec { left: 1rem; top: 50%; translate: 0 -50%; }
.visionneuse .visionneuse-suiv { right: 1rem; top: 50%; translate: 0 -50%; }
@media (max-width: 48rem) { .visionneuse img { max-width: 100vw; } .visionneuse .visionneuse-prec, .visionneuse .visionneuse-suiv { top: auto; bottom: 3.5rem; translate: none; } }
/* Appel : une phrase et des boutons, sur un fond teinté de l'accent (ou
   choisi, ou une photo sous son voile). Centré, ou en bandeau : le texte à
   gauche, les boutons à droite. */
.bloc-appel { position: relative; display: flex; flex-direction: column; gap: 1.2rem; overflow: clip;
  min-height: calc(var(--bloc-hauteur, 0) * var(--xxvii-vh, 1vh)); min-height: calc(var(--bloc-hauteur, 0) * var(--xxvii-vh, 1svh));
  padding: calc(var(--marges) * var(--bloc-marges, 3)); border-radius: var(--arrondi);
  background: var(--bloc-fond, color-mix(in srgb, var(--accent) 10%, var(--fond))); color: var(--bloc-texte, inherit); }
.bloc-appel.avec-image { color: var(--bloc-texte, #fff); }
.bloc-appel.est-pleine { width: 100vw; max-width: none; margin-left: calc(50% - 50vw); margin-right: calc(50% - 50vw); }
/* Bord à bord, plus d'arrondi (Apparence → Forme ne vaut que pour un bloc
   encadré) — pour l'ÉLÉMENT mis en pleine largeur, pas pour ses enfants :
   le fond du bloc, la photo de fond d'une ouverture ou d'un appel, l'image
   seule d'un bloc Image(s) (sauf à la mesure du texte), la carte des lieux.
   Les vignettes d'une galerie, les cartes d'une sélection, les vignettes des
   lieux gardent leurs arrondis : c'est le bloc qui est bord à bord, pas elles. */
.bloc.est-pleine { border-radius: 0; }
:is(.bloc-ouverture, .bloc-appel).est-pleine, .bloc-media.est-pleine.est-seule:not(.taille-texte) { --arrondi: 0px; --arrondi-images: 0px; }
.bloc-carte.est-pleine { --arrondi: 0px; } /* la carte ; pas les vignettes des lieux (--arrondi-images) */
.bloc-appel.tete-gauche { align-items: flex-start; text-align: left; } .bloc-appel.tete-centre { align-items: center; text-align: center; } .bloc-appel.tete-droite { align-items: flex-end; text-align: right; }
.bloc-appel.contenu-haut { justify-content: flex-start; } .bloc-appel.contenu-milieu { justify-content: center; } .bloc-appel.contenu-bas { justify-content: flex-end; }
.bloc-appel.disposition-bandeau { flex-direction: row; flex-wrap: wrap; justify-content: space-between; align-items: center; text-align: left; }
.bloc-appel.disposition-bandeau.contenu-haut { align-items: flex-start; } .bloc-appel.disposition-bandeau.contenu-bas { align-items: flex-end; }
.appel-fond { position: absolute; inset: 0; overflow: clip; }
.appel-fond img { width: 100%; height: 100%; object-fit: cover; display: block; }
.appel-fond::after { content: ""; position: absolute; inset: 0; background: var(--bloc-voile, rgb(0 0 0 / .35)); }
.appel-contenu, .appel-boutons { position: relative; }
.appel-contenu { max-width: 40rem; }
.appel-surtitre { font-size: .8rem; text-transform: uppercase; letter-spacing: .1em; opacity: .75; margin: 0 0 .6rem; }
.bloc-appel-texte { font-family: var(--site-police-titres, inherit); font-size: clamp(1.25rem, 3vw, 1.6rem); line-height: 1.3; margin: 0; }
.appel-boutons { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.4rem; }
.tete-centre .appel-boutons { justify-content: center; } .tete-droite .appel-boutons { justify-content: flex-end; }
.disposition-bandeau .appel-boutons { justify-content: flex-end; }
.bloc-appel.avec-couleur .corps a { color: inherit; }
.bloc-a-completer { margin: 0; padding: 2rem; text-align: center; color: var(--gris); border: 1px dashed var(--filet); border-radius: var(--arrondi); }
@media (max-width: 48rem) {
  .bloc-grille { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bloc-colonnes .bloc-grille { grid-template-columns: minmax(0, 1fr); }
}

/* Page introuvable : titre et texte de l'Apparence, photo et voile en option. */
.introuvable { text-align: center; padding: calc(var(--marges) * 3.2) 1.25rem; }
.introuvable p { color: var(--gris); }
.introuvable.avec-image { position: relative; overflow: hidden; border-radius: var(--arrondi-images); color: var(--texte-404, #fff); min-height: 60vh;
  display: flex; flex-direction: column; align-items: center; justify-content: center; max-width: var(--site-largeur, 70rem); }
.introuvable.avec-image > :not(.fond-404, .voile-404) { position: relative; }
.introuvable.avec-image p, .introuvable.avec-image a { color: var(--texte-404, #fff); }
/* Plein écran : bord à bord, toute la hauteur de la fenêtre. */
.introuvable.est-plein-ecran { max-width: none; width: 100vw; margin-left: calc(50% - 50vw); margin-right: 0; border-radius: 0; min-height: 100vh; min-height: 100svh; }
.fond-404 { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.voile-404 { position: absolute; inset: 0; background: var(--voile-404, rgba(0,0,0,.45)); }

/* Options de tous les blocs : apparition au défilement (liée au défilement,
   sans script ; sans prise en charge, le bloc est simplement là), visibilité
   par appareil. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    :is(.bloc, .liste).apparait { animation: sobre-apparait linear both; animation-timeline: view(); animation-range: entry 0% entry 60%; }
  }
}
/* Les éléments d'un bloc, un à un : un observateur (apparition.js) les arme
   et leur donne un retard croissant à mesure qu'ils arrivent à l'écran. ⚠ On
   ne peut PAS s'en remettre à animation-timeline: view() : tous les éléments
   d'une rangée entrent ensemble, donc s'animent ensemble — ce sont les
   rangées qui paraissent une à une, jamais les vignettes. C'est le RETARD qui
   fait la cascade, pas la position dans le défilement.
   L'attente est posée par le script, jamais par cette feuille : sans lui,
   rien n'est masqué. */
.attend-apparition { opacity: 0; }
.est-arrive { animation: sobre-apparait .8s cubic-bezier(.16, 1, .3, 1) both; }
:is(.cartes, .bloc-grille, .galerie, .carte-lieux) > .est-arrive { animation-name: sobre-apparait-vignette; }
@media (prefers-reduced-motion: reduce) {
  .attend-apparition { opacity: 1; }
  .est-arrive { animation: none; }
}
@keyframes sobre-apparait { from { opacity: 0; translate: 0 4rem; } }
/* Les vignettes d'une grille viennent aussi d'un peu plus loin : le texte
   courant, lui, ne change pas d'échelle (il resterait flou pendant le geste). */
@keyframes sobre-apparait-vignette { from { opacity: 0; translate: 0 4rem; scale: .94; } }
@media (max-width: 48rem) { .bloc.masque-mobile { display: none; } }
@media (min-width: 48.001rem) { .bloc.masque-ordinateur { display: none; } }

/* Animations d'apparition (Apparence → Forme), jamais pour qui les a coupées. */
@media (prefers-reduced-motion: no-preference) {
  .avec-animations .page > * { animation: sobre-monte .5s cubic-bezier(.2, .7, .2, 1) both; }
  .avec-animations .page > * + * { animation-delay: .08s; }
}
@keyframes sobre-monte { from { opacity: 0; transform: translateY(12px); } }

/* ═══════════════════════════════════════════════════════════════════════════
   TYPOGRAPHIE FINE (Apparence → Polices → Affiner)

   Chaque élément lit sa dérogation et RETOMBE SEUL sur le système simple
   quand elle n'est pas émise : le noyau n'écrit une variable que si elle
   déroge (variables_fin), donc une feuille sans dérogation se comporte
   exactement comme avant.

   ⚠ LA RECETTE EST ÉCRITE UNE SEULE FOIS. Le premier jet la recopiait pour
   chacun des onze éléments — sept propriétés × onze — et le cliquet des
   doublons l'a refusé, à juste titre. Ici un seul bloc applique les sept
   propriétés ; chaque élément ne déclare que ses variables et sa chaîne de
   repli. Ajouter un élément coûte désormais six lignes, pas treize.

   ⚠ Cette section vient EN DERNIER, à spécificité égale : elle gagne sur les
   règles plus haut sans avoir à les modifier une à une. Les valeurs de repli
   sont celles de ces règles, reprises à l'identique.
   ═══════════════════════════════════════════════════════════════════════════ */
body, .entree h1, .liste h1, .corps h2, .corps h3, .corps h4,
.carte-titre, .fiche-nav-titre, .nav-col.est-titre-grand .nav-titre,
.bloc-chiffres strong, .bloc-appel-texte,
.ouverture-surtitre, .ouverture-chapo,
.media figcaption, .bloc-media figcaption, .bloc-legende, .est-visionneuse .scene-texte,
.bouton {
  font-family: var(--t-police); font-size: var(--t-taille); font-weight: var(--t-graisse);
  line-height: var(--t-interligne); letter-spacing: var(--t-approche);
  text-transform: var(--t-casse); font-variant-caps: var(--t-variante);
}
body {
  --t-police: var(--site-texte-police, var(--site-police-texte, ui-sans-serif, system-ui, sans-serif));
  --t-taille: var(--site-texte-taille, var(--site-taille, 17px));
  --t-graisse: var(--site-texte-graisse, var(--site-graisse-texte, 400));
  --t-interligne: var(--site-texte-interligne, 1.65);
  --t-approche: var(--site-texte-approche, normal);
  --t-casse: var(--site-texte-casse, none); --t-variante: var(--site-texte-variante, normal);
}
.entree h1, .liste h1 {
  --t-police: var(--site-h1-police, var(--site-police-titres, inherit));
  --t-taille: clamp(calc(var(--site-h1-taille, var(--site-h1, 2.75rem)) * .62), 7vw, var(--site-h1-taille, var(--site-h1, 2.75rem)));
  --t-graisse: var(--site-h1-graisse, var(--site-graisse-titres, 700));
  --t-interligne: var(--site-h1-interligne, 1.08);
  --t-approche: var(--site-h1-approche, var(--site-interlettre-titres, -.01em));
  --t-casse: var(--site-h1-casse, var(--site-casse-titres, none)); --t-variante: var(--site-h1-variante, normal);
}
.bloc-ouverture h1 {
  --t-taille: clamp(calc(var(--site-h1-taille, var(--site-h1, 2.75rem)) * .7), 8vw, calc(var(--site-h1-taille, var(--site-h1, 2.75rem)) * 1.3));
  --t-interligne: var(--site-h1-interligne, 1.04);
}
.corps h2 {
  --t-police: var(--site-h2-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-h2-taille, var(--site-h2, 1.5rem));
  --t-graisse: var(--site-h2-graisse, var(--site-graisse-titres, 700));
  --t-interligne: var(--site-h2-interligne, 1.2);
  --t-approche: var(--site-h2-approche, var(--site-interlettre-titres, -.01em));
  --t-casse: var(--site-h2-casse, var(--site-casse-titres, none)); --t-variante: var(--site-h2-variante, normal);
}
.corps h3 {
  --t-police: var(--site-h3-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-h3-taille, var(--site-h3, 1.2rem));
  --t-graisse: var(--site-h3-graisse, var(--site-graisse-titres, 700));
  --t-interligne: var(--site-h3-interligne, 1.3);
  --t-approche: var(--site-h3-approche, var(--site-interlettre-titres, -.01em));
  --t-casse: var(--site-h3-casse, var(--site-casse-titres, none)); --t-variante: var(--site-h3-variante, normal);
}
/* ⚠ h4 n'avait AUCUNE règle : il héritait du corps, donc de la police du
   texte, alors qu'il porte un titre. C'est le seul élément dont « Affiner »
   change le rendu par défaut. */
.corps h4 {
  --t-police: var(--site-h4-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-h4-taille, 1.05rem);
  --t-graisse: var(--site-h4-graisse, var(--site-graisse-titres, 700));
  --t-interligne: var(--site-h4-interligne, 1.35);
  --t-approche: var(--site-h4-approche, var(--site-interlettre-titres, -.01em));
  --t-casse: var(--site-h4-casse, var(--site-casse-titres, none)); --t-variante: var(--site-h4-variante, normal);
}
.carte-titre, .fiche-nav-titre {
  --t-police: var(--site-carte-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-carte-taille, inherit);
  --t-graisse: var(--site-carte-graisse, var(--site-graisse-titres, 600));
  --t-interligne: var(--site-carte-interligne, 1.15);
  --t-approche: var(--site-carte-approche, normal);
  --t-casse: var(--site-carte-casse, none); --t-variante: var(--site-carte-variante, normal);
}
.nav-col.est-titre-grand .nav-titre {
  --t-police: var(--site-menu-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-menu-taille, var(--site-h3, 1.5rem));
  --t-graisse: var(--site-menu-graisse, var(--site-graisse-titres, 600));
  --t-interligne: var(--site-menu-interligne, 1.15);
  --t-approche: var(--site-menu-approche, -.01em);
  --t-casse: var(--site-menu-casse, none); --t-variante: var(--site-menu-variante, normal);
}
.bloc-chiffres strong {
  --t-police: var(--site-chiffres-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-chiffres-taille, clamp(1.8rem, 5vw, 2.6rem));
  --t-graisse: var(--site-chiffres-graisse, var(--site-graisse-titres, 700));
  --t-interligne: var(--site-chiffres-interligne, 1);
  --t-approche: var(--site-chiffres-approche, normal);
  --t-casse: var(--site-chiffres-casse, none); --t-variante: var(--site-chiffres-variante, normal);
}
.bloc-appel-texte {
  --t-police: var(--site-appel-police, var(--site-police-titres, inherit));
  --t-taille: var(--site-appel-taille, clamp(1.25rem, 3vw, 1.6rem));
  --t-graisse: var(--site-appel-graisse, inherit);
  --t-interligne: var(--site-appel-interligne, 1.3);
  --t-approche: var(--site-appel-approche, normal);
  --t-casse: var(--site-appel-casse, none); --t-variante: var(--site-appel-variante, normal);
}
/* ⚠ EN « em », PAS EN « rem ». Ces deux textes étaient en rem, donc indexés
   sur la taille par défaut du NAVIGATEUR (16 px) et non sur celle du site :
   passer le texte de 17 à 20 px ne les bougeait pas d'un pixel. En em, ils
   suivent la taille effective du corps — celle des Réglages, ou celle
   qu'Affiner pose sur « Texte courant ». Leurs valeurs de repli (uppercase,
   .1em) sont celles que le thème posait en dur : Affiner les remplace. */
.ouverture-surtitre {
  --t-police: var(--site-surtitre-police, inherit);
  --t-taille: var(--site-surtitre-taille, .8em);
  --t-graisse: var(--site-surtitre-graisse, inherit);
  --t-interligne: var(--site-surtitre-interligne, inherit);
  --t-approche: var(--site-surtitre-approche, .1em);
  --t-casse: var(--site-surtitre-casse, uppercase); --t-variante: var(--site-surtitre-variante, normal);
}
.ouverture-chapo {
  --t-police: var(--site-chapo-police, inherit);
  --t-taille: var(--site-chapo-taille, 1.15em);
  --t-graisse: var(--site-chapo-graisse, inherit);
  --t-interligne: var(--site-chapo-interligne, inherit);
  --t-approche: var(--site-chapo-approche, normal);
  --t-casse: var(--site-chapo-casse, none); --t-variante: var(--site-chapo-variante, normal);
}
.media figcaption, .bloc-media figcaption, .bloc-legende, .est-visionneuse .scene-texte {
  --t-police: var(--site-legende-police, inherit);
  --t-taille: var(--site-legende-taille, .85rem);
  --t-graisse: var(--site-legende-graisse, inherit);
  --t-interligne: var(--site-legende-interligne, inherit);
  --t-approche: var(--site-legende-approche, normal);
  --t-casse: var(--site-legende-casse, none); --t-variante: var(--site-legende-variante, normal);
}
.bouton {
  --t-police: var(--site-bouton-police, inherit);
  --t-taille: var(--site-bouton-taille, inherit);
  --t-graisse: var(--site-bouton-graisse, 600);
  --t-interligne: var(--site-bouton-interligne, 1.3);
  --t-approche: var(--site-bouton-approche, normal);
  --t-casse: var(--site-bouton-casse, none); --t-variante: var(--site-bouton-variante, normal);
}
