/* @override 
	https://site-violette.ddev.site/themes/custom/theme_violette/css/style.css?* */

/**
 * theme_violette — feuille principale.
 *
 * Bulma a été retiré du thème. Ce fichier reprend à sa charge les seules
 * classes de Bulma que le site émet encore — elles proviennent de
 * `ff_components` et de valeurs choisies en back-office, deux surfaces hors du
 * périmètre du thème — et applique le système de design « Violette Bernad,
 * version 2 » (voir css/tokens.css pour les jetons).
 *
 * Sommaire
 *   1. Base
 *   2. Typographie
 *   3. Mise en page — section de page, colonne de lecture, duo
 *   4. Sous-ensemble Bulma repris — content, title, field, image, table, tabs
 *   5. Focus et évitement
 *   6. En-tête, marque, navigation, réseaux
 *   7. Pied de page
 *   8. Boutons et liens d'action
 *   9. Messages système
 *  10. Mouvement
 */

/* ------------------------------------------------------------------ */
/* 1. Base                                                            */
/* ------------------------------------------------------------------ */

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

html {
  color-scheme: light;
  /* Hors-page : même papier que le contenu, sans démarcation. */
  background: var(--papier);
  font-size: 100%;
  -webkit-text-size-adjust: 100%;
  caret-color: var(--accent);
}

/**
 * Le corps ne porte plus ni fond ni cran de texte : le fond appartient à
 * `.page`, et chaque pièce prend son cran par un jeton de rôle. La famille par
 * défaut est celle des titres — le texte courant demande Lora explicitement.
 */
body {
  margin: 0;
  /* Pied collé au bas de fenêtre quand le contenu est court : la colonne fait
     au moins la hauteur du viewport, et `.page` absorbe le vide restant.
     Contenu long, elle pousse le pied hors du champ, comme il se doit. */
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  font-family: var(--font-titre);
  color: var(--encre);
  font-synthesis: none;
  -webkit-font-smoothing: antialiased;
}

/**
 * Drupal enveloppe toute la page dans ce conteneur : c'est lui, et non `body`,
 * qui porte l'en-tête, `.page`, le bandeau d'appel et le pied. La colonne
 * flexible doit donc le traverser pour atteindre `.page`.
 */
.dialog-off-canvas-main-canvas {
  display: flex;
  flex-direction: column;
  flex: 1;
}

/**
 * Le cadre. Il suit la fenêtre jusqu'à 1840, papier, sans bord dessiné : la mesure du texte
 * suffit à tenir la colonne, le fond ne change pas d'un côté à l'autre.
 */
.page {
  flex: 1;
  max-width: var(--max);
  margin: 0 auto;
  background: var(--papier);
  color: var(--encre);
}

/* Le système interdit l'ombre, le dégradé et le rayon. */
*,
*::before,
*::after {
  border-radius: var(--radius);
  box-shadow: none;
  text-shadow: none;
}

/**
 * `iframe` est volontairement absent : l'attribut `height` d'un iframe est un
 * indice de présentation de spécificité nulle, qu'un `height: auto` bat — et
 * `auto` vaut 150px sur un iframe. Le formateur oEmbed de `video_distante` sort
 * un `<iframe width height>` hors du conteneur à ratio de `comp--embed` : il
 * serait écrasé à 150px de haut.
 */
img,
video {
  display: block;
  max-width: 100%;
  height: auto;
  background: var(--papier-presse);
}

iframe {
  max-width: 100%;
  border: 0;
}

hr {
  border: 0;
  border-block-end: var(--trait);
  margin-block: var(--space-6);
}

/**
 * Les surfaces que le navigateur dessine à notre place appartiennent au
 * système elles aussi : sélection sur le surlignage de citation, curseur de
 * saisie au bleu-vert. Sans ça, la page emprunte deux couleurs à personne.
 */
::selection {
  background: var(--surlignage);
  color: var(--encre);
}

/**
 * Liens. Hors du texte lu — navigation, pied, boutons — le lien est
 * identifiable par sa position et son gabarit : pas de soulignement. Dans le
 * texte courant il reste souligné, le bleu-vert seul ne fournissant qu'un
 * rapport de 3,0:1 avec l'encre environnante (RGAA 3.3).
 */
a {
  color: var(--accent);
  text-decoration: none;
  transition: color var(--t-survol), border-color var(--t-survol);
}

a:hover {
  color: var(--encre);
}

