/*
Theme Name: Yukademia Petale
Theme URI: https://github.com/yukademia/yukademia-theme-petale
Author: Yukademia
Description: Style Template du système Préau. Registre calme et arrondi : chaque bloc porte un angle largement ouvert et trois angles discrets. Requiert le plugin yukademia-core.
Version: 1.16.0
Requires PHP: 8.0
License: GPL-2.0-or-later
Text Domain: yukademia-theme-petale
*/

/* ==========================================================================
   PÉTALE — la feuille unique

   Le nom dit la règle : un bloc porte UN angle largement ouvert et trois
   angles discrets. Jamais deux, jamais zéro, jamais au hasard. La position
   de l'angle ouvert vient du rôle du bloc, pas de son rang.

   Le reste tient en trois échelles fermées — rayons, espacements, tailles
   de texte. Une valeur qui n'y figure pas est une valeur de trop.

   Ordre de la feuille : variables, polices, base, mise en page, composants,
   mouvement, puis les utilitaires EN DERNIER. À spécificité égale c'est la
   dernière règle qui gagne, et un utilitaire déclaré en tête se fait
   écraser par le `margin: 0` du premier composant venu.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Les cinq variables de l'école, et leur repli
   --------------------------------------------------------------------------
   Le plugin les injecte à `wp_head` priorité 99, donc APRÈS cette feuille.
   Ce qui suit est le visage de Pétale quand aucun réglage n'a été saisi :
   un site sans branding doit rendre un design complet, pas un brouillon.
   -------------------------------------------------------------------------- */

:root {
	--ecole-primaire:    #0e3b2e;
	--ecole-secondaire:  #2ecfa1;
	--ecole-accent:      #ef7c57;
	--ecole-fond:        #fffef6;
	--ecole-texte:       #1b1b1a;
	--ecole-font-titre:  'Poppins', 'Figtree', ui-sans-serif, system-ui, sans-serif;
	--ecole-font-texte:  'Figtree', ui-sans-serif, system-ui, sans-serif;
}


/* --------------------------------------------------------------------------
   2. Les polices
   --------------------------------------------------------------------------
   Auto-hébergées, jamais Google Fonts : ce sont des sites d'écoles
   primaires, les données concernent des enfants, et l'appel à un CDN tiers
   est un transfert de données que la CNIL a déjà sanctionné.

   Poppins est la police PROPRE au thème. Elle ne figure pas dans le `select`
   du branding, n'a donc rien à propager aux autres Style Templates, et sert
   quand l'école ne choisit pas — c'est-à-dire presque toujours. Les dix
   familles de la liste fermée suivent : le navigateur ne télécharge que
   celle qui est réellement utilisée, le coût dormant est nul.

   Seuls les poids réellement embarqués sont déclarés. Sans le fichier, la
   correspondance CSS remonte au poids voisin en silence, et le titre gagne
   deux crans sans que personne ne l'ait demandé.
   -------------------------------------------------------------------------- */

