/* ============================================================================
   CORPUS - BLOCS, la feuille du site

   ELLE EST COURTE, ET C'EST VOULU. Tout ce qui a deja un dessin dans Corpus est
   employe tel quel : `.carte`, `.carte__image`, `.carte__titre`,
   `.carte__corps`, `.bouton` et ses variantes. Ce fichier ne pose que ce qui
   n'existait pas : la rangee du module, la pile de l'ouverture, la grille des
   cartes et les trois alignements.

   AUCUNE COULEUR EN DUR, AUCUNE VALEUR EN DUR. Uniquement les jetons de Corpus
   (--e-*, --gouttiere, --fond-teinte, --forme-carte-*), qui sont redeclares en
   mode sombre par le template. Le mode sombre suit donc tout seul, sans une
   seule regle de plus ici : c'est la raison pour laquelle on ne melange jamais
   ses couleurs a la main quand le theme en fournit.

   ZERO !important.
   ========================================================================== */

/* ---------------------------------------------------------------------------
   LA RANGEE

   Une grille, et le repli en une colonne sous 48 rem, comme partout dans
   Corpus. Le ratio ne s'applique qu'au-dessus de ce seuil : en dessous, deux
   colonnes ne montrent plus ni l'une ni l'autre.

   L'ORDRE DES DEUX COLONNES EST CELUI DU HTML. Le reglage « cote de
   l'ouverture » change ce que la mise en page ecrit, et non un `order` en CSS,
   qui ferait diverger la lecture au clavier de ce qui est affiche.
   --------------------------------------------------------------------------- */
/*
 * LA RANGEE N'A PLUS DE GRILLE A ELLE, ET C'EST LE POINT DE CETTE VERSION.
 *
 * `grille` et `colonne-N` sont les classes du template : `template.css` l. 469
 * pose la grille de douze colonnes, l. 475 a 519 les douze largeurs, et
 * l. 8529 les fait toutes retomber sur douze sous 62 rem. Le module ecrit donc
 * le meme balisage qu'un gabarit d'article, et herite des douze rapports, de
 * la gouttiere et du repli sans une regle de plus.
 *
 * Ce qui suit est tout ce que Corpus ne sait pas : l'alignement vertical, qui
 * n'existe pas dans ses gabarits, et le retrait qui accompagne un fond.
 */
/*
 * LE DEFAUT DE LA RANGEE EST « AU MILIEU » DEPUIS LE 23 SEPTEMBRE 2026.
 *
 * « Tes alignements devraient etre toujours par defaut au milieu », Cyrille.
 * Deux colonnes de hauteurs differentes collees en haut laissent un vide sous
 * la plus courte, et c'est ce vide qu'on voit ; au milieu, les deux se
 * repondent. C'est aussi ce que font les tampons de Corpus, qui posent
 * `align-items-center` sur leurs rangees a deux colonnes.
 *
 * LA CLASSE NE S'ECRIT PLUS QUE POUR LES DEUX AUTRES VALEURS : la mise en page
 * n'ajoute une classe que lorsqu'on s'ecarte du defaut, et c'est la feuille
 * qui porte ce defaut.
 */
.opus__rangee {
  align-items: center;
}

.opus__rangee--v-start  { align-items: start; }
.opus__rangee--v-center { align-items: center; }
.opus__rangee--v-end    { align-items: end; }

/*
 * LE FOND APPORTE SON RETRAIT, ET IL LE FAUT.
 *
 * `section--alt` et `section--tint` ne posent qu'une couleur : sur une bande
 * de page, le retrait vient du conteneur de la section. Ici l'aplat se pose
 * sur une rangee ou une colonne, qui n'en ont pas, et le texte viendrait se
 * coller contre le bord de la couleur.
 *
 * Le rayon est celui des cartes du template : un aplat carre au milieu de
 * cartes arrondies se lit comme un defaut.
 *
 * LE FOND SE PEINT ICI, CAR `section--alt` NE PEINT RIEN.
 *
 * « Les teintes ne fonctionnent pas », signale le 21 septembre. Mesure du
 * 25 septembre dans `template.css` : `.section--alt` et `.section--tint` ne
 * posent qu'un jeton, `--fond-zone`. Chaque conteneur de Corpus le peint
 * lui-meme (`.section`, `.rangee-article`, `.colonne-blog`...), par
 * `background: var(--fond-zone, transparent)`. Notre rangee n'en faisait rien :
 * la classe sortait, l'aplat restait transparent. On lit le jeton comme eux,
 * en `background-color` pour ne rien effacer d'autre.
 */
.opus__fond {
  background-color: var(--fond-zone, transparent);
  padding: var(--e-5);
  border-radius: var(--forme-carte-angle, var(--angle-lg));
}

/*
 * UNE COLONNE EST UNE PILE, ET CELA DECOULE DU MODELE.
 *
 * Deux blocs peuvent partager la meme colonne de la meme rangee : une
 * ouverture et une grille de cartes dessous, par exemple. Ils s'empilent donc,
 * avec l'ecart des elements et non celui des rangees, qui serait deux fois
 * trop grand a l'interieur d'une colonne.
 */
.opus__colonne {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
  min-width: 0;
}

/* Les rangees s'empilent avec la gouttiere, comme les bandes d'une page. */
.opus__rangee + .opus__rangee {
  margin-top: var(--gouttiere, var(--e-6));
}

/* ---------------------------------------------------------------------------
   L'OUVERTURE
   --------------------------------------------------------------------------- */
.opus__ouverture {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
  min-width: 0;
}

/*
 * LES MARGES DE BORD. Le premier enfant ne s'ecarte pas du haut, le dernier ne
 * pousse pas le fond : sans cela un aplat montre une bande vide, et une colonne
 * parait plus haute que sa voisine alors qu'elles sont egales.
 */
/*
 * OU LE BLOC SE PLACE DANS LA HAUTEUR DE SA COLONNE.
 *
 * DES MARGES AUTOMATIQUES, PAS `align-self` : la colonne est une pile
 * verticale, son axe croise est donc l'HORIZONTALE. `align-self: center` y
 * centrerait le bloc de gauche a droite, ce qui n'est pas ce qui est demande,
 * et le ferait en plus cesser de s'etirer. Une marge automatique mange
 * l'espace libre du cote ou elle est posee, quel que soit le nombre de blocs.
 *
 * « En haut » n'a pas de regle : c'est deja ce que fait la pile.
 */
.opus__ouverture--v-center { margin-block: auto; }
.opus__ouverture--v-end    { margin-top: auto; }

/*
 * UN BLOC QUI DEMANDE « EN HAUT » OU « EN BAS » ETIRE SA COLONNE.
 *
 * « Je n'ai pas reussi a mettre la zone Bloc simple en haut et non au
 * centre », Cyrille, 2 octobre 2026. Mesure sur le banc : la rangee centrait
 * ses colonnes (`align-items: center`, son defaut), la colonne n'avait donc
 * que la hauteur de son bloc, et un bloc ne peut monter ni descendre dans une
 * boite qui a exactement sa taille. Le reglage du bloc etait ecrit, valide,
 * et sans aucun effet.
 *
 * LA COLONNE S'ETIRE ALORS A LA HAUTEUR DE LA RANGEE, et le bloc s'y place :
 * en haut par la pile elle-meme, en bas par sa marge automatique. Un bloc
 * laisse « Au milieu », le defaut, ne touche a rien : c'est la rangee qui
 * decide, comme avant.
 */
.opus__colonne:has(> .opus__ouverture--v-start, > .opus__ouverture--v-end) {
  align-self: stretch;
}

.opus__ouverture > :first-child { margin-top: 0; }
.opus__ouverture > :last-child  { margin-bottom: 0; }

/* ---------------------------------------------------------------------------
   LA RANGEE DE BOUTONS

   Elle n'avait aucune regle a elle : le `<p>` laissait les boutons couler
   comme du texte, et l'espace entre eux etait l'espace d'un mot. Une liste
   multipliable demandait de trancher, puisque le nombre de boutons n'est plus
   borne a trois.

   `gap` PLUTOT QU'UNE MARGE SUR CHAQUE BOUTON : une marge se pose aussi au
   bord, et il faut ensuite la retirer au premier et au dernier.

   LE SENS EMPILE SUIT L'ALIGNEMENT DE L'ELEMENT. `align-items` est l'axe
   croise : en colonne, c'est l'horizontale. Sans ces deux lignes, des boutons
   empiles dans un bloc centre restaient colles a gauche, alors que le texte
   au-dessus d'eux etait centre.
   --------------------------------------------------------------------------- */
.opus__boutons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e-2);
}

.opus__boutons--pile {
  flex-direction: column;
  align-items: flex-start;
}

.opus__el--center.opus__boutons--pile { align-items: center; }
.opus__el--end.opus__boutons--pile    { align-items: flex-end; }

.opus__espace { height: var(--e-5); }

.opus__separateur {
  width: 100%;
  margin: var(--e-2) 0;
  border: 0;
  /* `border-style` seul ne dessine rien : sans epaisseur, la regle est valide
     et invisible. On declare donc la bordure haute en entier. */
  border-top: var(--filet-epaisseur, 1px) solid var(--bord);
}

.opus__separateur--thick {
  border-top-width: calc(var(--filet-epaisseur, 1px) * 3);
}

/* ---------------------------------------------------------------------------
   LES TROIS ALIGNEMENTS

   `align-self` place la boite, `text-align` place le texte dedans. Aucun des
   deux ne touche a l'ordre du document, contrairement a `order`.
   --------------------------------------------------------------------------- */
.opus__el--center { align-self: center; text-align: center; }
.opus__el--end    { align-self: flex-end; text-align: right; }

/* ---------------------------------------------------------------------------
   LA GRILLE DES CARTES

   ON DECLARE UNE LARGEUR, JAMAIS UN NOMBRE DE COLONNES. `auto-fit` en met
   autant que la place le permet : trois sur un ecran large, deux quand la
   colonne se resserre, une sur un telephone. Ajouter une carte ne demande de
   changer aucun reglage, et les cartes ont la meme hauteur sans qu'on le
   demande, parce qu'une grille etire ses cellules.

   La largeur minimale arrive en variable, posee par la mise en page depuis le
   reglage. Le repli a 11 rem sert si la variable manque.
   --------------------------------------------------------------------------- */
.opus__cartes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--opus-carte-mini, 11rem), 1fr));
  gap: var(--gouttiere-grille, var(--e-4));
  align-items: stretch;
  min-width: 0;
}

/*
 * LE PLAFOND DE COLONNES. Chaque colonne vaut au moins la largeur minimale ET
 * la part d'une rangee de N : il n'en tient donc jamais plus de N. Quand cette
 * part devient plus etroite que la largeur minimale, c'est elle qui l'emporte,
 * et la grille redescend a deux puis a une comme en automatique.
 */
.opus__cartes--plafond {
  grid-template-columns: repeat(auto-fit, minmax(max(var(--opus-carte-mini, 11rem), calc((100% - (var(--opus-cartes-max, 3) - 1) * var(--gouttiere-grille, var(--e-4))) / var(--opus-cartes-max, 3))), 1fr));
}

/*
 * UNE VARIANTE NE REDEFINIT QUE DES JETONS, JAMAIS DES REGLES.
 *
 * `.carte` du template lit deja --forme-carte-bordure et --forme-carte-ombre.
 * Le reglage « cadre » se contente donc de changer ces jetons sur la grille :
 * aucune regle de Corpus n'est doublee, aucune specificite n'est a gagner, et
 * le jour ou la forme des cartes change dans le template, ces variantes
 * suivent sans etre touchees.
 */
.opus__cartes--none .carte {
  --forme-carte-bordure: 0;
  --forme-carte-ombre: none;
}

.opus__cartes--shadow .carte {
  --forme-carte-bordure: 0;
}

/*
 * LE LIEN ETIRE N'EST PAS ECRIT ICI NON PLUS, ET J'AVAIS MAL LU LA CAUSE.
 *
 * Je pensais l'obtenir de `.stretched-link` de Bootstrap. Il vient en realite
 * de Corpus lui-meme : `media/css/template.css` l. 2291 donne a
 * `.carte__titre a` un `::after` en `position: absolute; inset: 0`, et
 * `.carte` porte `position: relative`. Le lien du titre couvre donc la carte
 * TOUJOURS, avec le survol et le `:focus-within` qui vont avec.
 *
 * C'est pourquoi le reglage « carte entierement cliquable » ne peut pas se
 * contenter d'AJOUTER quelque chose : il doit RETIRER ce que le template pose.
 * D'ou cette regle, la seule de la feuille qui defasse une regle de Corpus.
 * Elle est nommee pour qu'on la retrouve le jour ou le template change.
 */
.opus__cartes--inerte .carte__titre a::after {
  content: none;
}

/*
 * L'ALIGNEMENT DANS UNE CARTE SE POSE SUR SON CORPS, PAS SUR LA CARTE.
 *
 * `.carte__corps` est une colonne flexible : `align-items` y range les enfants
 * dans la largeur, et la carte garde sa hauteur de cellule de grille. Pose sur
 * `.carte`, `align-self` l'aurait au contraire empechee de s'etirer, et une
 * carte plus courte que ses voisines se voit au premier coup d'oeil.
 */
.opus__carte--center {
  align-items: center;
  text-align: center;
}

.opus__carte--end {
  align-items: flex-end;
  text-align: right;
}


/* ============================================================================
   L'IMAGE, ET SES SIX REGLAGES, 23 septembre 2026

   LA BORDURE ET L'ANGLE VIENNENT DE CORPUS, PAS D'ICI. Le template porte
   `--forme-image-bordure` et `--forme-image-angle` (`template.css` l. 68), et
   ce module s'y branche. Il ne choisit donc ni epaisseur ni rayon : changer la
   variante du site change l'habillage de toutes les images, y compris
   celles-ci, sans qu'on touche a ce fichier.

   LES VALEURS DE SECOURS SONT LA POUR UN SITE SANS CORPUS : le module doit
   rester regardable sous n'importe quel template, et un jeton absent rend une
   declaration invalide, donc aucune bordure du tout.
   ========================================================================= */
.opus__image {
  display: block;
  max-width: 100%;
  height: auto;
  border: var(--forme-image-bordure, 1px solid rgb(0 0 0 / 12%));
  border-radius: var(--forme-image-angle, .25rem);
}

/* --- Le format impose ------------------------------------------------------
   Quatre rapports, ceux que Corpus emploie deja dans ses propres mises en
   page. Des qu'un rapport est impose, l'image doit remplir sa boite : sans
   `object-fit`, elle serait etiree, ce qui ne se rattrape jamais. */
.opus__image--16-9,
.opus__image--4-3,
.opus__image--1-1,
.opus__image--3-4 {
  width: 100%;
  object-fit: cover;
}

.opus__image--16-9 { aspect-ratio: 16 / 9; }
.opus__image--4-3  { aspect-ratio: 4 / 3; }
.opus__image--1-1  { aspect-ratio: 1 / 1; }
.opus__image--3-4  { aspect-ratio: 3 / 4; }

/* « Entiere » : l'image tient dans le format sans etre recadree, et laisse du
   vide sur les cotes. C'est le bon choix pour un logo ou un schema, ou couper
   un bord change le sens. */
.opus__image--entiere {
  object-fit: contain;
}

/* --- L'habillage ----------------------------------------------------------
   LA CLASSE EST DOUBLEE (`.opus__image.opus__image--...`), et ce n'est pas
   une coquetterie. Pose dans un article (`{loadmoduleid}`), le module tombe
   sous `.contenu img` de Corpus (`template.css`), qui donne a toute image
   d'article la bordure et l'angle du template : une classe et une balise,
   plus fort qu'une classe seule. Les portraits ronds sortaient carres, vu par
   Cyrille le 10 octobre 2026. Deux classes passent devant. */
.opus__image.opus__image--nue {
  border: 0;
  border-radius: 0;
}

/*
 * RONDE, DONC CARREE D'ABORD. Un cercle suppose un carre : pose sur une image
 * panoramique, `border-radius: 50%` donne une ellipse. Le rapport est donc
 * force ici, et le recadrage avec, comme Corpus le fait pour ses portraits
 * (`template.css` l. 3492).
 */
.opus__image--ronde {
  aspect-ratio: 1 / 1;
  width: auto;
  object-fit: cover;
}

/* Seul l'angle passe en classe doublee : la largeur garde son poids, pour que
   le plafond (`.opus__image--plafond`, plus bas) l'emporte comme avant. */