p a,
li a,
blockquote a,
figcaption a {
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

h1,
h2,
h3 {
  margin: 0;
  font-weight: 600;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

button {
  font: inherit;
  color: inherit;
}

/* ------------------------------------------------------------------ */
/* 2. Typographie                                                     */
/* ------------------------------------------------------------------ */

/**
 * Le h1 de page ne s'affiche jamais : il reste dans le DOM pour les lecteurs
 * d'écran et le référencement. Le titre visible d'une page est un h2.
 *
 * La règle vise le seul bloc de titre du cœur, pas tout h1 sous `.page` : un
 * h1 saisi dans un corps de texte éditorial doit rester visible. Le second
 * porteur de titre de page, l'extra field de `ff_components:page`, est masqué
 * plus bas par son propre conteneur.
 */
#block-theme-violette-page-title h1,
.block-page-title-block h1 {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/**
 * Titre de page masqué visuellement, présent dans le DOM.
 *
 * Le h1 est émis par l'extra field « titre » du composant `ff_components:page`.
 * On masque le conteneur entier plutôt que le seul h1 : le wrapper restant
 * laisserait la gouttière de `page__top` dans le flux. La technique retenue est
 * le clip 1×1 px, pas `display: none` ni `visibility: hidden`, qui retirent
 * l'élément de l'arbre d'accessibilité — le titre doit rester lu par les
 * lecteurs d'écran et exploitable comme premier niveau de titrage.
 */
.extra-field--titre-entity-extra-field {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Titre visible de page : un h2, jamais le h1. */
.titre-page,
.page main > h2 {
  font: var(--titre-l);
}

.contenu-edito h2 {
  font: var(--titre-l);
}

.contenu-edito h3 {
  font: var(--titre-m);
}

/* Rôles de texte. La mesure borne la ligne, pas le conteneur. */
.contenu-edito p,
.texte-m {
  font: var(--texte-m);
  max-width: 66ch;
  color: var(--encre-92);
}

.chapo,
.texte-l {
  font: var(--texte-l);
  max-width: 60ch;
  color: var(--encre-92);
}

.texte-s {
  font: var(--texte-s);
  color: var(--encre-90);
}

.contenu-edito p + p {
  margin-top: 14px;
}

.contenu-edito a {
  border-bottom: 1px solid var(--accent-45);
}

.exergue {
  font: var(--citation);
  max-width: 34ch;
}

ul,
ol,
dl,
figure,
blockquote,
table {
  margin: 0;
}

/* Le soulignement ne vaut que dans le texte lu — mêmes conteneurs que la règle
   `p a, li a, …` plus haut, dont ce bloc ne change que l'appui de la ligne.
   Hors de ces conteneurs, un lien pose son propre filet (`.lien-fleche`, titre
   de carte, lien d'annonce) : l'attraper ici lui collait un second trait. */
.content :is(p, li, blockquote, figcaption) a:not(.button):not(.comp--bouton),
.comp--texte :is(p, li, blockquote, figcaption) a:not(.button):not(.comp--bouton),
.text-formatted :is(p, li, blockquote, figcaption) a:not(.button):not(.comp--bouton) {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

strong,
b {
  font-weight: var(--fw-demi);
}

/* L'italique sert les titres d'œuvres et les respirations. */
em,
i,
cite {
  font-style: italic;
}

figcaption {
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
  color: var(--meta);
  margin-block-start: var(--space-3);
}

code,
kbd,
samp,
pre {
  font-family: var(--font-mono);
  /* Relatif au parent, volontairement hors échelle. */
  font-size: 0.9375em;
}

/* Chiffres et dates toujours en mono. */
time {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-normal);
  line-height: var(--lh-l);
  color: var(--meta);
}

/* La valeur « Date » du composant titre prend ce style : deux classes pour
   passer devant `.comp--titre` (section 4), plus bas dans le fichier. */
.date-mono {
  font: var(--date-mono);
  color: var(--accent);
}

/* La valeur « Date » du composant titre est une date de corps de page, pas la
   date d'une actualité : elle se retire au gris méta plutôt que de prendre
   l'accent, qui appelle l'œil sur une carte. */
.comp--titre.comp--titre--date {
  font: var(--date-mono);
  color: var(--meta);
}

.label-mono {
  font: var(--label);
  text-transform: uppercase;
}

/* Liste à filets : la seule forme de liste du système. La valeur « Liste à
   filets » du composant texte la pose sur ses listes ; le sélecteur double la
   classe pour passer devant `.comp--texte :is(ul, ol)` et `.comp--texte li + li`
   (section 4), quel que soit l'ordre. */
.liste-filets,
.comp--texte.comp--texte-filets :is(ul, ol) {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  max-width: 70ch;
  border-bottom: 1px solid var(--filet);
}

/* Le filet est porté par le haut de chaque entrée, et la fermeture par le bas
   de la liste : une entrée qui disparaît emporte son propre trait. L'entrée
   s'empile en colonne — l'intitulé sur sa ligne, le détail sous lui. */
.liste-filets > li,
.comp--texte.comp--texte-filets :is(ul, ol) > li {
  margin: 0;
  padding: 14px 0;
  border-top: 1px solid var(--filet);
  font: var(--texte-s);
  color: var(--encre-88);
  display: flex;
  flex-direction: column;
  gap: 4px;
}

/* L'entrée au cran des petits titres, le détail en Lora texte S (DESIGN.md,
   « Liste à filets ») : l'éditrice met l'entrée en gras. */
.comp--texte.comp--texte-filets li strong {
  font: 600 17px / 1.3 var(--font-titre);
}

/* ------------------------------------------------------------------ */
/* 3. Mise en page — section de page, colonne de lecture, duo         */
/* ------------------------------------------------------------------ */

main {
  display: block;
  /* Les sections se suivent à `--ffc-espace-section` ; le même écart ferme la
     colonne, sans quoi la dernière collerait au bandeau d'appel. */
  padding-block-end: var(--ffc-espace-section, 3rem);
}

/**
 * La section de page. C'est la pièce de mise en page du site : une rangée de
 * contenu qui porte elle-même sa marge horizontale et se ferme par un filet.
 * Le cadre `.page` ne pose plus de gouttière — c'est ce décalage entre le
 * filet, qui court d'un bord à l'autre, et le contenu rentré de 64px qui fait
 * voir la grille.
 */
.section-page {
  padding: clamp(32px, 4vw, 52px) var(--marge);
  border-bottom: 1px solid var(--filet);
}

.section-page--fine {
  padding-top: clamp(28px, 3vw, 40px);
  padding-bottom: clamp(28px, 3vw, 40px);
}

/**
 * Colonne de lecture : 680px, soit 62 à 68 signes au cran texte/m. Sans borne,
 * un paragraphe court sur toute la largeur du cadre et l'œil ne retrouve pas
 * le début de la ligne suivante.
 */
.colonne-lecture {
  max-width: var(--lecture);
}

/* Deux blocs côte à côte qui s'empilent sans media query : image 340 et
   texte 440 de base, l'ordre du flux décide (fiches 13, 15). */
.duo {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(28px, 4vw, 52px);
  align-items: flex-start;
}

.duo__image {
  flex: 0 0 340px;
  width: 340px;
  max-width: 100%;
}

.duo__texte {
  flex: 1 1 440px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/**
 * Le sous-menu n'est pas une bande de contenu : c'est un étage de navigation.
 * Il n'en prend donc ni le pas vertical ni le filet — posés par le composant —
 * mais il se lit comme le filet fort de l'en-tête : d'un bord à l'autre de
 * l'écran, pas du cadre. L'aplat sort donc du conteneur (`50% - 50vw` annule
 * exactement la moitié gauche du cadre) pendant que les entrées sont ramenées
 * dans la colonne de texte par le padding — au-delà de 1280px, la moitié du
 * débord plus la marge ; en deçà, la marge seule.
 *
 * Le sous-menu n'a plus de réserve haute à respecter : l'en-tête du système v2
 * ne colle pas, il défile avec la page. Le composant `submenu` de
 * `ff_components` garde son propre comportement collant.
 */
 .section--submenu-scroll {
  /* Papier-presse, pas surlignage (fiche 11) : le bleu du surlignage est
     réservé à l'annonce, une seule teinte par écran. */
  background: var(--papier-presse);
}
main .section--submenu-scroll {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-inline: max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge)));
  /* Le composant écarte le sous-menu du contenu d'une section entière ; la
     bande qui suit porte déjà son propre pas vertical. */
  margin-bottom: 0;
  gap: 4px 26px;
}

main .section--submenu-scroll .section-menu ul {
  gap: 4px 26px;
}

/**
 * Une entrée d'ancre (fiche 11) : caractère de titre, soulignement par filet
 * de 2px sous la cible — pas par `text-decoration`, dont l'épaisseur se colle
 * au texte. Le filet est transparent au repos, encre au survol et sur l'entrée
 * courante : la rangée ne bouge pas d'un pixel quand on la parcourt.
 *
 * Le chemin reprend celui du composant, `main` en plus, pour le battre en
 * spécificité sans `!important`.
 */
main .section--submenu-scroll .inner .section-menu ul li a {
  padding: 14px 0 12px;
  border-bottom: 2px solid transparent;
  letter-spacing: normal;
  text-decoration: none;
}

main .section--submenu-scroll .inner .section-menu ul li a:hover,
main .section--submenu-scroll .inner .section-menu ul li a.is-active {
  color: var(--encre);
  border-bottom-color: var(--encre);
  text-decoration: none;
}

/**
 * Sous 1024px, `ff_components` masque le sous-menu et le rend non collant :
 * ici il reste, sous l'en-tête comme sur grand écran. Une page longue se lit
 * autant sur un téléphone, et le sous-menu y est le seul moyen d'aller d'une
 * section à l'autre sans tout dérouler.
 *
 * Le composant pose un `display: none !important` : on le bat par la
 * spécificité — le sélecteur porte `main` en plus — et non par l'ordre des
 * fichiers, que l'agrégation CSS de Drupal ne garantit pas entre deux
 * bibliothèques.
 */
@media screen and (max-width: 1024px) {
  main .section--submenu-scroll {
    display: flex !important;
    position: sticky;
    /* Les entrées défilent au doigt plutôt que de passer à la ligne : deux ou
       trois rangées d'ancres mangeraient l'écran qu'elles servent à parcourir.
       L'ascenseur reste caché, le débord se voit au premier glissement. */
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }

  main .section--submenu-scroll::-webkit-scrollbar {
    display: none;
  }

  main .section--submenu-scroll .section-menu ul {
    flex-wrap: nowrap;
  }

  main .section--submenu-scroll .inner .section-menu ul li a {
    white-space: nowrap;
  }
}

/**
 * Un séparateur posé entre deux bandes ferait un second filet à 24px du
 * premier. La bande porte déjà le trait : le séparateur s'efface et rend son
 * intention. Entre deux blocs d'une même colonne, il continue de s'afficher.
 */
.section + .comp--separateur {
  display: none;
}

/**
 * Trois portes : trois colonnes de même poids, séparées par des filets
 * verticaux. C'est le gabarit de l'accueil et des index — le filet dit que les
 * trois entrées sont à égalité, ce que trois colonnes flottantes ne disent pas.
 */
.section--cols-3 > .section__col + .section__col {
  border-inline-start: var(--trait);
  padding-inline-start: var(--gouttiere);
}

@media (max-width: 1024px) {
  /* La rangée passe à deux colonnes : la troisième repart en tête de ligne. */
  .section--cols-3 > .section__col--3 {
    border-inline-start: 0;
    padding-inline-start: 0;
  }
}

@media (max-width: 640px) {
  .section--cols-3 > .section__col + .section__col {
    border-inline-start: 0;
    padding-inline-start: 0;
  }
}

/**
 * Aplats. Deux par page au maximum, et jamais un de plus : l'encre pleine du
 * pied de page, et un seul bloc coloré au fil de la page. Un aplat prend toute
 * la largeur du cadre, comme une bande.
 */
/* L'aplat vient du composant, qui le tient de sa prop `ambiance`. Le thème ne
   garde que l'air, qu'il calcule sur la largeur du cadre — et il en donne un
   peu plus aux deux ambiances sombres, où le texte a besoin de respirer
   davantage pour ne pas toucher le bord de l'aplat.

   Pas de `gap` ici, contrairement à la maquette : les composants posés dans un
   fond portent déjà leur propre marge basse, et le `> * + *` du thème règle
   l'écart entre deux blocs. Un `gap` s'y ajouterait au lieu de s'y substituer,
   et doublerait l'air sous chaque paragraphe. */
.comp--fond {
  padding: clamp(20px, 2.6vw, 30px);
}

.comp--fond--encre,
.comp--fond--bandeau {
  padding: clamp(22px, 2.8vw, 34px);
}

/* Papier sur papier ne fait pas un aplat : c'est un filet qui fait le bloc.
   Deux classes, pour passer devant le composant quel que soit l'ordre
   d'agrégation. */
.comp--fond.comp--fond--papier {
  border: 1px solid var(--filet);
}

/* Sur encre et sur bandeau, le texte est papier : le bleu-vert ne passe plus
   le contraste. Les liens prennent la couleur du texte, soulignés, et le
   bouton s'inverse. */
:is(.comp--fond--encre, .comp--fond--bandeau) a {
  color: var(--papier);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

/* Le soulignement se retire à mi-voix : à pleine opacité il double le mot d'un
   trait aussi franc que lui. */
.comp--fond--encre :is(p, li, blockquote, figcaption) a {
  text-decoration-color: var(--papier-50);
}

.comp--fond--bandeau :is(p, li, blockquote, figcaption) a {
  text-decoration-color: var(--papier-60);
}

:is(.comp--fond--encre, .comp--fond--bandeau) :is(.comp--bouton--normal, .comp--bouton--simple) {
  background: var(--papier);
  border-color: var(--papier);
  color: var(--encre);
  text-decoration: none;
}

/* Le bouton inversé ne se vide pas au survol : il prend la couleur qui
   contraste encore avec son fond — l'accent sur encre, l'encre sur bandeau. Le
   contour vidé, à peine visible sur bandeau, ne disait plus rien. */
.comp--fond--encre :is(.comp--bouton--normal, .comp--bouton--simple):hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--papier);
}

.comp--fond--bandeau :is(.comp--bouton--normal, .comp--bouton--simple):hover {
  background: var(--encre);
  border-color: var(--encre);
  color: var(--papier);
}

:is(.comp--fond--encre, .comp--fond--bandeau) .comp--bouton--lien-fleche {
  color: var(--papier);
  border-bottom-color: var(--papier);
  text-decoration: none;
}

/* Au survol, le lien fléché reste papier : l'encre du thème disparaîtrait sur
   encre et ne passerait pas le contraste sur bandeau. Le filet s'épaissit à la
   place, et l'air du dessous cède un pixel pour ne rien décaler. */
:is(.comp--fond--encre, .comp--fond--bandeau) .comp--bouton--lien-fleche:is(:hover, :focus-visible) {
  color: var(--papier);
  border-bottom-color: var(--papier);
  border-bottom-width: 2px;
  padding-bottom: 1px;
}

:is(.comp--fond--encre, .comp--fond--bandeau) :focus-visible {
  outline-color: currentColor;
}

/* Les composants de texte fixent leur propre couleur (encre, méta, bleu-vert
   de l'étiquette et de la date) : sur un fond coloré, ils reprennent celle que
   le fond a posée, sinon encre sur encre ou bleu-vert sur bleu-vert. */
:is(.comp--fond--papier-gris, .comp--fond--encre, .comp--fond--bandeau)
  :is(.comp--texte, .comp--texte-petit, .comp--titre, .comp--titre--leger, .comp--titre--superleger, .comp--medias figcaption, .comp--texte p.meta, .comp--texte p.meta strong) {
  color: inherit;
}

/* Le texte lu garde son retrait d'opacité sur un aplat comme sur le papier :
   c'est ce qui le distingue d'un titre posé juste au-dessus. Le bandeau fait
   exception — sur bleu-vert, le papier plein passe tout juste le contraste. */
.comp--fond--papier-gris .comp--texte {
  color: var(--encre-92);
}

.comp--fond--encre .comp--texte {
  color: var(--papier-92);
}

:is(.comp--fond--papier-gris, .comp--fond--encre, .comp--fond--bandeau) .comp--texte ul > li::marker {
  color: inherit;
}

/**
 * Colonne de lecture : 680px, soit 62 à 68 signes au cran texte/m. Sans borne,
 * un paragraphe court sur toute la largeur du conteneur et l'œil ne retrouve
 * pas le début de la ligne suivante.
 */
.comp--texte,
main .text-formatted,
main .field--type-text-long {
  max-width: var(--lecture);
}
/* ------------------------------------------------------------------ */
/* 4. Composants ff_components et classes du cœur                     */
/* ------------------------------------------------------------------ */

/**
 * Une rangée `section` posée à la racine d'une page composée EST une bande du
 * système (fiches 13, 14, 15) : elle porte la marge horizontale de la page, son
 * pas vertical et le filet qui la ferme. Sans cela, un texte de la page Autrice
 * commence au pixel zéro de l'écran et rien ne sépare deux œuvres.
 *
 * Le sélecteur est étroit à dessein, et sur trois points :
 *
 *   `.page__col >`  ne prend que les rangées de premier niveau. Les blocs
 *                   (bandeau d'annonce de l'accueil, encart pratique d'une
 *                   actualité) portent leurs propres rangées imbriquées, qui
 *                   ont déjà leur cadre et n'en veulent pas un second ;
 *   `:has(… .comp)` ne prend que les rangées de contenu composé. Celles de
 *                   l'accueil enveloppent un bloc Drupal — bandeau, grille
 *                   d'actualités — qui court volontairement d'un bord à
 *                   l'autre ;
 *   `:not(…submenu)` laisse le sous-menu d'ancres, qui n'est pas une bande de
 *                   contenu mais un étage de navigation (voir section 3).
 */
.page__col > .field--name-field-blocs > .section:not(.section--submenu):has(> .section__col > :is(.comp, .groupe)) {
  padding: clamp(32px, 4vw, 52px) var(--marge);
  border-bottom: 1px solid var(--filet);
}

/* La dernière bande d'une page ne se ferme pas : le bandeau d'appel qui suit
   pose déjà son propre filet. */
.page__col > .field--name-field-blocs > .section:not(.section--submenu):has(> .section__col > :is(.comp, .groupe)):last-child {
  border-bottom: 0;
}

/* Réglage « Espacement : resserré » de la section : le pas vertical de
   `.section-page--fine` (section 3). Même sélecteur que la bande, plus la
   classe, pour passer devant son `padding`. */
.page__col > .field--name-field-blocs > .section.section--resserre:not(.section--submenu):has(> .section__col > :is(.comp, .groupe)) {
  padding-top: clamp(28px, 3vw, 40px);
  padding-bottom: clamp(28px, 3vw, 40px);
}

/* Réglage « Largeur : colonne de lecture » : le contenu s'arrête à
   `--lecture`, comme `.colonne-lecture` (section 3), mais la bande garde sa
   largeur — son filet court toujours d'un bord à l'autre. La marge droite
   absorbe le reste ; le pourcentage se lit sur la largeur de la bande. */
.page__col > .field--name-field-blocs > .section.section--lecture:not(.section--submenu):has(> .section__col > :is(.comp, .groupe)) {
  padding-inline-end: max(var(--marge), calc(100% - var(--lecture) - var(--marge)));
}

/**
 * Bloc titre + texte côte à côte (fiches 9 et 15) : le titre tient une colonne
 * étroite à gauche, le texte la colonne large. C'est le gabarit des trois
 * blocs de Coordination éditoriale.
 *
 * La condition est portée par le contenu et non par une classe de mise en
 * page : une colonne pleine largeur dont le titre est marqué `titrage` et qui
 * ne contient que ce titre et son texte. Une colonne qui enchaîne plusieurs
 * paires — les financements des Ateliers — reste empilée, la mettre en rangée
 * mélangerait les paires.
 */
.section--cols-1 > .section__col:has(> .comp--titre.titrage + .comp--texte:last-child) {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(20px, 3vw, 44px);
  align-items: flex-start;
}

.section--cols-1 > .section__col:has(> .comp--titre.titrage + .comp--texte:last-child) > .comp--titre {
  flex: 1 1 220px;
  margin-block-end: 0;
}

.section--cols-1 > .section__col:has(> .comp--titre.titrage + .comp--texte:last-child) > .comp--texte {
  flex: 2 1 400px;
  min-width: 0;
}

/**
 * `.comp--texte` est la prose du module : c'est le bloc de texte lu. `.content`
 * est la même chose côté cœur (nœud rendu, bloc de contenu) — les deux
 * partagent le rythme et les listes.
 */
.comp--texte,
.content {
  font: var(--texte-m);
  color: var(--encre-92);
}

/* La mesure borne la ligne du bloc lu, pas celle du conteneur de nœud :
   `.content` enveloppe la page entière, la lui poser rentrerait tout. */
.comp--texte {
  max-width: 66ch;
}

/* Les paragraphes d'un même bloc se suivent au pas court des maquettes ; le
   pas long (`> * + *`, plus bas) reste celui des blocs entre eux. */
.comp--texte p + p {
  margin-top: 14px;
}

.comp--texte-grand {
  font: var(--texte-l);
  max-width: 62ch;
}

.comp--texte-petit {
  font: var(--texte-s);
  color: var(--encre-88);
}

/* Le cran « Très grand » du composant n'est pas une citation : il porte une
   phrase d'ouverture, en encre pleine et sur une mesure de paragraphe court.
   Le cran `--citation` reste au témoignage, qui garde son italique et sa
   mesure de 34 signes. */
.comp--texte-xl {
  font: var(--citation);
  font-size: clamp(22px, 2.4vw, 26px);
  max-width: 54ch;
  color: var(--encre);
}

/**
 * Témoignage (système v2). Une citation n'est pas un encadré : la série
 * s'ouvre sur un trait d'encre de 2px, chaque parole se ferme par le filet du
 * système. Lora italique au cran texte/m, mesure 60ch, alignée à gauche : la
 * répétition des filets fait la série, pas un zigzag.
 */
.comp--texte blockquote {
  margin: 0;
  padding-block: 16px;
  border-bottom: 1px solid var(--filet);
  font: italic var(--texte-m);
  color: var(--encre-92);
}

.comp--texte blockquote p {
  max-width: 60ch;
  text-wrap: pretty;
}

.comp--texte > blockquote:first-child {
  border-top: 2px solid var(--encre);
}

/* Le dernier ferme la série : le filet de la bande suffit. */
.comp--texte blockquote:last-child {
  border-bottom: 0;
}

/**
 * Fiche rendez-vous régulier (système v2). Surcharge du composant de
 * ff_components, laissé intact : plus de carte ni de retrait latéral, la
 * fiche tient au filet bleu-vert de 1px (le module en pose 3, la grille n'admet
 * que des filets).
 *
 * La fiche s'empile : lieu et tarif sur une rangée, puis le quand, puis les
 * conditions. Elle a été un temps rangée en deux colonnes ; la maquette
 * « Les composants » la remet en colonne, où les trois informations se lisent
 * dans l'ordre où on les cherche — et où une fiche réduite à son lieu ne laisse
 * plus de piste vide à droite.
 */
.comp.comp--rendezvous {
  border-block-start-width: 1px;
  padding: 18px 0 20px;
  background: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.comp.comp--rendezvous + .comp--rendezvous {
  margin-block-start: var(--space-3);
}

.comp--rendezvous .rdv__tete {
  gap: 6px 16px;
  padding-block-end: 0;
  border-block-end: 0;
}

.comp--rendezvous .rdv__lieu {
  font: 600 22px / 1.15 var(--font-titre);
}

.comp--rendezvous .rdv__tarif {
  font: var(--fw-moyenne) var(--fs-2xs) / var(--lh-l) var(--font-mono);
  white-space: nowrap;
}

/* Le filet interne sépare l'identité de la fiche — son lieu, son tarif — de ce
   qui en fait un rendez-vous : quand il a lieu. */
.comp--rendezvous .rdv__quand {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 0;
  padding-block-start: 10px;
  border-block-start: 1px solid var(--encre-12);
}

.comp--rendezvous .rdv__rythme {
  font: 600 17px / 1.3 var(--font-titre);
}

.comp--rendezvous .rdv__horaire {
  margin: 0;
  font: 500 13px / 1.5 var(--font-mono);
  color: var(--encre-75);
}

.comp--rendezvous .rdv__conditions {
  margin: 0;
  font: var(--texte-s);
  color: var(--encre-90);
}

/* Pied de la pile : le bouton d'agenda à gauche, l'inscription ferrée à
   droite. Replié faute de place, le texte garde son fer à droite.
   C'est l'exception à la liste en pile : ici la « liste » n'en est pas une,
   c'est une rangée d'actions — elle reprend donc la rangée et laisse les
   filets de côté. */
.comp--rendezvous ~ .comp--presentation-liste {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--gouttiere);
  max-width: none;
  border-bottom: 0;
}

.comp--rendezvous ~ .comp--presentation-liste > .comp {
  padding-block: 0;
  border-top: 0;
}

.comp--rendezvous ~ .comp--presentation-liste > .comp--texte {
  margin-inline-start: auto;
  text-align: right;
}

/**
 * La ligne de données — public, format, durée, tarif, EAN. C'est elle qui
 * donne au site son second registre : à côté du texte lu, une ligne qu'on
 * repère du coin de l'œil sans la lire. Chiffres tabulaires, pour que deux
 * lignes superposées s'alignent.
 */
.comp--texte p.meta,
.content p.meta {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-normal);
  line-height: var(--lh-l);
  font-variant-numeric: tabular-nums;
  color: var(--meta);
  text-wrap: pretty;
}