@font-face { font-family: 'Poppins'; src: url( assets/fonts/poppins-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url( assets/fonts/poppins-latin-600-normal.woff2 ) format('woff2'); font-weight: 600; font-style: normal; font-display: swap; }
@font-face { font-family: 'Poppins'; src: url( assets/fonts/poppins-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Figtree'; src: url( assets/fonts/figtree-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Figtree'; src: url( assets/fonts/figtree-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Figtree'; src: url( assets/fonts/figtree-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Figtree'; src: url( assets/fonts/figtree-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Libre Baskerville'; src: url( assets/fonts/libre-baskerville-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Libre Baskerville'; src: url( assets/fonts/libre-baskerville-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Libre Baskerville'; src: url( assets/fonts/libre-baskerville-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Libre Baskerville'; src: url( assets/fonts/libre-baskerville-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Lora'; src: url( assets/fonts/lora-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Lora'; src: url( assets/fonts/lora-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Lora'; src: url( assets/fonts/lora-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Lora'; src: url( assets/fonts/lora-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Playfair Display'; src: url( assets/fonts/playfair-display-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Playfair Display'; src: url( assets/fonts/playfair-display-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Playfair Display'; src: url( assets/fonts/playfair-display-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Playfair Display'; src: url( assets/fonts/playfair-display-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'EB Garamond'; src: url( assets/fonts/eb-garamond-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'EB Garamond'; src: url( assets/fonts/eb-garamond-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'EB Garamond'; src: url( assets/fonts/eb-garamond-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'EB Garamond'; src: url( assets/fonts/eb-garamond-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

/* Bricolage Grotesque n'existe pas en italique : un `<em>` dans un titre y
   produit un faux italique de synthèse. Réserve connue, pas un oubli. */
@font-face { font-family: 'Bricolage Grotesque'; src: url( assets/fonts/bricolage-grotesque-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Bricolage Grotesque'; src: url( assets/fonts/bricolage-grotesque-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Bricolage Grotesque'; src: url( assets/fonts/bricolage-grotesque-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'DM Sans'; src: url( assets/fonts/dm-sans-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'DM Sans'; src: url( assets/fonts/dm-sans-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'DM Sans'; src: url( assets/fonts/dm-sans-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'DM Sans'; src: url( assets/fonts/dm-sans-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Inter'; src: url( assets/fonts/inter-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url( assets/fonts/inter-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Inter'; src: url( assets/fonts/inter-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Inter'; src: url( assets/fonts/inter-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Nunito Sans'; src: url( assets/fonts/nunito-sans-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Nunito Sans'; src: url( assets/fonts/nunito-sans-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Nunito Sans'; src: url( assets/fonts/nunito-sans-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Nunito Sans'; src: url( assets/fonts/nunito-sans-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }

@font-face { font-family: 'Work Sans'; src: url( assets/fonts/work-sans-latin-400-normal.woff2 ) format('woff2'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'Work Sans'; src: url( assets/fonts/work-sans-latin-400-italic.woff2 ) format('woff2'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'Work Sans'; src: url( assets/fonts/work-sans-latin-500-normal.woff2 ) format('woff2'); font-weight: 500; font-style: normal; font-display: swap; }
@font-face { font-family: 'Work Sans'; src: url( assets/fonts/work-sans-latin-700-normal.woff2 ) format('woff2'); font-weight: 700; font-style: normal; font-display: swap; }


/* --------------------------------------------------------------------------
   3. Les teintes dérivées
   --------------------------------------------------------------------------
   Le branding reste à cinq couleurs : le thème n'en réclame aucune de plus,
   il les MÉLANGE. Un aplat clair est la couleur primaire diluée dans le
   fond, un filet est le texte dilué dans le fond. L'école change une
   couleur, tout le système suit.

   Deux règles de lisibilité, valables quelle que soit la palette saisie :

   1. `--ecole-accent` et `--ecole-secondaire` ne portent JAMAIS de texte
      courant sur le fond clair. Une menthe sur ivoire plafonne à 1,7:1.
      Elles servent d'aplat, de marque, de soulignement — et de texte
      uniquement sur l'aplat sombre.
   2. Un libellé posé sur `--ecole-secondaire` ou `--ecole-accent` prend
      `--ecole-texte` ; posé sur `--ecole-primaire`, il prend `--ecole-fond`.
      Cela suppose une primaire sombre et une secondaire claire, ce que le
      modèle n'impose pas : c'est la seule hypothèse de couleur du thème, et
      elle est écrite ici plutôt que devinée à la lecture.
   -------------------------------------------------------------------------- */

:root {
	/* Repli sans mélange : plat, mais jamais faux. */
	--aplat:         var( --ecole-fond );
	--aplat-fort:    var( --ecole-fond );
	--pastel-vert:   var( --ecole-fond );
	--pastel-menthe: var( --ecole-fond );
	--pastel-accent: var( --ecole-fond );
	--sur-sombre:    var( --ecole-fond );
	--texte-doux:    var( --ecole-texte );
	--filet:         var( --ecole-secondaire );
	--voile:         var( --ecole-primaire );
}

@supports ( color: color-mix( in oklab, #000, #fff ) ) {
	:root {
		--aplat:      color-mix( in oklab, var( --ecole-primaire ) 4%,  var( --ecole-fond ) );
		--aplat-fort: color-mix( in oklab, var( --ecole-primaire ) 11%, var( --ecole-fond ) );

		/* Les trois pastels. Chacun est une des couleurs de l'école DILUÉE
		   dans son fond, jamais une teinte inventée : le branding reste à
		   cinq couleurs, et une école qui change son vert change toute la
		   gamme d'un coup. Diluer vers le fond donne toujours un pastel,
		   quelle que soit la couleur saisie — même très sombre, même très
		   saturée. Le texte encre y garde plus de 15:1. */
		--pastel-vert:   color-mix( in oklab, var( --ecole-primaire ) 7%,   var( --ecole-fond ) );
		--pastel-menthe: color-mix( in oklab, var( --ecole-secondaire ) 13%, var( --ecole-fond ) );
		--pastel-accent: color-mix( in oklab, var( --ecole-accent ) 13%,     var( --ecole-fond ) );

		--sur-sombre: color-mix( in oklab, var( --ecole-fond ) 90%, var( --ecole-primaire ) );
		--texte-doux: color-mix( in oklab, var( --ecole-texte ) 68%, var( --ecole-fond ) );
		--filet:      color-mix( in oklab, var( --ecole-texte ) 14%, var( --ecole-fond ) );
		--voile:      color-mix( in oklab, var( --ecole-primaire ) 82%, transparent );
	}
}


/* --------------------------------------------------------------------------
   4. Les trois échelles fermées
   -------------------------------------------------------------------------- */

:root {
	/* Rayons. Six valeurs, et rien entre les deux. L'ancien site en portait
	   sept sans lien entre elles — 10, 12, 20, 30, 45, 80, 150 — et c'est
	   exactement ce que cette échelle remplace. */
	--r-1:        10px;   /* champs de formulaire, puces, marques */
	--r-2:        16px;   /* image dans une grille, vignette */
	--r-3:        24px;   /* carte, panneau */
	--r-4:        32px;   /* grande surface, bande pleine largeur */
	--r-pilule:   999px;  /* tout ce qui se clique */
	--r-petale:   clamp( 56px, 9vw, 128px );  /* l'angle ouvert des bandes */
	--r-petale-c: clamp( 36px, 6vw, 76px );   /* l'angle ouvert des cartes */

	/* Espacement. Base 8, plus trois crans de section : liaison, standard,
	   moment. Un seul cran partout est reconnaissable — et c'est bien le
	   problème. */
	--sp-1: 0.25rem;
	--sp-2: 0.5rem;
	--sp-3: 0.75rem;
	--sp-4: 1rem;
	--sp-5: 1.5rem;
	--sp-6: 2rem;
	--sp-7: 3rem;
	--sp-8: 4rem;
	--sp-section-s: clamp( 2.75rem, 5vw,  4rem );
	--sp-section-m: clamp( 4rem,    8vw,  6.5rem );
	--sp-section-l: clamp( 5.5rem,  11vw, 9rem );

	/* Mesures. La largeur de référence est celle du CONTENU, pas de la boîte :
	   tous les thèmes sont en `border-box`, et un `max-width: 71.25rem` avec
	   le rembourrage dedans rendrait 1060 px de contenu à 1440, pas 1140.
	   La même valeur écrite au même endroit n'aurait donc pas donné la même
	   mesure. Largeur et gouttière ne sont pas au catalogue des
	   différenciateurs : trois valeurs communes à tout le parc. */
	--largeur:   71.25rem;
	--gouttiere: clamp( 1.25rem, 4vw, 2.5rem );
	--mesure:    62ch;

	/* La marque des liens de téléchargement, en masque sur `currentColor`.
	   Tracé Phosphor « download-simple », identique à celui du jeu d'icônes
	   PHP : le masque CSS ne sait pas lire un SVG inline. */
	--marque-telechargement: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M224%2C144v64a8%2C8%2C0%2C0%2C1-8%2C8H40a8%2C8%2C0%2C0%2C1-8-8V144a8%2C8%2C0%2C0%2C1%2C16%2C0v56H208V144a8%2C8%2C0%2C0%2C1%2C16%2C0Zm-101.66%2C5.66a8%2C8%2C0%2C0%2C0%2C11.32%2C0l40-40a8%2C8%2C0%2C0%2C0-11.32-11.32L136%2C124.69V32a8%2C8%2C0%2C0%2C0-16%2C0v92.69L93.66%2C98.34a8%2C8%2C0%2C0%2C0-11.32%2C11.32Z'/%3E%3C/svg%3E" );

	/* Typographie. Rapport voisin de 1,22 au palier haut. */
	--t-hero:    clamp( 2.375rem, 1.55rem + 3.4vw,  3.9rem );
	--t-h2:      clamp( 1.75rem,  1.3rem  + 1.85vw, 2.6rem );
	--t-h3:      clamp( 1.3rem,   1.15rem + 0.6vw,  1.65rem );
	--t-h4:      clamp( 1.1rem,   1.03rem + 0.3vw,  1.3rem );
	--t-corps:   1.0625rem;
	--t-petit:   0.9375rem;
	--t-micro:   0.8125rem;
	--t-chiffre: clamp( 2.25rem,  1.6rem  + 2.6vw,  3.4rem );

	/* Mouvement. Une seule courbe, une seule durée. */
	--transition: 180ms cubic-bezier( 0.16, 1, 0.3, 1 );
	--entete-h:   72px;
}


/* --------------------------------------------------------------------------
   5. Base
   -------------------------------------------------------------------------- */

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

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: calc( var( --entete-h ) + var( --sp-4 ) );
}

body {
	margin: 0;
	background: var( --ecole-fond );
	color: var( --ecole-texte );
	font-family: var( --ecole-font-texte );
	font-size: var( --t-corps );
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
	overflow-x: clip;
}

img,
svg,
video { display: block; max-width: 100%; }

img { height: auto; }

figure { margin: 0; }

/* Aucun ratio d'image n'est garanti : beaucoup de photos sont des captures
   verticales prises au téléphone. Tout conteneur impose donc le sien. */
.media { position: relative; overflow: hidden; background: var( --aplat ); }
.media img { width: 100%; height: 100%; object-fit: cover; }

.media--portrait { aspect-ratio: 4 / 5; }
.media--paysage  { aspect-ratio: 16 / 10; }
.media--carre    { aspect-ratio: 1 / 1; }
.media--large    { aspect-ratio: 21 / 9; }

/* Le repli d'image : un aplat traversé d'une marque discrète, pour qu'un
   cadre vide ne ressemble jamais à une panne de chargement. */
.media--vide {
	background:
		radial-gradient( circle at 50% 42%, var( --aplat-fort ) 0 38%, transparent 38% ),
		var( --aplat );
}

.ico {
	width: 1em;
	height: 1em;
	flex: none;
	vertical-align: -0.125em;
}

::selection {
	background: var( --ecole-secondaire );
	color: var( --ecole-texte );
}

:focus-visible {
	outline: 2px solid var( --ecole-texte );
	outline-offset: 3px;
	border-radius: 4px;
}

.saut-contenu {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: var( --sp-3 ) var( --sp-5 );
	background: var( --ecole-primaire );
	color: var( --ecole-fond );
	border-radius: 0 0 var( --r-2 ) 0;
}
.saut-contenu:focus { left: 0; }


/* --------------------------------------------------------------------------
   6. Typographie
   -------------------------------------------------------------------------- */

h1, h2, h3, h4, h5, h6 {
	margin: 0;
	font-family: var( --ecole-font-titre );
	font-weight: 600;
	line-height: 1.15;
	letter-spacing: -0.015em;
	text-wrap: balance;
}

h1 { font-size: var( --t-hero ); }
h2 { font-size: var( --t-h2 ); line-height: 1.18; }
h3 { font-size: var( --t-h3 ); line-height: 1.3; letter-spacing: -0.01em; }
h4 { font-size: var( --t-h4 ); line-height: 1.35; letter-spacing: 0; }
h5, h6 { font-size: var( --t-corps ); line-height: 1.4; letter-spacing: 0; }

p { margin: 0 0 var( --sp-4 ); }
p:last-child { margin-bottom: 0; }

.mesure { max-width: var( --mesure ); }

/* Le sur-titre. Ce thème n'en pose qu'UN par page, sur le héro ou la
   bannière : un libellé capitale au-dessus de chaque section produit le
   même rythme partout, et c'est la signature la plus reconnaissable d'une
   page composée machinalement. */
.surtitre {
	margin: 0 0 var( --sp-3 );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-micro );
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var( --texte-doux );
}
.surtitre::after {
	content: "";
	display: inline-block;
	width: 1.6em;
	height: 2px;
	margin-left: 0.7em;
	vertical-align: 0.25em;
	background: var( --ecole-accent );
}

.intro {
	max-width: var( --mesure );
	font-size: clamp( var( --t-corps ), 0.98rem + 0.35vw, 1.2rem );
	color: var( --texte-doux );
}

.legende {
	font-size: var( --t-petit );
	color: var( --texte-doux );
}

/* Le texte riche vient d'un `wysiwyg` : il arrive avec ses propres balises,
   et il faut donc styler ce que l'école a écrit, pas ce qu'on avait prévu. */
.riche > *:first-child { margin-top: 0; }
.riche > *:last-child  { margin-bottom: 0; }
.riche h2, .riche h3, .riche h4 { margin: var( --sp-6 ) 0 var( --sp-3 ); }
.riche ul, .riche ol { margin: 0 0 var( --sp-4 ); padding-left: 1.35em; }
.riche li { margin-bottom: var( --sp-2 ); }
.riche ul { list-style: none; padding-left: 0; }
.riche ul li { position: relative; padding-left: 1.5em; }
.riche ul li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.62em;
	width: 8px;
	height: 8px;
	border-radius: 999px 2px 999px 999px;
	background: var( --ecole-secondaire );
}
.riche blockquote {
	margin: var( --sp-6 ) 0;
	padding-left: var( --sp-5 );
	border-left: 3px solid var( --ecole-secondaire );
	font-size: var( --t-h4 );
	font-style: italic;
}
.riche img { border-radius: var( --r-2 ); margin: var( --sp-5 ) 0; }
.riche table { width: 100%; border-collapse: collapse; margin: var( --sp-5 ) 0; }
.riche th, .riche td { padding: var( --sp-3 ); text-align: left; border-bottom: 1px solid var( --filet ); }


/* --------------------------------------------------------------------------
   7. Liens
   --------------------------------------------------------------------------
   Le lien courant garde la couleur du texte et prend un soulignement à la
   couleur secondaire. C'est le point de lisibilité le plus rentable du
   thème : la teinte reste présente, le contraste ne dépend plus d'elle.
   -------------------------------------------------------------------------- */

a { color: inherit; }

.riche a,
.lien-texte {
	text-decoration: underline;
	text-decoration-color: var( --ecole-secondaire );
	text-decoration-thickness: 2px;
	text-underline-offset: 0.18em;
	transition: text-decoration-color var( --transition );
}
.riche a:hover,
.lien-texte:hover { text-decoration-color: currentColor; }

/* Le lien de section, celui qui emmène ailleurs. La flèche avance au
   survol : c'est le seul mouvement de la page qui dise une direction. */
.lien-fleche {
	display: inline-flex;
	align-items: center;
	gap: var( --sp-2 );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
	text-decoration: none;
	color: var( --ecole-texte );
}
.lien-fleche .ico { transition: transform var( --transition ); }
.lien-fleche:hover .ico { transform: translateX( 4px ); }


/* --------------------------------------------------------------------------
   8. Boutons
   --------------------------------------------------------------------------
   Une seule géométrie, trois variantes, deux tailles. L'ancien site en
   portait deux géométries : 15/32 dans le héro, 11/16 dans l'en-tête, pour
   le même composant.

   Cible tactile de 48 px sur la taille normale, 40 px sur la petite —
   au-dessous, un doigt manque le bouton une fois sur cinq.
   -------------------------------------------------------------------------- */

.bouton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var( --sp-2 );
	min-height: 48px;
	padding: 0.8125rem 1.5rem;
	border: 2px solid transparent;
	border-radius: var( --r-pilule );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color var( --transition ), color var( --transition ), transform var( --transition ), border-color var( --transition );
}

.bouton:active { transform: translateY( 1px ); }

.bouton--plein {
	background: var( --ecole-secondaire );
	color: var( --ecole-texte );
	border-color: var( --ecole-secondaire );
}
.bouton--plein:hover {
	background: var( --ecole-primaire );
	border-color: var( --ecole-primaire );
	color: var( --ecole-fond );
}

.bouton--sombre {
	background: var( --ecole-primaire );
	color: var( --ecole-fond );
	border-color: var( --ecole-primaire );
}
.bouton--sombre:hover {
	background: var( --ecole-secondaire );
	border-color: var( --ecole-secondaire );
	color: var( --ecole-texte );
}

.bouton--fantome {
	background: transparent;
	color: currentColor;
	border-color: currentColor;
}
.bouton--fantome:hover {
	background: var( --ecole-texte );
	border-color: var( --ecole-texte );
	color: var( --ecole-fond );
}

.bouton--petit {
	min-height: 40px;
	padding: 0.5rem 1.125rem;
	font-size: var( --t-micro );
}

/* La flèche avance au survol. C'est le seul mouvement du thème qui dise une
   direction, et il ne sert donc qu'aux boutons qui emmènent ailleurs. */
.bouton .ico { transition: transform var( --transition ); }
.bouton:hover .ico { transform: translateX( 3px ); }

.boutons {
	display: flex;
	flex-wrap: wrap;
	gap: var( --sp-3 );
}
.boutons--centre { justify-content: center; }

/* Sur l'aplat sombre, le bouton fantôme s'inverse : sans cette
   redéclaration il peindrait du sombre sur du sombre au survol, et un
   libellé invisible ressemble à un libellé absent. */
.sombre .bouton--fantome:hover {
	background: var( --ecole-fond );
	border-color: var( --ecole-fond );
	color: var( --ecole-primaire );
}


/* --------------------------------------------------------------------------
   9. Mise en page
   -------------------------------------------------------------------------- */

.contenant {
	width: 100%;
	max-width: calc( var( --largeur ) + 2 * var( --gouttiere ) );
	margin-inline: auto;
	padding-inline: var( --gouttiere );
}

@media ( min-width: 1440px ) {
	:root { --gouttiere: 3rem; }
}

.section { padding-block: var( --sp-section-m ); }
.section--liaison { padding-block: var( --sp-section-s ); }
.section--moment  { padding-block: var( --sp-section-l ); }

/* L'alternance de fond ne s'écrit pas en dur : une section vide ne se rend
   pas, et un rang codé en dur se décale dès qu'une école laisse un bloc
   vide. Le gabarit demande la classe à un compteur qui n'avance qu'au
   rendu réel. */
.section--aplat  { background: var( --aplat ); }
.section--vert   { background: var( --pastel-vert ); }
.section--menthe { background: var( --pastel-menthe ); }

.section-entete {
	max-width: var( --mesure );
	margin-bottom: var( --sp-7 );
}
.section-entete > * + * { margin-top: var( --sp-4 ); }

/* La bande sombre. Elle renverse le rapport clair/sombre en REDÉCLARANT
   les variables plutôt qu'en surchargeant les règles : une teinte juste sur
   fond clair devient illisible sur aplat profond, et corriger règle par
   règle laisse toujours un composant derrière. */
.sombre {
	background: var( --ecole-primaire );
	color: var( --sur-sombre );
	--aplat:      color-mix( in oklab, var( --ecole-fond ) 10%, var( --ecole-primaire ) );
	--aplat-fort: color-mix( in oklab, var( --ecole-fond ) 18%, var( --ecole-primaire ) );
	--texte-doux: color-mix( in oklab, var( --ecole-fond ) 72%, var( --ecole-primaire ) );
	--filet:      color-mix( in oklab, var( --ecole-fond ) 22%, var( --ecole-primaire ) );
}
.sombre .surtitre::after { background: var( --ecole-secondaire ); }


/* --------------------------------------------------------------------------
   10. La règle du pétale
   --------------------------------------------------------------------------
   UN angle ouvert par bloc, trois angles discrets. La position vient du
   rôle :

   - une bande pleine largeur ouvre en HAUT À DROITE, comme une page qu'on
     soulève ;
   - les cartes d'une même série ouvrent toutes du MÊME côté, ce qui fait
     lire la rangée comme un ensemble et non comme trois objets ;
   - dans un duo texte + image, l'image ouvre du côté EXTÉRIEUR, à l'opposé
     du texte ;
   - le pied de page ferme la lecture : il ouvre en HAUT À GAUCHE, en miroir
     de la première bande.

   Aucune règle ne nomme un rang. Un rang se revérifie à chaque école, un
   bord jamais.
   -------------------------------------------------------------------------- */

.petale     { border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 ); }
.petale--hg { border-radius: var( --r-petale-c ) var( --r-3 ) var( --r-3 ) var( --r-3 ); }
.petale--bd { border-radius: var( --r-3 ) var( --r-3 ) var( --r-petale-c ) var( --r-3 ); }
.petale--bg { border-radius: var( --r-3 ) var( --r-3 ) var( --r-3 ) var( --r-petale-c ); }

.petale-bande     { border-radius: var( --r-4 ) var( --r-petale ) var( --r-4 ) var( --r-4 ); }
.petale-bande--bd { border-radius: var( --r-4 ) var( --r-4 ) var( --r-petale ) var( --r-4 ); }

/* Deux cas d'ouverture partielle : une image posée en tête de carte
   n'arrondit que ses deux angles hauts, et le pied de page n'arrondit que
   les siens. */
.petale-haut { border-radius: var( --r-3 ) var( --r-petale-c ) 0 0; }
.petale-pied { border-radius: var( --r-petale ) var( --r-4 ) 0 0; }


/* --------------------------------------------------------------------------
   11. Bandeau d'alerte
   -------------------------------------------------------------------------- */

.alerte {
	background: var( --ecole-accent );
	color: var( --ecole-texte );
	font-size: var( --t-petit );
}
.alerte .contenant {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var( --sp-2 ) var( --sp-4 );
	padding-block: var( --sp-3 );
	text-align: center;
}
.alerte p { margin: 0; }
.alerte a {
	font-weight: 700;
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.18em;
}


/* --------------------------------------------------------------------------
   12. En-tête et navigation
   -------------------------------------------------------------------------- */

.entete {
	position: sticky;
	top: 0;
	z-index: 40;
	background: var( --ecole-fond );
	border-bottom: 1px solid transparent;
	transition: border-color var( --transition ), background-color var( --transition );
}
.entete[data-defile="oui"] { border-bottom-color: var( --filet ); }

.entete .contenant {
	display: flex;
	align-items: center;
	gap: var( --sp-5 );
	min-height: var( --entete-h );
}

.marque {
	display: flex;
	align-items: center;
	gap: var( --sp-3 );
	text-decoration: none;
	margin-right: auto;
}
/* Le plafond du logo se pose ICI et dans le panneau mobile. Posé d'un seul
   côté, il a déjà laissé un logo occuper tout l'écran du téléphone. */
.marque img {
	width: auto;
	max-height: 48px;
	max-width: 200px;
	object-fit: contain;
}
.marque-nom {
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: -0.01em;
}

.nav { display: none; }

@media ( min-width: 1024px ) {
	.nav { display: block; }
	.nav ul {
		display: flex;
		align-items: center;
		gap: var( --sp-1 );
		margin: 0;
		padding: 0;
		list-style: none;
	}
	.nav li { position: relative; }
	.nav a {
		display: block;
		padding: var( --sp-2 ) var( --sp-4 );
		border-radius: var( --r-pilule );
		font-family: var( --ecole-font-titre );
		font-size: var( --t-petit );
		font-weight: 500;
		text-decoration: none;
		white-space: nowrap;
		transition: background-color var( --transition );
	}
	.nav a:hover,
	.nav .current-menu-item > a,
	.nav .current-menu-ancestor > a { background: var( --aplat ); }

	/* Le panneau de sous-menu s'ancre sur le bord DROIT de sa rubrique. Un
	   pont invisible couvre le vide au-dessus, sans quoi la diagonale de la
	   souris referme le menu avant d'y arriver. */
	.nav .sub-menu {
		position: absolute;
		top: calc( 100% + var( --sp-3 ) );
		right: 0;
		left: auto;
		z-index: 2;
		display: block;
		min-width: 15rem;
		padding: var( --sp-3 );
		background: var( --ecole-fond );
		border: 1px solid var( --filet );
		border-radius: var( --r-2 ) var( --r-2 ) var( --r-2 ) var( --r-3 );
		box-shadow: 0 18px 40px -24px var( --voile );
		opacity: 0;
		visibility: hidden;
		transform: translateY( -6px );
		transition: opacity var( --transition ), transform var( --transition ), visibility 0s linear 200ms;
	}
	.nav li:hover > .sub-menu,
	.nav li:focus-within > .sub-menu {
		opacity: 1;
		visibility: visible;
		transform: none;
		transition-delay: 0s;
	}
	.nav li:has( .sub-menu )::after {
		content: "";
		position: absolute;
		top: 100%;
		right: 0;
		width: 15rem;
		height: var( --sp-4 );
	}
	.nav .sub-menu ul { display: block; }
	.nav .sub-menu li { width: 100%; }
	.nav .sub-menu a {
		padding: var( --sp-2 ) var( --sp-3 );
		border-radius: var( --r-1 );
		font-weight: 400;
		white-space: normal;
	}
}

.bascule-menu {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	padding: 0;
	background: var( --aplat );
	border: 0;
	border-radius: var( --r-pilule );
	color: inherit;
	font-size: 1.25rem;
	cursor: pointer;
}
@media ( min-width: 1024px ) { .bascule-menu { display: none; } }

.entete .bouton { display: none; }
@media ( min-width: 560px ) { .entete .bouton { display: inline-flex; } }

/* Le panneau mobile. La grande cible emmène ailleurs, le chevron explore —
   jamais l'inverse : c'est le geste sûr qui doit être le grand. */
.panneau {
	position: fixed;
	inset: 0;
	z-index: 50;
	display: flex;
	flex-direction: column;
	padding: var( --sp-5 ) var( --gouttiere ) var( --sp-8 );
	background: var( --ecole-fond );
	overflow-y: auto;
	overscroll-behavior: contain;
}
.panneau[hidden] { display: none !important; }
.panneau-haut {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var( --sp-4 );
	margin-bottom: var( --sp-6 );
}
.panneau-haut img { max-height: 44px; max-width: 170px; width: auto; object-fit: contain; }
.panneau ul { margin: 0; padding: 0; list-style: none; }
.panneau > nav > ul > li { border-bottom: 1px solid var( --filet ); }
.panneau > nav > ul > li > a {
	display: block;
	padding: var( --sp-4 ) 0;
	font-family: var( --ecole-font-titre );
	font-size: var( --t-h3 );
	font-weight: 600;
	text-decoration: none;
}
.panneau .sub-menu { padding: 0 0 var( --sp-4 ) var( --sp-4 ); }
.panneau .sub-menu a {
	display: block;
	padding: var( --sp-2 ) 0;
	color: var( --texte-doux );
	text-decoration: none;
}
.panneau-pied { margin-top: var( --sp-7 ); }


/* --------------------------------------------------------------------------
   13. Héro
   -------------------------------------------------------------------------- */

.hero { padding-block: var( --sp-5 ) var( --sp-section-m ); }

/* La scène : la photo EST le fond, le contenu se pose dessus. C'est la
   disposition du site d'origine et la seule que l'école reconnaisse.
   `isolation: isolate` ouvre un contexte d'empilement local, ce qui permet
   à la photo et au voile de vivre en z-index négatif sans jamais passer
   sous l'en-tête collant. */
.hero-scene {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: grid;
	align-items: end;
	min-height: clamp( 420px, 72svh, 620px );
}

.hero-fond {
	position: absolute;
	inset: 0;
	z-index: -2;
	background: none;
}

/* Le voile garantit le contraste quelle que soit la photo : claire, sombre
   ou à contre-jour. Sans lui, la lisibilité du titre dépendrait du cliché
   déposé par l'école, donc de rien. Il est presque opaque en bas, où le
   texte se pose, et s'ouvre vers le haut pour laisser voir la scène. */
/* Les paliers ne sont pas choisis à l'œil : ils sont calculés sur le PIRE
   cas, une photo presque blanche. Le contenu se pose en bas et occupe les
   70 % inférieurs de la scène, où le voile ne descend jamais sous 70 % de
   la primaire. Sur un cliché à 85 % de blanc, cela laisse 5,9:1 pour un
   texte ivoire. Un voile réglé sur une belle photo sombre ne dit rien de
   celle que l'école déposera l'an prochain. */
.hero-voile {
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var( --ecole-primaire );
	opacity: 0.7;
}

@supports ( color: color-mix( in oklab, #000, #fff ) ) {
	.hero-voile {
		opacity: 1;
		background: linear-gradient(
			to top,
			color-mix( in oklab, var( --ecole-primaire ) 92%, transparent ) 0%,
			color-mix( in oklab, var( --ecole-primaire ) 84%, transparent ) 50%,
			color-mix( in oklab, var( --ecole-primaire ) 62%, transparent ) 82%,
			color-mix( in oklab, var( --ecole-primaire ) 40%, transparent ) 100%
		);
	}
}

/* Le rembourrage bas ajoute la hauteur dont le bandeau de statut remonte,
   plus un cran. Sans cela, les boutons se retrouvaient à 16 px du bandeau
   qui leur passe devant : ils avaient l'air posés dessus. */
.hero-contenu {
	position: relative;
	padding: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
	padding-bottom: calc( clamp( var( --sp-6 ), 5vw, var( --sp-8 ) ) + var( --sp-7 ) + var( --sp-4 ) );
	max-width: 52rem;
}
.hero-contenu > * + * { margin-top: var( --sp-4 ); }

/* AUCUNE largeur maximale sur le nom de l'école.
   Un `max-width: 17ch` coupait « École Saint-Joseph » en deux alors que la
   ligne tenait largement. Un nom court reste sur une ligne, un nom long
   revient à la ligne tout seul et `text-wrap: balance` équilibre les deux
   lignes. *Une contrainte de largeur posée pour un cas long abîme tous les
   cas courts, qui sont la majorité.* */
.hero-contenu .boutons { margin-top: var( --sp-6 ); }

/* Le sur-titre reste ivoire, et c'est le tiret qui porte la menthe.
   Une menthe pâlie donnait 4,05:1 sur une photo claire — sous le seuil, pour
   du 13 px. Le rappel de couleur ne vaut pas un libellé qu'on devine. */
.hero-contenu .surtitre { color: var( --sur-sombre ); }
.hero-contenu .surtitre::after { background: var( --ecole-secondaire ); }

.hero-accroche {
	max-width: 46ch;
	font-size: clamp( var( --t-corps ), 0.98rem + 0.35vw, 1.2rem );
}

/* Le bandeau de statut, qui déborde sur le bas de la photo. Il ferme le
   groupe du héro : son angle ouvert est en bas à droite, en diagonale de
   celui de la scène. */
.bandeau-statut {
	position: relative;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --sp-4 ) var( --sp-5 );
	width: min( 100%, 58rem );
	margin: calc( -1 * var( --sp-7 ) ) auto 0;
	padding: var( --sp-5 ) clamp( var( --sp-5 ), 4vw, var( --sp-7 ) );
	background: var( --ecole-fond );
	border: 1px solid var( --filet );
	font-size: var( --t-petit );
	color: var( --texte-doux );
}
.bandeau-logo img {
	max-height: 48px;
	max-width: 150px;
	width: auto;
	object-fit: contain;
}
.bandeau-statut p { flex: 1 1 18rem; }


/* --------------------------------------------------------------------------
   14. Les chiffres
   --------------------------------------------------------------------------
   Une bande, pas des cartes : quatre boîtes encadrées pour quatre nombres
   ajoutent trois traits et zéro information.
   -------------------------------------------------------------------------- */

.chiffres {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 150px, 1fr ) );
	gap: var( --sp-6 ) var( --sp-5 );
	padding: var( --sp-7 ) clamp( var( --sp-5 ), 5vw, var( --sp-8 ) );
	background: var( --pastel-accent );
}
.chiffre-valeur {
	display: block;
	font-family: var( --ecole-font-titre );
	font-size: var( --t-chiffre );
	font-weight: 600;
	line-height: 1;
	letter-spacing: -0.03em;
}
.chiffre-libelle {
	display: block;
	margin-top: var( --sp-2 );
	font-size: var( --t-petit );
	color: var( --texte-doux );
}


/* --------------------------------------------------------------------------
   15. Le duo texte et image
   -------------------------------------------------------------------------- */

.duo {
	display: grid;
	gap: var( --sp-6 );
	align-items: center;
}
/* Deux colonnes à partir de 1024, pas de 768.
   À 768, le duo donnait 375 px de texte contre 277 px d'image : côte à côte
   à cette mesure, une image et un texte se lisent MOINS bien qu'empilés. Un
   palier ne se choisit pas par arrondi au plus proche. */
@media ( min-width: 1024px ) {
	.duo { grid-template-columns: 1fr 1fr; gap: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) ); }
	.duo--texte-large { grid-template-columns: 1.15fr 0.85fr; }
	.duo--media-large { grid-template-columns: 0.8fr 1.2fr; align-items: start; }
	/* Le duo inversé permute les colonnes sans toucher à l'ordre du
	   balisage : la lecture au clavier et au lecteur d'écran reste celle du
	   document. */
	.duo--inverse > :first-child { order: 2; }
}
.duo-texte > * + * { margin-top: var( --sp-4 ); }
.duo-texte .boutons { margin-top: var( --sp-6 ); }
.duo-media { aspect-ratio: 4 / 3; }
@media ( min-width: 1024px ) { .duo-media { aspect-ratio: 5 / 6; } }


/* --------------------------------------------------------------------------
   16. La grille des valeurs
   --------------------------------------------------------------------------
   Pas trois cartes identiques alignées. La première valeur porte l'image et
   occupe deux pistes ; les suivantes sont des tuiles compactes. Le nombre
   de cellules est exactement le nombre de valeurs remplies — une case vide
   au milieu d'une grille est une grille mal pensée, pas un espace.
   -------------------------------------------------------------------------- */

.valeurs {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 240px, 1fr ) );
	gap: var( --sp-5 );
}
.valeur {
	display: flex;
	flex-direction: column;
	gap: var( --sp-3 );
	padding: var( --sp-6 );
	background: var( --ecole-fond );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.valeur h3 { font-size: var( --t-h4 ); }
.valeur p { color: var( --texte-doux ); font-size: var( --t-petit ); }
.valeur-icone {
	display: grid;
	place-items: center;
	width: 56px;
	height: 56px;
	margin-bottom: var( --sp-2 );
	background: var( --ecole-secondaire );
	border-radius: var( --r-pilule ) var( --r-1 ) var( --r-pilule ) var( --r-pilule );
	overflow: hidden;
}
.valeur-icone img { width: 60%; height: 60%; object-fit: contain; }

/* La valeur en vedette porte sa photo et renverse le rapport clair/sombre.
   Ces règles valent DÈS le petit écran : posées dans la media query, elles
   auraient laissé sur mobile une image pleine largeur rembourrée de 2 rem
   à l'intérieur d'un aplat clair. */
.valeur--vedette {
	padding: 0;
	overflow: hidden;
	background: var( --ecole-primaire );
	color: var( --sur-sombre );
	--texte-doux: color-mix( in oklab, var( --ecole-fond ) 74%, var( --ecole-primaire ) );
}
.valeur--vedette .valeur-media { aspect-ratio: 16 / 10; }
.valeur--vedette .valeur-corps { display: grid; gap: var( --sp-3 ); padding: var( --sp-6 ); }
.valeur--vedette p { color: var( --texte-doux ); }

/* La grille en six pistes n'entre qu'à 1024 : à 768 elle produisait des
   tuiles de 285 px dont 190 px de texte utile. En dessous, `auto-fit` fait
   le travail et donne deux colonnes franches. */
@media ( min-width: 1024px ) {
	.valeurs--riche { grid-template-columns: repeat( 6, 1fr ); }
	.valeurs--riche > .valeur { grid-column: span 2; }
	.valeurs--riche > .valeur--vedette { grid-column: span 2; grid-row: span 2; }
}

/* La dernière rangée se remplit.
   Quatre tuiles bordent la vedette, les suivantes vont par trois. À huit
   entrées le compte tombait juste ; à douze, depuis que « Nos
   spécificités » en porte douze (DECISIONS.md, 13 septembre 2026), la
   dernière restait seule devant deux tiers de vide. Les tuiles de la
   dernière rangée prennent donc la place qui reste : seule, toute la
   rangée ; à deux, la moitié chacune. À trois et quatre entrées, la vedette
   n'est bordée que d'une rangée et demie, et la tuile du bas s'étire. */
@media ( min-width: 1024px ) {
	.valeurs--riche > .valeur:nth-child( 3n ):last-child:not( :nth-child( 3 ) ) { grid-column: span 6; }

	.valeurs--riche > .valeur:nth-child( 3n ):nth-last-child( 2 ):not( :nth-child( 3 ) ),
	.valeurs--riche > .valeur:nth-child( 3n + 1 ):last-child:not( :nth-child( 4 ) ) { grid-column: span 3; }

	.valeurs--riche > .valeur:nth-child( 2 ):nth-last-child( 2 ),
	.valeurs--riche > .valeur:nth-child( 3 ):last-child,
	.valeurs--riche > .valeur:nth-child( 4 ):last-child { grid-column: span 4; }
}

/* Une tuile élargie ne l'est que pour la grille : son texte garde la mesure
   de lecture. */
.valeur .riche,
.valeur p { max-width: var( --mesure ); }


/* --------------------------------------------------------------------------
   17. Le mot du chef d'établissement
   -------------------------------------------------------------------------- */

/* Le panneau du mot tient dans la largeur du site, il ne va PAS d'un bord à
   l'autre. Pleine largeur, l'aplat profond écrasait la page et cassait
   l'alignement de toutes les sections voisines : la seule bande qui traverse
   l'écran de bout en bout est le pied, parce qu'elle ferme la lecture. */
.mot {
	overflow: hidden;
	padding: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
}
.mot-grille {
	display: grid;
	gap: var( --sp-6 );
	align-items: start;
}
@media ( min-width: 1024px ) {
	.mot-grille { grid-template-columns: 300px 1fr; gap: var( --sp-8 ); align-items: center; }
}
.mot-portrait {
	width: 100%;
	max-width: 300px;
	aspect-ratio: 1 / 1;
	border-radius: 999px 999px 999px var( --r-4 );
}
.mot-texte { font-size: clamp( var( --t-corps ), 0.98rem + 0.35vw, 1.2rem ); }
.mot-signature { margin-top: var( --sp-6 ); }
.mot-signature img { max-height: 64px; width: auto; opacity: 0.9; }
.mot-nom {
	margin-top: var( --sp-4 );
	font-family: var( --ecole-font-titre );
	font-weight: 600;
}
.mot-fonction { font-size: var( --t-petit ); color: var( --texte-doux ); }


/* --------------------------------------------------------------------------
   18. Cartes d'actualité
   -------------------------------------------------------------------------- */

.cartes {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 270px, 1fr ) );
	gap: var( --sp-5 );
}
/* Même plafond, même motif : une actualité seule s'étalait sur 1140 px et
   sa vignette en 3/2 montait à 760 px de haut. */
.carte {
	display: flex;
	flex-direction: column;
	max-width: 420px;
	background: var( --pastel-menthe );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
	overflow: hidden;
	transition: transform var( --transition );
}
.carte:hover { transform: translateY( -3px ); }
.carte-media { aspect-ratio: 3 / 2; }
.carte-corps {
	display: flex;
	flex-direction: column;
	gap: var( --sp-3 );
	padding: var( --sp-5 );
	flex: 1;
}
.carte h3 { font-size: var( --t-h4 ); }
.carte-date {
	font-size: var( --t-micro );
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var( --texte-doux );
}
.carte-extrait { font-size: var( --t-petit ); color: var( --texte-doux ); }
/* Le titre porte le lien, la carte entière l'étend. Un seul lien dans
   l'arbre, donc une seule tabulation et un seul libellé annoncé. */
.carte-lien { text-decoration: none; }
.carte-lien::after { content: ""; position: absolute; inset: 0; }
.carte { position: relative; }


/* --------------------------------------------------------------------------
   19. Le diaporama de la galerie
   --------------------------------------------------------------------------
   Sans JavaScript la scène reste une piste défilante et toutes les photos
   sont atteignables : une galerie qui disparaît faute de script serait un
   défaut bien pire que l'absence d'animation.

   La lecture automatique s'arrête au survol, au focus clavier, quand
   l'onglet passe en arrière-plan, quand le bloc sort de l'écran, et ne
   démarre pas du tout sous `prefers-reduced-motion`.
   -------------------------------------------------------------------------- */

.galerie-panneau {
	padding: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
	background: var( --pastel-menthe );
}

.section-entete--centre {
	margin-inline: auto;
	text-align: center;
}
.section-entete--centre .intro { margin-inline: auto; }

.diaporama { position: relative; }

/* SANS SCRIPT : la scène est une grille, toutes les photos sont là, chacune
   avec sa légende. Une galerie qui disparaît faute de script serait un
   défaut bien pire que l'absence d'animation. */
.diaporama-scene {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 200px, 1fr ) );
	gap: var( --sp-5 );
}
.diaporama-cadre {
	aspect-ratio: 4 / 3;
	border-radius: var( --r-2 ) var( --r-petale-c ) var( --r-2 ) var( --r-2 );
}
.diaporama-legende {
	margin-top: var( --sp-3 );
	font-size: var( --t-petit );
	color: var( --texte-doux );
	transition: opacity var( --transition );
}

/* AVEC SCRIPT : la pile.
   Une photo en grand, les deux suivantes rangées derrière elle, décalées
   vers la droite et rapetissées. Passer à la suivante fait glisser celle de
   devant vers l'arrière de la pile pendant que la suivante prend sa place.

   Pas une once de rotation, et c'est délibéré : le tirage posé de travers
   appartient à Marelle. Pétale range ses photos droites, et c'est l'angle
   ouvert répété trois fois sur le bord droit qui signe la pile. */
.diaporama[data-pile] .diaporama-scene {
	display: block;
	position: relative;
	height: clamp( 300px, 46vw, 560px );
}
.diaporama[data-pile] .diaporama-vue {
	position: absolute;
	inset: 0;
	display: grid;
	grid-template-rows: 1fr auto;
	gap: var( --sp-3 );
	transform-origin: 50% 55%;
	transition: transform 520ms cubic-bezier( 0.16, 1, 0.3, 1 ), opacity 380ms linear;
}
.diaporama[data-pile] .diaporama-cadre { height: 100%; aspect-ratio: auto; }
.diaporama[data-pile] .diaporama-vue:not( [data-rang="0"] ) { pointer-events: none; }
.diaporama[data-pile] .diaporama-vue:not( [data-rang="0"] ) .diaporama-legende { opacity: 0; }

/* Les décalages sont bornés par le rembourrage du panneau, pas choisis à
   l'œil. Une vue à `translateX(15%) scale(0.88)` dépasse de 9 % de sa
   largeur, soit 91 px sur un panneau qui n'en rembourre que 64 : la pile
   sortait du cadre. À 9 %, le dépassement retombe à 3 %, et la pile tient
   dans son panneau à tous les paliers. */
.diaporama[data-pile] .diaporama-vue[data-rang="0"]    { transform: none;                          opacity: 1;    z-index: 4; }
.diaporama[data-pile] .diaporama-vue[data-rang="1"]    { transform: translateX( 5% )  scale( 0.94 ); opacity: 0.55; z-index: 3; }
.diaporama[data-pile] .diaporama-vue[data-rang="2"]    { transform: translateX( 9% )  scale( 0.88 ); opacity: 0.28; z-index: 2; }
.diaporama[data-pile] .diaporama-vue[data-rang="fond"] { transform: translateX( 12% ) scale( 0.84 ); opacity: 0;    z-index: 1; }

@media ( prefers-reduced-motion: reduce ) {
	.diaporama[data-pile] .diaporama-vue { transition: none; }
}

.diaporama-barre {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var( --sp-4 );
	margin-top: var( --sp-5 );
}
/* Sans script elle reste vide : elle ne doit alors rien occuper du tout. */
.diaporama-barre:empty { display: none; }
.diaporama-bouton {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	flex: none;
	background: transparent;
	border: 2px solid var( --filet );
	border-radius: var( --r-pilule );
	color: inherit;
	cursor: pointer;
	transition: background-color var( --transition ), border-color var( --transition ), transform var( --transition );
}
.diaporama-bouton:hover { background: var( --ecole-secondaire ); border-color: var( --ecole-secondaire ); color: var( --ecole-texte ); }
.diaporama-bouton:active { transform: scale( 0.94 ); }
.diaporama-bouton .ico { font-size: 1.15rem; }
.diaporama-bouton[data-va="precedent"] .ico { transform: rotate( 180deg ); }

/* Les pastilles sont posées par le script, pas par le gabarit : sans lui
   elles ne mèneraient nulle part, et une commande morte est pire qu'une
   commande absente. */
.diaporama-points {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 2px;
}
.diaporama-point {
	display: grid;
	place-items: center;
	width: 26px;
	height: 44px;
	padding: 0;
	background: none;
	border: 0;
	cursor: pointer;
}
.diaporama-point::before {
	content: "";
	width: 10px;
	height: 10px;
	border-radius: 999px 2px 999px 999px;
	background: var( --filet );
	transition: background-color var( --transition ), width var( --transition );
}
.diaporama-point:hover::before { background: var( --texte-doux ); }
.diaporama-point[aria-current="true"]::before {
	width: 26px;
	background: var( --ecole-secondaire );
}

/* Sur le petit écran, huit pastilles plus deux flèches ne tiennent pas sur
   la largeur : elles passaient à la ligne. On resserre plutôt que de les
   laisser se replier. Au-delà de huit photos, le repli reprend, et c'est
   le bon comportement — un rang de pastilles illisible ne sert personne. */
@media ( max-width: 559.98px ) {
	.diaporama-barre { gap: var( --sp-2 ); }
	.diaporama-points { gap: 0; }
	.diaporama-point { width: 20px; }
	.diaporama-point[aria-current="true"]::before { width: 20px; }
}


/* --------------------------------------------------------------------------
   20. Témoignages
   -------------------------------------------------------------------------- */

.temoignages {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 280px, 1fr ) );
	gap: var( --sp-5 );
}
.temoignage {
	display: flex;
	flex-direction: column;
	gap: var( --sp-4 );
	padding: var( --sp-6 );
	background: var( --pastel-accent );
	border-radius: var( --r-petale-c ) var( --r-3 ) var( --r-3 ) var( --r-3 );
}
.temoignage-guillemet {
	font-size: 1.75rem;
	line-height: 1;
	color: var( --ecole-secondaire );
}
.temoignage p { font-size: var( --t-petit ); }
.temoignage-auteur {
	margin-top: auto;
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
}
.temoignage-date { font-size: var( --t-micro ); color: var( --texte-doux ); }
.note { display: flex; gap: 3px; color: var( --ecole-accent ); }
.note span { width: 10px; height: 10px; border-radius: 999px 2px 999px 999px; background: currentColor; }
.note span[data-vide="oui"] { background: var( --filet ); }


/* --------------------------------------------------------------------------
   21. Accordéon
   --------------------------------------------------------------------------
   `<details>` passe de `display: none` à `block` d'un coup : le script
   reprend la main sur l'ouverture pour interpoler la hauteur, et le CSS
   doit donc laisser le panneau mesurable.
   -------------------------------------------------------------------------- */

.accordeon { border-top: 1px solid var( --filet ); }
.accordeon details { border-bottom: 1px solid var( --filet ); }
.accordeon summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var( --sp-4 );
	padding: var( --sp-5 ) 0;
	font-family: var( --ecole-font-titre );
	font-size: var( --t-h4 );
	font-weight: 600;
	cursor: pointer;
	list-style: none;
}
.accordeon summary::-webkit-details-marker { display: none; }
.accordeon summary .ico {
	flex: none;
	font-size: 1.25rem;
	color: var( --texte-doux );
	transition: transform var( --transition );
}
.accordeon details[open] summary .ico { transform: rotate( 180deg ); }
.accordeon-corps { overflow: hidden; }
.accordeon details[data-anime] .accordeon-corps { transition: height 260ms cubic-bezier( 0.16, 1, 0.3, 1 ); }
.accordeon-corps > div { padding-bottom: var( --sp-5 ); max-width: var( --mesure ); }


/* --------------------------------------------------------------------------
   22. Panneaux, coordonnées, documents
   -------------------------------------------------------------------------- */

.panneau-plat {
	padding: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
	background: var( --pastel-vert );
	border-radius: var( --r-4 ) var( --r-petale ) var( --r-4 ) var( --r-4 );
}
.panneau-plat.sombre { background: var( --ecole-primaire ); }
.panneau-plat--formulaire { background: var( --ecole-fond ); }

.coordonnees { display: grid; gap: var( --sp-4 ); margin: 0; padding: 0; list-style: none; }
.coordonnees li { display: flex; align-items: flex-start; gap: var( --sp-3 ); }
.coordonnees .ico { margin-top: 0.3em; font-size: 1.15rem; color: var( --ecole-secondaire ); }
.coordonnees a { text-decoration: none; }
.coordonnees a:hover { text-decoration: underline; text-underline-offset: 0.18em; }

/* `ecole_document_lien()` échappe son libellé : aucune icône ne peut y être
   glissée, elle s'afficherait en toutes lettres. La marque se pose donc en
   CSS, et sur l'attribut `download` plutôt que sur une classe — tous les
   liens de fichier le portent, d'où qu'ils viennent. En masque sur
   `currentColor` elle reste juste sur l'ivoire comme sur l'aplat profond ;
   sous `@supports`, faute de quoi un navigateur sans masque peint un carré
   plein. Une icône absente passe inaperçue, un carré noir non. */
.documents { display: grid; gap: var( --sp-3 ); margin: 0; padding: 0; list-style: none; }
.documents li {
	display: flex;
	align-items: center;
	gap: var( --sp-3 );
	padding: var( --sp-4 ) var( --sp-5 );
	background: var( --aplat );
	border-radius: var( --r-1 ) var( --r-3 ) var( --r-1 ) var( --r-1 );
}
.documents a { text-decoration: none; font-weight: 500; }
.documents a:hover { text-decoration: underline; text-underline-offset: 0.18em; }

@supports ( mask-image: url( "" ) ) or ( -webkit-mask-image: url( "" ) ) {
	a[download]::before {
		content: "";
		display: inline-block;
		width: 1.05em;
		height: 1.05em;
		margin-right: 0.45em;
		vertical-align: -0.16em;
		background: currentColor;
		-webkit-mask: var( --marque-telechargement ) center / contain no-repeat;
		mask: var( --marque-telechargement ) center / contain no-repeat;
	}
}


/* --------------------------------------------------------------------------
   23. Formulaires
   --------------------------------------------------------------------------
   Contact Form 7, habillé par SES classes et jamais par celles d'un
   gabarit. Le gabarit est une donnée du site : le plugin pose le sien sur
   un site neuf, Barcelonnette nomme ses champs autrement, Pélissanne a le
   sien (DECISIONS.md, 13 septembre 2026). Cette section habillait `.champ`
   et `.b-form__duo`, deux classes d'un gabarit qu'aucun site ne porte plus :
   aucune de ses règles n'atteignait les champs du formulaire français.

   Ce qui suit ne connaît que ce que CF7 écrit lui-même : `.wpcf7-form`, le
   `label` qui enveloppe le champ, `.wpcf7-form-control`, le bouton, la
   bulle d'erreur et le message de retour. Seule exception, `.yk-duo`, que
   le plugin pose pour réunir les deux champs courts ; sans elle, un champ
   par ligne, ce qui reste juste.
   -------------------------------------------------------------------------- */

/* Le formulaire se rythme par l'écart de sa grille, pas par les marges des
   paragraphes que CF7 ajoute autour de chaque ligne : le dernier paragraphe
   d'un groupe perd la sienne, et deux champs se seraient touchés. */
.formulaire .wpcf7-form,
.formulaire .yk-duo {
	display: grid;
	gap: var( --sp-5 );
}
.formulaire .wpcf7-form p { margin: 0; }

/* Deux champs courts sur une ligne à partir de 560 px, et non 600 : le jeu
   de points de rupture du parc est fermé, 560 / 768 / 1024 / 1440
   (DECISIONS.md). La v1.8.3 avait posé un 600 px inédit, que
   `verifier-css.py` a signalé dès qu'on l'a relancé. *Un contrôle qu'on
   n'exécute pas ne trouve rien.* */
@media ( min-width: 560px ) {
	.formulaire .yk-duo { grid-template-columns: 1fr 1fr; }
}

.formulaire .wpcf7-form label {
	display: grid;
	gap: var( --sp-2 );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
}
/* CF7 place un saut de ligne entre le libellé et son champ : la grille
   l'espace déjà. */
.formulaire .wpcf7-form label br { display: none; }

.formulaire input.wpcf7-form-control:not( .wpcf7-submit ),
.formulaire textarea.wpcf7-form-control,
.formulaire select.wpcf7-form-control {
	width: 100%;
	padding: 0.875rem 1.125rem;
	background: var( --ecole-fond );
	border: 2px solid var( --filet );
	border-radius: var( --r-1 );
	font-family: var( --ecole-font-texte );
	font-size: var( --t-corps );
	font-weight: 400;
	line-height: 1.4;
	color: var( --ecole-texte );
	transition: border-color var( --transition );
}
.formulaire textarea.wpcf7-form-control {
	height: 10rem;
	min-height: 7rem;
	resize: vertical;
	border-radius: var( --r-1 ) var( --r-3 ) var( --r-1 ) var( --r-1 );
}
.formulaire .wpcf7-form-control::placeholder { color: var( --texte-doux ); opacity: 1; }

/* Un champ refusé prend le filet d'accent. L'accent ne porte jamais le
   texte de l'erreur : sur le fond clair, il plafonne sous le seuil. Le
   focus est déclaré APRÈS, pour qu'un champ refusé que l'on corrige
   montre où l'on écrit. */
.formulaire input.wpcf7-form-control[aria-invalid="true"],
.formulaire textarea.wpcf7-form-control[aria-invalid="true"],
.formulaire select.wpcf7-form-control[aria-invalid="true"] { border-color: var( --ecole-accent ); }

.formulaire input.wpcf7-form-control:not( .wpcf7-submit ):focus,
.formulaire textarea.wpcf7-form-control:focus,
.formulaire select.wpcf7-form-control:focus { border-color: var( --ecole-texte ); outline: none; }

.formulaire .wpcf7-form-control-wrap { display: block; }

/* La bulle d'erreur : du texte encre, et un pétale d'accent pour la
   repérer. Elle était écrite EN accent, la couleur qui ne porte jamais de
   texte sur le fond clair (§3). */
.formulaire .wpcf7-not-valid-tip {
	display: flex;
	align-items: center;
	gap: var( --sp-2 );
	margin-top: var( --sp-2 );
	font-family: var( --ecole-font-texte );
	font-size: var( --t-micro );
	font-weight: 600;
	color: var( --ecole-texte );
}
.formulaire .wpcf7-not-valid-tip::before {
	content: "";
	flex: none;
	width: 8px;
	height: 8px;
	border-radius: 999px 2px 999px 999px;
	background: var( --ecole-accent );
}

/* Le message de retour.
   La feuille de CF7 (6.1.7), chargée avant celle-ci, pèse une balise de
   plus : `.wpcf7 form .wpcf7-response-output` vaut (0,2,1), ses états
   (0,3,1). Écrites à deux classes, les règles du thème perdaient sans
   bruit, et le message gardait les marges et le filet bleu, vert ou jaune
   de l'extension. D'où `.wpcf7-form` en plus. Le `display` reste à CF7,
   qui cache le message tant que rien n'est parti. */
.formulaire .wpcf7-form .wpcf7-response-output {
	margin: 0;
	padding: var( --sp-4 ) var( --sp-5 );
	background: var( --ecole-fond );
	border: 2px solid var( --ecole-secondaire );
	border-radius: var( --r-1 ) var( --r-3 ) var( --r-1 ) var( --r-1 );
	font-size: var( --t-petit );
	color: var( --ecole-texte );
}
.formulaire .wpcf7-form.sent .wpcf7-response-output { border-color: var( --ecole-secondaire ); }
.formulaire .wpcf7-form.invalid .wpcf7-response-output,
.formulaire .wpcf7-form.unaccepted .wpcf7-response-output,
.formulaire .wpcf7-form.payment-required .wpcf7-response-output,
.formulaire .wpcf7-form.failed .wpcf7-response-output,
.formulaire .wpcf7-form.aborted .wpcf7-response-output,
.formulaire .wpcf7-form.spam .wpcf7-response-output { border-color: var( --ecole-accent ); }

/* Le bouton d'envoi reprend `.bouton--sombre`, sans pouvoir en porter la
   classe : c'est CF7 qui écrit le `<input type="submit">`. */
.formulaire .wpcf7-submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	width: auto;
	padding: 0.8125rem 1.5rem;
	background: var( --ecole-primaire );
	color: var( --ecole-fond );
	border: 2px solid var( --ecole-primaire );
	border-radius: var( --r-pilule );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
	line-height: 1.2;
	vertical-align: middle;
	cursor: pointer;
	transition: background var( --transition ), border-color var( --transition ), color var( --transition );
}
.formulaire .wpcf7-submit:hover {
	background: var( --ecole-secondaire );
	border-color: var( --ecole-secondaire );
	color: var( --ecole-texte );
}
.formulaire .wpcf7-submit:active { transform: translateY( 1px ); }
.formulaire .wpcf7-spinner { margin-left: var( --sp-3 ); vertical-align: middle; }


/* --------------------------------------------------------------------------
   24. Sommaire de page
   -------------------------------------------------------------------------- */

.sommaire {
	display: flex;
	flex-wrap: wrap;
	gap: var( --sp-2 );
	margin: 0;
	padding: 0;
	list-style: none;
}
.sommaire a {
	display: inline-block;
	padding: var( --sp-2 ) var( --sp-4 );
	background: var( --aplat );
	border-radius: var( --r-pilule );
	font-size: var( --t-petit );
	text-decoration: none;
	transition: background-color var( --transition );
}
.sommaire a:hover { background: var( --ecole-secondaire ); color: var( --ecole-texte ); }


/* --------------------------------------------------------------------------
   25. Bannière de page interne
   -------------------------------------------------------------------------- */

/* La bannière reprend la scène du héro, en plus bas : même voile, même
   angle ouvert, même texte ivoire. Une page interne ouverte depuis le menu
   doit se reconnaître d'un coup d'œil comme faisant partie du même site.

   Le titre y prend l'échelle H2, jamais celle du héro : *un titre d'article
   est une phrase, un titre de page une étiquette* — ils ne peuvent pas
   partager la même taille. */
.banniere { padding-block: var( --sp-5 ) var( --sp-section-s ); }
.banniere-scene {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: grid;
	align-items: end;
	min-height: clamp( 260px, 34svh, 380px );
}
.banniere-scene h1 { font-size: var( --t-h2 ); max-width: 20ch; }

/* Le voile du héro est calculé pour une scène de 620 px, où le texte occupe
   les 70 % inférieurs. La bannière fait 357 px pour le même texte : le
   sur-titre y monte à 82 % de la hauteur, donc PILE sur le palier à 62 %,
   là où le héro lui en donnait encore 66. Mesuré sur les photos de
   Pélissanne : 4,32:1 sur la cour, 4,38:1 sur la mosaïque — sous AA, alors
   que le héro tient 5,11:1 sur la même palette.

   *Un voile réglé en pourcentages de la scène ne garantit rien quand la
   scène change de hauteur.* La bannière reprend donc les mêmes paliers,
   redistribués sur SA hauteur : sous le texte, le voile ne descend jamais
   sous 72 % de la primaire, ce qui tient 5:1 même sur un pixel blanc. */
.banniere-scene .hero-voile {
	background: var( --ecole-primaire );
	opacity: 0.72;
}

@supports ( color: color-mix( in oklab, #000, #fff ) ) {
	.banniere-scene .hero-voile {
		opacity: 1;
		background: linear-gradient(
			to top,
			color-mix( in oklab, var( --ecole-primaire ) 92%, transparent ) 0%,
			color-mix( in oklab, var( --ecole-primaire ) 82%, transparent ) 55%,
			color-mix( in oklab, var( --ecole-primaire ) 72%, transparent ) 85%,
			color-mix( in oklab, var( --ecole-primaire ) 52%, transparent ) 100%
		);
	}
}


/* --------------------------------------------------------------------------
   26. Équipe
   -------------------------------------------------------------------------- */

/* La piste s'étire, la FICHE non.
   `auto-fit` donne toute la largeur au groupe qui ne compte qu'un membre, et
   comme le portrait est carré, sa largeur commande sa hauteur : une direction
   seule rendait un portrait de 1140 px de haut, et la page entière se lisait
   comme un accident. Le plafond est posé sur la fiche, pas sur la piste :
   la rangée pleine reste répartie, la fiche seule reste une fiche. */
.equipe {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 190px, 1fr ) );
	gap: var( --sp-5 );
}
.membre {
	display: flex;
	flex-direction: column;
	gap: var( --sp-3 );
	max-width: 280px;
}
.membre-photo { aspect-ratio: 1 / 1; border-radius: 999px 999px 999px var( --r-4 ); }
.membre-nom { font-family: var( --ecole-font-titre ); font-weight: 600; }
.membre-role { font-size: var( --t-petit ); color: var( --texte-doux ); }
/* Sans aucun portrait dans le groupe : des fiches nom + rôle, posées sur le
   fond comme les cartes d'une série — l'angle ouvert toutes du même côté.
   `auto-fill`, pas `auto-fit` : une direction seule reste une fiche. */
.equipe--fiches {
	grid-template-columns: repeat( auto-fill, minmax( 210px, 1fr ) );
	gap: var( --sp-3 );
}
.equipe--fiches .membre {
	max-width: none;
	gap: var( --sp-1 );
	padding: var( --sp-4 ) var( --sp-5 );
	background: var( --ecole-fond );
	border-radius: var( --r-2 ) var( --r-petale-c ) var( --r-2 ) var( --r-2 );
}
.equipe-groupe + .equipe-groupe { margin-top: var( --sp-7 ); }
.equipe-groupe h3 { margin-bottom: var( --sp-5 ); }


/* --------------------------------------------------------------------------
   27. Pied de page
   -------------------------------------------------------------------------- */

.pied {
	margin-top: var( --sp-section-m );
	background: var( --ecole-primaire );
	color: var( --sur-sombre );
	border-radius: var( --r-petale ) var( --r-4 ) 0 0;
	--filet:      color-mix( in oklab, var( --ecole-fond ) 22%, var( --ecole-primaire ) );
	--texte-doux: color-mix( in oklab, var( --ecole-fond ) 72%, var( --ecole-primaire ) );
}
.pied-grille {
	display: grid;
	gap: var( --sp-7 );
	padding-block: var( --sp-section-m ) var( --sp-6 );
}
@media ( min-width: 768px ) { .pied-grille { grid-template-columns: 1.4fr 1fr 1fr; } }
.pied h2, .pied h3 { font-size: var( --t-h4 ); margin-bottom: var( --sp-4 ); }
.pied ul { margin: 0; padding: 0; list-style: none; display: grid; gap: var( --sp-3 ); }
.pied a { text-decoration: none; }
.pied a:hover { text-decoration: underline; text-underline-offset: 0.18em; }
.pied-logo img { max-height: 64px; max-width: 190px; width: auto; object-fit: contain; }
.pied-accroche { color: var( --texte-doux ); max-width: 34ch; margin-top: var( --sp-4 ); }

.reseaux { display: flex; gap: var( --sp-3 ); margin-top: var( --sp-5 ); }
.reseaux a {
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	border: 1px solid var( --filet );
	border-radius: var( --r-pilule );
	font-size: 1.1rem;
	transition: background-color var( --transition ), color var( --transition );
}
.reseaux a:hover { background: var( --ecole-secondaire ); color: var( --ecole-texte ); border-color: var( --ecole-secondaire ); }

/* Les mêmes ronds dans la barre, aux couleurs du bouton qu'ils
   remplacent — `.bouton--sombre` : plein primaire, encre claire, survol
   qui bascule au secondaire. Sans la marge du pied, et d'un cran plus
   petits : la barre fait 72 px, trois ronds de 44 l'auraient remplie
   bord à bord. */
.reseaux--entete { margin-top: 0; gap: var( --sp-2 ); }
.reseaux--entete a {
	width: 40px;
	height: 40px;
	background: var( --ecole-primaire );
	border-color: var( --ecole-primaire );
	color: var( --ecole-fond );
}
.reseaux--entete a:hover {
	background: var( --ecole-secondaire );
	border-color: var( --ecole-secondaire );
	color: var( --ecole-texte );
}

/* Dans le panneau, ils occupent la ligne que le bouton pleine largeur
   laissait : le pied du panneau porte déjà sa marge haute. */
.panneau-pied .reseaux { margin-top: 0; }

.partenaires {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --sp-5 ) var( --sp-6 );
	padding-block: var( --sp-6 );
	border-top: 1px solid var( --filet );
}
.partenaires img {
	max-height: 44px;
	max-width: 130px;
	width: auto;
	object-fit: contain;
}

.pied-bas {
	display: flex;
	flex-wrap: wrap;
	gap: var( --sp-3 ) var( --sp-5 );
	justify-content: space-between;
	padding-block: var( --sp-5 ) var( --sp-6 );
	border-top: 1px solid var( --filet );
	font-size: var( --t-micro );
	color: var( --texte-doux );
}


/* --------------------------------------------------------------------------
   28. Article
   -------------------------------------------------------------------------- */

.article-entete { padding-block: var( --sp-7 ) var( --sp-6 ); }
/* Un titre d'article est une phrase, un titre de page une étiquette : ils
   ne peuvent pas partager la même échelle. */
.article-entete h1 { font-size: var( --t-h2 ); max-width: 24ch; letter-spacing: -0.02em; }
.article-media { aspect-ratio: 16 / 9; }
.article-corps { max-width: var( --mesure ); margin-inline: auto; }
.article-corps > * + * { margin-top: var( --sp-4 ); }


/* --------------------------------------------------------------------------
   29. Les composants des pages internes
   -------------------------------------------------------------------------- */

/* La frise de l'histoire. Une seule colonne, un filet vertical, l'année en
   regard : c'est la forme qui dit « dans l'ordre » sans l'écrire. */
.frise { display: grid; gap: 0; }
.frise-etape {
	display: grid;
	gap: var( --sp-2 ) var( --sp-5 );
	padding: var( --sp-5 ) 0 var( --sp-5 ) var( --sp-6 );
	border-left: 2px solid var( --filet );
	position: relative;
}
.frise-etape::before {
	content: "";
	position: absolute;
	left: -7px;
	top: calc( var( --sp-5 ) + 0.45em );
	width: 12px;
	height: 12px;
	border-radius: 999px 2px 999px 999px;
	background: var( --ecole-secondaire );
}
.frise-etape:last-child { border-left-color: transparent; }
.frise-annee {
	font-family: var( --ecole-font-titre );
	font-size: var( --t-h4 );
	font-weight: 600;
	line-height: 1.2;
}
.frise-texte { color: var( --texte-doux ); }
@media ( min-width: 768px ) {
	.frise-etape { grid-template-columns: 7rem 1fr; align-items: baseline; }
}

/* Les fiches de projet : un résumé en page ET le PDF. Le titre porte le
   lien de téléchargement quand il y a un fichier, rien sinon — une fiche
   sans document reste un texte, pas un lien mort. */
.fiches {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 260px, 1fr ) );
	gap: var( --sp-5 );
}
.fiche {
	display: flex;
	flex-direction: column;
	gap: var( --sp-3 );
	padding: var( --sp-6 );
	background: var( --ecole-fond );
	border: 1px solid var( --filet );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.fiche h3 { font-size: var( --t-h4 ); }
.fiche-corps { color: var( --texte-doux ); font-size: var( --t-petit ); }
.fiche-lien { margin-top: auto; padding-top: var( --sp-3 ); }

/* Les projets institutionnels — UN PAR RANGÉE.
 *
 * Ils étaient rendus en `.fiches`, donc côte à côte. Ce composant avait
 * été réglé sur un résumé de trois lignes plus un PDF, et il reçoit de 400
 * à 600 mots par projet : trois colonnes de 400 px pour un texte pareil,
 * cela fait des lignes de trente-cinq signes sur deux mètres de haut.
 * *Ce n'est pas le texte qui est trop long, c'est la forme qui suppose
 * qu'il est court.*
 *
 * Même surface que `.fiche` et le MÊME angle ouvert, en haut à droite :
 * les cartes d'une même série ouvrent toutes du même côté. Seule la piste
 * change. */
.projets { display: grid; gap: var( --sp-5 ); }
.projet {
	padding: clamp( var( --sp-6 ), 4vw, var( --sp-7 ) );
	background: var( --ecole-fond );
	border: 1px solid var( --filet );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.projet h3 { font-size: var( --t-h3 ); }
.projet-chapo { margin-top: var( --sp-4 ); max-width: var( --mesure ); }

/* Le repli. `<details>` natif : le texte reste dans le document même
   fermé, donc indexé et trouvable par la recherche du navigateur, et la
   page fonctionne sans JavaScript.

   Le libellé est en texte courant, pas en `--t-h4` : il ne doit pas
   disputer sa place au titre du projet, juste au-dessus. */
.projet-detail { margin-top: var( --sp-5 ); }
.projet-detail summary {
	display: inline-flex;
	align-items: center;
	gap: var( --sp-2 );
	/* 44 px de haut : la cible mesurait 41 px avec le seul rembourrage du
	   texte. Un contrôle qu'on rate au doigt n'est pas un contrôle. */
	min-height: 44px;
	padding: var( --sp-2 ) 0;
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
	color: var( --texte-doux );
	cursor: pointer;
	list-style: none;
	transition: color var( --transition );
}
.projet-detail summary::-webkit-details-marker { display: none; }
.projet-detail summary:hover { color: var( --ecole-texte ); }
.projet-detail summary .ico {
	flex: none;
	font-size: 1.125rem;
	transition: transform var( --transition );
}
.projet-detail[open] summary .ico { transform: rotate( 180deg ); }

/* Un seul des deux libellés à la fois. Le second existe parce qu'« ouvrir »
   et « replier » ne se disent pas avec le même mot, et qu'un bouton dont le
   texte ne change pas quand l'état change ment sur l'état. */
.projet-fermer { display: none; }
.projet-detail[open] .projet-ouvrir { display: none; }
.projet-detail[open] .projet-fermer { display: inline; }

.projet-suite {
	max-width: var( --mesure );
	padding-top: var( --sp-4 );
	border-top: 1px solid var( --filet );
	margin-top: var( --sp-3 );
}
.projet-lien { margin-top: var( --sp-5 ); }

/* Les tableaux de données : tarifs, calendrier, menu. Un filet SOUS chaque
   ligne et rien d'autre. Un filet au-dessus ET au-dessous de chaque rangée
   double les traits sans rien séparer de plus. */
.tableau { width: 100%; border-collapse: collapse; }
.tableau caption {
	text-align: left;
	padding-bottom: var( --sp-4 );
	color: var( --texte-doux );
	font-size: var( --t-petit );
}
.tableau th,
.tableau td {
	padding: var( --sp-4 ) var( --sp-3 );
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var( --filet );
}
.tableau th {
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 600;
}
.tableau tbody th { font-weight: 600; }
.tableau td:last-child,
.tableau th:last-child { text-align: right; }
.tableau-montant {
	font-family: var( --ecole-font-titre );
	font-weight: 600;
	white-space: nowrap;
}
.tableau-precision {
	display: block;
	font-family: var( --ecole-font-texte );
	font-weight: 400;
	font-size: var( --t-micro );
	color: var( --texte-doux );
}
/* Un tableau large ne fait jamais défiler la PAGE : il défile dans sa
   propre boîte. */
.tableau-boite { overflow-x: auto; }

/* Les horaires, une colonne par niveau. */
.horaires {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 240px, 1fr ) );
	gap: var( --sp-5 );
}
.horaire {
	padding: var( --sp-6 );
	background: var( --pastel-menthe );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.horaire h3 { font-size: var( --t-h4 ); margin-bottom: var( --sp-4 ); }
.horaire dl { display: grid; gap: var( --sp-3 ); margin: 0; }
.horaire .ligne {
	display: flex;
	justify-content: space-between;
	gap: var( --sp-4 );
	padding-bottom: var( --sp-3 );
	border-bottom: 1px solid var( --filet );
}
.horaire .ligne:last-child { border-bottom: 0; padding-bottom: 0; }
.horaire dt { color: var( --texte-doux ); font-size: var( --t-petit ); }
.horaire dd { margin: 0; font-family: var( --ecole-font-titre ); font-weight: 600; white-space: nowrap; }

/* L'agenda : une date en regard, pas une carte. Douze événements en douze
   cartes feraient une page de boîtes. */
.agenda { display: grid; gap: 0; }
.agenda-item {
	display: grid;
	gap: var( --sp-2 ) var( --sp-5 );
	padding-block: var( --sp-5 );
	border-bottom: 1px solid var( --filet );
}
.agenda-item:last-child { border-bottom: 0; }
@media ( min-width: 768px ) {
	.agenda-item { grid-template-columns: 12rem 1fr auto; align-items: start; }
}
.agenda-date {
	font-family: var( --ecole-font-titre );
	font-weight: 600;
	font-size: var( --t-petit );
}
.agenda-texte { color: var( --texte-doux ); font-size: var( --t-petit ); }
.agenda-media { width: 100%; max-width: 9rem; aspect-ratio: 4 / 3; border-radius: var( --r-1 ) var( --r-2 ) var( --r-1 ) var( --r-1 ); }

/* Les étapes d'une procédure. Le rang est la seule information que la
   forme doit porter — pas un libellé « Étape 1 » qui répète le chiffre. */
.etapes { display: grid; gap: var( --sp-5 ); counter-reset: petale-etape; }
@media ( min-width: 768px ) { .etapes { grid-template-columns: repeat( auto-fit, minmax( 260px, 1fr ) ); } }
.etape {
	display: grid;
	gap: var( --sp-3 );
	padding: var( --sp-6 );
	background: var( --pastel-vert );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
	counter-increment: petale-etape;
}
.etape::before {
	content: counter( petale-etape );
	display: grid;
	place-items: center;
	width: 44px;
	height: 44px;
	background: var( --ecole-primaire );
	color: var( --ecole-fond );
	border-radius: var( --r-pilule ) var( --r-1 ) var( --r-pilule ) var( --r-pilule );
	font-family: var( --ecole-font-titre );
	font-weight: 600;
}
.etape h3 { font-size: var( --t-h4 ); }
.etape p { color: var( --texte-doux ); font-size: var( --t-petit ); }

/* Le bandeau d'information : période d'inscription, message d'ouverture. */
.bandeau-info {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var( --sp-3 ) var( --sp-5 );
	padding: var( --sp-5 ) clamp( var( --sp-5 ), 4vw, var( --sp-7 ) );
	background: var( --ecole-secondaire );
	color: var( --ecole-texte );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.bandeau-info .ico { font-size: 1.35rem; flex: none; }
.bandeau-info p { flex: 1 1 16rem; }

/* La carte, chargée SUR DEMANDE.
   Une iframe Google posée d'office contacte un tiers avant que le visiteur
   n'ait rien demandé, et ce sont des sites d'écoles primaires. Le cadre
   reste donc vide jusqu'au clic, et le clic est annoncé. */
.carte-lieu {
	display: grid;
	place-items: center;
	align-content: center;
	gap: var( --sp-4 );
	padding: var( --sp-5 );
	text-align: center;
	background: var( --aplat );
	border: 1px dashed var( --filet );
	border-radius: var( --r-2 ) var( --r-petale-c ) var( --r-2 ) var( --r-2 );
	height: 24rem;
	min-width: 0;
	width: 100%;
}
.carte-lieu p { max-width: 34ch; margin: 0; color: var( --texte-doux ); font-size: var( --t-petit ); }
.carte-lieu iframe { display: block; width: 100%; height: 100%; border: 0; border-radius: inherit; }
.carte-lieu.est-chargee { display: block; padding: 0; border-style: solid; overflow: hidden; }

/* Le renvoi vers « Nos spécificités », sur l'accueil et sur Notre école.

   Il ANNONCE, la page détaille : un titre, une phrase au plus, quatre
   intitulés au plus et un lien qui nomme la page. Jamais les textes des
   entrées : ce serait recréer la section qui vient de quitter Notre école
   (DECISIONS.md, 13 septembre 2026). Il remplace ici les duos alternés de
   cette section, devenus morts avec elle.

   Un panneau menthe pâle dans la largeur du site, ouvert en haut à droite
   comme toute bande. Les intitulés forment une LISTE, pas des tuiles : rien
   n'y est cliquable, et une tuile promet un clic. Leur marque reprend la
   pastille de `.valeur-icone`, en plus petit ; sans icône, elle porte le
   pétale des listes et de la frise.

   À partir de 1024 px, le titre et le lien à gauche, la liste à droite. En
   dessous, la liste passe AVANT le lien : on voit ce qu'on va trouver, puis
   on y va. C'est l'ordre du balisage, donc aussi celui du clavier. */
.renvoi {
	display: grid;
	grid-template-areas: "entete" "liste" "lien";
	gap: var( --sp-6 );
	padding: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
	background: var( --pastel-menthe );
}
.renvoi-entete { grid-area: entete; }
.renvoi-entete > * + * { margin-top: var( --sp-4 ); }
.renvoi-liste {
	grid-area: liste;
	display: grid;
	gap: var( --sp-4 );
	margin: 0;
	padding: 0;
	list-style: none;
}
.renvoi-liste li {
	display: flex;
	align-items: center;
	gap: var( --sp-4 );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-h4 );
	font-weight: 600;
	line-height: 1.3;
	text-wrap: balance;
}
.renvoi-marque {
	display: grid;
	place-items: center;
	flex: none;
	width: 44px;
	height: 44px;
	background: var( --ecole-secondaire );
	border-radius: var( --r-pilule ) var( --r-1 ) var( --r-pilule ) var( --r-pilule );
	overflow: hidden;
}
.renvoi-marque img { width: 60%; height: 60%; object-fit: contain; }
.renvoi-marque--point::before {
	content: "";
	width: 10px;
	height: 10px;
	border-radius: 999px 2px 999px 999px;
	background: var( --ecole-fond );
}
.renvoi-lien { grid-area: lien; }
/* Le titre de la page est saisi par l'école : sur téléphone, un titre long
   revient à la ligne plutôt que de sortir du panneau. */
.renvoi .bouton { white-space: normal; }

@media ( min-width: 1024px ) {
	.renvoi {
		grid-template-columns: minmax( 0, 1fr ) minmax( 0, 1fr );
		grid-template-rows: auto 1fr;
		grid-template-areas: "entete liste" "lien liste";
		column-gap: clamp( var( --sp-6 ), 5vw, var( --sp-8 ) );
		align-items: start;
	}
	.renvoi-lien { align-self: end; }
	.renvoi .bouton { white-space: nowrap; }
}

/* Deux instances côte à côte : APEL et OGEC. */
.instances {
	display: grid;
	gap: var( --sp-5 );
}
@media ( min-width: 768px ) { .instances { grid-template-columns: 1fr 1fr; } }
.instance-logo img { max-height: 56px; max-width: 160px; width: auto; object-fit: contain; }
.instance-personnes { display: grid; gap: var( --sp-2 ); margin: 0; padding: 0; list-style: none; }
.instance-personnes li { display: flex; justify-content: space-between; gap: var( --sp-4 ); }
.instance-personnes span:first-child { color: var( --texte-doux ); font-size: var( --t-petit ); }
.instance-personnes span:last-child { font-family: var( --ecole-font-titre ); font-weight: 600; font-size: var( --t-petit ); }

/* Les documents, groupés par catégorie. Quinze lignes à filet plein sont
   la mise en page la plus paresseuse qui soit : on regroupe. */
.documents-groupe + .documents-groupe { margin-top: var( --sp-7 ); }
.documents-groupe h3 { font-size: var( --t-h4 ); margin-bottom: var( --sp-4 ); }

/* Les paires libellé / valeur servent aussi bien à une liste de personnes
   qu'à un menu de cantine : mêmes deux colonnes, même filet. */
.instance-personnes > div {
	display: flex;
	justify-content: space-between;
	gap: var( --sp-4 );
}
.instance-personnes dt { color: var( --texte-doux ); font-size: var( --t-petit ); }
.instance-personnes dd { margin: 0; font-family: var( --ecole-font-titre ); font-weight: 600; font-size: var( --t-petit ); text-align: right; }

.fiche h4 { font-size: var( --t-h4 ); }

/* Le menu de la semaine.
   Première version : libellé à gauche, plat à droite, `space-between`. Un
   plat de trois mots repassait à la ligne et s'alignait à droite en drapeau,
   sous un libellé resté à gauche. *Deux colonnes ne tiennent pas dans 220 px
   quand la valeur est une phrase.*

   Ici le libellé est POSÉ AU-DESSUS de son plat, tout à gauche, avec un
   filet entre les services. Rien ne se dispute la largeur, et la carte se
   lit comme une carte de restaurant. */
/* Menus de cantine, semaine par semaine : cinq au plus, une par onglet
   (DECISIONS.md, 12 septembre 2026). L'onglet se clique, donc il est en
   PILULE — le pétale reste aux blocs, il ne descend pas sur les commandes.
   Ivoire sur le vert pâle au repos, filet menthe au survol, et la semaine
   ouverte prend l'aplat du bouton sombre : primaire plein, encre claire.
   La menthe ne porte aucun mot : elle plafonne à 1,7:1 sur l'ivoire.

   SANS JAVASCRIPT, la rangée reste cachée et les semaines s'empilent sous
   leur titre. `petale-js` est posée sur `<html>` en tête de page, AVANT le
   premier rendu : le script, chargé en pied, replierait sinon sous les
   yeux du visiteur des semaines déjà peintes. */
.cantine-onglets { display: none; }
.petale-js .cantine-onglets {
	display: flex;
	gap: var( --sp-3 );
	overflow-x: auto;
	/* Le contour de focus sort de 5 px : une boîte qui défile le rognerait.
	   Le rembourrage lui laisse la place, la marge négative rend
	   l'alignement. */
	margin-inline: -0.375rem;
	padding: 0.375rem;
}
.cantine-onglet {
	flex: none;
	min-height: 44px;
	padding: 0.5rem 1.125rem;
	border: 2px solid transparent;
	border-radius: var( --r-pilule );
	background: var( --ecole-fond );
	color: var( --ecole-texte );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-micro );
	font-weight: 500;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color var( --transition ), border-color var( --transition ), color var( --transition );
}
.cantine-onglet:hover { border-color: var( --ecole-secondaire ); }
.cantine-onglet:active { transform: translateY( 1px ); }
.cantine-onglet[aria-selected="true"] {
	background: var( --ecole-primaire );
	border-color: var( --ecole-primaire );
	color: var( --ecole-fond );
}
.cantine-semaine__titre { margin: var( --sp-5 ) 0 0; }
.cantine-semaine + .cantine-semaine { margin-top: var( --sp-6 ); }
.petale-js .cantine-menus--onglets .cantine-semaine { margin-top: 0; }
.petale-js .cantine-menus--onglets .cantine-semaine__titre,
.petale-js .cantine-menus--onglets .cantine-semaine:not( .est-ouverte ) { display: none; }

.menu-semaine {
	display: grid;
	grid-template-columns: repeat( auto-fit, minmax( 210px, 1fr ) );
	gap: var( --sp-5 );
}
.menu-jour {
	display: flex;
	flex-direction: column;
	gap: var( --sp-4 );
	padding: var( --sp-6 );
	background: var( --ecole-fond );
	border-radius: var( --r-3 ) var( --r-petale-c ) var( --r-3 ) var( --r-3 );
}
.menu-jour h4 { font-size: var( --t-h3 ); }
.menu-plats {
	display: grid;
	gap: var( --sp-4 );
	margin: 0;
	padding: 0;
	list-style: none;
}
.menu-plat {
	padding-top: var( --sp-4 );
	border-top: 1px solid var( --filet );
	font-family: var( --ecole-font-titre );
	font-weight: 500;
	font-size: var( --t-petit );
	line-height: 1.35;
	text-wrap: balance;
}
.menu-plat:first-child { padding-top: 0; border-top: 0; }

/* Le titre d'une carte, quel que soit son rang de titre. L'accueil rend des
   `h3`, l'archive des `h2` : le RANG suit le plan du document, la TAILLE
   suit le composant. Les deux ne se commandent pas l'un l'autre. */
.carte-titre { font-size: var( --t-h4 ); }

.pagination {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var( --sp-2 );
}
.pagination .page-numbers {
	display: grid;
	place-items: center;
	min-width: 44px;
	height: 44px;
	padding-inline: var( --sp-3 );
	border-radius: var( --r-pilule );
	font-family: var( --ecole-font-titre );
	font-size: var( --t-petit );
	font-weight: 500;
	text-decoration: none;
	transition: background-color var( --transition );
}
.pagination a.page-numbers:hover { background: var( --aplat ); }
.pagination .page-numbers.current {
	background: var( --ecole-secondaire );
	color: var( --ecole-texte );
	font-weight: 600;
}


/* --------------------------------------------------------------------------
   30. Mouvement
   --------------------------------------------------------------------------
   AUCUNE apparition au défilement, et c'est une décision.

   Le site d'origine faisait entrer chaque bloc en fondu : la page restait
   blanche tant qu'on ne défilait pas. Une première version de Pétale a repris
   le procédé proprement — `IntersectionObserver`, une seule fois, coupé sous
   `prefers-reduced-motion` — et le défaut est réapparu autrement : les blocs
   partaient à `opacity: 0` en CSS et seul le script les rallumait. **Sans
   JavaScript, la page entière était vide.** Une ancre profonde ou un retour
   d'historique laissaient aussi des sections éteintes le temps que
   l'observateur rattrape.

   Ce que le thème anime, il l'anime parce que ça dit quelque chose : le
   survol d'un bouton et d'une carte (retour tactile), la flèche qui avance
   (direction), la hauteur d'un accordéon (état), le glissement du diaporama
   (position dans la série). Un fondu d'entrée ne dit rien de tout cela sur un
   site que les parents ouvrent pour trouver un horaire.
   -------------------------------------------------------------------------- */

@media ( prefers-reduced-motion: reduce ) {
	html { scroll-behavior: auto; }
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}


/* --------------------------------------------------------------------------
   31. Utilitaires — EN DERNIER
   --------------------------------------------------------------------------
   À spécificité égale, la dernière règle gagne. Une classe utilitaire
   déclarée avant les composants se fait écraser par le `margin: 0` du
   premier composant venu, et aucune des deux règles n'est fausse.
   -------------------------------------------------------------------------- */

.hors-ecran {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset( 50% );
	white-space: nowrap;
	border: 0;
}

.mesure-centree { max-width: var( --mesure ); margin-inline: auto; }

.marge-haut-4 { margin-top: var( --sp-4 ); }
.marge-haut-5 { margin-top: var( --sp-5 ); }
.marge-haut-6 { margin-top: var( --sp-6 ); }
.marge-haut-7 { margin-top: var( --sp-7 ); }
.sans-marge   { margin: 0; }
.centre-texte { text-align: center; }