.opus__image.opus__image--ronde {
  border-radius: 50%;
}

/*
 * UNE ICONE N'EST PAS UNE PETITE PHOTO.
 *
 * Elle ne porte ni bordure ni angle, et elle ne s'etire jamais : 3 rem par
 * defaut, soit la taille ou un pictogramme reste lisible sans devenir une
 * illustration. Le reglage « Largeur limitee » la surcharge, puisqu'il
 * s'ecrit en style et passe devant.
 */
.opus__image--icone {
  width: auto;
  max-width: 3rem;
}

.opus__image.opus__image--icone {
  border: 0;
  border-radius: 0;
}

/* Le plafond etire toute image a la largeur disponible ; une icone, non. */
.opus__image--icone.opus__image--plafond {
  width: auto;
}

/* --- La largeur ------------------------------------------------------------
   Le plafond lui-meme est ecrit en ligne : c'est un nombre saisi, il ne peut
   pas vivre dans une feuille. La classe, elle, dit ce qu'il faut faire du
   reste de la place. */
.opus__image--plafond {
  width: 100%;
}

/*
 * UNE IMAGE PLAFONNEE SUIT L'ALIGNEMENT DE SON ELEMENT.
 *
 * `margin-inline` reprend la main sur le bloc : centre, l'image se pose au
 * milieu de la place restante ; alignee a droite, elle s'y colle. Sans cela,
 * une image de 40 rem dans un bloc de 60 restait a gauche quoi qu'on demande,
 * parce qu'une image est un bloc et qu'un bloc ne se centre pas tout seul.
 */
.opus__image--plafond.opus__el--center {
  margin-inline: auto;
}

.opus__image--plafond.opus__el--end {
  margin-inline: auto 0;
}


/*
 * LES CARTES L'UNE SOUS L'AUTRE.
 *
 * Demande de Cyrille, 23 septembre 2026, pour une rangee posee dans une
 * colonne laterale. La grille se replie deja d'elle-meme quand la place
 * manque ; ceci le demande quelle que soit la place.
 *
 * UNE SEULE COLONNE SUFFIT : la grille garde son ecart et ses cartes qui
 * s'etirent, il n'y a que le nombre de colonnes qui change. Passer en
 * `display: flex` aurait tout redit pour rien.
 */
.opus__cartes--pile {
  grid-template-columns: 1fr;
}


/* ===========================================================================
   LA GALERIE

   MEME MECANIQUE QUE LA GRILLE DE CARTES : on declare une largeur minimale,
   jamais un nombre de colonnes. Ajouter une image ne demande donc rien d'autre
   que d'ajouter l'image.

   UNE LISTE, ET C'EST VOULU. Une galerie est une enumeration : `ul` + `li` le
   disent au lecteur d'ecran, qui annonce alors « liste de 9 elements ». Le
   retrait et les puces sont retires ici, parce qu'une liste de vignettes n'en
   porte pas.
   ========================================================================= */
.opus__galerie {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--opus-vignette-mini, 12rem), 1fr));
  gap: var(--gouttiere-grille, var(--e-4));
  min-width: 0;
}

.opus__galerie--ecart-serre { gap: var(--e-2); }
.opus__galerie--ecart-large { gap: var(--e-6); }

.opus__vignette {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
  margin: 0;
  height: 100%;
  min-width: 0;
}

/*
 * LE LIEN EST UN BLOC, SINON L'IMAGE FLOTTE.
 *
 * Un `a` en ligne pose sa ligne de base sous l'image, et la vignette gagne
 * quatre pixels de vide qu'on ne s'explique pas.
 */
.opus__vignette-lien {
  display: block;
  min-width: 0;
}

.opus__vignette-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--forme-image-angle, .25rem);
}

/* --- Le format impose ------------------------------------------------------
   Des qu'un rapport est demande, l'image doit remplir sa boite : sans
   `object-fit`, elle serait etiree, ce qui ne se rattrape jamais. Le format
   « libre » n'ecrit aucune de ces classes, et la grille ondule, ce qui est
   alors le choix de l'utilisateur. */
.opus__galerie--1-1 .opus__vignette-image,
.opus__galerie--4-3 .opus__vignette-image,
.opus__galerie--16-9 .opus__vignette-image,
.opus__galerie--3-4 .opus__vignette-image {
  object-fit: cover;
}

.opus__galerie--1-1 .opus__vignette-image  { aspect-ratio: 1 / 1; }
.opus__galerie--4-3 .opus__vignette-image  { aspect-ratio: 4 / 3; }
.opus__galerie--16-9 .opus__vignette-image { aspect-ratio: 16 / 9; }
.opus__galerie--3-4 .opus__vignette-image  { aspect-ratio: 3 / 4; }

/* --- La legende ------------------------------------------------------------
   Elle reprend la taille et la teinte des legendes du template, et rien de
   plus : ce qu'elle contient est dessine par `_elements.php`, comme partout
   ailleurs dans le module. */
.opus__legende {
  font-size: var(--t-petit, .875rem);
  color: var(--texte-doux, inherit);
  line-height: 1.4;
}

.opus__legende > :first-child { margin-top: 0; }
.opus__legende > :last-child  { margin-bottom: 0; }

/*
 * LA LEGENDE AU SURVOL RESTE LISIBLE AU CLAVIER.
 *
 * `:focus-within` autant que `:hover` : une legende qui n'apparait qu'a la
 * souris n'existe pas pour qui navigue a la tabulation. Et elle reste dans le
 * flux au toucher, ou il n'y a pas de survol : sous 48 rem, on retombe sur la
 * legende posee dessous.
 */
@media (min-width: 48rem) and (hover: hover) {
  .opus__galerie--survol .opus__vignette {
    overflow: hidden;
    border-radius: var(--forme-image-angle, .25rem);
  }

  .opus__galerie--survol .opus__legende {
    position: absolute;
    inset: auto 0 0 0;
    margin: 0;
    padding: var(--e-3);
    color: #fff;
    background: linear-gradient(to top, rgb(0 0 0 / 72%), rgb(0 0 0 / 0%));
    opacity: 0;
    transition: opacity .2s ease;
  }

  .opus__galerie--survol .opus__vignette:hover .opus__legende,
  .opus__galerie--survol .opus__vignette:focus-within .opus__legende {
    opacity: 1;
  }
}


/* ===========================================================================
   LE CARROUSEL

   LE DEFILEMENT, LES FLECHES ET LES PASTILLES SONT CEUX DE BOOTSTRAP, que
   Corpus charge deja (`index.php` l. 85). Ce qui suit ne pose que ce que
   Bootstrap ne sait pas : le format impose, la lisibilite du texte sur
   l'image, et la place des commandes.
   ========================================================================= */
.opus__carrousel {
  position: relative;
  border-radius: var(--forme-carte-angle, var(--angle-lg));
  overflow: hidden;
}

.opus__diapo {
  position: relative;
  display: grid;
}

/*
 * L'IMAGE ET LE CONTENU OCCUPENT LA MEME CASE.
 *
 * Une grille a une seule case superpose ses enfants sans `position: absolute`,
 * donc sans sortir du flux : la diapositive garde la hauteur de son image, et
 * le texte ne peut pas deborder au-dessus de la diapositive suivante.
 */
/*
 * `min-height: 0` N'EST PAS UN DETAIL : SANS LUI LE FORMAT NE TIENT PAS.
 *
 * Un enfant de grille vaut `min-height: auto`, c'est-a-dire « au moins la
 * hauteur de mon contenu ». L'image y impose donc sa hauteur naturelle, et la
 * grille s'etire au-dela du rapport demande : `aspect-ratio` n'est pas une
 * consigne ferme, il cede devant un contenu plus grand.
 *
 * Mesure sur le banc, 23 septembre 2026, format 21/9 sur 1272 px de large :
 * la diapositive faisait 716 px de haut au lieu de 545, soit exactement la
 * hauteur naturelle de l'image (1600 x 900). « Le format des images du
 * carrousel devrait imposer la dimension des images », Cyrille. Il l'imposait
 * deja, mais il perdait.
 *
 * `overflow: hidden` SUR LA DIAPOSITIVE : c'est ce qui rend le recadrage
 * possible. L'image remplit la boite et ce qui depasse est coupe, ce que
 * `object-fit: cover` promet mais ne peut pas faire seul.
 */
.opus__diapo {
  overflow: hidden;
}

.opus__diapo > * {
  grid-area: 1 / 1;
  min-width: 0;
  min-height: 0;
}

.opus__diapo-image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;

  /* La hauteur naturelle ne doit jamais reprendre la main. */
  max-height: 100%;
}

.opus__carrousel--16-9 .opus__diapo { aspect-ratio: 16 / 9; }
.opus__carrousel--21-9 .opus__diapo { aspect-ratio: 21 / 9; }
.opus__carrousel--4-3 .opus__diapo  { aspect-ratio: 4 / 3; }
.opus__carrousel--1-1 .opus__diapo  { aspect-ratio: 1 / 1; }

/*
 * LE CONTENU SE POSE EN BAS, ET NON AU MILIEU.
 *
 * Le milieu d'une photo est presque toujours son sujet ; le bas est presque
 * toujours du decor. C'est aussi la ou l'oeil finit sa lecture.
 */
.opus__diapo-contenu {
  align-self: end;
  padding: var(--e-5);
  color: #fff;
}

/*
 * LE TEXTE HERITE DE LA COULEUR DU VOILE, PAS DE CELLE DU SITE.
 *
 * Les titres de Corpus portent leur propre teinte : sans cela, un h2 sombre
 * resterait sombre sur une photo sombre.
 */
.opus__diapo-contenu :is(h1, h2, h3, h4, h5, h6, p, li) {
  color: inherit;
}

.opus__diapo-contenu > :first-child { margin-top: 0; }
.opus__diapo-contenu > :last-child  { margin-bottom: 0; }

/*
 * LE VOILE EST UN DEGRADE, PAS UN APLAT.
 *
 * Un aplat sur toute la diapositive ternit la photo entiere pour rendre
 * lisibles trois lignes. Le degrade ne fonce que la ou il y a a lire, et
 * s'efface au-dessus.
 */
.opus__diapo-contenu--voile-doux {
  background: linear-gradient(to top, rgb(0 0 0 / 65%), rgb(0 0 0 / 0%));
}

.opus__diapo-contenu--voile-marque {
  background: linear-gradient(to top, rgb(0 0 0 / 88%), rgb(0 0 0 / 25%));
}

/* Sans voile, le texte reprend la couleur du site : c'est alors a l'image
   d'etre assez claire, et c'est un choix assume par l'utilisateur. */
.opus__diapo-contenu--voile-aucun {
  color: inherit;
}

/* --- Les commandes ---------------------------------------------------------
   Aux cotes, ce sont les fleches de Bootstrap a leur place habituelle : la
   feuille du coeur les pose deja, il n'y a rien a ecrire. Dessous, elles
   quittent l'image et se rangent sous elle, pour une photo dont les bords
   comptent. */
.opus__carrousel--commandes-dessous {
  overflow: visible;
}

.opus__carrousel--commandes-dessous .opus__commandes {
  display: flex;
  justify-content: flex-end;
  gap: var(--e-2);
  margin-top: var(--e-3);
}

/*
 * SOUS L'IMAGE, C'EST LE PIED DE LA VISIONNEUSE.
 *
 * Deux boutons du template, ranges a droite sous la photo, exactement comme
 * `.visionneuse__pied` range les siens. Aucune couleur n'est declaree ici :
 * `bouton--second` peint, et le mode sombre suit tout seul.
 */
.opus__carrousel--commandes-dessous :is(.carousel-control-prev, .carousel-control-next) {
  position: static;
  width: auto;
  opacity: 1;
}

/*
 * LE MOUVEMENT SE COUPE QUAND ON LE DEMANDE.
 *
 * Bootstrap respecte deja `prefers-reduced-motion` pour ses transitions ; ceci
 * couvre le fondu de la legende de galerie, qui est a nous.
 */
@media (prefers-reduced-motion: reduce) {
  .opus__galerie--survol .opus__legende {
    transition: none;
  }
}


/* ---------------------------------------------------------------------------
   L'AGRANDISSEMENT EST CELUI DU TEMPLATE

   `.galerie-agrandir` est la classe de Corpus : `template.js` l. 665 la
   branche sur sa visionneuse, `template.css` l. 2811 habille son bouton, son
   image et sa legende. Le module n'ecrit donc AUCUNE regle pour la boite qui
   s'ouvre, et une galerie du module s'agrandit exactement comme une galerie
   posee avec le tampon de l'editeur.

   CE QUI SUIT NE REPREND QUE CE QUE LA GRILLE DEMANDE : le bouton de Corpus
   n'a pas de format impose, la grille du module si.
   --------------------------------------------------------------------------- */
.opus__galerie button {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
}

/* Sans Corpus, c'est un lien vers l'image : meme promesse, meme curseur. */
.opus__vignette-lien[href$=".jpg"],
.opus__vignette-lien[href$=".jpeg"],
.opus__vignette-lien[href$=".png"],
.opus__vignette-lien[href$=".gif"],
.opus__vignette-lien[href$=".webp"],
.opus__vignette-lien[href$=".avif"],
.opus__vignette-lien[href$=".svg"] {
  cursor: zoom-in;
}


/* --- Le bandeau tres large, 23 septembre 2026 ------------------------------
   Demande de Cyrille : « un format plus large et moins haut pour les cas ou il
   serait en pleine largeur du navigateur ». 32/9 est le rapport des
   emplacements que Corpus livre deja (`emplacement-32x9.svg`), donc le meme
   vocabulaire des deux cotes. */
.opus__carrousel--32-9 .opus__diapo { aspect-ratio: 32 / 9; }

/*
 * UN FORMAT TRES LARGE NE TIENT PAS SUR UN TELEPHONE, ET C'EST MECANIQUE.
 *
 * 32/9 dans une colonne de 360 px donne une bande de 101 px de haut : l'image
 * n'y montre plus rien, et le texte pose dessus ne tient pas. Le rapport n'est
 * donc large que la ou il y a de la largeur.
 *
 * LE SEUIL EST CELUI DE CORPUS, 48 rem, le meme que celui ou ses colonnes se
 * replient. Un seuil invente ici ferait basculer le carrousel a un endroit ou
 * rien d'autre ne bouge.
 *
 * 21/9 RETOMBE SUR 16/9, ET 32/9 SUR 21/9 : un cran, pas deux. Retomber d'un
 * coup sur 16/9 depuis 32/9 ferait un saut de hauteur du simple au double au
 * franchissement du seuil.
 */
@media (max-width: 47.99rem) {
  .opus__carrousel--21-9 .opus__diapo { aspect-ratio: 16 / 9; }
  .opus__carrousel--32-9 .opus__diapo { aspect-ratio: 21 / 9; }
}


/* ---------------------------------------------------------------------------
   LES COMMANDES DU CARROUSEL SE VOIENT SUR TOUTES LES IMAGES

   « Je n'ai pas vu de bouton suivant pour naviguer », Cyrille, 23 septembre
   2026. Elles etaient pourtant la : mesurees a 191 x 716 px, visibles,
   opacite 0,5. C'est le dessin de Bootstrap qui est en cause, pas leur
   presence.

   BOOTSTRAP DESSINE UNE FLECHE BLANCHE A MOITIE TRANSPARENTE. Le choix suppose
   une photo sombre ; sur un fond clair, une image de produit ou un emplacement
   gris, il ne reste rien a voir. Une commande qu'on ne voit pas n'existe pas.

   ON POSE DONC UNE PASTILLE, comme la visionneuse de Corpus le fait pour les
   siennes : un rond sombre, une fleche blanche dessus, visible sur n'importe
   quelle image sans rien savoir d'elle. 2,75 rem, soit les 44 px de cible
   tactile recommandes, sans avoir a les regler.
   --------------------------------------------------------------------------- */
/*
 * `:not(.bouton)` : LA PASTILLE NE S'APPLIQUE PAS A UN BOUTON DU TEMPLATE.
 *
 * En coin, la commande porte `bouton bouton--second` et se peint toute seule.
 * Sans cette exclusion, la pastille lui imposait son rond sombre, et le
 * defaire a coups de `background: none` effacait aussi le fond du template :
 * un contour invisible, puis un ovale gris. Deux essais, deux echecs, la meme
 * cause.
 *
 * ON N'ECRASE PAS UNE REGLE, ON L'EMPECHE DE VISER. C'est la seule facon de
 * n'avoir jamais a la defaire.
 */