.comp--texte p.meta strong,
.content p.meta strong {
  font-weight: var(--fw-moyenne);
  color: var(--encre);
}

/* Source d'un extrait : la ligne mono qui suit la citation. */
.comp--texte-xl + .comp--texte-petit,
.comp--texte-xl p.meta {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-normal);
  line-height: var(--lh-l);
  color: var(--meta);
}

.comp--texte > * + *,
.content > * + * {
  margin-block-start: var(--space-4);
}

.comp--texte :is(h1, h2, h3, h4, h5, h6):not(:first-child),
.content :is(h1, h2, h3, h4, h5, h6):not(:first-child) {
  margin-block-start: 0
}

.comp--texte :is(ul, ol),
.content :is(ul, ol) {
  padding-inline-start: var(--space-4);
}

.comp--texte li + li,
.content li + li {
  margin-block-start: var(--space-2);
}

/**
 * Le filet est le seul ornement du système : la puce en reprend le trait. Elle
 * passe par `::marker` et non par un `::before` absolu, sinon les listes que
 * les composants neutralisent en `list-style: none` — pagination du diaporama,
 * sous-menus — récupèrent une puce parasite.
 */
.comp--texte ul,
.content ul {
  list-style: square;
}

.comp--texte ul > li::marker,
.content ul > li::marker {
  color: var(--encre);
  /* Relatif au parent, volontairement hors échelle. */
  font-size: 0.7em;
}

.comp--texte ol,
.content ol {
  list-style: decimal;
}

.comp--texte ol > li::marker,
.content ol > li::marker {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-normal);
  line-height: var(--lh-l);
  color: var(--meta);
}

/**
 * Titres du module. Les quatre variantes offertes en back-office couvrent les
 * quatre registres d'annonce du système, du titre de section à l'étiquette :
 * c'est le seul choix que l'éditrice a à faire, la mise en forme suit.
 *
 *   Titre H2  → titre de section        titre/l   30
 *   Titre H3  → sous-titre, en-tête     22/1.15
 *   Titre H4  → petit item, nom de média 17/1.3
 *   Titre H5  → étiquette de section    mono 12, capitales, bleu-vert
 *
 * H3 et H4 sortent des crans du système (`--titre-m`, `--titre-s`) : la
 * maquette « Les composants » les fixe à 22/1.15 et 17/1.3, et c'est elle qui
 * fait foi pour les composants. Les crans restent ce qu'ils sont partout
 * ailleurs — les toucher aurait déplacé l'en-tête et les cartes avec.
 */
.comp--titre {
  font: var(--titre-l);
  margin-block-end: var(--space-4);
}

/**
 * L'intitulé de la boîte atelier (Claude Design) : mono en capitales
 * bleu-vert, sans filet. Il se colle au titre qu'il annonce (pas court sous
 * l'étiquette, pas long sous le titre) : l'étiquette appartient au titre, le
 * titre au texte. Pas de marge haute, la bande porte déjà la sienne.
 */
.comp--titre--superleger {
  display: flex;
  align-items: flex-end;
  box-sizing: border-box;
  font: 500 12px / 1.4 var(--font-mono);
  text-transform: uppercase;
  color: var(--accent);
  margin-block: 0 var(--space-2);
}

/**
 * Petit item, nom de média : la graisse du titre, au plus petit cran. Il a
 * longtemps porté l'italique du texte en retrait de couleur (sous-titre
 * d'œuvre) ; la maquette « Les composants » en fait un titre franc, de même
 * encre que les autres.
 */
.comp--titre--leger {
  font: 600 17px / 1.3 var(--font-titre);
  color: inherit;
  margin-block-end: var(--space-3);
}

.comp--titre--petit {
  font: 600 22px / 1.15 var(--font-titre);
}

/* Enveloppe de champ et enveloppe de bloc, posées par le cœur de Drupal. */
.field:not(:last-child) {
  margin-block-end: var(--space-4);
}

.block:not(:last-child) {
  margin-block-end: var(--space-6);
}

/* Tableaux — filets, jamais de cadre plein. Le module pose la structure, le
   thème pose la typographie. */
.comp--tableau__table th {
  font-family: var(--font-titre);
  font-size: var(--fs-s);
  font-weight: var(--fw-demi);
  line-height: var(--lh-m);
}

.comp--tableau__table td {
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
}

/**
 * Légende de média. La même partout où un composant en pose une — média seul,
 * item de présentation, slide de diaporama : l'italique du texte, un cran sous
 * `texte-s`, en gris méta, détachée de l'image par un filet.
 *
 * La figure empile image et légende : sans elle, la légende collait au bas du
 * visuel et le filet passait pour un bord d'image.
 */
.comp--medias figure,
.comp--presentation figure {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.comp--medias figcaption,
.comp--presentation figcaption {
  font: italic 400 13.5px / 1.6 var(--font-texte);
  color: var(--meta);
  border-top: 1px solid var(--filet);
  padding-top: 10px;
  margin-block-start: 0;
}

/* Un média cliquable ne change pas de dessin au survol : il s'éclaircit. */
a.comp--medias:hover img,
a.comp--medias:focus-visible img,
.comp--medias a:hover img,
.comp--medias a:focus-visible img {
  opacity: 0.88;
}

/**
 * Diaporama (fiche 14d). Le composant range tous ses médias à une hauteur
 * commune et laisse leur largeur suivre : c'est ce qui fait une bande régulière
 * quand les visuels sont de formats mêlés, et ce qui empêche la page de sauter
 * entre deux fondus.
 *
 * Le thème avait un temps inversé l'axe — largeur commune, hauteur libre — au
 * motif que les maquettes d'alors le demandaient. La maquette
 * « Les composants » revient à la hauteur commune (400px, largeur auto) ; cette
 * inversion est annulée, et le thème ne surcharge plus la taille des médias.
 *
 * Reste le fond de chargement, que le composant ne pose pas.
 */
main .comp--diaporama.splide .comp--medias img {
  background: var(--papier-presse);
}

/* La légende revient au cran des autres légendes de média. Le chemin est long
   pour battre celle du composant, qui la descend à 12px — sans cette règle, la
   légende de diaporama serait plus petite que les autres. */
main .comp--diaporama.splide .comp--medias .media__caption {
  font: italic 400 13.5px / 1.6 var(--font-texte);
  color: var(--meta);
}



/**
 * Le format d'un média vient du style d'image choisi en back-office, pas d'une
 * classe (fiche 16 : les ratios autorisés sont 4/5, 72/100, 16/9, 1/1). Le
 * thème ne pose donc pas d'`aspect-ratio` — il garantit seulement qu'une image
 * de grille garde ses proportions quelle que soit la largeur de sa case.
 */
.comp--medias__item img {
  height: auto;
}

/* Apparition des images au chargement : opacité seule, rien au scroll. */
.comp--medias img {
  animation: vb-apparition var(--t-image);
}

@keyframes vb-apparition {
  from {
    opacity: 0;
  }
}

/* Le filet est la seule ornementation autorisée. Gris filet 1px par défaut ;
   les props `couleur` et `epaisseur` du composant posent
   `--separateur-couleur` et `--separateur-epaisseur`. */
.comp--separateur {
  border: 0;
  border-block-end: var(--separateur-epaisseur, 1px) solid var(--separateur-couleur, var(--filet));
  margin-block: var(--space-4);
}

/* Entrée de liste renvoyant vers une page. */
.comp--teaser__titre {
  font-family: var(--font-titre);
  font-size: var(--fs-l);
  font-weight: var(--fw-demi);
  line-height: var(--lh-m);
}

.comp--teaser__surtitre {
  font-family: var(--font-mono);
  font-size: var(--fs-3xs);
  font-weight: var(--fw-moyenne);
  line-height: var(--lh-3xs);
  text-transform: uppercase;
}

/**
 * Onglets de tâches locales (Voir / Modifier / Supprimer), visibles seulement
 * pour les personnes connectées. Même vocabulaire que la navigation : filet
 * sous la ligne, filet bleu-vert sous l'onglet courant.
 */
.tabs {
  margin-block: var(--space-5);
  border-block-end: var(--trait);
}

.tabs ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.tabs li a {
  display: inline-flex;
  align-items: center;
  min-height: var(--cible);
  padding-block-end: var(--space-2);
  border-block-end: 2px solid transparent;
  color: var(--encre);
  font-family: var(--font-titre);
  font-size: var(--fs-s);
  font-weight: var(--fw-demi);
  line-height: var(--lh-m);
  text-decoration: none;
}

.tabs li a:hover {
  color: var(--accent);
}

.tabs li.is-active a {
  color: var(--accent);
  border-block-end-color: var(--accent);
}

/**
 * Détail d'actualité (fiche 8).
 *
 * Le fil de retour n'est pas une bande : il tient au-dessus de l'article, à
 * la marge du cadre, et se lit en label mono accent.
 */
.fil {
  padding: 22px var(--marge) 0;
}

.fil a {
  font: var(--label);
  text-transform: uppercase;
  color: var(--accent);
}

/* La fiche est un `duo` : image 340 à gauche, texte à droite, empilés sous
   la somme des deux. Elle n'emprunte à `.section-page` que son filet de bas
   de bande — son pas vertical propre est plus serré en tête. */
.actu-detail {
  padding: clamp(24px, 3vw, 34px) var(--marge) clamp(36px, 4vw, 56px);
}

.actu-detail img {
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

.actu-detail__titre {
  font: var(--titre-xl);
  max-width: 24ch;
}

/* Encart pratique : pas de fond, un filet fort de 2px qui le décroche du
   chapeau. Le bouton en est le dernier élément et se cale au fer à gauche. */
.actu-detail__pratique {
  display: flex;
  flex-direction: column;
  gap: 18px;
  max-width: 60ch;
  padding-top: 18px;
  border-top: 2px solid var(--encre);
}

.actu-detail__bouton {
  align-self: flex-start;
}

/* ------------------------------------------------------------------ */
/* 5. Focus et évitement                                              */
/* ------------------------------------------------------------------ */

/* Contour 2px bleu-vert, décalé de 2px. Jamais supprimé (RGAA 10.7). */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible,
[tabindex]:focus-visible {
  outline: var(--focus);
  outline-offset: 2px;
}

.skip-link {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  z-index: 100;
  padding: var(--space-3) var(--space-4);
  background: var(--encre);
  color: var(--papier);
  font-family: var(--font-titre);
  font-size: var(--fs-s);
  font-weight: var(--fw-demi);
  line-height: var(--lh-m);
  text-decoration: none;
}

.skip-link:not(:focus):not(:focus-within) {
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  overflow: hidden;
  white-space: nowrap;
}

.visually-hidden:not(:focus):not(:focus-within) {
  position: absolute;
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  overflow: hidden;
  white-space: nowrap;
}

/* ------------------------------------------------------------------ */
/* 6. En-tête, marque, navigation, réseaux                            */
/* ------------------------------------------------------------------ */

/**
 * Barre d'édition — premier étage de la pile collante, sous la barre
 * d'administration. Elle porte les onglets de tâches locales et n'existe que
 * pour les personnes connectées (voir page.html.twig).
 *
 * Elle ne prend ni le filet fort de l'en-tête ni le pas vertical des onglets
 * de contenu : c'est du mobilier d'édition, il se tient au-dessus du site sans
 * prétendre en faire partie. D'où l'aplat de papier pressé, un simple filet, et
 * la hauteur réduite au strict nécessaire.
 */
.barre-edition {
  position: sticky;
  inset-block-start: var(--gin-toolbar-y-offset, 0px);
  z-index: 6;
  background: var(--papier-presse);
  border-block-end: var(--trait);
  /* L'aplat court d'un bord à l'autre, les onglets reviennent sur la colonne
     de contenu — même calcul que le bandeau d'annonce, pour que le mobilier
     d'édition se cale sur le site plutôt que sur la fenêtre. */
  padding-inline: max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge)));
}