.opus__carrousel :is(.carousel-control-prev, .carousel-control-next):not(.bouton) {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  top: 50%;
  transform: translateY(-50%);
  border-radius: 50%;
  background: rgb(0 0 0 / 55%);
  opacity: 1;
}

.opus__carrousel .carousel-control-prev { left: var(--e-3, .75rem); }
.opus__carrousel .carousel-control-next { right: var(--e-3, .75rem); }

.opus__carrousel :is(.carousel-control-prev, .carousel-control-next):not(.bouton):hover,
.opus__carrousel :is(.carousel-control-prev, .carousel-control-next):not(.bouton):focus-visible {
  background: rgb(0 0 0 / 80%);
  opacity: 1;
}

/* L'icone de Bootstrap est une image de fond : sa taille se regle ici, et elle
   reste opaque, la pastille faisant deja le contraste. */
.opus__carrousel :not(.bouton) > :is(.carousel-control-prev-icon, .carousel-control-next-icon) {
  width: 1.25rem;
  height: 1.25rem;
}

/*
 * LES PASTILLES AUSSI SE PERDAIENT. Bootstrap en fait des traits blancs sans
 * contour : sur un fond clair, elles disparaissent comme les fleches. Un
 * contour sombre les tient sur n'importe quelle image, et la pastille active
 * se distingue par son remplissage, pas seulement par son opacite.
 */
.opus__carrousel .carousel-indicators [data-bs-target] {
  width: 1.75rem;
  height: .25rem;
  border: 0;
  border-radius: 1rem;
  background: rgb(255 255 255 / 55%);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 35%);
  opacity: 1;
}

.opus__carrousel .carousel-indicators .active {
  background: #fff;
}

/*
 * DESSOUS, LA PASTILLE SORT DE L'IMAGE ET RIEN D'AUTRE NE CHANGE.
 *
 * Elle garde son rond sombre et sa fleche blanche. J'avais d'abord voulu
 * l'eclaircir, puisqu'elle n'est plus posee sur une photo : il aurait fallu
 * inverser l'icone, qui est une image de fond de Bootstrap, et cette inversion
 * redevient fausse en theme sombre. Deux dessins a tenir au lieu d'un, pour un
 * gain nul.
 *
 * CE BLOC DOIT RESTER APRES LA REGLE GENERALE : elle repose le positionnement
 * absolu pour tout le monde, et c'est ici qu'on le retire.
 */
.opus__carrousel--commandes-dessous :is(.carousel-control-prev, .carousel-control-next) {
  position: static;
  transform: none;
}


/* --- Les commandes en coin, 23 septembre 2026 ------------------------------
   Deux boutons du template, groupes en bas a droite de la diapositive. Ils se
   posent SUR l'image, donc au-dessus du voile et du contenu : le contenu se
   loge en bas a gauche, les commandes en bas a droite, et les deux ne se
   marchent pas dessus tant que le texte est court.

   `z-index: 2` : le contenu de la diapositive est deja peint au-dessus de
   l'image, il faut passer devant lui aussi. */
.opus__carrousel--commandes-coin .opus__commandes {
  position: absolute;
  right: var(--e-4);
  bottom: var(--e-4);
  z-index: 2;
  display: flex;
  gap: var(--e-2);
}

/*
 * LE BOUTON REPREND SA TAILLE NATURELLE. Les regles de la pastille, plus haut,
 * imposent 2,75 rem et une forme ronde a tous les controles : il faut les
 * rendre ici, sinon l'intitule sort de son rond.
 */
/*
 * ON NE REPEINT RIEN : `bouton--second` PORTE DEJA SON FOND.
 *
 * Premiere version avec `background: none` ici, pour effacer le rond sombre de
 * la pastille : elle effacait aussi le fond blanc du bouton du template, et il
 * ne restait qu'un contour sur la photo. « Les boutons ne sont pas visibles »,
 * Cyrille, 23 septembre 2026, mesure faite sur le banc :
 * `background-color: rgba(0, 0, 0, 0)`.
 *
 * On ne declare donc AUCUNE couleur ici. Ce bloc ne fait que defaire la forme
 * ronde imposee plus haut a tous les controles, et laisse le template peindre :
 * fond, teinte, bordure, rayon et survol viennent de `.bouton--second`, comme
 * pour les boutons de la visionneuse.
 */
.opus__carrousel--commandes-coin :is(.carousel-control-prev, .carousel-control-next) {
  position: static;
  width: auto;
}

/* L'icone de Bootstrap est blanche : sur un bouton clair du template, elle
   disparaitrait. Le chevron est donc dessine par le bouton lui-meme. */
.opus__carrousel--commandes-coin :is(.carousel-control-prev-icon, .carousel-control-next-icon),
.opus__carrousel--commandes-dessous :is(.carousel-control-prev-icon, .carousel-control-next-icon) {
  width: .5rem;
  height: .5rem;
  background: none;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;

  /*
   * `align-self` PARCE QUE LE CHEVRON EST UN BLOC DANS UNE BOITE SOUPLE.
   *
   * Mesure sur le banc : sans lui, le chevron se posait 12 px au-dessus du
   * milieu du bouton, et le mot restait centre. Deux elements de la meme ligne
   * a deux hauteurs differentes se voit tout de suite.
   */
  align-self: center;
}

.opus__carrousel--commandes-coin .carousel-control-prev-icon,
.opus__carrousel--commandes-dessous .carousel-control-prev-icon {
  transform: rotate(-135deg);
}

.opus__carrousel--commandes-coin .carousel-control-next-icon,
.opus__carrousel--commandes-dessous .carousel-control-next-icon {
  transform: rotate(45deg);
}

/*
 * SOUS 48 REM, LES BOUTONS DESCENDENT SOUS L'IMAGE.
 *
 * Deux boutons a intitule dans le coin d'une diapositive de telephone
 * recouvrent le texte qu'ils cotoient. Le meme seuil que partout ailleurs dans
 * Corpus.
 */
@media (max-width: 47.99rem) {
  .opus__carrousel--commandes-coin .opus__commandes {
    position: static;
    justify-content: flex-end;
    margin-top: var(--e-3);
  }
}


/* ===========================================================================
   LA LISTE, L'ALERTE ET LES POINTS CLES - 23 septembre 2026

   TROIS ELEMENTS, ET PRESQUE AUCUNE REGLE : Corpus habille deja les listes du
   contenu et ses quatre messages. Ce qui suit ne pose que ce qu'il ne connait
   pas, c'est-a-dire les points cles, et le retrait des puces.
   ========================================================================= */
.opus__liste--nue {
  padding-inline-start: 0;
  list-style: none;
}

/*
 * LES POINTS CLES : une pastille, puis deux etages de texte.
 *
 * C'est la forme du tampon « Page - Points cles avec visuel », ou le tampon
 * emploie les utilitaires de Bootstrap (`d-flex gap-3 mb-4`). Le module ecrit
 * ici les memes valeurs avec les jetons de Corpus : le rendu est le meme, et
 * il ne depend pas de la presence des utilitaires.
 */
.opus__points {
  margin: 0;
  padding: 0;
  list-style: none;
}

.opus__point {
  display: flex;
  gap: var(--e-3);
  margin-bottom: var(--e-4);
}

.opus__point:last-child {
  margin-bottom: 0;
}

/*
 * LA PASTILLE NE SE COMPRIME PAS ET NE S'ETIRE PAS.
 *
 * `flex-shrink: 0` : sans lui, un texte long l'aplatit en ovale. `align-self`
 * la garde en haut, a hauteur de l'intitule, et non au milieu d'un paragraphe
 * de quatre lignes.
 */
.opus__point-marque {
  flex: 0 0 auto;
  align-self: flex-start;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  font-size: var(--t-petit, .875rem);
  font-weight: var(--graisse-appuyee, 600);
}

/* `--t-introduction` ET NON `--t-lead`, ET C'EST UNE CORRECTION DU
   24 SEPTEMBRE 2026. Question de Cyrille : « Corpus a aussi ses variables,
   tout est ok de ce cote ? » Balayage fait : sur les 37 jetons que cette
   feuille emploie, deux n'existaient nulle part, ni chez Corpus ni chez nous.
   `--t-lead` et `--graisse-titre` etaient des noms INVENTES : ils retombaient
   toujours sur leur repli, meme sous Corpus, et la taille ne suivait donc pas
   l'echelle du template comme le commentaire le promettait.

   LES DEUX VRAIS NOMS, releves dans `_echelle.scss` : `--t-introduction`
   (l. 92) et `--graisse-forte` (l. 74). Les replis restent pour Cassiopeia. */
.opus__point-titre {
  margin: 0 0 var(--e-2);
  font-size: var(--t-introduction, 1.125rem);
  font-weight: var(--graisse-appuyee, 600);
}

.opus__point-texte {
  margin: 0;
}


/* ===========================================================================
   CITATION, CHIFFRES CLES ET ACCORDEON - 23 septembre 2026

   L'accordeon n'a AUCUNE regle ici : `template.css` l'habille deja et
   `template.js` le fait vivre. Le module ecrit son balisage, un point c'est
   tout. La citation n'en a presque pas, pour la meme raison : Corpus dessine
   deja `blockquote`.
   ========================================================================= */
.opus__citation {
  margin: 0;
}

.opus__citation blockquote {
  margin-bottom: var(--e-2);
}

/*
 * L'ATTRIBUTION EST PLUS DISCRETE QUE LA CITATION, jamais l'inverse : c'est
 * la phrase qu'on retient, pas le nom.
 */
.opus__citation-source {
  font-size: var(--t-petit, .875rem);
  color: var(--texte-doux, inherit);
}

/* --- Les chiffres cles -----------------------------------------------------
   Meme mecanique que les cartes et la galerie : une largeur minimale, jamais
   un nombre de colonnes. Trois chiffres tiennent sur une ligne, quatre aussi
   si la place le permet, et un telephone les empile sans rien regler. */
.opus__chiffres {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
  gap: var(--gouttiere-grille, var(--e-4));
  margin: 0;
}

.opus__chiffre {
  min-width: 0;
}

/*
 * LA VALEUR EST GRANDE, MAIS PAS EN DUR. Le tampon de l'editeur ecrit
 * `font-size: 2.5rem` dans l'attribut `style`, faute de pouvoir faire
 * autrement dans TinyMCE. Ici, la taille suit l'echelle du template : un site
 * qui agrandit sa typographie agrandit aussi ses chiffres.
 */
.opus__chiffre-valeur {
  font-size: var(--t-h2, 2.25rem);
  font-weight: var(--graisse-forte, 700);
  line-height: 1.1;
}

.opus__chiffre-mesure {
  margin: var(--e-1) 0 0;
  color: var(--texte-doux, inherit);
}

/* --- Les onglets ------------------------------------------------------------
   « Un element tabulation, axe horizontal ou vertical dans le cas d'une
   position sidebar », Cyrille, 24 septembre 2026.

   LE COMPORTEMENT EST CELUI DU COEUR, L'HABILLAGE EST LE NOTRE. `joomla-tab`
   fabrique les boutons et gere le clavier ; sa feuille, elle, n'est pas
   chargee, parce qu'elle ecrit des gris en dur (`#f5f5f5`, `#ccc`, `#fefefe`)
   qui ne suivraient ni la charte du site ni le mode sombre.

   CE QUI SUIT N'EST DONC PAS DE LA DECORATION SEULEMENT : les trois premieres
   regles sont ce qui FAIT FONCTIONNER l'element. Sans elles, tous les panneaux
   s'affichent en meme temps. La feuille du coeur les portait ; en la laissant
   de cote, on en herite la charge.
   --------------------------------------------------------------------------- */
.opus__onglets {
  display: flex;
  flex-direction: column;
  gap: var(--e-4, 1rem);
}

.opus__onglets > joomla-tab-element {
  display: none;
}

.opus__onglets > joomla-tab-element[active] {
  display: block;
}

/* AVANT QUE LE SCRIPT N'ARRIVE, LE PREMIER PANNEAU EST VISIBLE. Le script est
   differe : sans cette regle, la zone serait vide une fraction de seconde, ce
   qui se voit et fait douter. `:not(:defined)` vaut exactement « le navigateur
   ne connait pas encore cet element ». */
.opus__onglets:not(:defined) > joomla-tab-element:first-of-type {
  display: block;
}

/* --- La barre des boutons ------------------------------------------------ */
/* `overflow-y: hidden` N'EST PAS UNE PRECAUTION, C'EST LA CORRECTION D'UN
   DEFAUT MESURE, et il a fallu trois echanges pour le trouver.

   « J'ai toujours en front mes fleches et point », Cyrille, trois fois entre
   17 h et 19 h le 24 septembre 2026, avec une capture ou l'on voit un petit
   triangle, un point et un autre triangle au bout de la barre d'onglets. Je
   cherchais un element flottant du template ; ce n'etait pas un element, mais
   UNE BARRE DE DEFILEMENT VERTICALE, celle de la barre d'onglets, rendue par
   Windows avec ses deux fleches et son curseur.

   DEUX CAUSES QUI SE COMBINENT, et aucune ne se voit dans la feuille.

   1. `overflow-x: auto` NE LAISSE PAS `overflow-y` EN `visible`. Le langage
      l'interdit : quand l'un des deux axes vaut autre chose que `visible`,
      l'autre, s'il valait `visible`, est CALCULE en `auto`. Releve sur le
      banc : `overflow-y` rendait bien `auto` alors que rien ne l'ecrivait.

   2. LE TRAIT DE L'ONGLET OUVERT DEBORDAIT D'UN PIXEL. Il etait pose a
      `bottom: -1px` pour couvrir la bordure de la barre. Mesure : hauteur
      utile 42 pixels, hauteur de contenu 43. Un pixel de trop, et la barre de
      defilement apparait, large de 15.

   LE TRAIT REVIENT DONC A `bottom: 0`, juste au-dessus de la bordure, ou il se
   voit tout aussi bien, et l'axe vertical est ferme explicitement. */
.opus__onglets > [role="tablist"] {
  display: flex;
  gap: var(--e-1, .25rem);
  overflow-x: auto;
  overflow-y: hidden;
  border-bottom: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 15%));
}

.opus__onglets button[role="tab"] {
  position: relative;
  flex: 0 0 auto;
  padding: var(--e-2, .5rem) var(--e-4, 1rem);
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  font-weight: var(--graisse-appuyee, 600);
  cursor: pointer;
}

/* LE TRAIT DE L'ONGLET OUVERT EST UN PSEUDO, PAS UNE BORDURE : une bordure
   deplacerait le texte de deux pixels a chaque changement d'onglet, et la
   rangee entiere sauterait. */
.opus__onglets button[role="tab"]::after {
  content: "";
  position: absolute;
  inset-inline: var(--e-2, .5rem);
  bottom: 0;
  height: var(--trait-fort, 2px);
  border-radius: var(--trait-fort, 2px);
  background: transparent;
}

.opus__onglets button[role="tab"]:hover {
  color: var(--accent, inherit);
}

.opus__onglets button[role="tab"][aria-selected="true"] {
  color: var(--accent, inherit);
}

.opus__onglets button[role="tab"][aria-selected="true"]::after {
  background: var(--accent, currentColor);
}

/* --- Le sens vertical, pour une colonne ---------------------------------- */
.opus__onglets[orientation="vertical"] {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--e-5, 1.5rem);
}

.opus__onglets[orientation="vertical"] > [role="tablist"] {
  flex: 0 0 auto;
  min-width: 10rem;
  max-width: 40%;
  flex-direction: column;
  /* EN COLONNE, C'EST L'AUTRE AXE QUI PEUT DEBORDER. Les deux sont fermes :
     une barre de defilement dans une barre d'onglets ne sert jamais a rien,
     elle se contente de s'y montrer. */
  overflow-x: hidden;
  overflow-y: auto;
  border-bottom: 0;
  border-inline-start: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 15%));
}

.opus__onglets[orientation="vertical"] button[role="tab"] {
  text-align: start;
}

/* LE TRAIT PASSE A GAUCHE, sur le meme principe. */
.opus__onglets[orientation="vertical"] button[role="tab"]::after {
  inset-inline: auto;
  inset-block: var(--e-1, .25rem);
  inset-inline-start: 0;
  width: var(--trait-fort, 2px);
  height: auto;
}

.opus__onglets[orientation="vertical"] > joomla-tab-element {
  flex: 1 1 auto;
  min-width: 0;
}