.barre-edition .tabs {
  margin-block: 0;
  border-block-end: 0;
}

.barre-edition .tabs ul {
  gap: var(--space-5);
}

.barre-edition .tabs li a {
  min-height: 38px;
  padding-block-end: 0;
  font-size: var(--fs-xs);
  color: var(--meta);
}

.barre-edition .tabs li a:hover {
  color: var(--accent);
}

/* L'onglet courant se marque à l'encre pleine, pas au bleu-vert : l'accent
   reste au site, la barre d'édition s'en tient au gris et au noir. */
.barre-edition .tabs li.is-active a {
  color: var(--encre);
  border-block-end-color: var(--encre);
}

/**
 * Sur petit écran, les huit onglets d'un nœud tiennent sur trois rangées : la
 * pile collante prendrait un tiers de la hauteur avant la première ligne de
 * texte. Ils défilent au doigt sur une seule rangée, comme les entrées du
 * sous-menu.
 */
@media screen and (max-width: 1024px) {
  .barre-edition .tabs ul {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: none;
  }

  .barre-edition .tabs ul::-webkit-scrollbar {
    display: none;
  }

  .barre-edition .tabs li a {
    white-space: nowrap;
  }
}

/**
 * En-tête. Elle colle en haut de fenêtre, sous la barre d'administration et
 * la barre d'édition dont navbar.js mesure la hauteur (`--barre-edition-h`).
 * Le sous-menu d'ancres vient se coller juste dessous : les deux bandeaux
 * restent soudés au défilement.
 *
 * Dès le premier pixel de défilement, navbar.js pose `.barre--compacte` : le
 * nom passe au cran des entrées de navigation et la baseline s'efface, pour
 * que l'en-tête collé pèse la même hauteur que le sous-menu.
 */
.barre {
  position: sticky;
  inset-block-start: calc(var(--gin-toolbar-y-offset, 0px) + var(--barre-edition-h, 0px));
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px 24px;
  /* Le bandeau court d'un bord à l'autre, son contenu revient sur la colonne
     de texte : même calcul que le sous-menu d'ancres et que le pied — la
     moitié du débord du cadre, plus la marge des sections. En deçà du cadre,
     la marge seule. */
  padding: 14px max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge))) 10px;
  background: var(--papier);
  border-bottom: 1px solid var(--filet-fort);
  transition: padding var(--t-deplie);
}

.barre--compacte {
  padding-block: 4px;
}

.marque__nom {
  transition: font-size var(--t-deplie);
}

.barre--compacte .marque__nom {
  font-size: var(--fs-l);
}

/**
 * La baseline s'efface au lieu de disparaître d'un coup. Ce n'est pas `height`
 * qui se ferme mais `max-height` : une hauteur `auto` ne s'anime pas, un
 * plafond chiffré si. Le plafond vaut deux lignes — de quoi laisser le texte
 * passer à la ligne sur un écran étroit sans qu'il soit coupé au repos.
 */
.marque__baseline {
  max-height: 3rem;
  overflow: hidden;
  transition: max-height var(--t-deplie), opacity var(--t-deplie);
}

.barre--compacte .marque__baseline {
  max-height: 0;
  opacity: 0;
}

/* Le drapeau de marque referme aussi son interligne. */
.marque {
  transition: gap var(--t-deplie);
}

.barre--compacte .marque {
  gap: 0;
}

/* La barre est un repère, pas une animation : réglage système respecté. */
@media (prefers-reduced-motion: reduce) {
  .barre,
  .marque,
  .marque__nom,
  .marque__baseline {
    transition: none;
  }
}

/**
 * Le sous-menu se colle sous l'en-tête, dont navbar.js publie la hauteur
 * courante — compacte au défilement — dans `--barre-h`. Le composant pose
 * `top: 0` à spécificité 0,1,0 ; le `main` d'ici le bat sans `!important`.
 */
main .section--submenu-scroll {
  top: calc(var(--gin-toolbar-y-offset, 0px) + var(--barre-edition-h, 0px) + var(--barre-h, 0px));
}

.marque {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  color: var(--encre);
}

.marque__nom {
  font: var(--marque);
  text-transform: uppercase;
}

.marque__baseline {
  font: var(--texte-s);
  font-size: var(--fs-2xs);
  font-style: italic;
  color: var(--encre-75);
}

.barre__droite {
  display: flex;
  flex: none;
  align-items: center;
  justify-content: flex-end;
  gap: 8px 18px;
}

.nav-liens {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 6px 28px;
  font: var(--titre-s);
}

.nav-liens a {
  color: var(--encre);
  padding: 11px 0 9px;
  border-bottom: 2px solid transparent;
}

.nav-liens a:hover {
  border-bottom-color: var(--encre);
}

.nav-liens a[aria-current="page"] {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/**
 * Réseaux sociaux — le balisage vient du module `violette_admin` et ne se
 * touche pas : la barre le rhabille depuis le thème. Glyphes en encre
 * atténuée, dans la cible de 44px, détachés de la navigation par un filet.
 */
.reseaux-barre {
  display: flex;
  align-items: center;
  gap: 2px;
  padding-left: 10px;
  /* Moitié du blanc de centrage d'une cible de 36px autour d'un glyphe de 20 :
     le dernier glyphe tombe alors sur le bord de contenu, comme le burger. */
  margin-right: -8px;
  /* 0,2 n'a pas de jeton : ni `--filet` (0,14) ni `--encre-68`. Valeur des
     maquettes, littérale jusqu'à ce qu'un cran soit posé dans tokens.css. */
  border-left: 1px solid rgba(28, 26, 22, 0.2);
}

.reseaux-barre .violette-reseaux {
  display: flex;
  gap: 2px;
}

/* Cible resserrée pour compacter la barre : 36px au lieu des 44 de `--cible`,
   soit 8px de blanc autour d'un glyphe de 20. On reste au-dessus du minimum de
   24px du critère « taille de cible », qui est le plancher ici. */
.reseaux-barre .violette-reseaux__link {
  display: flex;
  width: 36px;
  height: 36px;
  align-items: center;
  justify-content: center;
  color: var(--encre);
  opacity: 0.72;
}

.reseaux-barre .violette-reseaux__link:hover {
  opacity: 1;
}

.reseaux-barre .violette-reseaux__link svg {
  width: 20px;
  height: 20px;
}

.reseaux-barre .violette-reseaux__nom {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/**
 * Bouton de dépliage. Aucun libellé visible : le nom accessible vient de
 * l'`aria-label`, et le pictogramme, tracé par `currentColor`, survit au
 * contraste forcé. La marge négative aligne le glyphe sur le bord de la cible.
 */
.burger {
  display: none;
  width: var(--cible);
  height: var(--cible);
  align-items: center;
  justify-content: center;
  /* Le glyphe fait 26px dans une cible de 44 : la moitié du blanc restant, 9px,
     le ramène exactement sur le bord de contenu. La cible garde ses 44px, c'est
     le seul contrôle tactile de la barre en mobile. */
  margin-right: -9px;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--encre);
  cursor: pointer;
}

@media (max-width: 1024px) {
  .nav-liens {
    display: none;
  }

  .burger {
    display: flex;
  }
}

/* Menu plein écran */
body[data-menu-ouvert] {
  overflow: hidden;
}

.menu-plein {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  flex-direction: column;
  padding: var(--marge);
  background: var(--encre);
  color: var(--papier);
  overflow: auto;
  animation: menu-plein var(--t-deplie);
}

/**
 * Le panneau se ferme par l'attribut `hidden`, posé par navbar.js — mais le
 * `display: flex` ci-dessus, écrit par la feuille de l'auteur, l'emporte sur le
 * `display: none` que le navigateur attache à `[hidden]`. Sans cette règle, le
 * menu resterait déplié en permanence, à toutes les largeurs.
 */
.menu-plein[hidden] {
  display: none;
}

@keyframes menu-plein {
  from { opacity: 0; }
  to { opacity: 1; }
}

.menu-plein__tete {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: clamp(18px, 3.5vw, 32px);
  border-bottom: 1px solid var(--papier-28);
}

.menu-plein .marque {
  color: var(--papier);
}

.menu-plein .marque__nom {
  font-size: 34px;
}

.menu-plein .marque__baseline {
  color: var(--papier-75);
}

.menu-plein__fermer {
  flex: none;
  display: flex;
  width: var(--cible);
  height: var(--cible);
  align-items: center;
  justify-content: center;
  margin: -11px -11px 0 0;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--papier);
  cursor: pointer;
}

/**
 * La maquette pose le `<nav>` en enfant direct du panneau ; Drupal glisse deux
 * conteneurs entre les deux — la région et le bloc. Le `flex: 1` qui plaque le
 * contact en bas de fenêtre doit donc traverser la chaîne, sans quoi il ne
 * s'applique qu'à un enfant qui, lui, ne grandit pas.
 */
.menu-plein .region-menu-plein,
.menu-plein .region-menu-plein > *,
.menu-plein__nav {
  display: flex;
  flex: 1;
  flex-direction: column;
}

.menu-plein__nav a {
  padding: clamp(13px, 2.2vw, 19px) 0;
  border-bottom: 1px solid var(--papier-16);
  color: var(--papier);
  font: 600 clamp(26px, 6vw, 40px) / 1.1 var(--font-titre);
}

.menu-plein__contact {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 24px;
  padding-top: clamp(18px, 3vw, 28px);
}

.menu-plein__contact a:first-child {
  font: var(--titre-s);
  color: var(--papier);
  border-bottom: 1px solid var(--papier-40);
  padding-bottom: 2px;
}

.menu-plein__contact a:last-child {
  font: var(--date-mono);
  color: var(--papier-75);
}

/* ------------------------------------------------------------------ */
/* 7. Bandeau d'appel et pied de page                                 */
/* ------------------------------------------------------------------ */

/**
 * Les deux pièces qui ferment chaque page : le bandeau d'appel sur papier
 * presse, puis le pied sur l'aplat d'encre.
 *
 * Elles sont alimentées par des blocs Drupal, dont l'emboîtement — région,
 * bloc, layout, champ — n'a aucune valeur visuelle. On l'efface au
 * `display: contents` pour que les paragraphes et les colonnes deviennent
 * directement les éléments flexibles ou de grille attendus.
 */

/* Bandeau d'appel — papier presse, une fois par page, avant le pied */
.cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px clamp(24px, 4vw, 40px);
  padding: clamp(22px, 2.6vw, 30px) max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge)));
  background: var(--papier-presse);
  border-top: 1px solid var(--filet);
}

.cta > .region,
.cta > .region > [id^='block-'],
.cta .layout,
.cta .layout__region,
.cta .field,
.cta .field__item {
  display: contents;
}

.cta h3 {
  flex: 1 1 380px;
  margin: 0;
  font: 600 clamp(20px, 1.8vw, 23px) / 1.15 var(--font-titre);
}

.cta p {
  margin: 0;
  font: 400 16px / 1.6 var(--font-texte);
  max-width: 56ch;
  color: var(--encre-80);
}

/* Le dernier paragraphe ne porte que le bouton : il va se coller à droite. */
.cta p:last-child {
  flex: 0 0 auto;
  margin-left: auto;
}

/**
 * Pied de page — aplat d'encre, trois colonnes.
 *
 * Les maquettes rangent les réseaux sous les coordonnées, dans la même
 * colonne ; Drupal en fait deux blocs frères. La grille nommée reconstitue
 * l'intention sans toucher au balisage : `coord` et `reso` se partagent la
 * première colonne, `site` et `news` occupent les deux rangées.
 */
.pied {
  display: grid;
  /* Rapport 260 / 180 / 260 de la fiche, en colonnes fluides. */
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1.4fr);
  grid-template-areas:
    'coord site news'
    'reso  site news';
  /* La première rangée se règle sur les coordonnées : sans quoi les deux
     colonnes de droite, qui traversent les deux rangées, l'étireraient et
     décrocheraient les réseaux. */
  grid-template-rows: min-content 1fr;
  align-items: start;
  /* Deux écarts, pas un : les colonnes respirent (--space-6), les rangées se
     tiennent au pas du texte (--space-5). Un `gap` unique de 44px ne tombait
     sur aucun cran de l'échelle et creusait la colonne des coordonnées. */
  gap: var(--space-5) var(--space-6);
  padding: var(--space-5) max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge)));
  background: var(--encre);
  color: var(--papier);
}

.pied > .region {
  display: contents;
}

.pied a {
  color: var(--papier);
}

/* Sur l'aplat d'encre le bleu-vert du contour de focus ne passe pas : il vire
   au papier. Le menu plein écran de l'en-tête est sur le même fond. */
.pied :focus-visible,
.menu-plein :focus-visible {
  outline-color: var(--papier);
}

/* Colonne des coordonnées : nom, adresse, téléphone. */
.pied #block-theme-violette-adresse {
  grid-area: coord;
}

.pied #block-theme-violette-adresse .layout,
.pied #block-theme-violette-adresse .layout__region,
.pied #block-theme-violette-adresse .field {
  display: contents;
}

.pied #block-theme-violette-adresse .field__item {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.pied #block-theme-violette-adresse p {
  margin: 0;
}

.pied #block-theme-violette-adresse strong:first-child {
  font: 700 24px / 1 var(--font-titre);
  text-transform: uppercase;
}

/**
 * L'adresse passe par le filtre spamspan : sans JavaScript elle sort en
 * `<span class="spamspan">`, et spamspan.js la remplace par le lien réel.
 * Les deux formes portent donc le même cran.
 */
.pied #block-theme-violette-adresse a[href^='mailto'],
.pied #block-theme-violette-adresse .spamspan {
  font: var(--titre-s);
}

.pied #block-theme-violette-adresse a[href^='tel'] {
  font: var(--date-mono);
  color: var(--papier-75);
}

/* Réseaux : la fin de la colonne des coordonnées, à 12px du téléphone. */
.pied #block-theme-violette-reseaux-footer {
  grid-area: reso;
  /* Rattrape le `row-gap` de la grille (--space-5) pour retomber sur les 12px
     qui séparent les lignes de la colonne des coordonnées. */
  margin-top: calc(var(--space-3) - var(--space-5));
}

.pied .violette-reseaux {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: -11px;
  padding-top: 2px;
}

.pied .violette-reseaux__link {
  display: flex;
  width: var(--cible);
  height: var(--cible);
  align-items: center;
  justify-content: center;
  opacity: 0.8;
}

.pied .violette-reseaux__link:hover {
  opacity: 1;
}

/* Le glyphe reprend la taille de celui de la barre : le composant le dessine à
   26px, deux crans plus gros que dans l'en-tête pour la même icône. */
.pied .violette-reseaux__link svg {
  width: 20px;
  height: 20px;
}

.pied .violette-reseaux__nom {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
}

/* Colonne « Le site » : le plan du site, une entrée par ligne. */
.pied #block-theme-violette-footer-menu {
  grid-area: site;
  display: flex;
  flex-direction: column;
  font: var(--date-mono);
}

.pied #block-theme-violette-newsletter {
  grid-area: news;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/**
 * Les deux colonnes de droite affichent leur libellé de bloc : c'est lui qui
 * sert de titre de colonne, au cran étiquette sur encre.
 */
.pied #block-theme-violette-footer-menu > h2,
.pied #block-theme-violette-newsletter > .bloc__titre {
  margin: 0;
  font: var(--label);
  text-transform: uppercase;
  color: var(--papier-68);
}

.pied #block-theme-violette-footer-menu > h2 {
  padding-bottom: 8px;
}

/* Les coordonnées arrivent dans un champ texte long, donc dans un `<p>` : la
   règle du texte lu les soulignait. Dans le pied, l'adresse n'est pas du texte
   courant, c'est un bloc de contact. */
.pied p a {
  text-decoration: none;
}

.pied__site-liens {
  display: flex;
  flex-direction: column;
}

/* Colonne de liens serrée : l'espacement vient du seul padding, la hauteur de
   cible descend donc avec lui. 5px tient 27,5px de haut — au-dessus du minimum
   de 24px du critère « taille de cible », qui est le plancher ici. */
.pied__site-liens a {
  display: inline-block;
  align-self: flex-start;
  padding: 5px 0;
  color: var(--papier-92);
}

.pied__site-liens a[aria-current='page'] {
  color: var(--papier);
  border-bottom: 1px solid var(--papier-50);
}

/* Newsletter : un champ souligné, le bouton posé dans la même ligne. */
.violette-newsletter {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.violette-newsletter__champ {
  display: flex;
  align-items: center;
  gap: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--papier-35);
}

/* Le champ se dépouille : c'est le filet du groupe qui le dessine. Le pied
   entre dans le sélecteur pour passer devant la règle générale des champs. */
.pied .violette-newsletter__saisie {
  flex: 1;
  width: auto;
  min-width: 0;
  height: var(--cible);
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  font: var(--texte-s);
  color: var(--papier);
}

.pied .violette-newsletter__saisie::placeholder {
  color: var(--papier-60);
}

.violette-newsletter__envoi {
  height: var(--cible);
  padding: 0 14px;
  background: transparent;
  /* Sur l'aplat d'encre, le bouton se détachait du seul poids de son libellé.
     Un filet papier atténué lui rend son contour sans en faire un aplat. */
  border: 1px solid var(--papier-40);
  border-radius: 0;
  font: 600 16px / 1 var(--font-titre);
  color: var(--papier);
  white-space: nowrap;
  cursor: pointer;
}

.violette-newsletter__piege {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
}

/* Deux colonnes : la newsletter passe sous les deux autres. */
@media (max-width: 1024px) {
  .pied {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas:
      'coord site'
      'reso  site'
      'news  news';
  }
}

/* Une colonne : chaque bloc à la suite, les réseaux collés aux coordonnées. */
@media (max-width: 640px) {
  .pied {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      'coord'
      'reso'
      'site'
      'news';
  }
}

/* ------------------------------------------------------------------ */
/* 8. Boutons et liens d'action                                       */
/* ------------------------------------------------------------------ */

/**
 * Hauteur 44px minimum, rayon 0, jamais deux boutons primaires dans un même
 * bloc. Par défaut on utilise le lien texte en bleu-vert ; le bouton est
 * réservé au contact et aux téléchargements.
 */
.btn-primaire,
.btn-secondaire,
.comp--bouton--normal,
.comp--bouton--simple,
.button,
button.form-submit,
input[type='submit'] {
  /* `min-height` porte la cible à 44px. En `inline-block`, une étiquette plus
     courte que cette hauteur laisse le rab sous le texte au lieu de l'encadrer :
     le centrage devient approximatif dès que le padding ne comble pas la cible
     à lui seul, comme sur la variante d'accent. Le flex répartit. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--cible);
  padding: 13px 22px;
  background: var(--encre);
  color: var(--papier);
  border: 1px solid var(--encre);
  border-radius: var(--radius);
  font: var(--titre-s);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--t-survol), color var(--t-survol),
    border-color var(--t-survol);
}

.btn-primaire:hover,
.comp--bouton--normal:hover,
.button:hover,
button.form-submit:hover,
input[type='submit']:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--papier);
}

/* Variante contour, choisie en back-office (« bouton simple ») : même
   métrique, fond transparent. Un pas de côté dans la lecture, pas une action
   principale. */
.btn-secondaire,
.comp--bouton--simple {
  background: transparent;
  color: var(--encre);
}

.btn-secondaire:hover,
.comp--bouton--simple:hover {
  background: var(--encre);
  border-color: var(--encre);
  color: var(--papier);
}

/* Variante d'accent, plus légère : c'est le bouton du bandeau d'appel. */
.btn-secondaire--accent {
  padding: 10px 18px;
  color: var(--accent);
  border-color: var(--accent-45);
  font-size: 15px;
}

.btn-secondaire--accent:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--papier);
}