/* --- Les boutons d'accordeon, quand la rangee se replie ------------------ */
/* `joomla-tab` les fabrique toujours et les masque par `hidden` tant qu'on est
   en onglets ; il retire l'attribut sous le seuil. Ils ne sont donc habilles
   qu'ici, et ne coutent rien le reste du temps. */
.opus__onglets > button[aria-controls] {
  display: block;
  width: 100%;
  padding: var(--e-3, .75rem) 0;
  border: 0;
  border-top: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 15%));
  background: none;
  color: inherit;
  font: inherit;
  font-weight: var(--graisse-appuyee, 600);
  text-align: start;
  cursor: pointer;
}

.opus__onglets > button[aria-controls][hidden] {
  display: none;
}

.opus__onglets > button[aria-controls]:hover {
  color: var(--accent, inherit);
}

/* --- Le contenu d'un panneau --------------------------------------------- */
/* UN PANNEAU EST UNE PILE D'ELEMENTS, comme une carte : il n'a pas de forme a
   lui, ce sont ses elements qui en ont une. */
.opus__onglet-corps > :first-child { margin-top: 0; }
.opus__onglet-corps > :last-child  { margin-bottom: 0; }

/* LE PARTAGE EN DEUX ZONES, quand l'onglet le demande. « Pouvoir deplacer les
   images a gauche et le sous-titre, texte, a droite », Cyrille, 24 septembre
   2026.

   UNE GRILLE, PAS UN FLEX, et la raison vient d'une mesure faite une heure plus
   tot : en flex, la taille minimale automatique d'une IMAGE vaut sa taille
   intrinseque, et un emplacement de 1600 pixels ecrasait le texte a zero. Une
   grille dont les deux pistes sont declarees `minmax(0, 1fr)` ne peut pas
   connaitre ce probleme : les parts sont fixees par la grille, et le contenu
   s'y range.

   L'ORDRE DU DOCUMENT NE BOUGE JAMAIS : le corps est ecrit avant les images,
   quel que soit le cote choisi. Seul `order` les replace, et seulement pour
   l'oeil. */
.opus__onglet--media-droite,
.opus__onglet--media-gauche {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--e-5, 1.5rem);
  align-items: start;
}

.opus__onglet--media-gauche .opus__onglet-media {
  order: -1;
}

.opus__onglet-media > :first-child { margin-top: 0; }
.opus__onglet-media > :last-child  { margin-bottom: 0; }

/* SOUS 40 REM, LES DEUX ZONES S'EMPILENT, et l'image repasse apres le texte :
   deux demi-colonnes dans une largeur de poche ne donnent ni un texte lisible
   ni une image regardable. */
@media (max-width: 40rem) {
  .opus__onglet--media-droite,
  .opus__onglet--media-gauche {
    grid-template-columns: minmax(0, 1fr);
  }

  .opus__onglet--media-gauche .opus__onglet-media {
    order: 0;
  }
}

/* --- La frise ---------------------------------------------------------------
   « Un montage sur deux axes pour presenter une echelle de temps, par exemple
   une entreprise qui evolue », Cyrille, 24 septembre 2026.

   TROIS FORMES, UN SEUL BALISAGE. Verticale d'un cote, verticale alternee,
   horizontale : le `ol` ne change pas, seule la feuille replace. Un montage
   enregistre dans un sens et relu dans l'autre garde donc tout son contenu.

   L'AXE EST UNE BORDURE, LES PASTILLES DES PSEUDO-ELEMENTS, et rien n'est
   dessine en JavaScript. C'est aussi ce que font les exemples de MDBootstrap
   qui ont servi de reference ; c'est la seule chose qu'on leur emprunte.

   LA PASTILLE EST DECORATIVE ET N'EST ANNONCEE A PERSONNE : un pseudo-element
   ne porte ni texte ni role. Ce qui situe l'etape, c'est son repere, ecrit en
   toutes lettres, et le fait que la liste soit ORDONNEE.
   --------------------------------------------------------------------------- */
.opus__frise {
  --frise-trait: 2px;
  --frise-pastille: .75rem;

  margin: 0;
  padding: 0;
  list-style: none;
}

.opus__etape {
  position: relative;
}

/* LA PASTILLE, commune aux trois formes. Sa couleur suit le ton de l'etape, et
   le fond du site la detoure : sans ce liseré, une pastille posee sur l'axe
   laisserait voir le trait au travers. */