/* Lien texte fléché : la forme par défaut d'une action, avant le bouton. La
   valeur « Lien fléché » du composant bouton prend le même dessin. */
.lien-fleche,
.comp--bouton--lien-fleche {
  font: var(--titre-s);
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
  text-decoration: none;
}

.lien-fleche:hover,
.comp--bouton--lien-fleche:hover {
  color: var(--encre);
  border-bottom-color: var(--encre);
}

.comp--bouton[disabled],
.button[disabled],
button.form-submit[disabled],
input[type='submit'][disabled] {
  background: var(--filet);
  border-color: transparent;
  color: var(--meta);
  cursor: not-allowed;
}

/* Champs de formulaire : label au-dessus, jamais un placeholder seul. */
input[type='text'],
input[type='email'],
input[type='search'],
input[type='tel'],
input[type='url'],
input[type='password'],
input[type='number'],
input[type='date'],
select,
textarea {
  width: 100%;
  min-height: var(--cible);
  padding: var(--space-3) var(--space-3);
  border: var(--trait-champ);
  background: var(--papier);
  color: var(--encre);
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
}

/**
 * Label au-dessus du champ, jamais un placeholder seul. Les libellés de case à
 * cocher et de bouton radio en sont exclus — Drupal leur pose la classe
 * `option`, et ils se placent à côté du contrôle, pas au-dessus.
 */
label:not(.option),
.label {
  display: block;
  font-family: var(--font-titre);
  font-size: var(--fs-s);
  font-weight: var(--fw-demi);
  line-height: var(--lh-m);
  color: var(--meta);
  margin-block-end: var(--space-2);
}

label.option {
  color: var(--encre);
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
}

input[type='checkbox'],
input[type='radio'] {
  width: auto;
  min-height: 0;
}

/* Une erreur s'écrit en français lisible, signalée par un filet brun — le site
   n'a pas de palette d'états. */
.form-item--error-message,
.error {
  color: var(--alerte);
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
}

input.error,
select.error,
textarea.error {
  border-color: var(--alerte);
}

/* ------------------------------------------------------------------ */
/* 9. Messages système                                               */
/* ------------------------------------------------------------------ */

/**
 * Un aplat, sans bordure : le type se lit au fond et, pour l'état, à la coche
 * qui se trace une fois à l'arrivée — une confirmation posée au crayon, pas
 * une célébration.
 */
.messages {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  margin-block: var(--space-5);
  padding: var(--space-4);
  background: var(--papier-presse);
  color: var(--encre);
  font-family: var(--font-texte);
  font-size: var(--fs-s);
  font-weight: var(--fw-normal);
  line-height: var(--lh-2xl);
}

.messages--status {
  background: var(--surlignage);
}

.messages--status a {
  color: var(--encre);
}

.messages__coche {
  flex: none;
  width: 22px;
  height: 22px;
  margin-block-start: 2px;
}

.messages__coche path {
  stroke-dasharray: 24;
  animation: messages-coche 420ms cubic-bezier(0.16, 1, 0.3, 1) 80ms both;
}

@keyframes messages-coche {
  from { stroke-dashoffset: 24; }
}

@media (prefers-reduced-motion: reduce) {
  .messages__coche path {
    animation: none;
  }
}

.messages__liste {
  margin: 0;
  padding-inline-start: var(--space-4);
}

/* ------------------------------------------------------------------ */
/* 10. Mouvement                                                      */
/* ------------------------------------------------------------------ */

/* Trois transitions autorisées, rien au-delà ; prefers-reduced-motion
   supprime tout. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/**
 * Grille d'actualités (fiche 6). Trois colonnes de même poids, sans gouttière :
 * l'écart d'un pixel laisse voir le fond `--filet` posé sur la grille, et ce
 * sont ces traits — pas des bordures de carte — qui séparent les entrées. La
 * grille s'ouvre sur le filet fort et se referme sur le filet pâle.
 */
.actus {
  /* Le fond filet et les deux bords courent d'un bord à l'autre du cadre, mais
     le contenu des cartes doit tomber sur la marge des sections. La cellule
     pose déjà `--pad-cellule` : la grille n'ajoute que ce qui manque. */
  padding-inline: calc(var(--marge) - var(--pad-cellule));
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  /* Le fond filet ne doit se voir que dans les gouttières, pas dans le retrait
     qui ramène les cartes sur la marge : `content-box` le borne aux colonnes
     et laisse le papier du cadre passer de part et d'autre. Le filet fort du
     haut est une bordure, il court d'un bord à l'autre ; le filet pâle du bas
     s'arrête sur la marge, comme le texte des cartes. C'est un trait dessiné
     dans le pixel de retrait du bas, hors de la `content-box`. */
  background:
    linear-gradient(var(--filet), var(--filet)) 50% 100% / calc(100% - 2 * var(--marge)) 1px no-repeat,
    var(--filet) content-box;
  border-top: 1px solid var(--filet-fort);
  padding-bottom: 1px;
}

/* Sur la page d'index, la grille ouvre l'écran : le filet fort de la barre lui
   sert de bord haut, elle n'en pose pas un second par-dessus. */
.actus--index {
  border-top: 0;
}

/**
 * Le fond de la grille ne doit se voir que dans les gouttières d'un pixel.
 * Quand la dernière rangée est incomplète, les cases restées libres n'ont
 * aucune carte pour le couvrir : le gris s'y étale en aplat. Un remplissage
 * papier prend leur place, dimensionné sur ce qui manque — et posé seulement
 * dans ce cas, sans quoi il ouvrirait une rangée de plus.
 *
 * Le compte dépend du nombre de colonnes, chaque palier a donc sa règle. Sous
 * 640px la grille tient sur une colonne : aucune case ne peut rester libre.
 */
@media (min-width: 1025px) {
  .actus:has(> .actu:last-child:nth-child(3n + 1))::after,
  .actus:has(> .actu:last-child:nth-child(3n + 2))::after {
    content: '';
    background: var(--papier);
  }

  .actus:has(> .actu:last-child:nth-child(3n + 1))::after {
    grid-column: span 2;
  }
}

@media (min-width: 641px) and (max-width: 1024px) {
  .actus:has(> .actu:last-child:nth-child(2n + 1))::after {
    content: '';
    background: var(--papier);
  }
}

/**
 * La carte. Pas de carte, justement : ni bordure, ni ombre, ni survol de bloc.
 * Son fond papier est ce qui la découpe dans le fond filet de la grille.
 */
.actu {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: var(--pad-cellule);
  background: var(--papier);
}

/**
 * Le 4:5 est imposé ici autant que dans le style d'image. Les deux se
 * répondent : le style fabrique un fichier au bon ratio, la règle garantit que
 * la rangée reste alignée même si un fichier ancien remonte au mauvais format.
 */
.actu img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--papier-presse);
}

/* Le lien de visuel, et non l'image, est l'enfant de la carte : c'est lui que
   la colonne dispose, et lui qu'il faudra réduire en vignette sous 640px. Le
   visuel pointe vers la même cible que le titre. */
.actu__visuel,
.actu .field--name-field-couverture,
.actu .field--name-field-couverture .field__item {
  display: block;
  min-width: 0;
}

/* Le corps prend la hauteur restante : c'est ce qui permet au lien de carte
   de se coller au bas de la colonne, quelle que soit la longueur du chapeau. */
.actu__corps {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
}

.actu h2 {
  margin: 0;
  font: var(--titre-m);
}

/* Le titre n'est pas un lien dans le texte : il ne prend pas le soulignement
   du texte courant, mais un filet propre, pâle, qui vire à l'accent au survol. */
.actu h2 a {
  color: var(--encre);
  border-bottom: 1px solid var(--encre-25);
  text-decoration: none;
}

.actu h2 a:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* Le chapeau reste au cran `texte-s` : dans une cellule de grille il accompagne
   le titre sans se lire comme du texte courant, et un cran plus bas le rendait
   illisible à côté d'un titre de 20px. */
.actu .field--name-field-chapeau,
.actu .field--name-field-chapeau p {
  margin: 0;
  font: var(--texte-s);
  color: var(--encre-90);
}

/* Le lien de carte descend au bas du corps : les rangées gardent leurs liens
   alignés même quand les chapeaux n'ont pas la même longueur. C'est le champ,
   et non le lien, qui est l'enfant du corps — c'est donc lui qu'on pousse. */
.actu .field--name-field-alt-link {
  margin-top: auto;
}

.actu .field--name-field-alt-link a {
  display: inline-block;
  font: var(--titre-s);
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
  text-decoration: none;
}

/**
 * « Le lien porte son symbole : → pour une destination interne au site, ↗ pour
 * un site extérieur, en espace insécable, jamais une icône dessinée. »
 * (système de design, fiche du teaser d'actualité)
 *
 * Le tri se fait sur le `href` et non sur la classe `ext` : extlink la pose en
 * JavaScript, après rendu — le symbole interne s'afficherait d'abord, puis
 * basculerait. Le texte de remplacement vide (`/ ""`) garde la flèche hors de
 * la synthèse vocale ; là où il n'est pas connu, elle est simplement lue.
 */
/* Archivo Narrow ne dessine ni ↗ ni →, la flèche tombe donc sur la police de
   repli : à 16px et en demi-gras, elle arrivait plus lourde que le mot qu'elle
   suit. Le pseudo-élément reprend la main sur la taille et la graisse pour la
   ramener au rang de signe de ponctuation. */
.actu .field--name-field-alt-link a::after {
  font-size: 0.72em;
  font-weight: 400;
}

.actu .field--name-field-alt-link a[href^='/']::after {
  content: '\00A0→' / '';
}

.actu .field--name-field-alt-link a:not([href^='/'])::after {
  content: '\00A0↗' / '';
}

.actu .field--name-field-alt-link a:hover {
  color: var(--encre);
  border-bottom-color: var(--encre);
}

/* Renvoi du bloc d'accueil vers l'index, aligné sur la marge comme le bord
   droit des cartes — même retrait que la pagination de l'index. */
.actus-suite {
  display: flex;
  justify-content: flex-end;
  padding: 26px var(--marge) 40px;
}

@media (max-width: 1024px) {
  .actus {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/**
 * Sous 640px la carte se couche : l'image passe à gauche en vignette de
 * 130px, le corps à droite. Le rapport 4:5 et le cran du titre ne bougent pas.
 */
@media (max-width: 640px) {
  .actus {
    grid-template-columns: 1fr;
  }

  .actu {
    flex-direction: row;
    align-items: flex-start;
    gap: 18px;
  }

  .actu__visuel {
    flex: 0 0 130px;
    width: 130px;
  }
}

/**
 * Pied de l'index : où l'on en est à gauche, par où continuer à droite. Même
 * gabarit que la ligne « Toutes les actualités » sous la grille de l'accueil —
 * c'est la même rangée de sortie, avec un état à annoncer en plus.
 */
.pagination-actualites {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 26px var(--marge) 40px;
}

.pagination-actualites__etat {
  margin: 0;
  font: var(--meta-mono);
  color: var(--meta);
}

.pagination-actualites__liens {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
}

/* ------------------------------------------------------------------ */
/* 11. Tableau                                                        */
/* ------------------------------------------------------------------ */

/**
 * Le module dessine déjà la table — balise, défilement, filets — et prend ses
 * couleurs aux jetons `--ffc-*`. Le thème n'ajoute donc que ce que le système
 * impose en plus, et le pose case par case : rien ici ne redéfinit la table,
 * chaque règle vise une colonne ou une rangée.
 *
 * C'est ce qui fait tenir la ligne d'agenda : première colonne la date,
 * dernière colonne les conditions, et entre les deux le texte courant.
 */

/**
 * L'en-tête se lit (fiche 10). Un agenda à cinq colonnes — date, événement,
 * description, lieu, conditions — a deux colonnes de prose consécutives que
 * rien ne distingue sans étiquette. Elle est posée au cran le plus bas du
 * système, l'étiquette mono en capitales, et se ferme par un filet plus franc
 * que celui des rangées : c'est la ligne qui ouvre le tableau.
 */
.comp--tableau__table thead th {
  font: 500 12px / 1.4 var(--font-mono);
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid var(--filet-fort);
}

/* La colonne clé ne se coupe jamais, en-tête comprise : « Date » sur deux
   lignes ferait flotter la première rangée. */
.comp--tableau__table thead th:first-child {
  white-space: nowrap;
}

/**
 * Le module écarte les cases avec ses propres valeurs ; on repasse à celles de
 * la maquette. Une rangée n'a pas de bordure verticale : elle est fermée en
 * haut et en bas, jamais encadrée. Vingt pixels séparent les colonnes, et la
 * rangée se ferme à ras du filet des deux côtés.
 */
.comp--tableau__table th {
  padding: 0 20px 10px 0;
}

.comp--tableau__table td {
  padding: 14px 20px 14px 0;
  border-bottom: 1px solid var(--filet);
  font: var(--texte-s);
  color: var(--encre-88);
  vertical-align: baseline;
}

.comp--tableau__table :is(th, td):last-child {
  padding-inline-end: 0;
}

/**
 * Première colonne : la clé de la rangée. Dans un agenda c'est la date — mono
 * bleu-vert, chiffres tabulaires pour que les rangées superposées s'alignent au
 * chiffre près, jamais coupée. Format invariable JJ.MM.AAAA : un agenda se lit
 * en diagonale, deux formats concurrents cassent la colonne.
 */
.comp--tableau__table td:first-child {
  font: var(--date-mono);
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  color: var(--encre-80);
  white-space: nowrap;
}

/**
 * Deuxième colonne : ce qui se passe, et rien d'autre. C'est le seul gras de
 * la rangée, donc il doit rester court — la mesure le force. Un titre qui
 * déborde de 38 caractères n'est plus un titre, c'est une phrase, et une
 * phrase entière en 600 efface la hiérarchie qu'elle était censée poser.
 */
.comp--tableau__table td:nth-child(2) {
  font: 600 17px / 1.35 var(--font-titre);
}

/* Colonnes de contexte : description, lieu. Un cran en dessous. Le second
   sélecteur rattrape la troisième colonne quand elle ferme la rangée — dans un
   tableau à trois colonnes, c'est un lieu, pas une condition. */
.comp--tableau__table td:nth-child(n + 3):not(:last-child),
.comp--tableau__table td:nth-child(3):last-child {
  color: var(--encre-88);
  max-width: 44ch;
}

/**
 * Dernière colonne : horaire, tarif, inscription. Le cran mono des métadonnées,
 * poussé contre le bord droit de la rangée.
 *
 * À partir de la quatrième seulement. Une rangée de trois colonnes se lit date,
 * titre, lieu — sa dernière case est du texte, et la pousser à droite en mono
 * la détacherait de l'événement qu'elle situe.
 */
.comp--tableau__table td:last-child:nth-child(n + 4) {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-normal);
  line-height: var(--lh-l);
  font-variant-numeric: tabular-nums;
  color: var(--meta);
  text-align: end;
}

/**
 * Le site n'a que deux ruptures, 1024 et 640, et la fiche 10 replie le tableau
 * à la seconde. Le composant, lui, le replie dès 900px : entre 641 et 1024, on
 * lui rend son affichage de table. Une largeur de tablette a de quoi tenir
 * cinq colonnes ; les replier plus tôt allongerait la page d'un tiers pour
 * rien. Au-delà de 900px le composant n'a plus rien à défaire — ces règles y
 * répètent son propre affichage, sans conflit.
 *
 * Le chemin porte `main` en plus de celui du composant : à spécificité égale,
 * l'ordre d'agrégation CSS de Drupal entre deux bibliothèques n'est pas
 * garanti, et le repli reviendrait au premier chargement contraire.
 */
@media (min-width: 40.0625rem) and (max-width: 64rem) {
  main .comp--tableau__defilement {
    overflow-x: auto;
  }

  main .comp--tableau__table {
    display: table;
  }

  main .comp--tableau__table tbody {
    display: table-row-group;
  }

  main .comp--tableau__table tr {
    display: table-row;
    padding-block: 0;
    border-bottom: 0;
  }

  /* La case redevient une colonne : elle reprend sa gouttière et son filet,
     que le repli du composant lui avait retirés. */
  main .comp--tableau__table td {
    display: table-cell;
    padding: 11px var(--gouttiere) 11px 0;
    border-bottom: 1px solid var(--encre-12);
  }

  main .comp--tableau__table :is(th, td):last-child {
    padding-inline-end: 0;
  }

  /* L'en-tête reprend sa place : c'est lui qui nomme les cinq colonnes. */
  main .comp--tableau__table thead {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }
}

/**
 * Sous 640px les colonnes tombent — le composant replie la table en blocs, le
 * thème n'a plus qu'à lui redonner son rythme. Une rangée devient alors une
 * petite fiche : la date en tête, le titre, ce qu'il faut savoir, l'horaire
 * pour finir. Rien ne se justifie plus à droite : sur une colonne, un horaire
 * collé au bord opposé de son événement n'appartient visiblement plus à
 * personne.
 */
@media (max-width: 40rem) {
  .comp--tableau__table tr {
    padding-block: 11px;
    border-bottom-color: var(--encre-12);
  }

  /* Le padding qui écartait les colonnes n'a plus rien à écarter : laissé en
     place, il ouvrirait 40px entre deux lignes de la même fiche. C'est la
     rangée qui porte le rythme maintenant. */
  .comp--tableau__table td {
    max-width: none;
    width: auto;
    padding: 2px 0;
    /* La case n'est plus une colonne : c'est la rangée qui se ferme, sinon
       chaque ligne de la fiche porterait son propre filet. */
    border-bottom: 0;
  }

  /* La date reprend sa place de titre de bloc : c'est elle qu'on cherche. La
     colonne de 180px n'a plus de colonne en face, elle repasse au flux. */
  .comp--tableau__table td:first-child {
    width: auto;
    margin-block-end: var(--space-3);
  }

  .comp--tableau__table td:last-child:not(:nth-child(-n + 2)) {
    text-align: start;
    margin-block-start: var(--space-3);
  }
}

/* Bandeau d'annonce (fiche 4)
   ───────────────────────────
   Le bloc « Annonce » posé au-dessus de la grille d'actualités. Une bande de
   surlignage pleine largeur : le message à gauche, le renvoi à droite, sans
   bordure haute — la barre de l'en-tête a déjà son filet fort.

   La classe `bandeau-annonce` est posée sur l'enveloppe du bloc par
   `violette_admin_preprocess_block()` ; `annonce` est le nom du système. Les
   deux nomment la même pièce, d'où l'alias dans chaque sélecteur. */
.annonce,
.bandeau-annonce {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px 40px;
  /* L'aplat se lit comme la barre et le pied : d'un bord à l'autre de l'écran,
     pas du cadre — le `50% - 50vw` annule exactement la moitié gauche de
     celui-ci. Le texte, lui, tombe sur la marge des sections, comme le
     contenu des cartes de la grille qu'il coiffe : la moitié du débord ramène
     au bord du cadre, `--marge` fait le reste. En deçà du cadre le débord est
     nul et il ne reste que la marge. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding: clamp(16px, 2vw, 22px)
    max(var(--marge), calc((100vw - var(--max)) / 2 + var(--marge)));
  background: var(--surlignage);
  color: var(--encre);
  /* Filet fort, comme celui qui ferme la barre : une bande pleine largeur se
     clôt d'un bord à l'autre. Le filet pâle disparaissait sous celui, opaque
     mais borné au cadre, que posait la grille suivante. */
  border-bottom: 1px solid var(--filet-fort);
}

/* La grille qui suit une annonce n'ouvre pas un second filet fort : celui du
   bandeau lui sert de bord haut. Même règle que `.actus--index` sous la barre. */
.field--name-field-blocs
  > .section:has(> .section__col > .bandeau-annonce)
  + .section
  .actus {
  border-top: 0;
}

.annonce p,
.bandeau-annonce p {
  margin: 0;
  font: 600 clamp(17px, 1.7vw, 20px) / 1.3 var(--font-titre);
  max-width: 60ch;
}

.annonce a,
.bandeau-annonce a {
  flex: none;
  font: var(--titre-s);
  color: var(--accent);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
  text-decoration: none;
}

.annonce a:hover,
.bandeau-annonce a:hover {
  color: var(--encre);
  border-bottom-color: var(--encre);
}