.opus__etape::before {
  content: "";
  position: absolute;
  width: var(--frise-pastille);
  height: var(--frise-pastille);
  border-radius: 50%;
  background: var(--etape-ton, var(--accent, currentColor));
  box-shadow: 0 0 0 3px var(--fond, #fff);
}

.opus__etape-repere {
  margin: 0 0 var(--e-1, .25rem);
  font-size: var(--t-petit, .9375rem);
  line-height: var(--i-petit, 1.5);
  font-weight: var(--graisse-forte, 700);
  color: var(--etape-ton, var(--accent, inherit));
}

.opus__etape-corps > :first-child { margin-top: 0; }
.opus__etape-corps > :last-child  { margin-bottom: 0; }

.opus__etape--accent { --etape-ton: var(--accent, currentColor); }
.opus__etape--succes { --etape-ton: var(--succes, currentColor); }
.opus__etape--alerte { --etape-ton: var(--alerte, currentColor); }
.opus__etape--erreur { --etape-ton: var(--erreur, currentColor); }

/* --- Verticale, tout d'un cote ------------------------------------------- */
.opus__frise--vertical .opus__etape {
  padding-inline-start: var(--e-6, 2rem);
  padding-bottom: var(--e-5, 1.5rem);
  border-inline-start: var(--frise-trait) solid var(--bord, rgb(0 0 0 / 15%));
}

/* LA DERNIERE ETAPE NE PROLONGE PAS L'AXE : un trait qui continue apres le
   dernier jalon promet une suite qui n'existe pas. */
.opus__frise--vertical .opus__etape:last-child {
  padding-bottom: 0;
  border-inline-start-color: transparent;
}

.opus__frise--vertical .opus__etape::before {
  inset-inline-start: calc((var(--frise-pastille) + var(--frise-trait)) / -2);
  top: .25rem;
}

/* --- Verticale alternee --------------------------------------------------- */
/* L'ALTERNANCE EST BELLE ET SE LIT MOINS BIEN : l'oeil fait des allers-retours.
   Elle reste un choix, jamais le defaut, et sous 48 rem elle repasse d'un seul
   cote, ou elle redevient lisible. */
@media (min-width: 48rem) {
  .opus__frise--alterne {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 0 minmax(0, 1fr);
  }

  .opus__frise--alterne .opus__etape {
    grid-column: 3;
    border-inline-start: var(--frise-trait) solid var(--bord, rgb(0 0 0 / 15%));
    padding-inline-start: var(--e-6, 2rem);
    padding-bottom: var(--e-5, 1.5rem);
  }

  /* UNE ETAPE SUR DEUX PASSE A GAUCHE, et son axe avec elle. Le texte s'aligne
     alors a droite, vers le centre, sinon les deux colonnes ne se repondent
     pas. */
  .opus__frise--alterne .opus__etape:nth-child(odd) {
    grid-column: 1;
    text-align: end;
    border-inline-start: 0;
    border-inline-end: var(--frise-trait) solid var(--bord, rgb(0 0 0 / 15%));
    padding-inline-start: 0;
    padding-inline-end: var(--e-6, 2rem);
  }

  .opus__frise--alterne .opus__etape:nth-child(odd)::before {
    inset-inline-start: auto;
    inset-inline-end: calc((var(--frise-pastille) + var(--frise-trait)) / -2);
  }

  /* LA DERNIERE ETAPE D'UNE COLONNE GARDE SON AXE : contrairement a la frise
     d'un seul cote, ce n'est pas forcement la derniere de la frise. On ne coupe
     donc que la toute derniere, quel que soit son cote. */
  .opus__frise--alterne .opus__etape:last-child {
    padding-bottom: 0;
  }
}

/* --- Horizontale ---------------------------------------------------------- */
/* ELLE MONTRE UN PARCOURS D'UN COUP D'OEIL, et demande des textes courts : les
   colonnes sont de largeur egale, un paragraphe de dix lignes y ferait une
   colonne trois fois plus haute que ses voisines.

   L'AXE EST EN HAUT, les pastilles dessus, les textes dessous. Sous 48 rem, la
   frise redevient verticale : quatre colonnes sur une largeur de poche ne
   donnent rien de lisible. */
@media (min-width: 48rem) {
  .opus__frise--horizontal {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    gap: var(--e-4, 1rem);
  }

  .opus__frise--horizontal .opus__etape {
    padding-top: var(--e-5, 1.5rem);
    padding-inline-end: var(--e-4, 1rem);
    border-top: var(--frise-trait) solid var(--bord, rgb(0 0 0 / 15%));
  }

  .opus__frise--horizontal .opus__etape:last-child {
    padding-inline-end: 0;
  }

  .opus__frise--horizontal .opus__etape::before {
    top: calc((var(--frise-pastille) + var(--frise-trait)) / -2);
    inset-inline-start: 0;
  }
}

/* SOUS 48 REM, L'HORIZONTALE REDEVIENT VERTICALE. Les memes regles que la frise
   d'un seul cote, parce que c'est la seule forme qui tienne dans une colonne
   etroite. */
@media (max-width: 47.999rem) {
  .opus__frise--horizontal .opus__etape {
    padding-inline-start: var(--e-6, 2rem);
    padding-bottom: var(--e-5, 1.5rem);
    border-inline-start: var(--frise-trait) solid var(--bord, rgb(0 0 0 / 15%));
  }

  .opus__frise--horizontal .opus__etape:last-child {
    padding-bottom: 0;
    border-inline-start-color: transparent;
  }

  .opus__frise--horizontal .opus__etape::before {
    inset-inline-start: calc((var(--frise-pastille) + var(--frise-trait)) / -2);
    top: .25rem;
  }
}

/* --- Les barres -------------------------------------------------------------
   « Ce qui manque : des barres graphe », Cyrille, 24 septembre 2026.

   UNE GRILLE DE DEUX COLONNES, PAS UN FLOTTANT : le mot a gauche, la part a
   droite, et les traits de toutes les lignes commencent au meme endroit quelle
   que soit la longueur des mots. Avec un flottant, « Developpement » et « SEO »
   decaleraient leurs traits, et la comparaison, qui est tout l'interet de
   l'element, deviendrait fausse a l'oeil.

   LA LARGEUR DU MOT EST BORNEE : `minmax(auto, 12rem)`. Sans borne, un mot long
   mangerait la piste ; sous la borne, la colonne se sert de ce dont elle a
   besoin et pas plus.
   --------------------------------------------------------------------------- */
.opus__barres {
  --barre-trait: .5rem;

  display: grid;
  gap: var(--e-2, .5rem) var(--e-4, 1rem);
  margin: 0;
}

.opus__barre {
  display: grid;
  grid-template-columns: minmax(auto, 12rem) 1fr;
  align-items: center;
  gap: var(--e-3, .75rem);
  min-width: 0;
}

.opus__barre-terme {
  font-weight: var(--graisse-appuyee, 600);
  font-size: var(--t-petit, .9375rem);
  line-height: var(--i-petit, 1.5);
  min-width: 0;
}

/* LA PART EST UNE LIGNE SOUPLE : la piste prend la place qui reste, le nombre
   se pose au bout et ne bouge plus. */
.opus__barre-part {
  display: flex;
  align-items: center;
  gap: var(--e-3, .75rem);
  margin: 0;
  min-width: 0;
}

.opus__barre-piste {
  flex: 1 1 auto;
  min-width: 0;
  height: var(--barre-trait);
  border-radius: 999px;
  background: var(--fond-teinte, rgb(0 0 0 / 8%));
  overflow: hidden;
}

/* LE TRAIT LUI-MEME. Sa longueur vient de `--part`, ecrit par le gabarit, et
   c'est la seule chose que le gabarit impose. */
.opus__barre-trait {
  display: block;
  width: var(--part, 0%);
  height: 100%;
  border-radius: inherit;
  background: var(--barre-ton, var(--accent, currentColor));
}

/* LE MOUVEMENT EST UNE FAVEUR, PAS UN DU : il ne se declenche que pour qui ne
   demande pas moins d'animations, et son absence ne change rien a la lecture. */
@media (prefers-reduced-motion: no-preference) {
  .opus__barre-trait {
    transition: width .4s ease;
  }
}

.opus__barre-nombre {
  flex: 0 0 auto;
  font-size: var(--t-petit, .9375rem);
  line-height: var(--i-petit, 1.5);
  font-variant-numeric: tabular-nums;
  color: var(--texte-doux, inherit);
}

/* LE NOMBRE MASQUE RESTE LU. « Masquer » veut dire « retirer de l'image », pas
   « retirer de la page » : un `display: none` l'enleverait aussi aux lecteurs
   d'ecran, et la ligne ne dirait plus rien du tout a qui ne voit pas le trait.
   Il sort donc de l'ecran, et reste dans le document. */
.opus__barres--muettes .opus__barre-nombre {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.opus__barres--fine    { --barre-trait: .25rem; }
.opus__barres--epaisse { --barre-trait: 1rem; }

/* LES TONS PASSENT PAR UNE VARIABLE, et non par quatre fonds ecrits en dur :
   les traits s'en servent comme fond, les anneaux comme couleur d'arc. Une
   seule declaration sert les deux formes.

   La regle est celle des chiffres : la couleur ne porte aucune information ici,
   le mot et le nombre sont ecrits a cote. */
.opus__barre--accent { --barre-ton: var(--accent, currentColor); }
.opus__barre--succes { --barre-ton: var(--succes, currentColor); }
.opus__barre--alerte { --barre-ton: var(--alerte, currentColor); }
.opus__barre--erreur { --barre-ton: var(--erreur, currentColor); }

/* --- Les anneaux ------------------------------------------------------------
   « Je peux les avoir en rond ? », Cyrille, 24 septembre 2026.

   LE MEME BALISAGE, UNE AUTRE FEUILLE. Rien ne change dans le document : la
   ligne devient une colonne, la piste devient un disque, et le trait ne sort
   pas. Passer d'une forme a l'autre ne casse donc aucune classe posee a la
   main, et ne change rien a ce que lit un lecteur d'ecran.

   L'ARC EST UN DEGRADE CONIQUE, ET LE TROU UN MASQUE. Pas de SVG, pas de
   `stroke-dasharray` a calculer, pas une ligne de JavaScript : deux
   proprietes, et l'epaisseur du trait reste celle des trois reglages.
   `conic-gradient` et `mask` sont dans tous les navigateurs a jour ; la regle
   de repli juste apres garde un navigateur trop vieux devant un disque plein,
   qui dit encore la part.
   --------------------------------------------------------------------------- */
.opus__barres--anneaux {
  --anneau: 6rem;
  --barre-trait: .75rem;

  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--e-4, 1rem);
  text-align: center;
}

.opus__barres--anneaux.opus__barres--fine    { --barre-trait: .375rem; }
.opus__barres--anneaux.opus__barres--epaisse { --barre-trait: 1.25rem; }

/* LE MOT PASSE SOUS L'ANNEAU. Il reste ecrit AVANT lui dans le document, parce
   que c'est l'ordre de lecture juste : « Formation, 27 % ». Seul l'affichage
   les inverse. */
.opus__barres--anneaux .opus__barre {
  display: flex;
  flex-direction: column-reverse;
  align-items: center;
  gap: var(--e-2, .5rem);
}

.opus__barres--anneaux .opus__barre-terme {
  text-align: center;
}

/* LE NOMBRE SE POSE AU CENTRE DE L'ANNEAU : les deux occupent la meme cellule
   de grille, l'un par-dessus l'autre. */
.opus__barres--anneaux .opus__barre-part {
  display: grid;
  place-items: center;
}

.opus__barres--anneaux .opus__barre-piste,
.opus__barres--anneaux .opus__barre-nombre {
  grid-area: 1 / 1;
}

.opus__barres--anneaux .opus__barre-piste {
  width: var(--anneau);
  height: var(--anneau);
  border-radius: 50%;
  background: var(--barre-ton, var(--accent, currentColor));
}

@supports (background: conic-gradient(red 10%, blue 0)) {
  .opus__barres--anneaux .opus__barre-piste {
    background: conic-gradient(
      var(--barre-ton, var(--accent, currentColor)) var(--part, 0%),
      var(--fond-teinte, rgb(0 0 0 / 8%)) 0
    );
  }
}

/* LE TROU DU MILIEU. Sans masque, l'anneau reste un camembert a une part, ce
   qui se lit encore ; avec, le nombre ecrit au centre se pose sur le fond de la
   page et non sur la couleur. */
@supports (mask: radial-gradient(#000, #000)) {
  .opus__barres--anneaux .opus__barre-piste {
    mask: radial-gradient(farthest-side, transparent calc(100% - var(--barre-trait)), #000 calc(100% - var(--barre-trait)));
  }
}

/* LE TRAIT NE SERT PLUS : l'arc le remplace. */
.opus__barres--anneaux .opus__barre-trait {
  display: none;
}

.opus__barres--anneaux .opus__barre-nombre {
  font-size: var(--t-introduction, 1.125rem);
  font-weight: var(--graisse-forte, 700);
  color: inherit;
}

/* SOUS 30 REM, LE MOT PASSE AU-DESSUS DE SON TRAIT. A deux colonnes dans une
   colonne etroite, il resterait deux ou trois centimetres de piste, et le trait
   ne se comparerait plus a rien. */
@media (max-width: 30rem) {
  .opus__barres:not(.opus__barres--anneaux) .opus__barre {
    grid-template-columns: 1fr;
    gap: var(--e-1, .25rem);
  }
}

/* --- Une liste sur plusieurs colonnes --------------------------------------
   Des colonnes de TEXTE, pas une grille : la liste se coupe en deux au milieu,
   l'ordre de lecture ne change pas, et l'element le plus long n'impose pas sa
   hauteur aux autres. Sous 48 rem, elles retombent a une seule. */
.opus__liste--colonnes-2,
.opus__liste--colonnes-3 {
  column-gap: var(--e-5, 2rem);
}

@media (min-width: 48rem) {
  .opus__liste--colonnes-2 { column-count: 2; }
  .opus__liste--colonnes-3 { column-count: 3; }
}

/* Une entree ne doit jamais etre coupee entre deux colonnes. */
.opus__liste--colonnes-2 li,
.opus__liste--colonnes-3 li {
  break-inside: avoid;
}


/* --- Le cadre d'un bloc, 23 septembre 2026 ---------------------------------
   Il groupe ce que le bloc contient, la ou le fond de rangee prenait toute la
   colonne. Trois formes, aucune couleur inventee : ce sont les jetons de
   Corpus, donc le mode sombre suit sans une regle de plus. */
.opus__cadre {
  padding: var(--e-4);
  border-radius: var(--forme-carte-angle, var(--angle-lg));
}

.opus__cadre--doux {
  background: var(--fond-creuse, rgb(0 0 0 / 3%));
}

.opus__cadre--teinte {
  background: var(--fond-teinte, rgb(0 0 0 / 6%));
}

/*
 * « TRAIT » NE PEINT RIEN : un contour, et le fond de la page au travers. Sur
 * une bande deja teintee, un cadre de plus en couleur fait deux aplats l'un
 * sur l'autre ; le trait, lui, se voit partout.
 */
.opus__cadre--trait {
  border: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 12%));
}

/* Le premier et le dernier enfant ne doivent pas ajouter leur marge a celle
   du cadre : deux retraits qui se suivent se lisent comme un defaut. */
.opus__cadre > :first-child { margin-top: 0; }
.opus__cadre > :last-child  { margin-bottom: 0; }


/* --- L'etat : une pastille, un mot -----------------------------------------
   Le tampon « Grille - Cartes avec etat » ecrit ses couleurs en style, faute
   de pouvoir faire autrement dans TinyMCE. Ici elles sont nommees, et ce sont
   les jetons de Corpus : le mode sombre suit tout seul. */
.opus__etat {
  display: flex;
  align-items: center;
  gap: .4em;
  margin: 0;
}

.opus__etat-puce {
  flex: 0 0 auto;
  width: .6em;
  height: .6em;
  border-radius: 50%;
  background: currentColor;
}

.opus__etat--succes { color: var(--succes, #136c3a); }
.opus__etat--alerte { color: var(--alerte, #8a5300); }
.opus__etat--erreur { color: var(--erreur, #a11b1b); }
.opus__etat--neutre { color: var(--texte-doux, inherit); }


/* --- Les chiffres : taille et pose, 23 septembre 2026 ----------------------
   Trois tailles, et la possibilite de poser ce que le chiffre mesure A COTE
   plutot que dessous. Un prix et son unite forment une phrase : « 39 EUR par
   an » se lit d'un trait, coupe en deux il devient deux informations. */
.opus__chiffres--grande .opus__chiffre-valeur { font-size: var(--t-h1, 3rem); }
.opus__chiffres--enorme .opus__chiffre-valeur { font-size: calc(var(--t-h1, 3rem) * 1.4); }

/*
 * EN LIGNE, LA VALEUR ET SON UNITE PARTAGENT LA LIGNE DE BASE.
 *
 * `align-items: baseline` et non `center` : un chiffre de 3 rem a cote d'un
 * mot de 1 rem, centres l'un sur l'autre, flottent ; poses sur la meme ligne
 * d'ecriture, ils se tiennent.
 */
.opus__chiffres--en-ligne .opus__chiffre {
  display: flex;
  align-items: baseline;
  gap: var(--e-2);
  flex-wrap: wrap;
}

.opus__chiffres--en-ligne .opus__chiffre-mesure {
  margin: 0;
}

/* --- Le ton d'une carte ----------------------------------------------------
   LA MISE EN VALEUR D'UNE CITATION, REPRISE TELLE QUELLE.

   Deux essais rejetes par Cyrille le 24 septembre 2026. Le premier, un contour
   en couleur d'accent plus un filet epais en haut : « c'est beaucoup trop
   vu ». Le second, le filet vertical seul : « c'est bizarre ce trait ».
   Il avait raison les deux fois, et la deuxieme fois pour une raison que le
   premier essai cachait : DANS CORPUS, LE FILET VERTICAL NE VIT JAMAIS SEUL.

   Mesure faite dans `template.css` l. 3351 : un `blockquote` pose un fond
   `--accent-doux` ET le filet sur son cote. Le fond porte la mise en valeur,
   le filet la signe. Le trait tout seul sur un fond blanc n'a rien a border :
   il flotte, et c'est exactement ce qui se voyait.

   LA CARTE PRIMAIRE PREND DONC LES DEUX, comme la citation : le meme fond, le
   meme filet, aux memes jetons. Rien de neuf a retenir, et le mode sombre
   suit sans une regle de plus puisque Corpus redeclare `--accent-doux`.

   `--accent-doux` EST TRES PALE (95 % de clarte en theme clair), ce qui leve
   l'objection que je posais ici avant : ce n'est pas un aplat de couleur
   derriere un texte long, c'est une nuance.

   LES DEUX ANGLES DU BAS DEVIENNENT DROITS, ET C'EST LA TROISIEME PIECE.
   « Quand il y a un trait, il n'y a plus de radius dans l'angle », Cyrille,
   24 septembre 2026. Verifie : le `blockquote` de Corpus porte
   `border-radius: var(--angle) var(--angle) 0 0` (l. 3354). La raison est
   dans son propre commentaire : le filet part de `bottom: 0` sans retrait,
   « les angles du bas sont droits, il n'y a plus de courbe a eviter ». Un
   angle arrondi couperait le pied du trait.

   LES REPLIS SONT LA POUR CASSIOPEIA : sans Corpus, un gris tres clair, 2 px
   et 70 % valent mieux qu'une regle qui ne dessine rien.

   LA CARTE SECONDAIRE NE CHANGE PAS : un fond creuse, sans filet. C'est le
   ton discret, il ne signe rien. */
.opus__carte--primaire {
  position: relative;
  background: var(--accent-doux, rgb(0 0 0 / 4%));
  border-radius: var(--forme-carte-angle, var(--angle-lg, .5rem)) var(--forme-carte-angle, var(--angle-lg, .5rem)) 0 0;
}

.opus__carte--primaire::after {
  content: "";
  position: absolute;
  top: auto;
  bottom: 0;
  left: 0;
  width: var(--filet-epaisseur, 2px);
  height: var(--filet-part, 70%);
  background: var(--filet-couleur, var(--accent, currentColor));
  border-radius: var(--filet-epaisseur, 2px);
}

.opus__carte--secondaire {
  background: var(--fond-creuse, rgb(0 0 0 / 3%));
}

/* --- L'adresse et le contact -----------------------------------------------
   PRESQUE RIEN A HABILLER, ET C'EST VOULU. Le tampon « Page - Coordonnees »
   n'a pas une seule classe : il pose un `address` et deux paragraphes, et le
   template s'en occupe. On ne fait ici que deux choses que le navigateur rend
   mal tout seul.

   1. `address` SORT EN ITALIQUE par defaut dans tous les navigateurs. Une
      adresse postale n'est pas une citation ; l'italique sur trois lignes de
      chiffres et de noms propres se lit moins bien, et rien ne le justifie.

   2. LES DEUX PARAGRAPHES DU CONTACT SE SUIVENT SANS SE COLLER. Un seul `gap`
      sur le conteneur, plutot qu'une marge sur chacun : le dernier ne laisse
      alors pas de marge en trop au bas du bloc. */
.opus__adresse {
  margin: 0;
  font-style: normal;
}

.opus__contact {
  display: flex;
  flex-direction: column;
  gap: var(--e-3, .75rem);
}

.opus__coord-joindre,
.opus__coord-heures {
  margin: 0;
}

/* --- La source d'un chiffre ------------------------------------------------
   ELLE NE SUIT PAS LA TAILLE DU CHIFFRE. Un chiffre en « enorme » emporterait
   sa source avec lui si elle heritait ; or c'est une mention, et une mention
   reste petite quel que soit ce qu'elle accompagne. La classe `note` de Corpus
   pose la taille et la couleur ; on ne fait ici que rendre la marge.

   ELLE PASSE A LA LIGNE MEME EN POSE « A DROITE ». La mesure peut tenir a
   cote du chiffre, la source non : elle est trop longue, et la mettre en bout
   de ligne la ferait lire comme la suite de la mesure. */
.opus__chiffre-source {
  flex-basis: 100%;
  margin: var(--e-1, .25rem) 0 0;
}

/* --- Le ton d'une part de chiffre ------------------------------------------
   TROIS PARTS, LES MEMES QUATRE COULEURS. « Il me faudrait cela pour chaque
   champ, valeur, mesure et source », Cyrille, 24 septembre 2026.

   QUATRE COULEURS, CELLES DE CORPUS, et pas une de plus. `--accent`,
   `--succes`, `--alerte` et `--erreur` sont deja les couleurs des alertes et
   des etats du module : un chiffre en vert et un etat « Disponible » en vert
   parlent alors de la meme chose. Le mode sombre les redeclare, donc rien a
   ecrire pour lui.

   LA COULEUR NE PORTE AUCUNE INFORMATION ICI, et c'est ce qui l'autorise : le
   chiffre et ce qu'il mesure sont ecrits a cote. Qui ne distingue pas les
   couleurs lit la meme chose que tout le monde. Un ton qui voudrait dire
   « attention » demanderait un element Etat, pas une teinte.

   LES REPLIS RENVOIENT A LA COULEUR DU TEXTE : sans Corpus, un chiffre de la
   meme couleur que le reste vaut mieux qu'un chiffre invisible. */
.opus__chiffre-valeur--accent,
.opus__chiffre-mesure--accent,
.opus__chiffre-source--accent { color: var(--accent, currentColor); }

.opus__chiffre-valeur--succes,
.opus__chiffre-mesure--succes,
.opus__chiffre-source--succes { color: var(--succes, currentColor); }

.opus__chiffre-valeur--alerte,
.opus__chiffre-mesure--alerte,
.opus__chiffre-source--alerte { color: var(--alerte, currentColor); }

.opus__chiffre-valeur--erreur,
.opus__chiffre-mesure--erreur,
.opus__chiffre-source--erreur { color: var(--erreur, currentColor); }

/* --- Le sous-titre ---------------------------------------------------------
   IL NE PESAIT RIEN, ET PERSONNE NE S'EN ETAIT APERCU. `opus__soustitre`
   etait ecrit dans la mise en page depuis le premier jour et habille nulle
   part : un sous-titre sortait en paragraphe ordinaire, indiscernable du texte
   qui le suit. Mesure faite le 24 septembre 2026, apres la question de Cyrille
   sur l'accessibilite des atouts.

   `--t-introduction` EST LE JETON DU CHAPO DE CORPUS, celui que `.lead` emploie
   (`template.css` l. 7592). Un sous-titre de module et une introduction
   d'article se ressemblent donc, ce qui est voulu : c'est la meme fonction, une
   phrase qui ouvre et qui n'est pas un titre.

   IL N'EST PAS APPUYE, ET C'EST DELIBERE. Un texte en gras et plus grand se lit
   comme un titre ; s'il n'en est pas un, le balisage et l'oeil se contredisent,
   et c'est exactement ce que le critere « information et relations » du RGAA
   interdit. Un intitule qui doit ressortir demande l'element Titre, pas un
   sous-titre deguise.

   LES REPLIS SONT LA POUR CASSIOPEIA. */
.opus__soustitre {
  font-size: var(--t-introduction, 1.125rem);
  line-height: var(--i-introduction, 1.5);
  color: var(--texte-doux, inherit);
}

/* --- Des cartes calmes -----------------------------------------------------
   « Comment je supprime l'effet au survol ? », Cyrille, 24 septembre 2026.
   Il avait la reponse en trois lignes de CSS personnalise ; la voici en un
   reglage, puisque la question se posera a chaque site.

   ELLE S'APPLIQUE QUELLE QUE SOIT LA FORME, et c'est la correction de la
   demi-heure suivante. J'en avais fait une quatrieme forme, « Cadre, sans
   effet au survol » : sur une carte reglee « Aucun cadre », l'ombre revenait
   donc au survol. « Le reglage est sur aucun et pourtant il y a l'ombre au
   survol. » La forme et le survol sont deux questions ; ce sont deux champs.

   DEUX JETONS ET UNE REGLE, ET PAS AUTREMENT. Corpus pose trois choses au
   survol d'une carte (`template.css` l. 2297) : une ombre, un fond et une
   couleur de bordure. Les deux premieres passent par des jetons, donc on les
   eteint en les redeclarant, sans ecrire une regle qui doive gagner. La
   troisieme n'a pas de jeton a elle : elle demande une vraie regle, et c'est
   la seule.

   ELLE EST NOMMEE POUR QU'ON LA RETROUVE le jour ou Corpus donnera un jeton a
   cette bordure : il n'y aura plus qu'a la supprimer.

   LE FOCUS N'EST PAS TOUCHE. `:focus-within` garde son contour et son halo :
   c'est la trace du clavier, elle n'a rien de decoratif, et l'eteindre rendrait
   le montage inutilisable sans souris. */
.opus__cartes--calme .carte {
  --forme-carte-ombre-survol: none;
  --forme-carte-fond-survol: var(--forme-carte-fond);
}

/* La bordure de survol n'a pas de jeton : seule regle de ce bloc a en defaire
   une de Corpus. */
.opus__cartes--calme .carte:hover {
  border-color: var(--bord, currentColor);
}

/* UNE ICONE A SOI, POSEE EN MASQUE - 25 septembre 2026.

   Le fichier choisi par l'administrateur ne rentre pas dans la page : il est
   donne en `mask`, le navigateur n'en lit que la FORME, et c'est le fond qui
   la remplit. `currentColor` fait donc que l'icone prend la couleur du texte
   du bouton, exactement comme un symbole de la planche, sur une variante
   pleine comme sur un bouton de contour.

   `-webkit-mask` EST ENCORE NECESSAIRE : Safari ne comprend la forme courte
   qu'a partir de la 15.4, et un site public ne choisit pas ses visiteurs.

   LES DIMENSIONS SONT CELLES DE `.i`, reprises ici parce qu'un `<span>` n'a
   pas les dimensions intrinseques d'un `<svg>`. */
.opus .i--perso {
  display: inline-block;
  flex: none;
  width: 1.25em;
  height: 1.25em;
  vertical-align: -0.25em;
  background-color: currentColor;
  -webkit-mask: var(--opus-icone) no-repeat center / contain;
  mask: var(--opus-icone) no-repeat center / contain;
}

/* ---------------------------------------------------------------------------
   LE TABLEAU, 2 octobre 2026 (serie 1.5.4xx)

   LA TABLE PORTE `tableau`, LA CLASSE DE CORPUS : son cadre arrondi, ses
   filets, ses en-tetes et ses lignes alternees sont ceux de tous les tableaux
   du site. Ce qui suit n'ajoute que ce que Corpus ne sait pas faire : les
   reglages poses par ligne et par colonne, les quatre bordures, la premiere
   colonne figee et les fiches sur petit ecran.

   LA SPECIFICITE EST CHOISIE, PAS SUBIE. Les regles de Corpus pesent au plus
   une classe et deux balises (`.tableau tbody tr:nth-child(even)`) ; les
   notres partent de `.opus__tableau .opus__tableau-table`, deux classes, et
   l'emportent donc sans un seul `!important`.

   Maquette validee par Cyrille le 2 octobre 2026.
   --------------------------------------------------------------------------- */

/*
 * LE TABLEAU EST UN CONTENEUR DE TAILLE, ET IL DOIT PRENDRE TOUTE LA LARGEUR.
 *
 * C'est la largeur du BLOC qui decide des fiches, pas celle de l'ecran : un
 * tableau pose dans une colonne etroite sur ordinateur est aussi illisible
 * qu'un tableau sur telephone. D'ou `@container` plus bas, et donc
 * `container-type` ici.
 *
 * LE PIEGE EST CONNU : un conteneur de taille ne tire plus sa largeur de son
 * contenu. Dans la pile, un element aligne a gauche ou au centre ne s'etire
 * pas (`align-self`) : sa largeur tomberait a zero. `inline-size: 100%` et
 * `align-self: stretch` l'en empechent, quel que soit l'alignement choisi.
 */
.opus__tableau {
  container-type: inline-size;
  inline-size: 100%;
  align-self: stretch;
  min-width: 0;
}

/* La zone qui defile : nommee et atteignable au clavier (voir l'assistant). */
.opus__tableau-defile {
  overflow-x: auto;
}

.opus__tableau-defile:focus-visible {
  outline: var(--trait-fort, 2px) solid var(--focus, currentColor);
  outline-offset: 2px;
}

.opus__tableau .opus__tableau-table {
  margin: 0;
}

.opus__tableau .opus__tableau-table tr {
  height: var(--opus-tableau-h, auto);
}

/* --- Les bordures --------------------------------------------------------- */
/* « Cadre et lignes » est le dessin de Corpus tel quel : rien a ecrire. */
.opus__tableau--lignes .opus__tableau-table,
.opus__tableau--aucune .opus__tableau-table {
  border: 0;
  border-radius: 0;
}

.opus__tableau--aucune .opus__tableau-table :is(th, td) {
  border-bottom: 0;
}

/* UNE GRILLE SANS DOUBLES TRAITS. La table de Corpus est en `separate` : poser
   un cadre complet sur chaque case doublerait chaque trait. On ajoute donc
   seulement le trait de droite, sauf a la derniere case. */
.opus__tableau--grille .opus__tableau-table :is(th, td):not(:last-child) {
  border-inline-end: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 15%));
}

/* Lignes alternees decochees : la teinte de Corpus est retiree. */
.opus__tableau--uni .opus__tableau-table tbody tr:nth-child(even) {
  background-color: transparent;
}

/* LES EN-TETES DE LIGNES ONT TOUS LA MEME GRAISSE. Le navigateur les pose a
   700, la case « Texte en gras » a la graisse forte du template : mesure sur
   le banc le 2 octobre 2026, la ligne mise en gras paraissait PLUS maigre que
   ses voisines (600 contre 700). La graisse forte vaut pour tous. */
.opus__tableau .opus__tableau-table [scope="row"] {
  font-weight: var(--graisse-forte, 700);
}

/* --- La premiere colonne figee, en defilement ------------------------------
   UNE CASE FIGEE DOIT ETRE OPAQUE, sinon le texte des autres colonnes passe
   dessous et se lit au travers. Elle reprend donc le fond de sa ligne :
   alternee, neutre ou teintee. */
/* LA TABLE DE CORPUS COUPE CE QUI DEBORDE (`overflow: hidden`, pour son
   cadre arrondi). Une table qui coupe est elle-meme un conteneur de
   defilement : la case figee s'accrochait donc a la table, qui ne defile pas,
   et partait avec le reste. Mesure du 2 octobre 2026 : 149 px de decalage
   apres un defilement de 150. Rendue a `visible`, la case s'accroche a la
   zone qui defile vraiment.

   LA LEGENDE AUSSI DOIT RESTER EN PLACE : elle est dans la table, elle
   defilait avec elle et sortait de l'ecran. Son texte est donc fige au bord
   gauche, comme la premiere colonne. */
.opus__tableau--defile .opus__tableau-table {
  overflow: visible;
}

.opus__tableau--defile .opus__tableau-legende {
  position: sticky;
  inset-inline-start: 0;
  display: inline-block;
}

.opus__tableau--defile .opus__tableau-table :is([scope="row"], thead th:first-child) {
  position: sticky;
  inset-inline-start: 0;
  z-index: 1;
  background-color: var(--fond, #fff);
  box-shadow: inset calc(-1 * var(--trait, 1px)) 0 0 var(--bord, rgb(0 0 0 / 15%));
}

.opus__tableau--defile .opus__tableau-table thead th:first-child {
  background-color: var(--fond-alt, rgb(0 0 0 / 3%));
}

.opus__tableau--defile:not(.opus__tableau--uni) .opus__tableau-table tbody tr:nth-child(even) > [scope="row"] {
  background-color: var(--fond-creuse, rgb(0 0 0 / 3%));
}

/* --- Les fiches, sous 30 rem de bloc ----------------------------------------
   CHAQUE LIGNE DEVIENT UNE CARTE, ET CHAQUE CASE DIT DE QUELLE COLONNE ELLE
   VIENT. Les intitules de colonnes sont recopies dans `data-label` par
   l'assistant ; le texte genere ici est muet a l'oreille (`/ ""`) : le lecteur
   d'ecran, lui, entend deja l'en-tete par les roles du tableau, et
   l'entendrait sinon deux fois.

   L'EN-TETE N'EST PAS RETIRE, IL EST MASQUE A L'OEIL : il porte les noms des
   colonnes que les roles relient a chaque case. */
@container (max-width: 30rem) {
  .opus__tableau--fiches .opus__tableau-table,
  .opus__tableau--fiches .opus__tableau-table :is(caption, tbody, tr, th, td) {
    display: block;
  }

  .opus__tableau--fiches .opus__tableau-table {
    border: 0;
    border-radius: 0;
    overflow: visible;
  }

  .opus__tableau--fiches .opus__tableau-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .opus__tableau--fiches .opus__tableau-table colgroup {
    display: none;
  }

  .opus__tableau--fiches .opus__tableau-table tbody {
    display: grid;
    gap: var(--e-3, 12px);
  }

  .opus__tableau--fiches .opus__tableau-table tbody tr,
  .opus__tableau--fiches .opus__tableau-table tbody tr:nth-child(even) {
    height: auto;
    padding: var(--e-1, 4px) var(--e-3, 12px);
    border: var(--trait, 1px) solid var(--bord, rgb(0 0 0 / 15%));
    border-radius: var(--forme-carte-angle, var(--angle-lg, 0.5rem));
    background-color: transparent;
  }

  .opus__tableau.opus__tableau--fiches .opus__tableau-table :is(th, td) {
    padding: var(--e-2, 8px) 0;
    text-align: left;
    border-inline-end: 0;
    border-top: 0;
  }

  .opus__tableau--fiches .opus__tableau-table [scope="row"] {
    font-weight: var(--graisse-forte, 700);
  }

  .opus__tableau--fiches .opus__tableau-table td[data-label] {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: var(--e-3, 12px);
  }

  .opus__tableau--fiches .opus__tableau-table td[data-label]::before {
    content: attr(data-label);
    content: attr(data-label) / "";
    color: var(--texte-doux, inherit);
    font-weight: var(--graisse-normale, 400);
  }

  .opus__tableau--fiches .opus__tableau-table tr > :last-child {
    border-bottom: 0;
  }

  .opus__tableau--fiches .opus__tableau-table tr.opus__tableau-ligne--total {
    border-top-width: var(--trait-fort, 2px);
  }
}

/* --- Les reglages d'une ligne et d'une colonne ------------------------------
   APRES LES FICHES, ET C'EST VOULU : a poids egal, le fond choisi pour une
   ligne doit l'emporter sur le fond neutre des cartes. Le `:is(thead, tbody)`
   n'est pas decoratif : il donne au selecteur le poids exact de celui des
   cartes et des lignes alternees (deux balises), et c'est l'ordre qui
   tranche. Sans lui, une ligne paire perdait son fond. */
.opus__tableau .opus__tableau-table :is(thead, tbody) tr.opus__tableau-ligne--neutre,
.opus__tableau .opus__tableau-table :is(thead, tbody) tr.opus__tableau-ligne--neutre > [scope="row"],
.opus__tableau .opus__tableau-table .opus__tableau-case--neutre {
  background-color: var(--fond-alt, rgb(0 0 0 / 3%));
}

.opus__tableau .opus__tableau-table :is(thead, tbody) tr.opus__tableau-ligne--teinte,
.opus__tableau .opus__tableau-table :is(thead, tbody) tr.opus__tableau-ligne--teinte > [scope="row"],
.opus__tableau .opus__tableau-table .opus__tableau-case--teinte {
  background-color: var(--fond-teinte, rgb(0 0 0 / 6%));
}

.opus__tableau .opus__tableau-table :is(.opus__tableau-ligne--gras > *, .opus__tableau-case--gras) {
  font-weight: var(--graisse-forte, 700);
}

/* Les majuscules sont un affichage : le texte reste saisi tel quel, et c'est
   lui que le lecteur d'ecran lit. */
.opus__tableau .opus__tableau-table :is(.opus__tableau-ligne--maj > *, .opus__tableau-case--maj) {
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.opus__tableau .opus__tableau-table .opus__tableau-ligne--total > * {
  border-top: var(--trait-fort, 2px) solid var(--encre, currentColor);
}

.opus__tableau .opus__tableau-table .opus__tableau-case--centre {
  text-align: center;
}

.opus__tableau .opus__tableau-table .opus__tableau-case--droite {
  text-align: right;
}

/* COLONNES EGALES : `table-layout: fixed` partage a parts egales ce que les
   largeurs fixees laissent. Elles sont en pourcentages purs ou en pixels,
   jamais en `calc(% - rem)`, que ce mode ne resout pas (code moral, § 7). */
.opus__tableau--egales .opus__tableau-table {
  table-layout: fixed;
}

/* ---------------------------------------------------------------------------
   LA VIDEO, 3 octobre 2026 (serie 1.5.4xx)

   UN ECRAN AU FORMAT DE LA VIDEO. Le format est lu sur la plateforme par le
   serveur et pose en `--opus-video-ratio` : un Short sort vertical sans
   reglage. L'image remplit l'ecran (`cover`), centree, et la vignette de
   YouTube perd ses bandes noires.

   LE BOUTON LIRE COUVRE TOUT L'ECRAN : on clique ou l'on veut. Son rond est
   blanc sur la video, quel que soit le theme du site : il est pose sur une
   image, pas sur la page.

   UNE VIDEO VERTICALE NE PREND PAS TOUTE LA COLONNE : a pleine largeur, un
   9:16 ferait deux ecrans de haut.
   --------------------------------------------------------------------------- */
.opus__video {
  margin: 0;
}

.opus__video-ecran {
  position: relative;
  aspect-ratio: var(--opus-video-ratio, 16 / 9);
  max-width: 100%;
  overflow: hidden;
  border-radius: var(--forme-image-angle, 0.375rem);
  background: #10151d;
  color: #fff;
}

.opus__video--verticale .opus__video-ecran {
  max-width: min(100%, 22rem);
  margin-inline: auto;
}

.opus__video-ecran--fichier {
  aspect-ratio: auto;
  background: transparent;
}

.opus__video-image,
.opus__video-lecteur,
.opus__video-fichier {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

.opus__video-image {
  position: absolute;
  inset: 0;
  object-fit: cover;
}

.opus__video-fichier {
  height: auto;
  border-radius: inherit;
}

.opus__video-lire {
  position: absolute;
  inset: 0;
  /*
   * FLEX ET NON GRILLE : en grille, le titre en position absolue ouvrait
   * quand meme une deuxieme rangee, et le rond se calait au milieu de la
   * premiere. Mesure du 3 octobre 2026 : 90 px trop haut sur un ecran de 412.
   */
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  text-decoration: none;
  background: linear-gradient(transparent 55%, rgba(0, 0, 0, 0.6));
}

/*
 * PAS DE PICTOGRAMME DE LIEN EXTERNE. Corpus en pose un apres les liens qui
 * sortent du site : dans un bouton centre en flex, il comptait comme un
 * enfant et decalait le rond de 10 px vers la gauche (mesure du 3 octobre).
 * Le lien ne s'ouvre d'ailleurs plus dans un nouvel onglet.
 */
.opus__video-lire::before,
.opus__video-lire::after {
  content: none;
  display: none;
}

.opus__video-lire:focus-visible {
  outline: 3px solid #fff;
  outline-offset: -6px;
}

.opus__video-rond {
  width: 4.25rem;
  height: 4.25rem;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.94);
  box-shadow: 0 0.25rem 1.1rem rgba(0, 0, 0, 0.35);
  display: grid;
  place-items: center;
  transition: transform 0.15s;
}

.opus__video-rond::before {
  content: "";
  margin-left: 0.35rem;
  border-left: 1.4rem solid #111;
  border-top: 0.8rem solid transparent;
  border-bottom: 0.8rem solid transparent;
}

.opus__video-lire:hover .opus__video-rond,
.opus__video-lire:focus-visible .opus__video-rond {
  transform: scale(1.08);
}

.opus__video-titre {
  position: absolute;
  left: var(--e-3, 1rem);
  right: var(--e-3, 1rem);
  bottom: var(--e-2, 0.75rem);
  font-weight: var(--graisse-appuyee, 600);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
  line-height: 1.3;
}

/*
 * D'OU VIENT LA VIDEO SE LIT SUR L'IMAGE, EN HAUT A GAUCHE, et plus sous elle :
 * « J'ai l'impression de voir deux legendes sous la video », Cyrille, 3 octobre
 * 2026. La phrase est aussi dans le nom du bouton Lire, pour le lecteur
 * d'ecran ; l'etiquette, elle, ne se lit pas deux fois.
 */
.opus__video-avis {
  position: absolute;
  top: var(--e-2, 0.5rem);
  left: var(--e-2, 0.5rem);
  max-width: calc(100% - 1rem);
  padding: 0.15rem 0.5rem;
  border-radius: 0.25rem;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.75rem;
  line-height: 1.4;
  pointer-events: none;
}

.opus__video-legende {
  margin: var(--e-2, 0.5rem) 0 0;
  font-size: var(--t-petit, 0.875rem);
}

.opus__video-transcription {
  margin-top: var(--e-2, 0.5rem);
  border-top: 1px solid var(--bord, #d6dde8);
  padding-top: var(--e-2, 0.5rem);
}

.opus__video-transcription summary {
  cursor: pointer;
  color: var(--accent, #2f5fa7);
  font-weight: var(--graisse-appuyee, 600);
}

.opus__video-transcription-texte {
  margin-top: var(--e-2, 0.5rem);
  max-width: 65ch;
}

@container (max-width: 22rem) {
  .opus__video-rond { width: 3.25rem; height: 3.25rem; }
  .opus__video-titre { font-size: var(--t-petit, 0.875rem); }
}

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

/* ---------------------------------------------------------------------------
   LA CARTE, 3 octobre 2026 (serie 1.5.4xx)

   LA LISTE OU L'ON VEUT : a droite ou a gauche (deux colonnes), au-dessus ou
   en dessous (la carte en pleine largeur du bloc, les lieux en colonnes).
   Dans un bloc etroit, la liste passe toujours sous la carte : la largeur du
   BLOC decide, pas celle de l'ecran.

   LES REPERES PRENNENT LEUR COULEUR DE `--opus-repere`, posee lieu par lieu :
   un jeton du template ou une couleur libre. Le chiffre ou le pictogramme
   est blanc, sur un liseré blanc qui le detache de n'importe quel fond.
   --------------------------------------------------------------------------- */
.opus__carte {
  container-type: inline-size;
}

.opus__carte-titre {
  margin: 0 0 var(--e-2, 0.5rem);
  font-weight: var(--graisse-forte, 700);
}

.opus__carte-corps {
  display: grid;
  gap: var(--e-3, 1rem);
  align-items: start;
}

.opus__carte--liste-droite .opus__carte-corps { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.opus__carte--liste-gauche .opus__carte-corps { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.opus__carte--liste-gauche .opus__carte-defile,
.opus__carte--liste-dessus .opus__carte-defile { order: -1; }

.opus__carte--liste-dessus .opus__carte-lieux,
.opus__carte--liste-dessous .opus__carte-lieux {
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
}

/*
 * A COTE DE LA CARTE, LA LISTE NE DEPASSE PAS SA HAUTEUR. « Imaginons que
 * j'ai dix lieux », Cyrille, 3 octobre 2026 : la liste defile dans son cadre,
 * a la hauteur de la carte, et le repere clique sur la carte l'y fait venir.
 * Elle se prend au clavier (`tabindex`), pour defiler sans souris.
 */
.opus__carte--liste-droite .opus__carte-defile,
.opus__carte--liste-gauche .opus__carte-defile {
  max-height: min(var(--opus-carte-h, 420px), 85vh);
  overflow-y: auto;
  position: relative;
  overscroll-behavior: contain;
  padding-right: 0.25rem;
  scrollbar-gutter: stable;
}

.opus__carte-defile:focus-visible {
  outline: 3px solid var(--focus, #2f5fa7);
  outline-offset: 2px;
}

@container (max-width: 40rem) {
  .opus__carte .opus__carte-corps { grid-template-columns: minmax(0, 1fr); }
  .opus__carte .opus__carte-defile { order: 1; max-height: none; overflow: visible; }
}

.opus__carte-zone {
  position: relative;
  height: var(--opus-carte-h, 420px);
  max-height: 85vh;
  overflow: hidden;
  border: 1px solid var(--bord, #d6dde8);
  border-radius: var(--forme-image-angle, 0.375rem);
  background:
    linear-gradient(0deg, transparent 49.5%, rgba(127, 127, 127, 0.18) 49.5%, rgba(127, 127, 127, 0.18) 50.5%, transparent 50.5%) 0 0 / 100% 3rem,
    linear-gradient(90deg, transparent 49.5%, rgba(127, 127, 127, 0.18) 49.5%, rgba(127, 127, 127, 0.18) 50.5%, transparent 50.5%) 0 0 / 3rem 100%,
    var(--fond-creuse, #f1f4f9);
  user-select: none;
}

.opus__carte-zone--chargee {
  background: #e9e4dc;
  touch-action: none;
  cursor: grab;
}

.opus__carte-zone--chargee:active { cursor: grabbing; }

.opus__carte-zone:focus-visible {
  outline: 3px solid var(--focus, #2f5fa7);
  outline-offset: 2px;
}

.opus__carte-tuiles,
.opus__carte-reperes,
.opus__carte-trace {
  position: absolute;
  inset: 0;
}

.opus__carte-tuiles img {
  position: absolute;
  width: 256px;
  height: 256px;
  max-width: none;
}

.opus__carte-trace { pointer-events: none; }

.opus__carte-trace path {
  fill: none;
  stroke: #1a73e8;
  stroke-width: 5px;
  stroke-linejoin: round;
  stroke-linecap: round;
  opacity: 0.9;
}

.opus__carte-repere {
  --taille: 2rem;
  position: absolute;
  display: grid;
  place-items: center;
  width: var(--taille);
  height: var(--taille);
  transform: translate(-50%, -50%);
  border: 2px solid #fff;
  border-radius: 50%;
  background: var(--opus-repere, var(--accent, #2f5fa7));
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 700;
  line-height: 1;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.35);
}

.opus__carte--carre .opus__carte-repere { border-radius: 0.375rem; }

.opus__carte--goutte .opus__carte-reperes .opus__carte-repere {
  transform: translate(-50%, -100%) rotate(-45deg);
  transform-origin: center;
  border-radius: 50% 50% 50% 0;
  margin-top: -0.35rem;
}

.opus__carte--goutte .opus__carte-reperes .opus__carte-repere > span { transform: rotate(45deg); }

.opus__carte-repere .i {
  width: 1rem;
  height: 1rem;
  fill: currentColor;
}

.opus__carte-repere--actif {
  z-index: 2;
  outline: 3px solid #fff;
  box-shadow: 0 0 0 6px var(--opus-repere, var(--accent, #2f5fa7));
}

.opus__carte-vous {
  position: absolute;
  width: 1rem;
  height: 1rem;
  transform: translate(-50%, -50%);
  border: 3px solid #fff;
  border-radius: 50%;
  background: #1a73e8;
  box-shadow: 0 0 0 6px rgba(26, 115, 232, 0.25);
}

.opus__carte-afficher {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 0.6rem 1.1rem;
  border: 0;
  border-radius: 999px;
  background: #fff;
  color: #111;
  font: inherit;
  font-weight: var(--graisse-appuyee, 600);
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.3);
  cursor: pointer;
}

.opus__carte-afficher:focus-visible {
  outline: 3px solid var(--focus, #2f5fa7);
  outline-offset: 3px;
}

.opus__carte-avis {
  position: absolute;
  top: var(--e-2, 0.5rem);
  left: var(--e-2, 0.5rem);
  padding: 0.15rem 0.5rem;
  border-radius: 0.25rem;
  background: rgba(0, 0, 0, 0.62);
  color: #fff;
  font-size: 0.75rem;
  pointer-events: none;
}

.opus__carte-zone--chargee .opus__carte-avis { display: none; }

.opus__carte-zoom {
  position: absolute;
  top: var(--e-2, 0.5rem);
  right: var(--e-2, 0.5rem);
  display: grid;
  gap: 0.25rem;
  z-index: 3;
}

.opus__carte-zoom button {
  width: 2rem;
  height: 2rem;
  border: 1px solid rgba(0, 0, 0, 0.25);
  border-radius: 0.25rem;
  background: #fff;
  color: #111;
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}

.opus__carte-credit {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 3;
  padding: 0.1rem 0.4rem;
  background: rgba(255, 255, 255, 0.85);
  color: #222;
  font-size: 0.6875rem;
}

.opus__carte-credit a { color: inherit; }

.opus__carte-lieux {
  display: grid;
  gap: var(--e-2, 0.5rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

.opus__carte-lieu {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.2rem var(--e-2, 0.75rem);
  align-items: start;
  padding: var(--e-2, 0.75rem);
  border: 1px solid var(--bord, #d6dde8);
  border-radius: var(--forme-carte-angle, 0.375rem);
}

.opus__carte-lieu > :not(.opus__carte-repere) { grid-column: 2; }

/* La ligne choisie : le meme filet d'un pixel que les autres, en couleur. « Ultra fin », Cyrille, 4 octobre 2026. */
.opus__carte-lieu--actif {
  border-color: var(--opus-repere-actif, var(--accent, #2f5fa7));
}

.opus__carte-repere--liste {
  position: static;
  grid-row: 1 / span 3;
  transform: none;
  --taille: 1.75rem;
}

.opus__carte-nom { font-weight: var(--graisse-appuyee, 600); }

.opus__carte-adresse {
  margin: 0;
  font-style: normal;
  font-size: var(--t-petit, 0.875rem);
}

.opus__carte-route,
.opus__carte-guidage {
  justify-self: start;
  font-size: var(--t-petit, 0.875rem);
}

.opus__carte-route {
  margin-top: 0.25rem;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--accent, #2f5fa7);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  background: transparent;
  color: var(--accent, #2f5fa7);
  font: inherit;
  font-size: var(--t-petit, 0.875rem);
  cursor: pointer;
}

.opus__carte-route:hover,
.opus__carte-route:focus-visible {
  background: var(--accent, #2f5fa7);
  color: #fff;
}

.opus__carte-trajet {
  display: grid;
  gap: var(--e-2, 0.5rem);
  margin-top: var(--e-2, 0.75rem);
  padding: var(--e-2, 0.75rem);
  border: 1px solid var(--bord, #d6dde8);
  border-radius: var(--forme-carte-angle, 0.375rem);
}

.opus__carte-trajet[hidden] { display: none; }

.opus__carte-trajet-tete {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2, 0.5rem);
  align-items: baseline;
}

.opus__carte-trajet-tete strong { margin-right: auto; }

.opus__carte-modes {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}

.opus__carte-modes button {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--bord-fort, #9aa6b8);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--t-petit, 0.875rem);
  cursor: pointer;
}

.opus__carte-modes button[aria-pressed="true"] {
  border-color: var(--accent, #2f5fa7);
  background: var(--accent, #2f5fa7);
  color: #fff;
}

.opus__carte-trajet-pied {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem 1rem;
  font-size: var(--t-petit, 0.875rem);
}

.opus__carte-depart {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  align-items: end;
}

.opus__carte-depart label {
  display: grid;
  gap: 0.25rem;
  flex: 1 1 14rem;
  font-size: var(--t-petit, 0.875rem);
}

.opus__carte-depart input {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--bord-fort, #9aa6b8);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  font: inherit;
}

.opus__carte-lien {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent, #2f5fa7);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/*
 * L'IMAGE DE LA FACADE : la carte assemblee par le serveur, centree et a sa
 * taille reelle, sous un leger voile pour que le bouton se lise. Les reperes
 * sont places en decalage du centre : ils tombent juste a toute largeur.
 */
.opus__carte-fond {
  position: absolute;
  inset: 0;
  background-position: center;
  background-repeat: no-repeat;
}

.opus__carte-fond[style]::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(14, 20, 32, 0.12);
}

/*
 * LA LARGEUR DE LA LISTE, A COTE DE LA CARTE : un quart, un tiers, cinq
 * douziemes (le defaut) ou la moitie. La carte prend le reste. Sur douze
 * parts, comme la grille des rangees, pour parler la meme langue.
 */
.opus__carte--liste-droite.opus__carte--l3 .opus__carte-corps { grid-template-columns: minmax(0, 9fr) minmax(0, 3fr); }
.opus__carte--liste-droite.opus__carte--l4 .opus__carte-corps { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
.opus__carte--liste-droite.opus__carte--l6 .opus__carte-corps { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
.opus__carte--liste-gauche.opus__carte--l3 .opus__carte-corps { grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); }
.opus__carte--liste-gauche.opus__carte--l4 .opus__carte-corps { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
.opus__carte--liste-gauche.opus__carte--l6 .opus__carte-corps { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }

/* Les coordonnees d'un lieu : telephone, horaires, site, reseaux. */
.opus__carte-infos {
  display: grid;
  gap: 0.1rem;
  margin: 0.15rem 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-petit, 0.875rem);
}

.opus__carte-info-nom { color: var(--texte-doux, #5b6778); }

.opus__carte-zone--chargee .opus__carte-repere[data-n] { cursor: pointer; }

/* Le texte libre d'un lieu, sous ses coordonnees. */
.opus__carte-texte {
  margin: 0.15rem 0 0;
  font-size: var(--t-petit, 0.875rem);
}

/*
 * UNE CLASSE PAR TYPE D'INFORMATION, pour les viser depuis l'onglet CSS
 * personnalise sans toucher aux autres. Chacune porte deja la regle qui lui
 * sert : un numero ne se coupe pas, une adresse longue se coupe n'importe ou
 * plutot que de deborder, les heures s'alignent.
 */
.opus__carte-info--tel a { white-space: nowrap; }

.opus__carte-info--courriel a,
.opus__carte-info--site a,
.opus__carte-info--reseau a,
.opus__carte-info--page a { overflow-wrap: anywhere; }

.opus__carte-info--horaires { font-variant-numeric: tabular-nums; }

.opus__carte-info--texte { overflow-wrap: break-word; }

/* ==========================================================================
   L'AGENDA, 4 octobre 2026 (serie 1.5.4xx)

   Le mois est un vrai tableau, la liste des jours suit, la fiche se pose a
   droite, a gauche ou dessous, sur douze parts comme la liste de la carte.
   Une seule couleur par evenement, `--opus-agenda-c`, prise dans les jetons
   du template ; le texte des pastilles reste blanc.
   ========================================================================== */
.opus__agenda {
  container-type: inline-size;
}

.opus__agenda-titre {
  margin: 0 0 var(--e-2, 0.5rem);
  font-weight: var(--graisse-forte, 700);
}

.opus__agenda-corps {
  display: grid;
  gap: var(--e-3, 1rem);
  align-items: start;
}

.opus__agenda-corps > * { min-width: 0; }

.opus__agenda--fiche-droite .opus__agenda-corps { grid-template-columns: minmax(0, 8fr) minmax(0, 4fr); }
.opus__agenda--fiche-gauche .opus__agenda-corps { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); }
.opus__agenda--fiche-gauche .opus__agenda-fiches { order: -1; }
.opus__agenda--fiche-droite.opus__agenda--l3 .opus__agenda-corps { grid-template-columns: minmax(0, 9fr) minmax(0, 3fr); }
.opus__agenda--fiche-droite.opus__agenda--l5 .opus__agenda-corps { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
.opus__agenda--fiche-droite.opus__agenda--l6 .opus__agenda-corps { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }
.opus__agenda--fiche-gauche.opus__agenda--l3 .opus__agenda-corps { grid-template-columns: minmax(0, 3fr) minmax(0, 9fr); }
.opus__agenda--fiche-gauche.opus__agenda--l5 .opus__agenda-corps { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.opus__agenda--fiche-gauche.opus__agenda--l6 .opus__agenda-corps { grid-template-columns: minmax(0, 6fr) minmax(0, 6fr); }

/* Sur un ecran etroit, la fiche passe sous l'agenda, et la liste devant le mois. */
@container (max-width: 40rem) {
  .opus__agenda .opus__agenda-corps { grid-template-columns: minmax(0, 1fr); }
  .opus__agenda .opus__agenda-fiches { order: 1; }
}

/* LES OUTILS : fleches, aujourd'hui, le mois, la bascule mois / liste. */
.opus__agenda-outils {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2, 0.5rem);
  align-items: center;
  margin-bottom: var(--e-2, 0.5rem);
}

.opus__agenda-nav,
.opus__agenda-bascule { display: flex; gap: 0.25rem; }
.opus__agenda-nav[hidden],
.opus__agenda-bascule[hidden],
.opus__agenda-periode[hidden] { display: none; }

.opus__agenda-periode {
  margin: 0 auto;
  font-weight: var(--graisse-forte, 700);
  font-variant-numeric: tabular-nums;
}

.opus__agenda-btn {
  min-width: 2.25rem;
  padding: 0.25rem 0.65rem;
  border: 1px solid var(--bord, #d6dde8);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--t-petit, 0.875rem);
  cursor: pointer;
}

.opus__agenda-btn:hover { border-color: var(--accent, #2f5fa7); }

.opus__agenda-btn[aria-pressed="true"] {
  background: var(--accent, #2f5fa7);
  border-color: var(--accent, #2f5fa7);
  color: #fff;
}

.opus__agenda :is(button, a):focus-visible {
  outline: 3px solid var(--focus, #2f5fa7);
  outline-offset: 2px;
}

/* LE MOIS : un tableau a colonnes egales, qui defile sur lui-meme s'il le faut. */
.opus__agenda-mois { overflow-x: auto; }
.opus__agenda-mois[hidden],
.opus__agenda-liste[hidden],
.opus__agenda-jourvue[hidden],
.opus__agenda-annee[hidden] { display: none; }

.opus__agenda-table {
  width: 100%;
  min-width: 26rem;
  border-collapse: collapse;
  table-layout: fixed;
}

.opus__agenda-table th {
  padding: 0.3rem 0.2rem;
  border-bottom: 1px solid var(--bord, #d6dde8);
  color: var(--texte-doux, #5b6778);
  font-size: var(--t-petit, 0.875rem);
  font-weight: var(--graisse-forte, 700);
  text-align: center;
}

.opus__agenda-table abbr { text-decoration: none; }

.opus__agenda-table td {
  height: 6rem;
  padding: 0.2rem;
  border: 1px solid var(--bord, #d6dde8);
  vertical-align: top;
}

.opus__agenda-hors { background: var(--fond-creuse, #f1f4f9); }
.opus__agenda-hors .opus__agenda-num { opacity: 0.55; }
.opus__agenda-auj { background: color-mix(in srgb, var(--accent, #2f5fa7) 10%, transparent); }

.opus__agenda-num {
  display: block;
  margin-bottom: 0.15rem;
  color: var(--texte-doux, #5b6778);
  font-size: var(--t-petit, 0.875rem);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

.opus__agenda-auj .opus__agenda-num { color: inherit; font-weight: var(--graisse-forte, 700); }

.opus__agenda-puce {
  display: block;
  width: 100%;
  margin-bottom: 0.15rem;
  padding: 0.1rem 0.35rem;
  overflow: hidden;
  border: 0;
  border-radius: 0.2rem;
  background: var(--opus-agenda-c, var(--accent, #2f5fa7));
  color: #fff;
  font: inherit;
  font-size: 0.75rem;
  line-height: 1.3;
  text-align: left;
  /* Deux lignes au plus : un titre se lit, il ne se devine pas sur trois lettres. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow-wrap: anywhere;
  cursor: pointer;
}

.opus__agenda-puce b { font-variant-numeric: tabular-nums; }
.opus__agenda-passe .opus__agenda-puce { opacity: 0.55; }

.opus__agenda-plus {
  padding: 0 0.2rem;
  border: 0;
  background: none;
  color: var(--accent, #2f5fa7);
  font: inherit;
  font-size: 0.75rem;
  text-decoration: underline;
  cursor: pointer;
}

/* Avec toutes les vues, le numero du jour est un bouton : il ouvre la journee. */
button.opus__agenda-num {
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  cursor: pointer;
}

button.opus__agenda-num:hover { color: var(--accent, #2f5fa7); text-decoration: underline; }

/* Dans la fiche, la date ouvre la journee : un lien discret, souligne en pointilles. */
.opus__agenda-voirjour {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  text-decoration: underline dotted;
  text-underline-offset: 0.2em;
  cursor: pointer;
}

.opus__agenda-voirjour:hover { color: var(--accent, #2f5fa7); text-decoration-style: solid; }

/* LA VUE AU JOUR : les lignes de la liste, un peu plus grandes. */
/* Une hauteur de mois, ou presque : la fiche a cote garde sa place, meme un jour sans rien. */
.opus__agenda-jourvue { min-height: 26rem; }
.opus__agenda-jourvue .opus__agenda-evts { border-top: 1px solid var(--bord, #d6dde8); }
.opus__agenda-jourvue .opus__agenda-evt { padding-block: 0.75rem; }
.opus__agenda-jourvue .opus__agenda-ouvrir { font-weight: var(--graisse-forte, 700); }

/* L'ANNEE : douze petits mois, autant de colonnes que la largeur en tient. */
.opus__agenda-annee {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
  gap: var(--e-4, 1rem) var(--e-3, 0.75rem);
}

.opus__agenda-an-titre {
  display: block;
  margin: 0 0 0.25rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent, #2f5fa7);
  font: inherit;
  font-weight: var(--graisse-forte, 700);
  cursor: pointer;
}

.opus__agenda-an-titre:first-letter { text-transform: uppercase; }
.opus__agenda-an-titre:hover { text-decoration: underline; }

.opus__agenda-an-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.opus__agenda-an-table th { padding: 0 0 0.15rem; color: var(--texte-doux, #5b6778); font-size: 0.7rem; font-weight: normal; text-align: center; }
.opus__agenda-an-table abbr { text-decoration: none; }
.opus__agenda-an-table td { padding: 1px; text-align: center; }
.opus__agenda-an-table .opus__agenda-jour { font-size: 0.75rem; }
.opus__agenda-an-table .opus__agenda-jour--plein { background: color-mix(in srgb, var(--opus-agenda-c, var(--accent, #2f5fa7)) 16%, transparent); }

/* LA LISTE : un intitule par jour, puis une ligne par seance. */
.opus__agenda-listejour {
  display: flex;
  justify-content: space-between;
  gap: var(--e-2, 0.5rem);
  margin: 0;
  padding: 0.35rem 0.6rem;
  border-bottom: 1px solid var(--bord, #d6dde8);
  background: var(--fond-creuse, #f1f4f9);
  font-size: var(--t-petit, 0.875rem);
  font-weight: var(--graisse-forte, 700);
}

/* Le titre du jour est un h3 pour la structure, pas pour le decor : ni filet, ni largeur ajustee du template. */
.opus__agenda .opus__agenda-listejour {
  width: auto;
  max-width: none;
  font-family: inherit;
  line-height: 1.4;
}

.opus__agenda .opus__agenda-listejour::after,
.opus__agenda .opus__agenda-listejour::before { content: none; display: none; }

.opus__agenda-listejour span:first-letter { text-transform: uppercase; }
.opus__agenda-listejour span:last-child { color: var(--accent, #2f5fa7); }

.opus__agenda-evts {
  margin: 0 0 var(--e-2, 0.5rem);
  padding: 0;
  list-style: none;
}

.opus__agenda-evt {
  display: grid;
  grid-template-columns: 4.5rem 0.65rem minmax(0, 1fr);
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--bord, #d6dde8);
}

.opus__agenda-heure {
  color: var(--texte-doux, #5b6778);
  font-size: var(--t-petit, 0.875rem);
  font-variant-numeric: tabular-nums;
}

.opus__agenda-point {
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: var(--opus-agenda-c, var(--accent, #2f5fa7));
  align-self: center;
}

.opus__agenda-ouvrir {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.opus__agenda-ouvrir:hover { color: var(--accent, #2f5fa7); text-decoration: underline; }

.opus__agenda-ou {
  display: block;
  color: var(--texte-doux, #5b6778);
  font-size: var(--t-petit, 0.875rem);
}

/* LA LEGENDE : la couleur ne porte jamais seule l'information. */
.opus__agenda-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  margin: var(--e-2, 0.5rem) 0 0;
  padding: 0;
  list-style: none;
  color: var(--texte-doux, #5b6778);
  font-size: var(--t-petit, 0.875rem);
}

.opus__agenda-legende li { display: inline-flex; gap: 0.4rem; align-items: center; }

.opus__agenda-legende li::before {
  content: "";
  width: 0.65rem;
  height: 0.65rem;
  border-radius: 50%;
  background: var(--opus-agenda-c, var(--accent, #2f5fa7));
}

/* LA FICHE : la couleur de l'evenement en filet a gauche. */
.opus__agenda-fiche {
  display: grid;
  gap: var(--e-2, 0.5rem);
  padding: var(--e-3, 1rem);
  border: 1px solid var(--bord, #d6dde8);
  border-left: 4px solid var(--opus-agenda-c, var(--accent, #2f5fa7));
  border-radius: var(--forme-image-angle, 0.375rem);
}

.opus__agenda-fiche[hidden],
.opus__agenda-prochain[hidden],
.opus__agenda-ics[hidden],
.opus__agenda-retour[hidden] { display: none; }

/* Sans script, toutes les fiches restent lisibles, l'une sous l'autre. */
.opus__agenda:not(.opus__agenda--actif) .opus__agenda-fiche[hidden] { display: grid; }
.opus__agenda:not(.opus__agenda--actif) .opus__agenda-fiches { display: grid; gap: var(--e-2, 0.5rem); }

.opus__agenda-prochain {
  margin: 0;
  color: var(--texte-doux, #5b6778);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.opus__agenda-image {
  width: 100%;
  height: auto;
  border-radius: var(--forme-image-angle, 0.375rem);
}

.opus__agenda-fichetitre { margin: 0; font-size: 1.15em; }
.opus__agenda-fichetitre:focus,
.opus__agenda .opus__agenda-fichetitre:focus-visible { outline: none; }

.opus__agenda-infos { display: grid; gap: 0.35rem; margin: 0; }
.opus__agenda-info { display: grid; grid-template-columns: minmax(5rem, auto) minmax(0, 1fr); gap: 0 0.75rem; }
.opus__agenda-info dt { color: var(--texte-doux, #5b6778); font-weight: normal; }
.opus__agenda-info dd { margin: 0; overflow-wrap: break-word; }
.opus__agenda-info:not(:has(dt)) dd { grid-column: 1 / -1; }
.opus__agenda-info--quand dd:first-letter { text-transform: uppercase; }
.opus__agenda-adresse { font-style: normal; color: var(--texte-doux, #5b6778); }
.opus__agenda-voir { font-size: var(--t-petit, 0.875rem); }
.opus__agenda-info--tel a { white-space: nowrap; }
.opus__agenda-info--courriel a,
.opus__agenda-info--site a,
.opus__agenda-info--reservation a { overflow-wrap: anywhere; }

.opus__agenda-actions { display: flex; flex-wrap: wrap; gap: var(--e-2, 0.5rem); }
.opus__agenda-actions:empty { display: none; }

.opus__agenda-lien,
.opus__agenda-ics,
.opus__agenda-retour {
  display: inline-flex;
  gap: 0.35rem;
  align-items: center;
  padding: 0.15rem 0.55rem;
  border: 1px solid var(--accent, #2f5fa7);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  background: transparent;
  color: var(--accent, #2f5fa7);
  font: inherit;
  /* Apres `font: inherit`, qui remet la taille a zero : sans `!important`. */
  font-size: 0.8125rem;
  line-height: 1.5;
  text-decoration: none;
  cursor: pointer;
}

.opus__agenda-lien { background: var(--accent, #2f5fa7); color: #fff; }

/* Au survol, le lien du template repeignait le texte de la couleur du fond : on garde le blanc et on fonce le fond. */
.opus__agenda .opus__agenda-lien:is(:hover, :focus-visible, :visited) { color: #fff; text-decoration: none; }
.opus__agenda .opus__agenda-lien:is(:hover, :focus-visible) {
  background: color-mix(in srgb, var(--accent, #2f5fa7) 80%, #000);
  border-color: color-mix(in srgb, var(--accent, #2f5fa7) 80%, #000);
}
.opus__agenda-retour { margin-left: auto; border-color: var(--bord, #d6dde8); color: inherit; }
.opus__agenda-ics:hover,
.opus__agenda-ics:focus-visible { background: var(--accent, #2f5fa7); color: #fff; }

.opus__agenda-vide { margin: var(--e-2, 0.5rem) 0 0; color: var(--texte-doux, #5b6778); font-size: var(--t-petit, 0.875rem); }

/* LE MINI CALENDRIER, pour une colonne : un point sous chaque jour qui a un evenement. */
.opus__agenda--mini .opus__agenda-table { min-width: 0; }
.opus__agenda--mini .opus__agenda-table td { height: auto; padding: 1px; border: 0; background: none; text-align: center; }
.opus__agenda--mini .opus__agenda-table th { border: 0; font-size: 0.75rem; }
.opus__agenda--mini .opus__agenda-outils { flex-wrap: nowrap; }
.opus__agenda--mini .opus__agenda-nav { order: 0; }
.opus__agenda--mini .opus__agenda-periode { font-size: var(--t-petit, 0.875rem); }

.opus__agenda-jour {
  position: relative;
  width: 100%;
  aspect-ratio: 1;
  max-width: 2.5rem;
  border: 0;
  border-radius: 0.25rem;
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--t-petit, 0.875rem);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

.opus__agenda-hors .opus__agenda-jour { opacity: 0.5; }
.opus__agenda-auj .opus__agenda-jour { box-shadow: inset 0 0 0 1px var(--accent, #2f5fa7); }
.opus__agenda--mini .opus__agenda-auj { background: none; }
.opus__agenda-jour--plein { font-weight: var(--graisse-forte, 700); }

.opus__agenda-jour--plein::after {
  content: "";
  position: absolute;
  bottom: 0.2rem;
  left: 50%;
  width: 0.3rem;
  height: 0.3rem;
  margin-left: -0.15rem;
  border-radius: 50%;
  background: var(--opus-agenda-c, var(--accent, #2f5fa7));
}

.opus__agenda-jour[aria-pressed="true"] { background: var(--accent, #2f5fa7); color: #fff; }
.opus__agenda-jour[aria-pressed="true"]::after { background: #fff; }

.opus__agenda-jourtitre { margin: var(--e-2, 0.5rem) 0 0.25rem; font-weight: var(--graisse-forte, 700); font-size: var(--t-petit, 0.875rem); }
.opus__agenda-jourtitre:first-letter { text-transform: uppercase; }
.opus__agenda-jourevts { display: grid; gap: 0.2rem; margin: 0; padding: 0; list-style: none; font-size: var(--t-petit, 0.875rem); }
.opus__agenda-jourevts b { color: var(--texte-doux, #5b6778); font-weight: normal; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   A DROITE OU A GAUCHE, LA LISTE DES FICHES, 4 octobre 2026

   « Comme pour la carte, avec l'ascenseur si c'est plus haut que l'agenda »,
   Cyrille. Le cadre prend la hauteur de la rangee, que l'agenda decide : sa
   boite est en `position: relative`, la liste en `absolute` dedans, et
   n'ajoute donc rien a la hauteur. Elle defile sur elle-meme, au clavier
   aussi (`tabindex`).
   --------------------------------------------------------------------------- */
:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-corps { align-items: stretch; }
:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-fiches { position: relative; min-height: 16rem; }

:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-defile {
  position: absolute;
  inset: 0;
  display: grid;
  align-content: start;
  gap: var(--e-2, 0.5rem);
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-right: 0.25rem;
  scrollbar-gutter: stable;
}

.opus__agenda-defile:focus-visible { outline: 3px solid var(--focus, #2f5fa7); outline-offset: 2px; }

:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-fiche {
  gap: 0.35rem;
  padding: 0.6rem 0.75rem;
  font-size: var(--t-petit, 0.875rem);
}

:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-fichetitre { font-size: 1em; }
:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-fiche:not(.opus__agenda-fiche--active) .opus__agenda-prochain { display: none; }
:is(.opus__agenda--fiche-droite, .opus__agenda--fiche-gauche) .opus__agenda-fiche--passee { opacity: 0.6; }

.opus__agenda-fiche--active {
  border-color: var(--opus-agenda-c, var(--accent, #2f5fa7));
}

/* Sur un ecran etroit, plus de cadre : les fiches se suivent sous l'agenda. */
@container (max-width: 40rem) {
  .opus__agenda .opus__agenda-fiches { min-height: 0; }
  .opus__agenda .opus__agenda-defile { position: static; max-height: 28rem; }
}

/* ---------------------------------------------------------------------------
   EN FENETRE : un `dialog` du navigateur, la fiche au centre, un voile dessous.
   Sans script, les fiches restent sous l'agenda, comme « En dessous ».
   --------------------------------------------------------------------------- */
.opus__agenda-dialog {
  width: min(32rem, calc(100vw - 2rem));
  max-height: calc(100vh - 2rem);
  padding: 0;
  border: 0;
  border-radius: var(--forme-image-angle, 0.375rem);
  background: var(--fond, #fff);
  color: inherit;
  box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.3);
}

.opus__agenda-dialog::backdrop { background: rgba(15, 22, 34, 0.55); }
.opus__agenda-dialog .opus__agenda-fiche { border: 0; border-left: 4px solid var(--opus-agenda-c, var(--accent, #2f5fa7)); border-radius: 0; padding-right: 3rem; }

.opus__agenda-fermer {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border: 1px solid var(--bord, #d6dde8);
  border-radius: 50%;
  background: var(--fond, #fff);
  color: inherit;
  cursor: pointer;
}

/* L'image d'introduction d'un lieu venu d'un article : en tete de sa ligne, facon blog. */
.opus__carte-image {
  grid-column: 1 / -1;
  width: 100%;
  height: auto;
  max-height: 9rem;
  object-fit: cover;
  border-radius: var(--forme-image-angle, 0.375rem);
}

/* LE TITRE D'UNE FICHE MENE A L'ARTICLE ; le menu « Ajouter a mon agenda » se pose sous son bouton. */
.opus__agenda-fichetitre a { color: inherit; text-decoration: none; }
.opus__agenda-fichetitre a:hover { color: var(--accent, #2f5fa7); text-decoration: underline; }
.opus__agenda-actions { position: relative; }

.opus__agenda-ajout {
  position: absolute;
  z-index: 20;
  top: calc(100% + 0.25rem);
  left: 0;
  display: grid;
  min-width: 14rem;
  padding: 0.25rem;
  border: 1px solid var(--bord, #d6dde8);
  border-radius: var(--forme-bouton-angle, 0.25rem);
  background: var(--fond, #fff);
  box-shadow: 0 0.5rem 1.5rem rgba(0, 0, 0, 0.15);
}

.opus__agenda-ajout :is(a, button) {
  display: block;
  padding: 0.35rem 0.6rem;
  border: 0;
  border-radius: 0.2rem;
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--t-petit, 0.875rem);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}

.opus__agenda-ajout :is(a, button):is(:hover, :focus-visible) { background: var(--fond-creuse, #f1f4f9); }
