/**
 * La composition du site de Lina Hadid.
 *
 * ── LE PARTI PRIS, EN UNE PHRASE ───────────────────────────────────────────
 * La retenue d'une banque privée genevoise, appliquée au vocabulaire d'une
 * fiche technique. Deux mondes qui ne se rencontrent jamais : c'est le
 * frottement des deux qui fait la marque, parce que Lina est à la fois
 * entrepreneuse, autrice, et quelqu'un qui roule.
 *
 * ── LA RÈGLE QUI TIENT LE MÉLANGE ──────────────────────────────────────────
 * LE SERIF PARLE, LE MONO MESURE. Instrument Serif porte tout ce qui
 * s'énonce : titres, phrases, noms. IBM Plex Mono porte tout ce qui se
 * mesure : codes, dates, coordonnées, numéros, libellés de fiche. Aucun des
 * deux n'empiète sur le terrain de l'autre. Sans cette discipline, le mono
 * devient un effet de style et la page un collage.
 *
 * ── LES CINQ RÈGLES DE COMPOSITION ─────────────────────────────────────────
 * 1. LA BANDE SOMBRE NE PORTE JAMAIS DE CONTENU. Une phrase, et rien d'autre.
 *    Elle a d'abord porté les couvertures : saturées, elles s'y disputaient
 *    avec le fond. Elle est redevenue un fond.
 * 2. LES GRILLES QUAND ON CHERCHE (Livres), LES RANGÉES QUAND ON LIT
 *    (Univers), LES RAILS QUAND ON PASSE (l'accueil). Un rail sur la page
 *    catalogue obligerait à faire défiler vingt et un titres pour voir le
 *    dernier ; une grille sur Univers obligerait à couper les textes.
 * 3. RIEN NE DÉFILE TOUT SEUL. Les flèches poussent un défilement natif.
 * 4. LES LOGOS DES MARQUES SONT AU GRIS au repos. Sept logos en couleur côte
 *    à côte font une planche d'autocollants ; la couleur revient au survol,
 *    et devient une récompense au lieu d'un bruit de fond.
 * 5. PAS D'ORNEMENT QUE LE CONTENU DOIVE ÉVITER. Un filet vertical
 *    « décoratif » traversait le tableau de la fiche : il a été supprimé.
 *
 * ── CONTRASTES ─────────────────────────────────────────────────────────────
 * Le brand book chiffre des rapports, pas des couleurs : titre sur crème
 * ≥ 9,4 · corps ≥ 7,8 · mentions ≥ 4,8 · texte clair sur la bande ≥ 9,9 et
 * son secondaire ≥ 6,6. Les valeurs ci-dessous les tiennent toutes.
 *
 * @package linahadid
 */

/* ═══ 1. Jetons ═══════════════════════════════════════════════════════════ */

:root {
	--creme:      #f4f1ea;
	--creme-2:    #eae5da;
	--carte:      #fbf9f5;
	--navy:       #1f2b45;
	--texte:      #2c354a;
	--texte-doux: #5c6274;
	--trait:      #ddd7cb;
	--accent:     #b0915f;
	--accent-texte: #735830;
	--sur-navy:      #ece6da;
	--sur-navy-doux: #aab2c4;
	--navy-presse:   #162034;
	--blanc:         #fff;
	--alerte:        #a4342c;

	/* LE SOL DE LA SALLE. Cinq valeurs, et elles ne sont pas décoratives : ce
	   sont les cinq arrêts du dégradé qui fait le plancher et la cimaise. Les
	   nommer ici, c'est pouvoir les relire ; écrites dans le dégradé, elles
	   n'étaient qu'une suite de chiffres au milieu d'une ligne. */
	--sol-haut:      #f8f6f0;
	--sol-milieu:    #f1ede3;
	--sol-bord:      #e6e0d3;
	--sol-ombre:     #cfc7b4;
	--sol-bas:       #bdb49f;

	--e1: 4px;  --e2: 8px;   --e3: 16px; --e4: 24px;
	--e5: 40px; --e6: 64px;  --e7: 136px;

	--titre:   "Instrument Serif", Georgia, serif;
	--texte-f: "Instrument Sans", "Helvetica Neue", Arial, sans-serif;
	--mono:    "IBM Plex Mono", ui-monospace, Menlo, Consolas, monospace;
	/* L'ÉCHELLE TYPOGRAPHIQUE — posée le 28.10.2026, et elle manquait.
	   Le site portait SIX tailles pour trois rôles : 9,5 · 10 · 10,5 · 11 · 12
	   · 13 px, réparties au jugé, déclaration par déclaration. Mesuré : vingt
	   et une règles à 10 px et dix-sept à 11 px. Rien ne les distinguait, et
	   le plancher était sous la limite du lisible pour du capitale espacé.

	   Quatre degrés, et chacun a un emploi, pas une valeur :
	     étiquette  ce qui nomme une zone — filets-titres, `dt`, sceaux, codes
	     mention    ce qui commente — légendes, comptes, aides de formulaire
	     action     ce sur quoi on clique — liens et boutons en capitales
	     menu       la navigation, qui doit se voir depuis l'autre bout
	   Changer la taille d'un rôle se fait désormais à UN endroit.

	   LE PLANCHER EST À TREIZE, ET IL A ÉTÉ REMONTÉ LE 29.10.2026. L'échelle
	   partait de neuf et demi ; elle est remontée une première fois à douze,
	   puis à treize, parce qu'à chaque palier la même phrase revenait : « pas
	   assez lisible ». Treize en MONO espacé est le plus petit corps qui se
	   lise sans effort sur un écran ordinaire — et rien, sur ce site, n'a de
	   raison d'être plus petit que la plus petite étiquette. */
	--t-etiquette: 14px;
	--t-mention:   15px;
	--t-action:    14px;
	--t-menu:      16px;
	/* LE CINQUIÈME DEGRÉ, POSÉ LE 29.10.2026 : le corps de texte.
	   Il manquait, et son absence avait une conséquence visible — les chapôs
	   de magazine (`.menu`) empruntaient la taille de la NAVIGATION, 15 px,
	   parce que c'était le seul degré assez grand sous les titres. Un texte
	   qu'on lit n'a pas la taille d'un menu qu'on balaie : les deux rôles
	   réclamaient le même chiffre pour des raisons opposées.
	   Il vaut celui du `body`, et c'est la règle : sur ce site, tout ce qui
	   se lit fait dix-sept.

	   ET UN SIXIÈME, LE CHAPÔ. Un chapô de magazine n'a jamais le corps du
	   texte courant : il est un peu plus grand, dans une colonne plus
	   étroite, et c'est ce double écart qui le fait lire en premier. À la
	   taille du corps il se confond avec lui ; à la taille de la navigation
	   il est illisible. Dix-neuf. */
	--t-corps:     17px;
	--t-chapo:     19px;

	--marge: 64px;
	--mesure: 46ch;

	/* LA LARGEUR DE PAGE. C'est la décision qui manquait. Sans elle, une
	   section occupe tout l'écran : sur un 27 pouces, une rangée fait dix-sept
	   cents pixels de large, l'œil ne sait plus où revenir à la ligne, et la
	   page paraît interminable même quand elle est courte. Un magazine a des
	   marges — ce sont elles qui font qu'on tourne les pages au lieu de se
	   perdre.
	   Seuls trois éléments ont le droit de sortir de cette largeur, et c'est
	   ce qui leur donne leur force : l'ouverture, la double page, la bande
	   sombre. Le reste y rentre. */
	--large: 1280px;
}

/* ═══ 2. Socle ════════════════════════════════════════════════════════════ */

html { scroll-behavior: smooth; }

body {
	background: var(--creme);
	color: var(--texte);
	font-family: var(--texte-f);
	font-size: 17px;
	line-height: 28px;
	-webkit-font-smoothing: antialiased;
}

/* LES PARAGRAPHES SONT JUSTIFIÉS, ET AVEC CÉSURE.
   La césure n'est pas un raffinement : une colonne de trente-quatre signes
   justifiée SANS elle ouvre des rivières blanches au milieu du texte, et le
   remède devient pire que le mal. C'est `lang="fr"` sur le `<html>` — posé
   par WordPress — qui donne au navigateur le dictionnaire de coupure.
   Ce qui n'est pas justifié : les titres, les étiquettes en capitales et les
   légendes. Justifier trois mots ne fait pas un bloc, ça fait des trous. */
/* ⚠️ PAS DANS UNE TUILE. J'y avais mis `.mo-maison .mo-texte` le 30.10.2026,
   par simple reprise de l'ancien `.carre p`. Mesuré sur capture : dans une
   colonne de quart de page, la justification donnait « l'ac-compagnement »,
   « pré-sen-ta-tion », « dé-cide » — un mot coupé toutes les deux lignes.
   La justification demande une mesure ; une tuile n'en a pas. */
.lecture p, .colonne p, .chapitre-corps p, .menu,
.fiche p, .salle-texte p {
	/* 🔴 LA JUSTIFICATION REVIENT — 01.11.2026, demandée par Lina, et cette
	   fois la largeur la porte. Elle avait été retirée le 31.10 parce que
	   « sur une colonne de moins de quarante-cinq signes, le fer à droite
	   creuse des lézardes ». Le reproche visait la LARGEUR, pas le procédé :
	   mesuré aujourd'hui sur la page Univers, la colonne de texte fait
	   546 px, soit soixante-quatre signes — la mesure d'une colonne de
	   magazine, où la justification est chez elle.
	   La césure automatique reste : sans elle, justifier, c'est faire des
	   trous. */
	text-align: justify;
	hyphens: auto;
	-webkit-hyphens: auto;
}

/* WordPress pose ses propres marges entre blocs ; on les reprend à la main,
   sinon le rythme vertical vient de l'éditeur et non de la charte.

   🔴 ET LA RÈGLE S'ARRÊTAIT UN NIVEAU TROP HAUT — mesuré le 01.11.2026.
   `.wp-site-blocks > *` couvre l'en-tête, le `<main>` et le pied. Les
   SECTIONS, elles, sont enfants de `.entry-content`, deux crans plus bas :
   `is-layout-flow` leur donnait à chacune un `margin-top: 24px` que personne
   n'avait décidé.

   Conséquence, relevée section par section sur les sept pages : l'air entre
   deux gabarits ne valait jamais ce que les gabarits déclarent. Un `--duo`
   suivi d'un `--bloc` annonce 64 + 64 ; il en rendait 152. Et selon qu'un
   filet ou un groupe s'intercalait, l'écart mesuré tombait à 8, 24 ou 40 —
   trois valeurs, aucune écrite nulle part, pour une page qui prétend tenir
   son rythme dans six gabarits.

   C'est exactement la cause qui décalait le logo de l'en-tête le 31.10, et
   elle a été rediagnostiquée de zéro parce que la première correction n'avait
   été posée qu'à l'endroit où le défaut s'était vu.

   ⚠️ `> *` ET NON `*` : à l'intérieur d'une section, les marges entre
   paragraphes sont voulues — ce sont elles qui font le texte. On ne reprend
   que le rythme des BLOCS DE PREMIER NIVEAU. */
.wp-site-blocks > *,
.entry-content > * { margin-block: 0; }

img { max-width: 100%; height: auto; }

h1, h2, h3, h4, .wp-block-heading {
	font-family: var(--titre);
	font-weight: 400;
	color: var(--navy);
	margin: 0;
	text-wrap: balance;
}
h1 { font-size: clamp(44px, 6.6vw, 96px); line-height: .94; letter-spacing: -.022em;
	hanging-punctuation: first allow-end; }
h2 { font-size: clamp(30px, 4.2vw, 56px); line-height: 1.02; letter-spacing: -.015em; }
h3 { font-size: 25px; line-height: 1.12; }
h4 { font-size: 20px; line-height: 1.2; }
em { font-style: italic; }
p { text-wrap: pretty; }

a { color: inherit; }
a:focus-visible, button:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.ouverture a:focus-visible { outline-color: var(--sur-navy); }

/* ── LA VOIX TECHNIQUE. Tout ce qui MESURE passe ici, et rien d'autre. ── */
.mono, .eti {
	font-family: var(--mono);
	font-size: var(--t-action);
	line-height: 18px;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--accent-texte);
	margin: 0 0 var(--e4);
}
.mono--clair { color: var(--sur-navy-doux); }

/* La réglette : deux densités de graduations, en dégradés répétés — elle
   s'étire d'elle-même sur toute la largeur au lieu de finir en moignon. */
.reglette {
	height: 14px;
	margin: var(--e6) 0 0;
	background:
		repeating-linear-gradient(to right, var(--trait) 0 1px, transparent 1px 14px) left bottom/100% 6px no-repeat,
		repeating-linear-gradient(to right, var(--accent) 0 1px, transparent 1px 70px) left bottom/100% 13px no-repeat;
}
.chapo { max-width: var(--mesure); margin: var(--e4) 0 var(--e5); }

/* 🔴 « LES LIENS NE SONT PAS ASSEZ LISIBLES, ON NE LES VOIT PAS ASSEZ. »
 * Corrigé le 31.10.2026. Le lien était un texte en petites capitales mono
 * avec un filet d'un pixel : au milieu d'une page qui porte déjà des
 * étiquettes en petites capitales mono soulignées d'un filet, RIEN ne le
 * distinguait d'un intertitre. On ne voyait pas qu'il se cliquait parce
 * qu'il ressemblait à ce qui ne se clique pas.
 *
 * Trois signes qu'une étiquette n'a pas : une FLÈCHE, un filet de deux
 * pixels, et un décalage au survol. La flèche est posée en pseudo-élément —
 * elle n'est pas dans le texte, donc elle ne se lit pas deux fois à la
 * synthèse vocale. */
.lien {
	display: inline-flex;
	align-items: center;
	gap: .6em;
	font-family: var(--mono);
	font-size: var(--t-action);
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--navy);
	text-decoration: none;
	border-bottom: 2px solid var(--accent);
	padding-bottom: 6px;
	transition: border-color .18s ease;
}
.lien::after {
	content: "→";
	font-size: 1.1em; line-height: 1;
	transition: transform 220ms cubic-bezier(.16, 1, .3, 1);
}
.lien:hover::after, .lien:focus-visible::after { transform: translateX(4px); }
.lien:hover, .lien:focus-visible { border-bottom-color: var(--navy); }
@media (prefers-reduced-motion: reduce) { .lien::after { transition: none; } }

.lien:hover { border-bottom-color: var(--navy); }
.ouverture .lien { color: var(--sur-navy); }

.btn, .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	font-family: var(--mono);
	font-size: var(--t-action);
	letter-spacing: .1em;
	text-transform: uppercase;
	background: var(--navy);
	color: var(--sur-navy);
	text-decoration: none;
	padding: 18px 26px;
	border-radius: 0;
	transition: background .18s ease;
}
.btn:hover, .wp-block-button__link:hover { background: var(--navy-presse); color: var(--sur-navy); }
.ouverture .btn { background: var(--sur-navy); color: var(--navy); }
.ouverture .btn:hover { background: var(--blanc); }

.sect { padding: var(--e7) var(--marge); }
.sect > * { max-width: none; }

.sect-tete { max-width: 52ch; margin-bottom: var(--e6); }

/* ═══ 3. En-tête et pied ══════════════════════════════════════════════════ */

/* PIÈGE DU TEMPLATE PART. WordPress enveloppe l'en-tête dans un
   <header class="wp-block-template-part"> dont la hauteur est exactement
   celle de l'en-tête. Or un élément `sticky` ne peut pas sortir de la boîte
   de son parent : le menu restait collé… sur soixante pixels, ce qui
   ressemble à un menu qui ne colle pas du tout. `display: contents` efface
   l'enveloppe de la mise en page sans toucher au balisage. */
header.wp-block-template-part { display: contents; }

/* ── LA BARRE QUI MAIGRIT ───────────────────────────────────────────────────
   Mesuré le 30.10.2026 : l'en-tête faisait 117 px sur toutes les pages, et il
   est collant. Il prenait donc 13 % d'un écran de portable PENDANT TOUTE LA
   VISITE, avec un logo de 68 px — petit à l'arrivée, encombrant ensuite.
   C'est exactement l'inverse de ce qu'il faut.

   AU REPOS il grandit : logo à 88 px (68 + 30 %, comme Lina l'a demandé),
   barre à ~137 px. UNE FOIS QU'ON A DÉFILÉ il rend 53 px au contenu : logo à
   48, barre à ~84, soit 10 % de l'écran au lieu de 17.

   LA HAUTEUR N'EST PAS ÉCRITE, elle se déduit du logo et des entretoises.
   Écrire 137 et 84 aurait fait deux nombres à tenir à jour chaque fois que le
   logo change de taille — et le premier qu'on oublie fait sauter la barre. */
.hd {
	/* 🔴 88 px DE BOÎTE NE FAISAIENT QUE 65 px DE DESSIN. Le SVG arrivait dans
	   un `viewBox` carré de 3167 où le logo n'occupe que 2333 : un quart de
	   la hauteur était du vide, et « le logo est trop petit » était une
	   mesure, pas une impression. Le cadre est maintenant serré sur le
	   dessin (voir `inc/entete.php`), donc ces 84 px SONT 84 px de logo —
	   soit les 30 % de plus demandés, avec une barre qui rétrécit de 4 px au
	   lieu de grandir de 26. */
	--hd-logo: 84px;
	--hd-air: 24px;
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	/* 🔴 C'ÉTAIT WORDPRESS QUI DÉCALAIT LE LOGO, PAS LA GRILLE. L'en-tête
	   est un `wp-block-group` : WordPress lui pose la classe
	   `is-layout-flow`, qui donne à chaque enfant SAUF LE PREMIER un
	   `margin-block-start` égal au `blockGap` du thème. Le logo n'est pas le
	   premier enfant — il en recevait 24 px, invisibles dans le code du
	   thème puisqu'ils viennent d'une feuille de WordPress.
	   Mesuré le 31.10.2026 : 48 px au-dessus du logo contre 25 en dessous,
	   pour un padding parfaitement symétrique de 24. « Il faut que la marge
	   en haut du logo et en bas soit équilibrée. » Deux heures de
	   `grid-template-rows` auraient pu être évitées en lisant la classe. */
	grid-template-rows: auto;
	align-items: center;
	padding: var(--hd-air) var(--marge);
	border-bottom: 1px solid var(--navy);
	background: var(--creme);
	position: sticky;
	top: 0;
	z-index: 30;
	transition: padding 180ms ease;
}
/* L'ÉTAT « ON A DÉFILÉ » EST POSÉ SUR `<html>`, par un observateur
   d'intersection sur une sentinelle d'un pixel — pas par l'événement
   `scroll`, qui se déclenche soixante fois par seconde pour rien.
   Voir `assets/entete.js`. */
/* ⚠️ LA BARRE DÉFILÉE DOIT RENDRE DE LA PLACE, PAS SEULEMENT EN PERDRE.
   Premier réglage du 30.10.2026 : logo 48, air 14 — la barre tombait de 161
   à 101 px. Yan : « réduire un petit peu la marge du menu quand il shrink ».
   Il a raison, 14 px d'air autour d'un logo de 48 laissait une barre de cent
   pixels collée en haut pendant toute la lecture. À 40 et 10, elle tombe
   sous les 80 : moins de 9 % d'un écran de portable, contre 17 au repos. */
/* UNE FOIS DÉFILÉ, LE NOM S'EN VA ET IL NE RESTE QUE LE MONOGRAMME. Les
   34 px s'appliquent alors à un cadre qui ne contient plus que lui : il passe
   de 69 px à 34, soit la moitié, pendant que la barre tombe sous 60. C'est
   `assets/entete.js` qui échange le cadre — un `viewBox` ne se change pas en
   CSS. */
html.a-defile .hd { --hd-logo: 34px; --hd-air: 10px; }

/* ⚠️ SANS JAVASCRIPT, LA BARRE RESTE À SA TAILLE DE REPOS et le site
   fonctionne entièrement — il est seulement moins fin. C'est la même règle
   que pour le burger et pour les filtres de presse : rien d'essentiel ne
   dépend d'un script. */
@media (prefers-reduced-motion: reduce) {
	/* On coupe la TRANSITION, pas le redimensionnement : quelqu'un qui refuse
	   les animations veut quand même récupérer ses 53 px. */
	.hd, .hd .lha-logo { transition-duration: 1ms; }
}
.hd .wp-block-navigation,
.hd .wp-block-navigation__container { gap: 32px; }
/* ⚠️ ET 18 px DANS LA BANDE ÉTROITE. Même mesure que le seuil de `themes.css`
   juste à côté : entre 901 et 1000, les trois entrées de droite plus la
   réserve du sélecteur dépassaient leur colonne de quelques pixels, et le
   menu se repliait sur trois lignes. Quatorze pixels de gouttière en moins
   par entrée suffisent — on ne touche ni au corps du texte ni à
   l'interlettrage, qui sont la signature de cette barre. */
@media (min-width: 901px) and (max-width: 1250px) {
	.hd .wp-block-navigation,
	.hd .wp-block-navigation__container { gap: 24px; }
}
/* Et 10 px sur les cinquante premiers pixels au-dessus du seuil du burger :
   à 901, dix-huit ne suffisaient pas encore de quelques pixels. Mesuré, pas
   déduit — c'est la largeur où la barre bascule, donc la plus serrée qu'elle
   connaisse.

   ET UN LIBELLÉ DE MENU NE SE COUPE PAS. À 901 px exactement, « À PROPOS »
   passait sur deux lignes dans sa propre case plutôt que de déborder. La
   barre ne grandissait pas, donc rien ne le signalait : il fallait compter
   les rangées des entrées pour le voir. */
.hd .wp-block-navigation a { white-space: nowrap; }
/* LA NAVIGATION SE LIT DEPUIS L'AUTRE BOUT DE L'ÉCRAN. Elle était à 11 px,
   en capitales espacées, dans la couleur du texte courant : techniquement
   présente, visuellement absente. Elle prend son propre degré — le seul rôle
   du site qui doive attirer l'œil sans qu'on le cherche — et un peu d'air
   entre les entrées. */
.hd .wp-block-navigation a {
	font-family: var(--mono);
	font-size: var(--t-menu);
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--navy);
	text-decoration: none;
	padding-bottom: 5px;
	border-bottom: 1px solid transparent;
	transition: border-color .18s ease, color .18s ease;
}
.hd .wp-block-navigation a:hover { border-bottom-color: var(--accent); }
/* ⚠️ `.current-menu-item` NE MATCHAIT RIEN, et ne pouvait pas : les entrées
   sont des liens personnalisés, auxquels WordPress ne pose jamais cette
   classe. Le marquage se fait désormais sur `aria-current`, posé par
   `inc/entete.php` en comparant les CHEMINS — l'attribut d'abord, parce
   qu'il porte l'information pour un lecteur d'écran, la peinture ensuite.
   Une règle CSS qui ne matche rien ne lève aucune erreur : le menu actif
   n'a donc jamais fonctionné, et rien ne le disait. */
.hd .wp-block-navigation a[aria-current="page"] {
	color: var(--navy);
	border-bottom-color: var(--navy);
	border-bottom-width: 2px;
}
.hd .hd-droite { justify-content: flex-end; }
/* ⚠️ `margin-block: 0` PARTOUT, `grid-row: 1` SEULEMENT SUR GRAND ÉCRAN.
   La marge est le correctif de `is-layout-flow` : elle vaut à toute largeur.
   La rangée unique, non — sous 900 px la barre passe à deux colonnes et les
   deux menus descendent en rangée 2, dépliés par le burger. Forcés en
   rangée 1, ils se superposaient AU LOGO : « LIVRES » et « PRESSE » écrits
   par-dessus le monogramme, l'ordre des entrées mélangé, et la page qui
   débordait à droite. Mesuré sur iPhone le 31.10.2026 — la correction de
   l'en-tête de bureau, posée le matin même, avait cassé le menu du
   téléphone. */
.hd > * { align-self: center; margin-block: 0; }
@media (min-width: 901px) { .hd > * { grid-row: 1; } }
/* LE LOGO TIENT L'AXE, donc il doit peser autant que les six entrées qui
   l'encadrent. À 54 px il était la plus petite chose de la barre, et le
   centre ne tenait rien ; à 68 il tenait sans peser. Il est à 88 depuis le
   30.10.2026 — trente pour cent de plus, demandés par Lina, et c'est sa
   taille AU REPOS seulement. */
.hd .hd-logo { line-height: 0; }

/* ═══ LE BURGER ══════════════════════════════════════════════════════════ *
 * ⚠️ LA NAVIGATION ÉTAIT SIMPLEMENT ÉTEINTE SOUS 900 px. `display: none`
 * sur les deux blocs, et rien pour les remplacer : sur un téléphone, le site
 * n'avait AUCUN moyen d'aller ailleurs que par le pied de page. Mesuré sur
 * iPhone le 29.10.2026. Ce n'est pas un défaut de mise en page, c'est une
 * impasse — et elle a tenu parce qu'on regardait les captures à 390 px sans
 * jamais cliquer dedans.
 *
 * Il fonctionne SANS JAVASCRIPT : la case à cocher porte l'état, le libellé
 * la bascule, et le sélecteur de frère ouvre le panneau. La case est masquée
 * à l'œil mais pas au clavier — en `display:none` elle cesserait d'être
 * focusable, et le menu deviendrait inatteignable sans souris. */
.hors-ecran {
	position: absolute; width: 1px; height: 1px;
	margin: -1px; padding: 0; overflow: hidden;
	clip-path: inset(50%); white-space: nowrap; border: 0;
}
.hd-bascule { position: absolute; opacity: 0; width: 44px; height: 44px; margin: 0; }
.hd-burger {
	display: none;
	width: 44px; height: 44px;
	align-items: center; justify-content: center;
	cursor: pointer;
}
/* Les trois barres sont UN élément et deux pseudo-éléments : trois `<span>`
   auraient demandé au gabarit de connaître le dessin. */
.hd-trois, .hd-trois::before, .hd-trois::after {
	display: block; width: 24px; height: 2px;
	background: var(--navy);
	transition: transform .22s ease, opacity .18s ease;
}
.hd-trois { position: relative; }
.hd-trois::before, .hd-trois::after { content: ""; position: absolute; left: 0; }
.hd-trois::before { top: -7px; }
.hd-trois::after  { top: 7px; }
/* Ouvert, les trois barres deviennent une croix : l'icône dit l'état, pas
   seulement l'action. */
.hd-bascule:checked + .hd-burger .hd-trois { background: transparent; }
.hd-bascule:checked + .hd-burger .hd-trois::before { transform: translateY(7px) rotate(45deg); }
.hd-bascule:checked + .hd-burger .hd-trois::after  { transform: translateY(-7px) rotate(-45deg); }
.hd-bascule:focus-visible + .hd-burger { outline: 2px solid var(--accent); outline-offset: 2px; }

.pied {
	background: var(--carte);
	border-top: 1px solid var(--trait);
	padding: var(--e7) var(--marge) var(--e5);
	color: var(--texte);
}
/* ⚠️ VINGT-QUATRE PIXELS DE HAUT, AU MOINS. Mesuré le 29.10.2026 sur
   iPhone : vingt-deux cibles par page sous le minimum, toutes à dix-neuf
   pixels — la hauteur d'une ligne de texte, rien de plus. La largeur
   n'était jamais en cause.
   La règle WCAG 2.5.8 exempte les liens posés DANS une phrase : on vise
   donc les listes de liens isolés, où le doigt n'a aucun repère pour viser,
   et pas le lien au fil du texte. Le remède est du `padding`, jamais une
   hauteur fixe : une entrée qui passe sur deux lignes doit grandir. */
.pied a { color: var(--texte); text-decoration: none; }
.pied a:hover { border-bottom: 1px solid var(--accent); }
.pied li a, .pied .coord dd a, .pied-legal a, .coord dd a {
	display: inline-block;
	padding-block: 3px;
	min-height: 24px;
}
/* QUATRE COLONNES DEPUIS LE 02.11.2026, pas cinq : « La collection » est
   tombée, « Me joindre » a fusionné avec « Contact », et « La newsletter »
   est redevenue ce qu'elle était — un lien LinkedIn. */
.pied-cols { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--e5); padding-bottom: var(--e7); }
/* Le logo du réseau tient sur la ligne du lien, à sa hauteur de capitale. */
.lien--marque { display: inline-flex; align-items: center; gap: var(--e2); }
.marque-reseau { flex: none; }
.pied h4 { margin: 0 0 var(--e4); }
.pied ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 11px;
	font-size: var(--t-mention); line-height: 24px; color: var(--texte-doux); }
.pied .note { font-size: var(--t-mention); line-height: 25px; color: var(--texte-doux); margin: 0 0 var(--e3); }
/* 🔴 LA LIGNE DU BAS SE LISAIT COMME UNE PHRASE — corrigé le 02.11.2026.
   « Mentions légales Données personnelles Contact LinkedIn » : quatre liens
   posés côte à côte, séparés par la seule espace entre deux balises. Rien ne
   disait où l'un finissait. Yan : « toute cette partie en bas, il faudrait
   espacer un peu plus. »
   Deux écarts, pas un : --e5 entre les liens, --e3 quand la ligne se replie,
   pour que deux rangs ne se collent pas non plus. Et la barre entière
   respire davantage sous son filet. */
.pied-bas { display: flex; justify-content: space-between; gap: var(--e5); flex-wrap: wrap;
	border-top: 1px solid var(--trait); padding-top: var(--e5); }
.pied-bas p { margin: 0; }
.pied-legal { display: flex; flex-wrap: wrap; gap: var(--e3) var(--e5); }

/* ═══ 4. L'ouverture photographique ═══════════════════════════════════════ */

.ouverture { position: relative; background: var(--navy); overflow: hidden; }
.ouverture .fond { position: absolute; inset: 0; background: var(--navy); }

/* LE DUOTONE, sans toucher au fichier. Le calque est navy ; l'image,
   désaturée, s'y mélange en `luminosity` : elle n'apporte que ses valeurs, la
   couleur vient du fond. C'est la seule méthode qui donne un vrai bichrome —
   un aplat en `color` par-dessus ne donne qu'un lavis bleu. La cliente peut
   changer la photo sans rien savoir de tout ça. */
.ouverture .fond img {
	width: 100%; height: 100%;
	object-fit: cover; object-position: 46% 33%;
	filter: grayscale(1) contrast(1.28) brightness(1.06);
	mix-blend-mode: luminosity;
	opacity: .96;
}
.ouverture .voile {
	position: absolute; inset: 0;
	background: linear-gradient(to top, rgba(20,29,48,.96) 0%, rgba(20,29,48,.82) 30%,
		rgba(20,29,48,.28) 62%, rgba(20,29,48,.06) 100%);
}
.ouverture .dedans {
	position: relative;
	padding: var(--e7) var(--marge) var(--e6);
	/* Bornée : un `vh` seul donne une ouverture démesurée sur un grand écran
	   et illisible sur un portable. */
	min-height: clamp(560px, 80vh, 880px);
	display: flex; flex-direction: column; justify-content: flex-end;
}
.ouverture h1 { color: var(--sur-navy); max-width: 14ch; font-size: clamp(52px, 9vw, 132px);
	line-height: .88; letter-spacing: -.025em; }
.ouverture h1 em { color: var(--accent); }
.ouverture .sous { max-width: 46ch; color: var(--sur-navy-doux); margin: var(--e5) 0 var(--e6); }
.ouverture .act { display: flex; gap: var(--e5); align-items: center; flex-wrap: wrap; }

/* La bande de données : coordonnées, machine, œuvre. Le geste le plus
   inattendu de la page, et le plus sobre. */
.donnees { display: grid; grid-template-columns: repeat(5, 1fr);
	border-bottom: 1px solid var(--trait); background: var(--creme); }
.donnees > div { padding: var(--e4); border-right: 1px solid var(--trait); }
.donnees > div:first-child { padding-left: var(--marge); }
.donnees > div:last-child { border-right: 0; padding-right: var(--marge); }
.donnees dt { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--texte-doux); margin: 0 0 var(--e2); }
.donnees dd { margin: 0; font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .02em; color: var(--navy); }

/* ═══ 5. La fiche de repères ══════════════════════════════════════════════ */

.specs { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--e7); align-items: start; }
.specs dl { margin: 0; display: grid; grid-template-columns: 13ch 1fr; border-top: 1px solid var(--trait); }
.specs dt { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em; text-transform: uppercase;
	color: var(--texte-doux); padding: var(--e4) 0; border-bottom: 1px solid var(--trait); }
.specs dd { margin: 0; padding: var(--e4) 0; border-bottom: 1px solid var(--trait);
	font-size: 17px; line-height: 26px; color: var(--navy); }
.specs dd b { font-family: var(--titre); font-weight: 400; font-size: 26px; }

/* ═══ 6. La double page : le geste de magazine ════════════════════════════ *
 * Une image à fond perdu, une phrase dedans, et rien d'autre. Pas de bouton,
 * pas de lien : c'est une respiration, pas une étape. */

.doublepage { position: relative; background: var(--navy); overflow: hidden;
	min-height: clamp(420px, 58vh, 620px); display: flex; align-items: flex-end; }
.doublepage .fond { position: absolute; inset: 0; background: var(--navy); }
/* ⚠️ LE CADRAGE SE RÈGLE PAR IMAGE, ET 38 % N'EST QU'UN DÉFAUT.
   La double page est une bande très large et peu haute : `cover` n'en montre
   qu'une tranche, et où tombe cette tranche décide de tout. Sur la photo de
   la moto, 38 % coupait la tête de Lina — mesuré le 30.10.2026 : son visage
   occupe les 6 à 17 premiers pour cent de l'image, le cadrage en montrait
   une bande qui commence à 38 %. Un défaut de ce genre ne se voit pas dans
   le code, seulement sur la page. */
.doublepage .fond img { width: 100%; height: 100%; object-fit: cover;
	object-position: 50% var(--dp-cadrage, 20%);
	/* 🔴 20 % ET NON 38 % — « j'aime pas les photos où tu coupes la tête
	   comme ça, ça va pas du tout, tu arrêtes ». Un cadrage à 38 % convient
	   à un plan large et DÉCAPITE un portrait serré : la bande prend le
	   milieu de l'image, et sur un portrait le milieu commence au menton.
	   Le défaut n'était pas dans une page, il était dans le défaut. */
	/* Le défaut à 38 % convient à un plan large. Sur un portrait cadré
	   serré, il coupe le front — « je pense qu'on coupe un peu trop le front
	   sur la photo avec les lunettes ». `--dp-cadrage` existait déjà pour
	   ça ; il lui manquait une classe qui le pose sans écrire du style en
	   ligne dans le contenu. */
	filter: grayscale(1) contrast(1.25) brightness(1.04); mix-blend-mode: luminosity; opacity: .9; }
.doublepage--haut { --dp-cadrage: 14%; }

/* ── UNE DOUBLE PAGE QUI GARDE SES COULEURS ───────────────────────────────
 * Le bichrome navy est ce qui fait que toutes les doubles pages du site sont
 * de la même famille, et il ne se défait pas à la légère. Une seule image y
 * échappe : celle à la lame bleue, où la COULEUR EST LE SUJET. Désaturée,
 * elle rend un trait blanc dans de la brume grise — on ne voit plus de quoi
 * il s'agit.
 *
 * Elle est déjà dans la gamme froide du site, donc la laisser en couleur ne
 * casse rien ; le voile navy la ramène au ton de la page. */
.doublepage--couleur .fond img {
	filter: none; mix-blend-mode: normal; opacity: 1;
}
/* ⚠️ UNE IMAGE EN COULEUR DEMANDE UN VOILE PLUS FRANC. Le voile par défaut
   monte du bas et suffit à du bichrome, qui est déjà sombre partout. Ici la
   brume est CLAIRE au milieu droit — exactement là où tombe le paragraphe —
   et un texte en encre claire y perdait son contraste. On ajoute donc une
   seconde nappe qui vient de la droite. Mesuré, pas supposé : voir la sonde
   de contraste de la séance. */
.doublepage--couleur .voile {
	background:
		linear-gradient(to top, rgba(20,29,48,.94), rgba(20,29,48,.30) 72%),
		linear-gradient(to left, rgba(20,29,48,.66), rgba(20,29,48,0) 56%);
}

/* Un mot d'affiche et un paragraphe dans une double page, au lieu de la
   phrase et de sa légende : les trois objets de la page courante y entrent,
   mais leurs couleurs sont écrites pour le crème. Sur la plaque, c'est
   l'encre claire qui s'applique — les mêmes jetons que `.bloc`, donc les
   deux thèmes suivent sans une règle de plus. */
.doublepage .geant, .doublepage .geant em { color: var(--sur-navy); }
.doublepage .filet-titre { color: var(--sur-navy-doux);
	border-bottom-color: rgba(236, 230, 218, .35); }

/* 🔴 L'ENCRE DOUCE NE PASSE PAS SUR UNE PHOTOGRAPHIE. Mesuré au pixel le
   02.11.2026, sous le paragraphe de la double page en couleur : le point le
   plus clair du fond est rgb(79,99,121), et `--sur-navy-doux` (#aab2c4) n'y
   tient que 2,91:1 — il en faut 4,5 pour du 19 px.
   Une moyenne ne vaut rien ici : le fond est une brume, et c'est SON point
   le plus clair qui décide. `--sur-navy` (#ece6da) donne 4,98:1 au même
   endroit. Le voile s'étend aussi un peu plus, pour la marge.
   ⚠️ CE N'EST PAS `.menu--clair` QU'ON CHANGE : sur une plaque navy unie,
   l'encre douce tient largement, et c'est elle qui donne la hiérarchie. Le
   correctif vise la double page, où le fond n'est pas une couleur. */
.doublepage .menu, .doublepage .menu--clair { color: var(--sur-navy); }
.doublepage .voile { position: absolute; inset: 0;
	background: linear-gradient(to top, rgba(20,29,48,.92), rgba(20,29,48,.18) 70%); }
.doublepage .dedans { position: relative; padding: var(--e6) var(--marge); width: 100%;
	display: grid; grid-template-columns: 1fr 1fr; gap: var(--e6); align-items: end; }
.doublepage p.phrase { font-family: var(--titre); font-size: clamp(28px, 3.4vw, 46px); line-height: 1.1;
	color: var(--sur-navy); margin: 0; max-width: 18ch; }
.doublepage p.legende { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	text-transform: uppercase; color: var(--sur-navy-doux); margin: 0;
	align-self: end; justify-self: end; text-align: right; }

/* 🔴 LA « BANDE SOMBRE SANS IMAGE » A ÉTÉ RETIRÉE — 02.11.2026. Six règles
 * pour un bloc que PLUS AUCUNE page n'employait : vérifié sur les contenus,
 * les gabarits, les patterns et le prototype, zéro `class="bande"` en dehors
 * de `inc/bandes.php`, qui pose les bandes d'IMAGE.
 *
 * ⚠️ ET LES DEUX SE TÉLESCOPAIENT. `.bande` désignait ici un bloc navy et
 * là une bande du triptyque : la règle morte posait un `background` navy et
 * un `padding` sur chaque bande d'image. Sans effet visible — l'image
 * recouvre, et la découpe est faite par `background-size` — donc rien ne
 * l'aurait signalé. Un nom qui porte deux sens finit toujours par en perdre
 * un, et c'est l'autre qui casse. */

/* ═══ 7. Les rails ════════════════════════════════════════════════════════ *
 * Trois signaux disent qu'un rail défile, parce qu'un rail qui n'en donne
 * aucun se lit comme une rangée tronquée : la dernière vignette est COUPÉE
 * par le bord, un voile l'estompe pour faire « suite » plutôt que « fin », et
 * une barre de progression bouge quand on défile. */

.rail { margin-top: var(--e6); position: relative; }
.rail::after { content: ""; position: absolute; top: 0; bottom: 96px; right: 0; width: 120px;
	background: linear-gradient(to right, rgba(244,241,234,0), var(--creme)); pointer-events: none; }
.rail-piste { display: flex; flex-wrap: nowrap; gap: var(--e4);
	overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x proximity;
	padding-right: var(--marge); scrollbar-width: none; }
.rail-piste::-webkit-scrollbar { display: none; }
.rail-piste:focus-visible { outline: 2px solid var(--accent); outline-offset: 8px; }
.rail-piste > * { scroll-snap-align: start; }
.livres-piste > figure { flex: 0 0 164px; margin: 0; }

.jauge { position: relative; height: 1px; background: var(--trait); margin: var(--e5) var(--marge) 0 0; }
.jauge span { position: absolute; top: -1px; left: 0; height: 3px; width: 20%;
	background: var(--accent); transition: left .18s ease; }
.rail-cmd { display: flex; gap: var(--e2); justify-content: flex-end; align-items: center;
	margin-top: var(--e4); padding-right: var(--marge); }
.rail-cmd .compteur { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	color: var(--texte-doux); margin: 0 var(--e4) 0 0; }
.rail-cmd button { font-family: var(--mono); font-size: var(--t-menu); width: 44px; height: 44px;
	background: none; border: 1px solid var(--trait); color: var(--texte); cursor: pointer;
	transition: border-color .18s ease, color .18s ease; }
.rail-cmd button:hover { border-color: var(--accent); color: var(--accent-texte); }
.rail-cmd button[disabled] { opacity: .3; cursor: default; border-color: var(--trait); color: var(--texte-doux); }

/* ═══ 8. Les ouvrages ═════════════════════════════════════════════════════ */

.livres-sect { padding: var(--e7) 0 var(--e6); }
.livres-sect .livres-txt { padding: 0 var(--marge); max-width: 58ch; }
.livres-sect .rail { padding-left: var(--marge); }

.livre-legende { display: block; margin-top: var(--e3); }
.livre-legende .num { display: block; font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .14em; color: var(--accent-texte); margin-bottom: var(--e1); }
.livre-legende b { display: block; font-family: var(--titre); font-weight: 400;
	font-size: 17px; line-height: 1.18; color: var(--navy); }
.livre-lien { display: block; text-decoration: none; }
.livre-lien:hover .livre-legende b { text-decoration: underline;
	text-decoration-color: var(--accent); text-underline-offset: 5px; }

/* La grille du catalogue : ici on vient chercher, donc on montre tout. */
.livres-grille { display: grid; grid-template-columns: repeat(5, 1fr); gap: var(--e6) var(--e4); }
.livres-grille figure { margin: 0; }

/* Le retournement des couvertures, repris de `mentalsofa`, avec ses deux
   pièges déjà payés là-bas :
   1. `overflow:hidden` vit sur les DEUX FACES, jamais sur la scène 3D —
      plusieurs moteurs aplatissent alors la scène et rien ne tourne ;
   2. la rotation se déclenche au survol ET au `:focus-visible`, sans quoi la
      quatrième de couverture est réservée à la souris. */
.flip { display: block; perspective: 1400px; background: none; border: 0; padding: 0; width: 100%; cursor: pointer; }
.flip .scene { position: relative; transform-style: preserve-3d; transition: transform .7s cubic-bezier(.2,.7,.2,1); }
.flip:hover .scene, .flip:focus-visible .scene { transform: rotateY(180deg); }
.flip .face { display: block; backface-visibility: hidden; overflow: hidden; }
.flip .face img { display: block; width: 100%; }
.flip .dos { position: absolute; inset: 0; transform: rotateY(180deg); }
.flip .dos img { height: 100%; object-fit: cover; }

/* La fiche d'un ouvrage. */
.fiche { display: grid; grid-template-columns: 5fr 7fr; gap: var(--e6); padding: var(--e7) var(--marge); }
.fiche-couv { margin: 0; max-width: 380px; }
.fiche-couv img { display: block; width: 100%; }
.fiche h1 { font-size: clamp(34px, 3.6vw, 52px); }
.fiche-st { font-family: var(--titre); font-size: 24px; line-height: 1.2; color: var(--texte-doux);
	margin: var(--e3) 0 var(--e5); }
.fiche-act { display: flex; gap: var(--e5); align-items: center; flex-wrap: wrap; margin: var(--e5) 0; }
.fiche-tableau { width: 100%; border-collapse: collapse; margin-top: var(--e5); font-size: var(--t-mention); }
.fiche-tableau td { padding: 12px 0; border-top: 1px solid var(--trait); }
.fiche-tableau td:first-child { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	text-transform: uppercase; color: var(--texte-doux); width: 13em; }

/* ═══ 9. Les marques ══════════════════════════════════════════════════════ *
 * 🔴 PLUS DE `grayscale()` — retiré le 31.10.2026, après « ici les logos
 * s'affichent vraiment pas bien ». La règle d'avant était
 * `filter: grayscale(1) contrast(.78) opacity(.55)`, défaite au survol. Deux
 * mesures la condamnent. UN TÉLÉPHONE N'A PAS DE SURVOL : la moitié des
 * visiteurs ne voyaient que la version délavée, et jamais l'autre. Et sur la
 * tuile navy de Mental Sofa, un logo à 55 % d'opacité DISPARAÎT du fond —
 * vérifié au rendu, il ne restait rien. La règle de la maison tranche de
 * toute façon : un logo de marque tierce est un usage nominatif, on ne le
 * recolore pas.
 *
 * CE QUE LE GRIS VOULAIT ÉVITER RESTE VRAI — neuf logos en couleur, sans
 * cadrage commun, se disputent la page. On le règle par la GÉOMÉTRIE au lieu
 * de la teinte : une boîte de même emprise pour tous, `contain` pour
 * n'écraser personne, `left center` pour qu'ils s'alignent sur le bord du
 * texte.
 *
 * ⚠️ L'ALIGNEMENT SE FAISAIT SUR LA HAUTEUR SEULE, et c'est ce qui donnait la
 * disparité : mesuré, le bandeau de Symbiose Immobilier (3,27 : 1) occupait
 * 222 px de large quand l'écusson de Renaissance 69 (1 : 1) en occupait 68 —
 * trois fois et demie la surface, pour une maison qui n'en demandait pas
 * tant. Et Power-Fit, qui attend sa page, est à 5,92 : 1 : il sortirait à
 * 403 px. Une boîte commune rend la grille sûre quel que soit le logo qui
 * arrive demain. */

/* 🔴 CINQ EMPRISES, UNE PAR RAPPORT — et une échelle par contexte.
   La boîte unique de 168 × 60 rendait une aire de 3 600 px² à un carré et de
   9 780 à une bande : voir `lha_logo_emprise()` dans `inc/marques.php`, qui
   porte la mesure des neuf et le calcul. Les valeurs ci-dessous visent la
   même aire d'environ 5 800 px² dans la tuile ordinaire ; `contain` inscrit
   le dessin dedans sans jamais le déformer.

   ⚠️ L'AIRE VISÉE EST 9 000 px², PAS 5 800. Premier réglage : 5 800, la
   moyenne arithmétique des neuf. Équilibré et trop petit — Mecenda passait
   de 163 px de large à 122, et égaliser vers le bas, c'est rapetisser huit
   logos pour en consoler un. On vise donc le haut de l'ancienne fourchette.

   `--lk` est l'échelle du contexte, et c'est la seule chose qui change d'une
   tuile à l'autre : plus de vingt déclarations de largeur/hauteur à tenir
   (cinq emprises × quatre contextes × deux seuils) seraient devenues fausses
   au premier logo ajouté. */
.marque-logo {
	width: calc(var(--lw, 150px) * var(--lk, 1));
	height: calc(var(--lh, 48px) * var(--lk, 1));
	max-width: 100%;
	object-fit: contain; object-position: left center;
}
/* 🔴 UN SEUIL AU-DESSOUS DE UN — ajouté le 01.11.2026 avec le monogramme de
   Mecenda, qui est un ovale en 164 × 204, donc un rapport de 0,80. L'échelle
   s'arrêtait au carré parce que les neuf logos du jour étaient tous larges ou
   carrés : une marque PORTRAIT tombait dans la boîte carrée et y perdait un
   cinquième de son aire. Une échelle qui ne couvre que ce qu'on a sous la
   main n'est pas une échelle, c'est un relevé. */
.marque-logo--r0 { --lw:  85px; --lh: 106px; } /* portrait — Mecenda (monogramme) */
.marque-logo--r1 { --lw:  95px; --lh: 95px; } /* carré — Mental Sofa, Renaissance 69 */
.marque-logo--r2 { --lw: 116px; --lh: 78px; } /* Sport Dating */
.marque-logo--r3 { --lw: 139px; --lh: 66px; } /* Symbiose Bien-être */
.marque-logo--r4 { --lw: 163px; --lh: 56px; } /* Mecenda, Symbiose Immobilier */
.marque-logo--r5 { --lw: 195px; --lh: 46px; } /* La Fabrique, Power-Fit */
/* 🔴 UN SIXIÈME SEUIL, POUR LES MARQUES TRÈS LONGUES — 01.11.2026, avec la
   nouvelle identité Mecenda : symbole plus mot, 232 × 33, soit un rapport de
   SEPT. L'échelle s'arrêtait à 3,89, le plus allongé des neuf logos du jour.
   Rangée en `--r5`, cette marque sortait à 156 × 22 — 3 400 px² au lieu de
   9 000, une barrette deux fois trop maigre.
   Deux fois en deux jours que l'échelle manque un cas : hier le PORTRAIT
   (`--r0`), aujourd'hui le très large. Une échelle écrite sur les logos
   qu'on a sous la main n'en est pas une ; celle-ci couvre maintenant de
   0,80 à 7,0, ce qui laisse de la marge des deux côtés. */
.marque-logo--r6 { --lw: 230px; --lh: 33px; } /* très large — Mecenda */

/* ── LES ENSEIGNES : LA DEVANTURE DES MAISONS ───────────────────────────
 * L'accueil ne refait plus la page Univers (voir `lha_enseignes_marques`).
 * Neuf enseignes bord à bord, séparées par un seul filet : on voit qu'elles
 * sont neuf avant de savoir ce qu'elles font, et c'est tout ce que l'accueil
 * a à dire.
 *
 * `--lk` FAIT TOUT LE TRAVAIL. C'est l'échelle de contexte des emprises
 * ci-dessus : un seul nombre met les neuf logos à leur taille, chacun dans
 * son rapport. Écrire ici des largeurs serait rouvrir les vingt
 * déclarations que `--lk` existe pour éviter.
 *
 * Les logos sont adoucis au repos et repris en entier au survol du bloc —
 * le même geste que les bandes. Aucune teinte n'est appliquée : recolorer
 * le logo d'une marque tierce serait un usage fautif. */
.enseignes { display: block; text-decoration: none; color: inherit; }
.enseignes:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
/* 🔴 NEUF NE SE RÉPARTIT PAS TOUT SEUL. En `auto-fit minmax(150px, 1fr)`,
 * le mur posait huit enseignes sur la première ligne et UNE sur la seconde,
 * suivie d'une bande de fond vide aussi large que huit cases. Neuf n'a que
 * trois diviseurs — 9, 3, 1 — et ce sont les seuls comptes de colonnes qui
 * ne laissent aucun trou. Une devanture en une ligne quand la place est là,
 * trois par trois sinon. */
.enseignes-mur {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1px;
	background: var(--trait);
	border-block: 1px solid var(--trait);
}
@media (min-width: 1100px) {
	.enseignes-mur { grid-template-columns: repeat(9, 1fr); }
}
.enseigne {
	--lk: .52;
	display: grid; place-items: center;
	min-height: 118px; padding: var(--e4) var(--e3);
	background: var(--creme);
}
/* 🔴 .72 ET NON .5. Le mur est au repos tant qu'on ne le survole pas, et les
   logos y sont à .62 en gris — ils sont décoratifs, `aria-hidden`, et ce qui
   s'efface d'eux ne se lit de toute façon pas. CE NOM-LÀ EST DU TEXTE : c'est
   la seule maison qui n'a pas de logo, et son nom est tout ce qu'un visiteur
   a d'elle. Mesuré : à .5 il rendait 2,91:1 sur le crème et 4,05:1 sur le
   sombre — sous le seuil des deux côtés, pour une mention de 19 px. À .72 il
   tient 5,39:1 et 6,64:1, et le geste ne change pas : le mur reste discret,
   il s'allume au survol. Une discrétion ne se paie pas en lisibilité. */
.enseigne-nom {
	font-family: var(--titre); font-size: 19px; line-height: 1.15;
	text-align: center; color: var(--navy);
	opacity: .72; transition: opacity 400ms ease;
}
.enseignes:hover .enseigne-nom,
.enseignes:focus-visible .enseigne-nom { opacity: 1; }
.enseigne .marque-logo {
	object-position: center;
	opacity: .62; filter: grayscale(1);
	transition: opacity 400ms ease, filter 400ms ease;
}
.enseignes:hover .marque-logo,
.enseignes:focus-visible .marque-logo { opacity: 1; filter: none; }
/* 🔴 L'APPEL EST À GAUCHE — 02.11.2026, et c'est une règle de site, pas un
   réglage de ce mur-ci : « de manière générale, tous ces call to action
   pourraient être à gauche ». Un appel calé à droite part chercher l'œil là
   où la lecture ne va pas ; à gauche il est sur la colonne qu'on descend.
   `space-between` n'avait de sens que tant que « Neuf maisons fondées »
   tenait l'autre bout — ce compte est tombé le même jour. */
.enseignes-pied {
	display: flex; justify-content: flex-start; align-items: baseline;
	gap: var(--e4); margin-top: var(--e4);
}
.enseignes-aller {
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .14em; text-transform: uppercase;
	color: var(--accent-texte);
	border-bottom: 2px solid var(--accent); padding-bottom: 3px;
}
@media (prefers-reduced-motion: reduce) {
	.enseigne .marque-logo { transition: none; }
}
@media (max-width: 600px) {
	/* Deux par ligne : à 150 px une enseigne de quatre lettres n'est plus
	   une enseigne, c'est une vignette. */
	/* Toujours trois : à deux colonnes la neuvième enseigne resterait seule
	   sur sa ligne, et c'est le trou qu'on vient de supprimer. */
	.enseigne { --lk: .40; min-height: 88px; padding: var(--e3) var(--e2); }
	.enseignes-pied { flex-direction: column; align-items: flex-start; gap: var(--e2); }
}

/* En cases, sur l'accueil. */
.ecuries { display: grid; grid-template-columns: repeat(4, 1fr);
	border-top: 1px solid var(--trait); border-left: 1px solid var(--trait); }
.ecurie { border-right: 1px solid var(--trait); border-bottom: 1px solid var(--trait);
	padding: var(--e5) var(--e4) var(--e4); display: flex; flex-direction: column; gap: var(--e3);
	min-height: 270px; text-decoration: none; color: inherit; transition: background .2s ease; }
.ecurie:hover { background: var(--carte); }
.ecurie .code { display: block; font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	color: var(--accent-texte); }
.ecurie .nom { display: block; font-family: var(--titre); font-size: 22px; line-height: 1.1; }
.ecurie .bl { display: block; font-size: var(--t-mention); line-height: 24px; color: var(--texte-doux); }
.ecurie .aller { margin-top: auto; font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--texte-doux); display: flex; align-items: center; gap: 8px;
	transition: color .2s ease; }
.ecurie:hover .aller { color: var(--accent-texte); }
.ecurie .aller span { transition: transform .2s ease; }
.ecurie:hover .aller span { transform: translateX(4px); }
.ecurie--vide { background: repeating-linear-gradient(135deg, transparent 0 9px, rgba(221,215,203,.35) 9px 10px); }

/* La fiche d'une marque. */
.fiche-marque { display: grid; grid-template-columns: 1fr 1.6fr; gap: var(--e7);
	padding: var(--e7) var(--marge); }
.fiche-marque { --lk: 1.3; }

/* ═══ 10. Pages intérieures ═══════════════════════════════════════════════ */

.bandeau { padding: var(--e7) var(--marge) var(--e6); border-bottom: 1px solid var(--trait); }
.bandeau h1 { max-width: 16ch; }
.bandeau .chapo { margin-top: var(--e5); }

/* La barre de filtres : du mono, aucun bouton. Un filtre qui ressemble à un
   bouton attire le clic avant la lecture. */
.filtres { display: flex; flex-wrap: wrap; gap: var(--e5); align-items: baseline;
	padding: var(--e4) var(--marge); border-bottom: 1px solid var(--trait); }
.filtres a { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .14em; text-transform: uppercase;
	color: var(--texte-doux); text-decoration: none; padding-bottom: 4px; border-bottom: 1px solid transparent; }
.filtres a:hover { color: var(--navy); border-bottom-color: var(--accent); }
/* 🔴 L'ÉTAT ACTIF SE VOYAIT À UN PIXEL — 01.11.2026. « C'est très compliqué
   à utiliser. » Les cibles faisaient pourtant 33 × 44 px, bien assez : le
   défaut n'était pas la taille, c'était qu'on ne voyait pas CE QUI EST POSÉ.
   Vingt-deux liens de même graisse, et pour seul repère un filet d'un pixel
   dans la couleur du texte.
   La pastille ne vaut QUE pour l'actif : le commentaire ci-dessus refuse que
   les filtres ressemblent à des boutons, et il a raison — un filtre qui
   ressemble à un bouton attire le clic avant la lecture. Marquer l'état
   choisi n'est pas déguiser les vingt et un autres. */
/* ⚠️ LA PASTILLE PLEINE A ÉTÉ ABANDONNÉE, et c'est une mesure qui l'a dit.
   Essayée avec `--sur-navy` puis avec `--creme` : dans les deux cas le mot
   ressortait NAVY SUR NAVY — un rectangle bleu sans texte, vu sur capture les
   deux fois. Une autre règle, plus loin dans la feuille, reprend la couleur
   des liens de filtre ; la trouver et la contourner coûte plus que ce que la
   pastille apporte.
   Le marqueur reste donc un filet, mais un filet qu'on VOIT : deux pixels de
   laiton au lieu d'un pixel dans la couleur du texte, et le mot en navy
   plein. C'était le défaut d'origine — l'état posé ne se distinguait pas des
   vingt et un autres. */
.filtres a[aria-current] {
	color: var(--navy);
	border-bottom: 2px solid var(--accent);
	padding-bottom: 3px;
}
.filtres-effacer { margin: var(--e2) 0 0; }
.filtres-effacer a { color: var(--accent-texte); border-bottom-color: var(--accent); }
.filtres .compte { margin-left: auto; font-family: var(--mono); font-size: var(--t-mention);
	letter-spacing: .14em; color: var(--texte-doux); }

/* La colonne de lecture : À propos, article, mentions. La lettrine est le
   seul ornement admis, parce qu'elle appartient au livre. */
.lecture, .colonne { max-width: var(--mesure); margin-inline: auto; padding: var(--e7) var(--marge); }
.lecture > * + *, .colonne > * + * { margin-top: var(--e4); }
.lecture h2, .colonne h2 { margin-top: var(--e6); font-size: 30px; }
.lecture ul, .lecture ol, .colonne ul, .colonne ol { padding-left: 1.2em; }
.lecture li, .colonne li { margin: var(--e2) 0; }
.colonne figure { margin: var(--e5) 0; }
.colonne .wp-block-image img, .colonne .is-style-rounded img { border-radius: 0; }
.lettrine::first-letter { float: left; font-family: var(--titre); font-size: 76px; line-height: .78;
	padding: 6px 12px 0 0; color: var(--navy); }
.exergue, .colonne blockquote, .colonne .wp-block-quote {
	margin: var(--e6) 0; padding-left: var(--e4); border-left: 1px solid var(--accent);
	font-family: var(--titre); font-size: 28px; line-height: 1.2; color: var(--navy);
}
.exergue p, .colonne blockquote p { margin: 0; }

/* ═══ 11. Le journal ══════════════════════════════════════════════════════ *
 * PIÈGE DE LA REQUÊTE WORDPRESS : la classe posée sur `wp:query` atterrit sur
 * le conteneur, et celle de `wp:post-template` sur la LISTE — jamais sur les
 * articles. C'est la liste qu'il faut viser. */

.une .wp-block-post-template { list-style: none; margin: 0; padding: 0; }
.une .wp-block-post-template > li { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e6);
	align-items: end; padding: var(--e7) var(--marge); border-bottom: 1px solid var(--trait); }
.une .wp-block-post-date { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	text-transform: uppercase; color: var(--accent-texte); margin: 0 0 var(--e3); }
.une h2 { font-size: clamp(34px, 4.6vw, 62px); line-height: 1.02; }
.une h2 a { text-decoration: none; }
.une p { margin: 0; font-size: 18px; line-height: 29px; }

.index .wp-block-post-template { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--trait); }
.index .wp-block-post-template > li { display: grid; grid-template-columns: 150px 1.1fr 1fr;
	gap: var(--e5); align-items: baseline; padding: var(--e5) var(--marge);
	border-bottom: 1px solid var(--trait); transition: background .2s ease; }
.index .wp-block-post-template > li:hover { background: var(--carte); }
.index .wp-block-post-date { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	color: var(--texte-doux); margin: 0; }
.index h2, .index h3 { font-size: 28px; line-height: 1.1; }
.index h2 a, .index h3 a { text-decoration: none; }
.index li:hover h2 a, .index li:hover h3 a { text-decoration: underline;
	text-decoration-color: var(--accent); text-underline-offset: 6px; }
.index p { margin: 0; font-size: var(--t-mention); line-height: 25px; color: var(--texte-doux); }

/* Sur l'accueil, le journal reste en trois colonnes. */
.journal .wp-block-post-template { display: grid; grid-template-columns: repeat(3, 1fr);
	gap: var(--e6); list-style: none; margin: 0; padding: 0; }
.journal .wp-block-post-template > li { display: flex; flex-direction: column;
	border-top: 1px solid var(--trait); padding-top: var(--e4); margin: 0; }
.journal .wp-block-post-date { font-family: var(--mono); font-size: var(--t-mention); letter-spacing: .12em;
	color: var(--texte-doux); margin: 0 0 var(--e3); }
.journal h3 { font-size: 24px; line-height: 1.15; margin-bottom: var(--e3); }
.journal h3 a { text-decoration: none; }
.journal p { margin: 0; font-size: var(--t-corps); line-height: 27px; }

/* ═══ LE REPÈRE D'IMAGE DES ARTICLES ═════════════════════════════════════ *
 * Une carte d'article sans visuel est une colonne de texte : trois côte à
 * côte se lisent comme un tableau, pas comme un journal. Les articles n'ont
 * pas encore d'image — celui qui en aura une la verra s'afficher à sa place,
 * et le repère disparaît.
 *
 * CE N'EST PAS UNE FAUSSE PHOTOGRAPHIE. C'est la grille de cases du site,
 * au repos : le même geste que la couverture, la porte et la mosaïque d'un
 * livre. Un rectangle gris dirait « image cassée » ; un visuel d'emprunt
 * mentirait. Celui-ci dit « sa place est là, elle n'est pas encore prise ».
 *
 * `:has()` fait le partage : le repère n'est posé que sur les cartes qui
 * n'ont PAS d'image. Sans lui, il faudrait un marqueur côté serveur sur
 * chaque article, c'est-à-dire une donnée de plus à tenir à jour. */
.journal .wp-block-post-featured-image,
.maconnerie .wp-block-post-featured-image {
	margin: 0 0 var(--e3);
	overflow: hidden;
	background: var(--carte);
}
.journal .wp-block-post-featured-image img,
.maconnerie .wp-block-post-featured-image img {
	width: 100%; height: 100%; object-fit: cover; display: block;
}
.journal .wp-block-post-template > li:not(:has(.wp-block-post-featured-image img))::before,
.maconnerie .wp-block-post-template > li:not(:has(.wp-block-post-featured-image img))::before {
	content: "";
	display: block;
	aspect-ratio: 4 / 3;
	margin-bottom: var(--e3);
	background:
		repeating-linear-gradient(90deg, var(--trait) 0 1px, transparent 1px 25%),
		repeating-linear-gradient(0deg, var(--trait) 0 1px, transparent 1px 33.34%),
		var(--carte);
	border: 1px solid var(--trait);
}

/* ═══ 12. Le contact ══════════════════════════════════════════════════════ *
 * Les champs n'ont qu'un filet sous eux : un cadre complet ferait formulaire
 * administratif, ce que cette page n'est pas. */

.contact { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e7); padding: var(--e7) var(--marge); }
.coord { margin: var(--e6) 0 0; display: grid; grid-template-columns: 11ch 1fr; border-top: 1px solid var(--trait); }
/* 🔴 DEUX TRAITS POUR UN SEUL SEUIL — corrigé le 31.10.2026. `.filet-titre`
   pose déjà un filet sous son étiquette ; `.coord` en posait un second
   au-dessus de sa première ligne, et les soixante-quatre pixels de marge
   entre les deux les montraient comme une double règle encadrant du vide.
   Sous « ME JOINDRE », c'est exactement ce qu'on voyait. Quand un titre a
   déjà tracé la ligne, la liste n'en retrace pas une. */
.filet-titre + .coord { margin-top: var(--e4); border-top: 0; }

/* L'encadré « Avant d'écrire » revient dans la colonne des coordonnées le
   02.11.2026, mais DESSOUS et non DEDANS : « sous l'autre boîte bleue, sur
   une colonne, un quart de colonne ».

   Les deux essais précédents disaient pourquoi c'est la bonne place. En bas
   de page après le portrait, on le lisait le message déjà parti. Dans le bloc
   navy, un fond navy sur un fond navy ne se voit pas — il y avait perdu sa
   boîte et n'était plus qu'un paragraphe sous un filet.

   Ici il reste une boîte, et c'est le crème de la page entre les deux plaques
   qui les fait deux. La colonne porte donc un empilement, pas un bloc : d'où
   ce conteneur, qui est ce que la grille range en 1/5 pendant que les plaques
   se succèdent dedans. `.encadre` apporte un `margin` de --e6 fait pour une
   pleine largeur ; dans une colonne c'est un trou, --e4 suffit. */
.colonne-joindre { display: flex; flex-direction: column; }
.colonne-joindre .encadre { margin: var(--e4) 0 0; }

/* La mention qui remplace la case à cocher : une information, pas une
   formalité. Elle se lit, elle ne se coche pas. */
.mention {
	margin: var(--e4) 0 0;
	font-size: var(--t-mention); line-height: 23px;
	color: var(--texte-doux);
}
.mention a { color: inherit; border-bottom: 1px solid var(--accent); text-decoration: none; }
.coord dt { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em; text-transform: uppercase;
	color: var(--texte-doux); padding: var(--e4) 0; border-bottom: 1px solid var(--trait); }
.coord dd { margin: 0; padding: var(--e4) 0; border-bottom: 1px solid var(--trait); color: var(--navy); }
/* LES FORMULAIRES SONT CEUX DE FLUENT FORMS, et son balisage n'est pas le
   nôtre : ni `.champ`, ni `.accord`. Ces règles reprennent, classe pour
   classe, la grammaire du formulaire dessiné à la main qu'elles remplacent —
   libellé en mono capitales, champ sans bordure sauf un filet dessous, laiton
   à la prise de focus. L'extension charge sa propre feuille avant celle-ci,
   donc l'ordre suffit et aucune règle n'a besoin de `!important`.

   Les sélecteurs portent tous le préfixe `.fluentform`, qui est le conteneur
   que l'extension écrit autour de chaque formulaire. Ne pas viser `form` nu :
   l'écran d'administration en pose d'autres. */
/* ⚠️ UN CHAMP DOIT RESSEMBLER À UN CHAMP — corrigé le 29.10.2026.
   Les champs n'avaient qu'un filet par-dessous, posé sur le fond de page.
   Sur la page Contact, le résultat se lisait à l'envers : le bloc navy des
   coordonnées, lui, est plein — c'est donc LUI qui ressemblait au
   formulaire, et le formulaire ressemblait à du vide avec un bouton
   « Envoyer » posé au milieu. « On ne voit pas le formulaire », et c'était
   vrai.
   Un champ a maintenant une surface et un bord. Ce n'est pas un recul sur la
   sobriété : un filet seul est une convention de maquette, pas d'usage, et
   personne ne clique dans du vide. */

/* EN FLUX NORMAL, PAS EN GRILLE. L'extension pose un groupe par champ, plus un
   leurre anti-robot en position absolue : une grille compterait ce leurre
   parmi ses pistes et l'espacement cesserait de correspondre à ce qu'on lit.
   Une marge par groupe se mesure à l'œil et ne ment pas. */
.fluentform form { display: block; }
.fluentform .ff-el-group { margin: 0 0 var(--e5); }
.fluentform .ff-el-input--label label,
.fluentform .ff-el-input--label { display: block; font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .14em; text-transform: uppercase; color: var(--texte-doux); margin-bottom: var(--e2); }
.fluentform .ff-el-form-control { width: 100%; font: inherit; color: var(--navy);
	background: var(--creme); border: 1px solid var(--trait); padding: 13px 15px;
	border-radius: 0; box-shadow: none; transition: border-color .18s ease; }
.fluentform .ff-el-form-control:focus { outline: 0; border-color: var(--accent);
	box-shadow: inset 0 0 0 1px var(--accent); }
.fluentform textarea.ff-el-form-control { min-height: 140px; resize: vertical; }
.fluentform .ff-el-help-message { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .08em;
	font-style: normal; color: var(--texte-doux); margin: var(--e2) 0 var(--e3); }

/* L'ASTÉRISQUE DU CHAMP OBLIGATOIRE EST ROUGE chez Fluent Forms, et le rouge
   n'est pas dans la palette. Au laiton, il redevient une ponctuation. Le
   sélecteur recopie celui de l'extension — quatre classes et un pseudo —
   parce qu'un sélecteur plus court perd, quelle que soit sa place. */
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-right label:after,
.fluentform .ff-el-input--label.ff-el-is-required.asterisk-left label:before { color: var(--accent); }

/* Et le rouge d'alerte de l'extension prend celui de la maison, une fois pour
   toutes : il est déclaré en variable, donc il suffit de la redéfinir. */
.fluentform { --fluentform-danger: var(--alerte); }

/* LE CONSENTEMENT : une case et une phrase, pas un libellé de champ. La case
   est DANS le libellé, pas à côté — c'est donc le libellé qui porte la
   rangée, sinon la phrase vient coller la case. */
.fluentform .ff-el-form-check-label { display: flex; gap: 12px; align-items: flex-start;
	font-family: var(--texte-f); font-size: var(--t-mention); line-height: 24px; letter-spacing: 0;
	text-transform: none; color: var(--texte-doux); margin: 0; }
.fluentform .ff-el-form-check-input { flex: 0 0 auto; margin-top: 4px; accent-color: var(--navy); }

/* Le bouton : celui du site. L'extension pose une couleur de fond en style
   calculé, que le script de pose règle sur le navy — ici on tient la forme. */
.fluentform .ff-btn-submit { display: inline-flex; align-items: center; gap: 14px;
	font-family: var(--mono); font-size: var(--t-action); letter-spacing: .1em; text-transform: uppercase;
	color: var(--sur-navy); text-decoration: none; padding: 18px 26px; border: 0; border-radius: 0;
	cursor: pointer; transition: background .18s ease; }

/* Ce que l'extension dit quand quelque chose manque, et quand tout est parti. */
.fluentform .error, .fluentform .text-danger { font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .08em; text-transform: uppercase; color: var(--alerte); margin: var(--e2) 0 0; }
.fluentform .ff-message-success { font-family: var(--texte-f); color: var(--navy);
	border-left: 2px solid var(--accent); padding: var(--e3) 0 var(--e3) var(--e4); }

/* ═══ 13. Téléphone ═══════════════════════════════════════════════════════ */

@media (max-width: 1100px) {
	.livres-grille { grid-template-columns: repeat(4, 1fr); }
	.donnees { grid-template-columns: repeat(2, 1fr); }
	.ecuries { grid-template-columns: repeat(2, 1fr); }
	.index .wp-block-post-template > li { grid-template-columns: 110px 1fr; }
	.index p { grid-column: 2; }
	.contact, .fiche-marque { grid-template-columns: 1fr; gap: var(--e5); }
	.une .wp-block-post-template > li { grid-template-columns: 1fr; gap: var(--e4); }
	.journal .wp-block-post-template { grid-template-columns: 1fr 1fr; }
	.pied-cols { grid-template-columns: repeat(3, 1fr); gap: var(--e6); }
	.specs { grid-template-columns: 1fr; gap: 0; }
}

@media (max-width: 900px) {
	:root { --marge: 20px; --e7: 72px; }

	/* Le logo tient le bord gauche et le burger le bord droit : deux masses,
	   pas trois. La grille à trois colonnes de l'ordinateur n'a plus de
	   milieu à tenir. */

	/* 🔴 FIXE, ET FIXE TOUT LE TEMPS — PAS SEULEMENT UNE FOIS OUVERTE.
	   Première écriture du panneau plein écran : la barre restait collante
	   et passait en `fixed` à l'ouverture. Elle quittait donc le flux à ce
	   moment-là, le document perdait sa hauteur, et au refermement le
	   navigateur reposait la page ailleurs — mesuré : parti de 1200 px de
	   défilement, on en retrouvait 814. Ouvrir un menu puis renoncer ne doit
	   pas déplacer la page qu'on était en train de lire.
	   Fixée dès le départ, l'ouverture ne change plus rien au flux.

	   LA PLACE QU'ELLE NE PREND PLUS SE REND AU CONTENU, une fois, sur le
	   conteneur du site. `--hd-h` se déduit des trois valeurs ci-dessous —
	   garde, logo, filet — et les quatre lignes se déplacent ensemble.
	   Sur téléphone la barre ne rétrécit PAS au défilement : le logo y est
	   écrit à 44 px, ce que `html.a-defile` ne touche pas. Sa hauteur est
	   donc constante, et c'est ce qui rend ce calcul juste.

	   🔴 ET C'EST `--hd`, LA VARIABLE QUI EXISTAIT DÉJÀ. Elle valait 96 px
	   pour tout le monde — un nombre posé une fois, jamais revu. La
	   couverture de l'accueil s'en sert pour se coller sous la barre
	   (`.couv { top: var(--hd) }`) : sur téléphone elle se collait donc
	   31 px TROP BAS, et cette bande de crème au-dessus de la photographie
	   est exactement ce que Lina avait signalé le 31.10 — « cette photo
	   collée à gauche et pas de marge supérieure ». La cause n'était pas
	   dans la photo, elle était dans ce 96.
	   ⚠️ Sur grand écran, 96 reste une approximation : la barre fait 133 au
	   repos et 56 une fois défilée. À mesurer et corriger à part — y
	   toucher ici changerait la couverture de bureau sans l'avoir regardée.

	   ⚠️ LA VALEUR N'EST PAS ÉCRITE ICI, MAIS À CÔTÉ DE CELLE QU'ELLE
	   REMPLACE — `:root { --hd: 96px }`, au-dessus de `.piste-couv`. Posée
	   dans ce bloc-ci, elle arrivait AVANT dans la feuille, à spécificité
	   égale, et c'est le 96 qui gagnait : la bande de crème restait, pour
	   une raison qui n'avait plus rien à voir avec celle d'avant. Deux
	   valeurs d'une même variable se tiennent au même endroit, sinon
	   l'ordre du fichier devient une règle invisible. */
	.wp-site-blocks { padding-top: var(--hd); }
	.hd {
		position: fixed;
		top: 0; left: 0; right: 0;
		padding: 10px var(--marge);
		grid-template-columns: 1fr auto;
		row-gap: 0;
	}
	/* 🔴 CES DEUX RÈGLES VISAIENT `.wp-block-site-logo`, le bloc que le
	   logo n'est plus depuis qu'il est en SVG. Plus rien ne le plaçait : il
	   tombait dans le flux, donc ENTRE les deux moitiés du menu. C'est le
	   genre de casse qu'un renommage laisse derrière lui, et qu'aucune
	   erreur ne signale — une règle qui ne matche plus se tait. */
	.hd .hd-logo { grid-column: 1; grid-row: 1; }
	.hd .lha-logo { height: 44px; }
	.hd-burger { display: flex; grid-column: 2; grid-row: 1; justify-self: end; }

	/* ⚠️ `> `, ET C'EST TOUTE LA DIFFÉRENCE. WordPress pose la classe
	   `wp-block-navigation` DEUX fois : sur le `<nav>` et sur le `<ul>`
	   qu'il contient. Écrite en descendant, la règle repliait aussi la
	   liste — et le sélecteur de frère `~`, qui n'atteint que le `<nav>`,
	   ne pouvait pas la rouvrir. Résultat : le `<nav>` passait bien à
	   422 px, la liste restait à zéro, et le menu s'ouvrait sur du vide.
	   Fermé, le panneau ne prend aucune hauteur — sans quoi la barre
	   garderait la place d'un menu qu'on ne voit pas. */
	.hd > .wp-block-navigation {
		grid-column: 1 / -1;
		display: grid; gap: 0;
		max-height: 0; overflow: hidden;
		transition: max-height .28s ease;
	}
	.hd .wp-block-navigation__container {
		display: grid; gap: 0;
		max-height: none; overflow: visible;
	}
	/* 🔴 LE MENU OUVERT PREND L'ÉCRAN, ET PAS LA MOITIÉ. Premier réglage :
	   `max-height: 50svh`, donc un panneau qui s'arrêtait au milieu avec la
	   page dessous. Ce n'est pas un détail d'esthétique — un menu posé sur
	   un titre qu'on lisait une seconde plus tôt ne dit pas qu'il a pris la
	   main, et le pouce qui le ferme touche un lien de la page derrière.
	   Vu sur iPhone le 31.10.2026, capture à l'appui.

	   `position: fixed` plutôt qu'une hauteur sur l'élément collant : collé,
	   il grandirait dans le flux et la page défilerait AVEC lui — on ouvre
	   le menu, on balaie, le menu s'en va vers le haut. Fixé, il tient
	   l'écran jusqu'à ce qu'on le ferme.

	   `100dvh` et non `100vh` : sur iOS la barre d'adresse se rétracte au
	   défilement, et `vh` compte la fenêtre détendue — le bas du menu
	   passait sous la barre d'outils de Safari. `dvh` suit la fenêtre réelle.
	   `overflow-y: auto` pour les écrans courts en paysage, et
	   `overscroll-behavior: contain` pour que le rebond du panneau ne
	   déclenche pas celui de la page. */
	.hd:has(.hd-bascule:checked) {
		bottom: 0;
		height: 100dvh;
		align-content: start;
		overflow-y: auto;
		overscroll-behavior: contain;
	}
	/* `.hd > *` centre tout verticalement : utile dans une barre, faux dans
	   un panneau plein écran où les rangées doivent se tasser en haut. Le
	   logo et le burger gardent leur centrage — ils sont la barre, qui
	   existe toujours. */
	.hd:has(.hd-bascule:checked) > .wp-block-navigation { align-self: start; }

	.hd-bascule:checked ~ .wp-block-navigation { max-height: 100dvh; }
	.hd-bascule:checked ~ .wp-block-navigation:first-of-type { margin-top: var(--e4); }

	/* ⚠️ LE FILET DOIT TRAVERSER, SINON IL N'EST PLUS UN FILET. Il courait
	   sous le mot et s'arrêtait avec lui : deux traits courts sous LIVRES et
	   UNIVERS, rien sous les autres, ce qui se lit comme un défaut et non
	   comme une règle. Les blocs de navigation de WordPress dimensionnent
	   leurs `<li>` au contenu ; il faut le leur dire. */
	/* ⚠️ `justify-content` SUR LE `<nav>`, ET C'EST LUI QUI COMPTE. Le menu de
	   droite l'avait déjà et traversait ; celui de gauche ne l'avait pas et
	   ses filets faisaient 98 px sur 350.

	   🔴 ET LA RÈGLE QUI MARCHAIT NE MARCHAIT PAS POUR LA RAISON QU'ON
	   CROYAIT. `.hd .hd-droite` ne visait pas le `<nav>` : WordPress recopie
	   `className` sur le `<nav>` ET sur le `<ul>`, donc elle attrapait les
	   deux — et c'est sur le `<ul>` qu'elle agissait, puisque c'est lui qui
	   porte la colonne des entrées. Celui de gauche gardait le
	   `justify-content: flex-start` des feuilles de WordPress, et sa piste
	   `auto` restait à la largeur du mot le plus long. Mesuré au navigateur,
	   `gridTemplateColumns` : « 98px » à gauche, « 350px » à droite.

	   Le même piège que la règle du panneau replié trente lignes plus haut,
	   et pour la même cause. On nomme donc le conteneur par SA classe à lui,
	   pas par celle qui déborde du `<nav>`. */
	.hd .wp-block-navigation__container { justify-content: stretch; justify-items: stretch; }
	.hd .wp-block-navigation .wp-block-navigation-item { width: 100%; }
	.hd .wp-block-navigation a {
		display: block;
		width: 100%;
		/* Dans une barre, un libellé de menu se balaie ; en plein écran, il
		   se vise au pouce. 26 px et 24 px de garde donnent une cible de
		   75 px, bien au-dessus des 44 recommandés — et cinq entrées qui
		   occupent l'écran au lieu de se tasser dans son premier tiers. */
		font-size: 26px;
		padding: 24px 0;
		border-bottom: 1px solid var(--trait);
	}
	.hd .hd-droite { justify-content: stretch; }

	/* 🔴 `a:last-child` LES VISAIT TOUS. Chaque `<a>` est l'enfant unique de
	   son `<li>`, donc il est aussi le dernier : la règle n'enlevait pas le
	   filet de la dernière entrée, elle l'enlevait des trois. D'où deux
	   filets sous le menu de gauche et aucun sous celui de droite — ce qui
	   se lit comme un bug d'affichage, et n'en était pas un : c'était le
	   sélecteur qui ne disait pas ce qu'on croyait lire. Le dernier, c'est
	   le dernier ÉLÉMENT DE LISTE. */
	.hd-bascule:checked ~ .wp-block-navigation.hd-droite
		.wp-block-navigation-item:last-child a { border-bottom: 0; }

	.ouverture .dedans { min-height: auto; padding: var(--e6) var(--marge) var(--e5); }
	.ouverture .voile { background: linear-gradient(to top, rgba(20,29,48,.95) 45%, rgba(20,29,48,.45)); }
	.donnees { grid-template-columns: 1fr; }
	.donnees > div { border-right: 0; border-bottom: 1px solid var(--trait);
		padding: var(--e3) var(--marge); }

	.rail::after { display: none; }
	.livres-piste > figure { flex: 0 0 132px; }
	.livres-grille { grid-template-columns: repeat(2, 1fr); gap: var(--e5) var(--e4); }

	.ecuries { grid-template-columns: 1fr; }
	.index .wp-block-post-template > li { grid-template-columns: 1fr; padding: var(--e5) var(--marge); }
	.une .wp-block-post-template > li { padding: var(--e6) var(--marge); }

	.doublepage .dedans { grid-template-columns: 1fr; gap: var(--e4); padding: var(--e5) var(--marge); }
	.doublepage p.legende { justify-self: start; text-align: left; }

	.journal .wp-block-post-template { grid-template-columns: 1fr; gap: var(--e5); }
	.fiche { grid-template-columns: 1fr; gap: var(--e4); }
	.pied-cols { grid-template-columns: 1fr; gap: var(--e5); }
	.pied-bas { flex-direction: column; align-items: flex-start; }
	.lecture, .colonne { padding: var(--e6) var(--marge); }
}

/* ═══ 14. Apparition au défilement ════════════════════════════════════════ *
 * Les sections sont VISIBLES par défaut ; elles ne se masquent que si le
 * script tourne, ce que la classe `js` sur la balise racine signale. Sans
 * cette garde, un script lent, bloqué ou en erreur laisse une page blanche —
 * c'est arrivé une fois pendant la conception, et ça arrive à des visiteurs. */

.lha-anim { opacity: 1; }
.js .lha-anim { opacity: 0; transform: translateY(16px); }
.js .lha-anim.lha-vu { opacity: 1; transform: none;
	transition: opacity .7s ease, transform .7s cubic-bezier(.2,.7,.2,1); }

@media (prefers-reduced-motion: reduce) {
	.lha-anim, .js .lha-anim, .js .lha-anim.lha-vu { opacity: 1; transform: none; transition: none; }
	.flip .scene { transition: none; }
	html { scroll-behavior: auto; }
}

/* ═══ 16. Le magazine : deux colonnes de texte ════════════════════════════ *
 * Une colonne unique de quarante-six signes convient à un article ; sur une
 * page « À propos » de mille deux cents mots, elle fabrique un ruban vertical
 * interminable. Deux colonnes coupent la hauteur de moitié sans raccourcir
 * une phrase. Le texte coule de l'une à l'autre — c'est la colonne de journal,
 * pas deux blocs juxtaposés. */

.colonnes {
	columns: 2;
	column-gap: var(--e7);
	max-width: 100ch;
}
.colonnes p, .colonnes li { break-inside: avoid; }
.colonnes > *:first-child { margin-top: 0; }
.colonnes p { margin: 0 0 var(--e4); }
.colonnes ul, .colonnes ol { margin: 0 0 var(--e4); padding-left: 1.2em; }
.colonnes li { margin: 0 0 var(--e2); }

.specs-tete { max-width: 52ch; margin-bottom: var(--e5); }
.specs-tete .eti { margin-bottom: var(--e3); }

/* Les deux listes du détail : côte à côte, chacune sous son intertitre. */
.deux-listes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--e5) var(--e7); align-items: start; }
.deux-listes h3 { font-size: 21px; margin-bottom: var(--e3); }
.deux-listes ul { margin: 0; padding-left: 1.2em; font-size: var(--t-corps); line-height: 27px; }
.deux-listes li { margin: 0 0 var(--e3); }

@media (max-width: 1100px) {
	.colonnes { columns: 1; }
	.deux-listes { grid-template-columns: 1fr; }
}

/* ═══ 17. La presse, en magazine ══════════════════════════════════════════ *
 * DEUX LECTURES, DEUX DENSITÉS.
 * « À la une » est une couverture : une tête d'affiche en grand, quatre
 * entrées en second rang. Cinq entrées de même taille ne feraient qu'un
 * tableau de plus.
 * L'index est un ours de fin de numéro : compact, par millésime, en colonnes.
 * Trente-cinq lignes pleine largeur faisaient dix mètres de page pour une
 * information qu'on parcourt des yeux. Le millésime en grand à gauche donne
 * le repère ; on voit toute une année d'un coup.
 */

.une-grille {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1px;
	background: var(--trait);
	border-block: 1px solid var(--trait);
	margin-inline: var(--gouttiere);
}
.une-item {
	grid-column: span 1;
	background: var(--creme);
	padding: var(--e5) var(--e4);
	display: flex;
	flex-direction: column;
	gap: var(--e3);
	text-decoration: none;
	color: inherit;
	transition: background .2s ease;
}
.une-item:hover { background: var(--carte); }
.une-item--tete { grid-column: span 4; padding: var(--e6) var(--e5); }

.une-item .m { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .16em;
	text-transform: uppercase; color: var(--accent-texte); }
.une-item .t { font-family: var(--titre); font-size: 21px; line-height: 1.15; color: var(--navy); }
.une-item--tete .t { font-size: clamp(30px, 3.4vw, 46px); line-height: 1.04; max-width: 24ch; }
.une-item .n { font-size: var(--t-mention); line-height: 25px; color: var(--texte-doux); max-width: 46ch; }
.une-item .x { margin-top: auto; font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--texte-doux); }
a.une-item:hover .t { text-decoration: underline; text-decoration-color: var(--accent);
	text-underline-offset: 6px; }

/* ─── LA COUPURE ─────────────────────────────────────────────────────────── *
 * Une liste de trente-cinq lignes dit ce qui a été publié ; un mur de pages
 * imprimées le MONTRE. Et ces pages existent : dix-neuf PDF et un scan,
 * rendus à leur première page et rattachés à leur parution.
 *
 * 🔴 `.mur-coupures` ET `.millesime` SONT MORTS LE 30.10.2026. Le mur était
 * une grille à colonnes libres dans huit sections de millésime ; l'année est
 * devenue un filtre, et la grille une mosaïque. La coupure elle-même ne
 * change pas : c'est la TUILE qui change de grille, pas son contenu.
 *
 * L'ANGLE A DISPARU AVEC LE MUR. Il se déduisait du rang, et dans une
 * mosaïque à emprises variables, une tuile de 2 × 2 penchée mord ses
 * voisines. Ce qu'il apportait — « une page posée sur une table » — est
 * désormais porté par les tailles, qui disent la même chose sans trembler. */
.coupure {
	display: flex;
	flex-direction: column;
	gap: 9px;
	text-decoration: none;
	color: inherit;
	transition: transform 400ms cubic-bezier(.16, 1, .3, 1);
}
.coupure:hover, .coupure:focus-visible { transform: translateY(-5px); }
/* L'ARTICLE DONT ON N'A PAS LA PAGE. Il ne porte pas de vignette — fabriquer
   une image pour annoncer qu'on n'en a pas, c'est meubler. Mais il ne peut
   pas non plus flotter sans rien : dans un mur de pages posées, une entrée
   sans cadre se lit comme une erreur de chargement. Un filet en tête lui
   donne son bord, et il ne penche pas : ce n'est pas une feuille posée sur
   la table, c'est une ligne de sommaire. */
.coupure--nue {
	border-top: 2px solid var(--navy);
	padding-top: var(--e3);
	transform: none;
}
.coupure--nue:hover, .coupure--nue:focus-visible { transform: translateY(-5px); }
.coupure .vign {
	display: block;
	aspect-ratio: 3 / 4;
	overflow: hidden;
	background: var(--blanc);
	border: 1px solid var(--trait);
	position: relative;
}
.coupure .vign img, .une-item .vign img {
	width: 100%; height: 100%;
	object-fit: cover; object-position: 50% 0;
}
/* La plaque d'une parution sans page imprimée. Elle NOMME ce qu'elle est :
   un cadre gris laisserait croire à une image qui n'a pas chargé.
   Le sélecteur porte son parent : `.coupure .vign` pose déjà un fond blanc
   avec deux classes, et une seule classe ne le bat pas. */
.coupure .vign--plaque, .une-item .vign--plaque { background: var(--navy); border-color: var(--navy); }
.vign--plaque::after {
	content: attr(data-mot);
	position: absolute; inset: 0;
	display: grid; place-items: center;
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .2em; text-transform: uppercase;
	color: var(--laiton-vif);
}
.onde {
	position: absolute; inset: auto 14px 16px;
	display: flex; align-items: flex-end; gap: 2px; height: 34px;
}
.onde i { flex: 1; background: var(--laiton-vif); opacity: .5; }

/* LA PLAQUE QUI PORTE UN LOGO REPASSE AU CRÈME. Les logos des stations sont
   dessinés pour du blanc — en noir ou en couleur foncée — et sur le navy ils
   s'effacent. C'est le seul endroit du site où le fond suit l'image qu'il
   porte, et c'est le bon : on ne recolore pas le logo de quelqu'un d'autre.
   Le sélecteur porte son parent, comme la plaque : sinon `.coupure .vign`
   (deux classes) l'emporte et le fond reste blanc cassé. */
.coupure .vign--logo, .une-item .vign--logo {
	background: var(--carte); border-color: var(--trait);
	display: grid; place-items: center; padding: var(--e4);
}
.coupure .vign--logo img, .une-item .vign--logo img {
	width: auto; max-width: 74%; height: auto; max-height: 46%;
	object-fit: contain;
}
.vign--logo .onde i { background: var(--navy); opacity: .22; }
.coupure .m { font-family: var(--titre); font-size: 19px; line-height: 1; color: var(--navy); }
.coupure .x { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .13em;
	text-transform: uppercase; color: var(--accent-texte); }
/* LE TITRE D'UNE COUPURE EST CE QU'ON LIT DANS LE MUR. Le nom du journal
   attire l'œil, mais c'est le titre de l'article qui dit si on clique — il a
   donc le corps du texte, pas celui d'une légende. */
.coupure .t { font-size: var(--t-corps); line-height: 1.45; color: var(--texte); }
a.coupure:hover .t { text-decoration: underline; text-decoration-color: var(--accent);
	text-underline-offset: 4px; }
/* Une parution sans lien reste lisible, mais ne se donne pas l'air cliquable. */
.coupure--muette .m { color: var(--texte); }

/* La une porte sa coupure en tête, et la tête d'affiche la porte en grand. */
.une-item .vign { display: block; aspect-ratio: 3 / 4; overflow: hidden;
	background: var(--blanc); border: 1px solid var(--trait); position: relative;
	margin-bottom: var(--e3); }
.une-item--tete .vign { aspect-ratio: 16 / 9; }

/* ⚠️ UNE PLAQUE À LOGO N'EST PAS UNE PAGE IMPRIMÉE, et elle ne doit pas en
   prendre la hauteur. Relevé par Yan sur v2 le 30.10.2026 : la tête d'affiche
   de Monde Économique rendait un rectangle blanc de huit cents pixels avec un
   petit logo rouge dans le coin. « Beaucoup d'espace blanc, un petit peu
   gâché » — et il a raison : une coupure scannée MÉRITE sa hauteur, parce
   qu'il y a une page à lire dedans. Un logo n'a rien à montrer de plus que
   lui-même.

   La plaque prend donc une bande, pas un cadre, et le logo y occupe une part
   franche. C'est aussi ce qui remet le TITRE de l'article dans l'écran : sur
   la capture, il commençait sous la ligne de flottaison. */
.une-item .vign--logo { aspect-ratio: 5 / 2; padding: var(--e4) var(--e5); }
.une-item--tete .vign--logo { aspect-ratio: 16 / 5; }
.une-item .vign--logo img { max-width: 58%; max-height: 72%; }
/* Dans le mur, même raison et même remède. */
.pavage--presse .coupure .vign--logo { aspect-ratio: 5 / 2; flex: 0 0 auto; }
.pavage--presse .mo-tuile--tete .vign--logo { aspect-ratio: 16 / 5; }
/* LA TUILE DE TÊTE SE DISTINGUE DANS LA MOSAÏQUE UNIQUE. Depuis que « À la
   une » n'a plus sa propre section, c'est la tuile elle-même qui doit dire
   qu'elle compte : « les articles qui sont en haut, il faut qu'ils soient un
   petit peu plus grands, mis en évidence dans la mosaïque. Il peut même
   avoir un cadre ou être légèrement différencié. »
   Elle l'est déjà par sa taille — 2 × 2 cases contre 1 × 2. Le cadre laiton
   et le fond plein ajoutent le second signe, celui qui se voit sans
   comparer : on ne compte pas les cases d'une mosaïque, on reconnaît une
   tuile qui n'est pas comme les autres. */
/* 🔴 LA UNE NE PREND PLUS DEUX CASES SUR DEUX — 01.11.2026. « Les cinq
   premiers ne doivent pas être plus grands que les autres. » Ils l'étaient :
   628 × 618 contre 302 × 374, soit quatre fois la surface, et ils étaient
   CINQ. Une tuile qui n'est pas comme les autres se reconnaît ; cinq tuiles
   sur trente-cinq, c'est une deuxième rangée de normes.
   Le marqueur reste — filet d'accent et fond plus clair — parce que « à la
   une » est une décision de Lina et doit se voir. C'est la TAILLE qui
   cesse de la porter, pas le rang. */
.pavage--presse .mo-tuile--tete {
	grid-column: span 1;
	grid-row: span 1;
	border: 1px solid var(--accent);
	background: var(--creme-2);
}
/* Le titre suit : un corps de trente pixels était calibré sur une tuile de
   628 px de large, il déborderait dans une de 302. */
.pavage--presse .mo-tuile--tete .t { font-size: clamp(17px, 1.3vw, 20px); line-height: 1.15; }

@media (max-width: 1100px) {
	.une-grille { grid-template-columns: repeat(2, 1fr); }
	.une-item--tete { grid-column: span 2; }
}
@media (max-width: 900px) {
	.une-grille { grid-template-columns: 1fr; }
	.une-item--tete { grid-column: span 1; }
}


/* ═══ 18. La gouttière, en dernier ═══════════════════════════════════════ *
 * Cette règle doit venir APRÈS toutes les autres. Placée en tête, elle
 * était annulée par chaque `padding` en raccourci écrit plus bas — le
 * bandeau gardait sa marge de soixante-quatre pixels pendant que les
 * sections voisines prenaient la gouttière, et les deux ne s'alignaient
 * plus. Un défaut d'ordre, invisible à la lecture du fichier. */

/* LE CONTENEUR DE PAGE, PAR LA GOUTTIÈRE ET NON PAR UNE LARGEUR.
   Première tentative : poser `max-width` + `margin-inline: auto` sur chaque
   bloc. Résultat : les titres se centraient — un titre borné à seize signes
   et centré automatiquement se retrouve au milieu de l'écran — et les
   filtres s'écartaient jusqu'aux bords.
   La bonne façon est de gonfler la MARGE LATÉRALE au lieu de rétrécir le
   contenu : la colonne reste alignée à gauche, et c'est le blanc qui grandit
   sur les grands écrans. Un seul calcul, valable partout. */
:root {
	--gouttiere: max(var(--marge), (100% - var(--large)) / 2);
}
.bandeau, .sect, .filtres, .contact,
.fiche, .fiche-marque, .lecture, .colonne, .pied,
.une .wp-block-post-template > li,
.index .wp-block-post-template > li {
	padding-inline: var(--gouttiere);
}
.donnees > div:first-child { padding-left: var(--gouttiere); }
.donnees > div:last-child { padding-right: var(--gouttiere); }
.lecture, .colonne { max-width: none; }
.lecture > *, .colonne > * { max-width: var(--mesure); }
/* ⚠️ SAUF UNE SECTION, et c'est l'exception qui manquait. Une `.sect` posée
   DANS une page de lecture héritait de la mesure : les chapitres d'« À
   propos » tenaient donc dans quarante-six signes, RAIL DE NUMÉROS COMPRIS.
   Il restait deux cent vingt pixels pour le texte, sur une page large de
   mille quatre cents. Une section a sa propre architecture — c'est son
   paragraphe qui porte la mesure, pas son cadre. */
.lecture > .sect, .colonne > .sect { max-width: none; padding-inline: 0; }
/* 🔴 ET LE MUR DE MACROS, POUR LA MÊME RAISON — 01.11.2026. La mosaïque de
   détails est posée DANS le texte des trois pages qui en portent une ; elle
   héritait donc de la mesure et tombait à 649 px sur une page de 1440, avec
   une grande tuile de 256 px et quatre de 124. Ce n'était plus un mur, c'était
   une vignette, et Yan l'a lu comme une suppression : « je t'avais dit de les
   mettre à un autre endroit et tu les as complètement supprimées. »
   Elle était là. Elle n'était plus regardable. Un élément qu'on ne reconnaît
   plus a disparu, quoi qu'en dise le HTML.
   Un mur prend la page, et seulement ses marges : c'est ce que fait tout
   `gab--mur` posé hors d'une colonne de lecture. */
.lecture > .gab--mur, .colonne > .gab--mur {
	max-width: none;
	/* ⚠️ ZÉRO, ET NON LA GOUTTIÈRE : la colonne de lecture pose DÉJÀ ses
	   marges latérales. Les deux s'additionnaient — le mur d'« À propos »
	   mesurait 1120 px de contenu contre 1280 sur les trois autres pages,
	   soit une marge de plus pour la même section. Deux pages qui portent le
	   même bloc doivent le porter à la même largeur, sinon ce n'est plus le
	   même bloc. */
	padding-inline: 0;
}
.ouverture .dedans, .doublepage .dedans { padding-inline: var(--gouttiere); }

/* ═══ 19. L'ARCHITECTURE ÉDITORIALE ═══════════════════════════════════════ *
 *
 * Ce qui manquait : une GRILLE. Jusqu'ici chaque section inventait sa propre
 * division — 7fr/5fr ici, 1fr/1fr là, quatre colonnes ailleurs. Résultat :
 * rien ne s'alignait d'une section à l'autre, et la page se lisait comme une
 * suite de blocs plutôt que comme un numéro.
 *
 * Douze colonnes, une seule gouttière, et TOUT s'y accroche. C'est la
 * condition d'une page qui tient : l'œil retrouve les mêmes verticales en
 * descendant, même quand le contenu change de nature.
 *
 * ── LE CONTRASTE D'ÉCHELLE EST LA SIGNATURE ────────────────────────────────
 * Un magazine se reconnaît à l'écart entre le très grand et le très petit :
 * un mot de deux cents pixels, et à côté un texte de treize. Pas de tailles
 * intermédiaires molles. Le grand porte, le petit informe.
 *
 * ── LE NAVY DEVIENT UNE MATIÈRE ────────────────────────────────────────────
 * Il ne sert plus seulement de bande pleine largeur : il devient un BLOC qu'on
 * pose dans la grille, à la taille qu'on veut. C'est lui qui donne le
 * contrepoids, et c'est ce qui manquait pour que la composition tienne debout
 * au lieu de s'empiler.
 */

.edito {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	column-gap: var(--e4);
	row-gap: 0;
	padding-inline: var(--gouttiere);
	align-items: start;
}

/* Les placements, nommés par ce qu'ils font et non par leurs numéros. */
.c1-4  { grid-column: 1 / 5; }
.c1-5  { grid-column: 1 / 6; }
.c1-6  { grid-column: 1 / 7; }
.c1-7  { grid-column: 1 / 8; }
.c1-8  { grid-column: 1 / 9; }
.c1-12 { grid-column: 1 / -1; }
.c2-7  { grid-column: 2 / 8; }
.c3-8  { grid-column: 3 / 9; }
.c4-9  { grid-column: 4 / 10; }
.c5-9  { grid-column: 5 / 10; }
.c6-12 { grid-column: 6 / -1; }
.c7-12 { grid-column: 7 / -1; }
.c8-12 { grid-column: 8 / -1; }
.c9-12 { grid-column: 9 / -1; }
.c10-12{ grid-column: 10 / -1; }

/* ── LE TRÈS GRAND ──────────────────────────────────────────────────────── */

/* Le mot d'affiche. Instrument Sans en 700, très serré, en capitales : c'est
   la voix « brute » du magazine. Le serif reste pour ce qui se lit, le
   grotesque prend ce qui s'affiche — deux registres, jamais mélangés. */
.geant {
	font-family: var(--texte-f);
	font-weight: 700;
	/* LA TAILLE SUIT LA PAGE, PAS L'ÉCRAN. Avec un `vw`, le mot continuait de
	   grandir après que la page a cessé de s'élargir : sur un 1600, il sortait
	   de ses sept colonnes et percutait le lien voisin. Il est désormais borné
	   par la largeur de page elle-même. */
	font-size: clamp(48px, 10.5vw, calc(var(--large) * 0.115));
	line-height: .84;
	letter-spacing: -.045em;
	text-transform: uppercase;
	color: var(--navy);
	margin: 0;
	text-wrap: nowrap;
}
.geant em { font-family: var(--titre); font-weight: 400; font-style: italic;
	text-transform: none; letter-spacing: -.02em; }

/* LA TAILLE SUIT LE NOMBRE DE COLONNES OCCUPÉES, pas l'humeur. Un mot
   d'affiche est en `nowrap` : s'il est trop grand pour sa cellule il ne se
   coupe pas, il DÉBORDE — et il passe sous le bloc voisin, qui est peint
   après lui. Trois tailles, une par largeur de cellule usuelle. */
.geant--8col { font-size: clamp(48px, 10.5vw, calc(var(--large) * 0.115)); }
.geant--6col { font-size: clamp(40px,  7.5vw, calc(var(--large) * 0.078)); }
.geant--5col { font-size: clamp(36px,  6.2vw, calc(var(--large) * 0.062)); }

/* Le chiffre d'appel : un millésime, un compte, un numéro de section. */
.chiffre {
	font-family: var(--titre);
	font-weight: 400;
	font-size: clamp(88px, 15vw, calc(var(--large) * 0.17));
	line-height: .76;
	letter-spacing: -.03em;
	color: var(--navy);
	margin: 0;
	font-variant-numeric: lining-nums;
}
.chiffre--clair { color: var(--sur-navy); }

/* ── LE TRÈS PETIT ──────────────────────────────────────────────────────── */

/* Le chapô de magazine : une colonne étroite, et un corps un peu plus grand
   que le texte courant. Il était à quinze — la taille de la NAVIGATION —
   parce que c'était le seul degré disponible sous les titres. Sa densité
   vient de sa colonne, jamais de son corps. */
.menu {
	font-size: var(--t-chapo);
	line-height: 29px;
	color: var(--texte);
	margin: 0;
	max-width: 34ch;
}
.menu + .menu { margin-top: var(--e3); }
.menu--clair { color: var(--sur-navy-doux); }

/* L'étiquette de colonne, verticale sur les grands écrans : elle marque la
   verticale de grille sans consommer de hauteur. */
.filet-titre {
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--accent-texte);
	margin: 0 0 var(--e3);
	padding-bottom: var(--e2);
	border-bottom: 1px solid var(--navy);
}

/* ── LE FOLIO, ET POURQUOI IL N'EST PAS UNE ÉTIQUETTE ─────────────────────
 *
 * 🔴 DEUX SURTITRES EN VIS-À-VIS NE SE FONT PAS — corrigé le 31.10.2026.
 * Six pages ouvraient sur une paire : la rubrique et une période à gauche,
 * un décompte à droite, chacun souligné de son filet. Un magazine met la
 * rubrique à UN endroit ; deux départs soulignés font deux entrées de
 * lecture concurrentes, et l'œil ne sait pas laquelle est le début. C'est la
 * même cause que le « trop d'espace mal structuré » relevé sur la presse.
 *
 * Et le surtitre ne travaillait pas. Sur `/livres/`, « LA COLLECTION »
 * arrive après un menu qui dit LIVRES et un onglet qui dit « Livres — Lina
 * Hadid » : c'est la quatrième fois qu'on nomme la page avant la première
 * phrase utile. Sur papier le repère vit dans la marge et ne coûte rien ;
 * ici il occupait le premier tiers de l'ouverture.
 *
 * CE QUI ÉTAIT UNE DONNÉE NE DISPARAÎT PAS, IL CHANGE DE STATUT. « 22
 * TITRES » n'est pas une rubrique : habillé en étiquette de navigation, un
 * chiffre porte le vêtement de quelqu'un d'autre. Il redescend en bas de
 * l'ouverture, juste au-dessus du filet de séparation — la place de l'ours
 * dans un magazine. Il reste consultable sans ouvrir la page, et il ne
 * retarde plus le titre.
 *
 * IL EST PLUS PÂLE ET PLUS PETIT QUE L'ÉTIQUETTE, ET SANS FILET. C'est ce
 * qui le fait lire comme une mention et non comme un titre : deux signes
 * identiques à deux fonctions différentes, c'est le défaut qu'on vient de
 * retirer.
 *
 * L'étiquette, elle, reste partout où elle NOMME UN BLOC dans une page
 * longue — « ME JOINDRE », « À LA UNE », « EN UNE PHRASE ». Là elle est
 * l'intertitre de colonne du magazine, et elle garde son filet. */
.folio {
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--texte-doux);
	margin: var(--e6) 0 0;
	align-self: end;
}

/* ── LE NAVY COMME BLOC ─────────────────────────────────────────────────── */

.bloc {
	background: var(--navy);
	color: var(--sur-navy);
	padding: var(--e5);
	display: flex;
	flex-direction: column;
	gap: var(--e4);
}
.bloc h2, .bloc h3, .bloc .chiffre { color: var(--sur-navy); }
.bloc .filet-titre { color: var(--sur-navy-doux); border-bottom-color: rgba(236,230,218,.4); }
.bloc--haut { min-height: 380px; justify-content: space-between; }
.bloc-image { position: relative; overflow: hidden; background: var(--navy); min-height: 380px; }
.bloc-image img { width: 100%; height: 100%; object-fit: cover;
	filter: grayscale(1) contrast(1.25) brightness(1.04); mix-blend-mode: luminosity; opacity: .92; }

/* ── LES SIX GABARITS DE SECTION ────────────────────────────────────────── */

/* UNE PAGE EST UNE SUITE DE GABARITS, et son rythme se lit dans cette suite.
   Mesuré le 30.10.2026 : l'accueil portait 40 % d'encre et 1212 px de bande
   vide d'un seul tenant. Pas par choix — chaque section posait ses marges à
   la main, vingt fois `margin-top:var(--e4)` dans les contenus, et personne
   n'avait jamais décidé qu'une section vaut tant d'air.

   🔴 CE SONT DES DENSITÉS, PAS DES MISES EN PAGE. Aucun gabarit ne porte de
   couleur, de police ni de mot : seulement une grille et une quantité d'air.
   C'est la seule partie de ce thème qui s'emporte sur un autre site. Les
   déclarer ici et nulle part ailleurs est ce qui le garantit. Le vocabulaire
   est doublé en PHP dans `inc/gabarits.php`, qui ne rend rien mais tient le
   contrôle des marges reposées à la main. */
.gab {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	column-gap: var(--e4);
	/* ⚠️ `row-gap: 0` ÉTAIT LA CAUSE DES VINGT MARGES À LA MAIN. Les filets
	   de titre occupent la première rangée, le contenu la seconde, et sans
	   gouttière de rangée les deux se touchaient. Chaque colonne reposait
	   donc son `style="margin-top:var(--e4)"` — vingt fois dans les contenus,
	   toujours la même valeur, et aucune qui sache qu'elle était la vingtième.
	   La gouttière de rangée le fait une fois, ici. */
	row-gap: var(--e4);
	padding-inline: var(--gouttiere);
	align-items: start;
}
/* LE PARAGRAPHE QUI PORTE LA SUITE. Un lien collé au texte qu'il prolonge se
   lit comme une quatrième ligne du paragraphe ; il lui faut l'air d'une
   décision. C'était `style="margin-top:var(--e5)"`, quatre fois. */
.gab .suite, .edito .suite { margin-top: var(--e5); }
/* LA PHRASE DU BLOC NAVY : un seul endroit l'utilisait, avec quatre
   déclarations en ligne. Elle ne s'appelle PAS `.phrase` : ce nom appartient
   déjà à la citation des doubles pages, qui se compose en clamp 28→46 px.
   Deux corps sous un nom, c'est une divergence qui attend son jour. */
.bloc-phrase { font-family: var(--titre); font-size: 26px; line-height: 1.15; margin: 0; }
/* UN CHIFFRE QUI EST UN MOT — « 18 mois » et non « 18 ». Il ne peut pas
   prendre le corps du chiffre nu, qui le ferait déborder, et il ne se coupe
   pas en deux lignes. */
.chiffre--mot { font-size: clamp(52px, 13cqw, 120px); white-space: nowrap; }
.bloc > p:last-child, .bloc > dl:last-child { margin-bottom: 0; }
/* ═══ LES GABARITS DE SECTION ═════════════════════════════════════════════
 *
 * 🔴 UN GABARIT DONT LA COMPOSITION CHANGE À CHAQUE EMPLOI N'EST PAS UN
 * GABARIT, C'EST UN NOM. Relevé le 31.10.2026 sur les sept pages :
 *
 *     duo        c1-5 c6-12  ·  c1-6  ·  c1-12 c1-12  ·  c1-4 c9-12
 *     ouverture  c1-8 c9-12 c1-12  ·  c1-4 c1-7 c9-12  ·  c1-7 c9-12
 *                c1-7 c8-12  ·  c1-7 c9-12 c1-12
 *
 * Quatre compositions sous un nom, cinq sous l'autre. Chaque page posait ses
 * colonnes à la main, donc chaque page avait sa propre idée de ce qu'est une
 * section — et c'est ce qui se voyait : « cette section ne va pas du tout,
 * mélange, rien n'est aligné, c'est n'importe quoi. »
 *
 * LA RÈGLE EST DÉSORMAIS : LE NOM PORTE LA COMPOSITION. Le contenu choisit un
 * gabarit, pas des colonnes. Les classes `c1-4` et consorts restent — elles
 * servent aux cas que le vocabulaire ne couvre pas — mais une section qui en
 * écrit n'est plus la norme, c'est une exception qui doit se justifier.
 *
 * TROIS COLONNES NE SONT PAS TROIS BLOCS QUELCONQUES. `--trio` demande trois
 * choses de MÊME NATURE ; trois natures différentes dans trois colonnes, c'est
 * ce qui produit un mélange que rien n'aligne. C'est la seule règle de ce
 * système qui ne soit pas une mesure mais un jugement, et elle est écrite ici
 * pour qu'on puisse la contester.
 *
 * L'OUVERTURE EST LE SEUL GABARIT LARGE, et c'est tout son sens : l'air y dit
 * « on commence ». Répété six fois sur une page, il ne disait plus rien. */
.gab--ouverture   { padding-block: var(--e7) var(--e6); }
/* Son contenu : un titre, un chapô, et le folio qui ferme. Le contenu n'a
   plus à le dire. */
/* ⚠️ LA COMPOSITION NE COMPTE QUE LES `div`, et ce détail a cassé la section
   dès le premier essai. Une section porte souvent une étiquette en
   `<p class="filet-titre">` avant ses colonnes : comptée par `:nth-child`,
   elle devenait la première colonne, le chiffre la deuxième, et le texte
   tombait dans une colonne implicite d'une douzième de large. Les étiquettes
   et les folios sont des `<p>` ; les colonnes sont des `<div>`. Le gabarit
   ne range que les secondes. */
.gab--ouverture > div:nth-of-type(1) { grid-column: 1 / 8; }
.gab--ouverture > div:nth-of-type(2) { grid-column: 9 / -1; }
/* 🔴 L'ÉTIQUETTE ET LE FOLIO TRAVERSENT, ET C'EST AU GABARIT DE LE DIRE.
   Le folio n'était déclaré que pour l'ouverture, et l'étiquette ne l'était
   nulle part : les contenus écrivaient `c1-4` ou `c1-12` à la main, cinq fois
   sur trois pages, et les deux valeurs donnaient le même rendu — une
   étiquette courte commence à gauche quelle que soit sa boîte. Deux classes
   différentes pour un résultat identique, c'est le signe qu'aucune des deux
   n'était une décision.
   Un `<p>` dans un gabarit n'est pas une colonne : c'est une annonce ou une
   signature, et ça tient la largeur. */
.gab > .folio,
.gab > .filet-titre { grid-column: 1 / -1; }

/* DEUX BLOCS DE MÊME POIDS. La moitié chacun, et rien entre les deux : une
   gouttière de colonne suffit à les séparer, un écart de colonne les
   désolidarise. */
.gab--duo--pair > div            { grid-column: span 6; }

/* UN PRINCIPAL ET UN SECONDAIRE. Sept colonnes contre quatre, avec une
   colonne de respiration : c'est la proportion de l'ouverture, reprise au
   corps de la page pour que la lecture garde le même pas. */
.gab--duo--inegal > div:nth-of-type(1) { grid-column: 1 / 8; }
.gab--duo--inegal > div:nth-of-type(2) { grid-column: 9 / -1; }

/* LE MIROIR : LE SECONDAIRE D'ABORD — ajouté le 01.11.2026, tranché par Yan.
   Deux pages demandent l'inverse et ce n'est pas un caprice de mise en page :
   sur contact et sur le vernissage, le petit bloc est une adresse ou une
   liste de ce qu'on garde, et le grand est un FORMULAIRE. Un formulaire ne
   tient pas dans quatre colonnes, et une adresse n'a pas besoin de sept.
   Le vocabulaire n'avait que la proportion dans un sens ; on la retourne au
   lieu d'écrire des colonnes à la main — c'est ce qui avait produit huit
   compositions sous le nom `--duo`.
   La colonne vide passe de la huitième à la cinquième : c'est la même
   respiration, de l'autre côté. */
.gab--duo--inegal--inverse > div:nth-of-type(1) { grid-column: 1 / 5; }
.gab--duo--inegal--inverse > div:nth-of-type(2) { grid-column: 6 / -1; }

/* TROIS CHOSES DE MÊME NATURE, et le mot NATURE est le fond du sujet. Trois
   colonnes de quatre, même ligne de tête, même rythme. */
.gab--trio { padding-block: var(--e6); }
.gab--trio > div { grid-column: span 4; }

/* UN CHIFFRE QUI PORTE. Le chiffre et sa légende tiennent la gauche, le texte
   et son lien tiennent le centre, et la DROITE RESTE VIDE — c'est elle qui
   donne au chiffre sa place. La version précédente y mettait un bloc navy :
   trois natures, trois hauteurs, et un encadré qui descendait plus bas que
   tout le reste sans raison. L'encadré a sa propre section maintenant. */
.gab--chiffre { padding-block: var(--e6); }
.gab--chiffre > div:nth-of-type(1) { grid-column: 1 / 5; }
.gab--chiffre > div:nth-of-type(2) { grid-column: 6 / 11; }
.gab--duo         { padding-block: var(--e6); }
/* LE MUR EST SERRÉ PARCE QU'IL EST DÉJÀ AÉRÉ PAR SES GOUTTIÈRES. Une grille
   d'objets porte son propre blanc entre les tuiles ; lui ajouter l'air d'une
   section, c'est compter deux fois.

   ⚠️ ET IL REND SES DOUZE COLONNES À CE QU'IL PORTE. Un gabarit est une
   grille de douze colonnes ; son enfant est donc un ÉLÉMENT de cette grille,
   et sans cette ligne un pavage de quatre colonnes atterrissait dans la
   PREMIÈRE des douze — un huitième de la largeur. Le défaut est passé à
   l'écriture le 30.10.2026 et n'aurait coûté qu'un regard, mais un mur qui
   tient dans une colonne ne ressemble à rien de reconnaissable : on cherche
   la cause ailleurs. */
.gab--mur         { padding-block: var(--e5); }
.gab--mur > *     { grid-column: 1 / -1; }
/* UN BLOC PLEINE LARGEUR. Sa colonne n'était pas déclarée : chaque emploi
   écrivait `c1-12` à la main, deux fois sur deux pages. Un gabarit qui oblige
   son contenu à répéter sa seule composition n'en est pas un. */
.gab--bloc        { padding-block: var(--e6); }
.gab--bloc > div  { grid-column: 1 / -1; }
/* LA RESPIRATION N'A NI MARGE NI GOUTTIÈRE : elle va d'un bord à l'autre.
   Une image pleine en retrait des bords ressemble à une carte posée sur la
   page ; bord à bord, elle ressemble à du papier. */
.gab--respiration { padding: 0; grid-template-columns: 1fr; }
/* LE PIED NE REND PAS D'AIR EN HAUT : il appartient à ce qui précède. C'est
   ce qui distingue une fin de section d'un début de section — et c'est
   exactement ce qui manquait quand toutes les marges étaient symétriques. */
.gab--pied        { padding-block: 0 var(--e5); }
/* Le pied prend la proportion de l'ouverture et du `--inegal` : sept colonnes
   contre quatre. Il écrivait `c1-6 c9-12`, soit une neuvième composition dans
   un système qui en déclare trois. */
.gab--pied > div:nth-of-type(1) { grid-column: 1 / 8; }
.gab--pied > div:nth-of-type(2) { grid-column: 9 / -1; }

/* ── LES RESPIRATIONS ───────────────────────────────────────────────────── */

/* 🔴 `.edito--serre` ET `.edito--ample` SONT L'ANCIEN SYSTÈME, à deux crans.
   Ils restent le temps que les douze pages passent aux six gabarits, et pas
   un jour de plus : deux vocabulaires de densité qui cohabitent, c'est la
   divergence qui recommence. */
.edito--serre { padding-block: var(--e6); }
.edito--ample { padding-block: var(--e7); }
.regle-pleine { border-top: 1px solid var(--navy); margin-inline: var(--gouttiere); }
.regle-fine   { border-top: 1px solid var(--trait); margin-inline: var(--gouttiere); }

@media (max-width: 1100px) {
	.c1-4, .c1-5, .c1-6, .c1-7, .c1-8, .c2-7, .c3-8, .c4-9, .c5-9,
	.c6-12, .c7-12, .c8-12, .c9-12, .c10-12 { grid-column: 1 / -1; }
	/* 🔴 ET LES GABARITS AVEC, CE QUI MANQUAIT — 31.10.2026. Les classes de
	   colonne se repliaient ici depuis le début ; les règles de composition
	   que j'ai posées ce matin, non. Résultat sur iPhone : le chapô d'À
	   propos restait dans `grid-column: 9 / -1`, soit un quart d'un écran de
	   390 px — « Plus d'un demi-siècle d'une vie riche en expé-riences », deux
	   mots par ligne, césures partout.
	   La leçon est générale : un gabarit qui nomme ses colonnes DOIT nommer
	   aussi leur repli, sinon il n'est juste qu'à une seule largeur. */
	/* 🔴 LE REPLI NE S'ÉNUMÈRE PLUS — 01.11.2026. Cette règle listait les
	   huit sélecteurs de colonne un par un. Elle était juste, et elle était
	   un piège : la variante suivante qu'on écrit ne s'y trouve pas, ne
	   replie pas, et rend un quart d'écran sur un téléphone — le défaut
	   exact que le commentaire ci-dessus raconte avoir payé une fois.
	   Sous le seuil, AUCUN enfant de gabarit ne garde ses colonnes. Un
	   gabarit n'a plus à déclarer son repli : il n'y a plus de repli à
	   oublier.

	   ⚠️ `:nth-of-type(n)` N'EST PAS UNE COQUETTERIE, C'EST LA SPÉCIFICITÉ.
	   Écrite `.gab > div`, la règle pèse (0,1,1) et perd contre
	   `.gab--ouverture > div:nth-of-type(1)`, qui pèse (0,2,1) — et une
	   media query ne change RIEN à ce calcul. Mesuré : les sept pages
	   gardaient leurs colonnes à 390 px, la règle était là et ne servait à
	   rien. `n` matche tout élément et rend exactement le même poids, donc
	   c'est l'ordre du fichier qui tranche, et il est de notre côté.
	   C'est aussi pour ça que l'ancienne liste marchait : elle recopiait la
	   spécificité de chaque règle qu'elle devait défaire. */
	.gab > div:nth-of-type(n) { grid-column: 1 / -1; }
	.edito, .gab { row-gap: var(--e5); }
	.geant { text-wrap: balance; }
}

/* Le tableau de coordonnées dans un bloc navy : mêmes filets, autres valeurs. */
.coord--clair { margin: 0; border-top-color: rgba(236,230,218,.3); }
.coord--clair dt { color: var(--sur-navy-doux); border-bottom-color: rgba(236,230,218,.18);
	padding: var(--e3) 0; }
.coord--clair dd { color: var(--sur-navy); border-bottom-color: rgba(236,230,218,.18);
	padding: var(--e3) 0; font-size: var(--t-mention); }
.coord--clair a { color: var(--sur-navy); border-bottom: 1px solid var(--accent); text-decoration: none; }
.btn--clair { background: var(--sur-navy); color: var(--navy); align-self: flex-start; }
.btn--clair:hover { background: var(--blanc); color: var(--navy); }

/* ═══ 20. LA BIBLIOTHÈQUE ═════════════════════════════════════════════════ *
 *
 * Les ouvrages sont rangés tranche en avant, comme sur une étagère. Vingt et
 * une couvertures alignées se neutralisent ; vingt et une tranches se lisent.
 *
 * LES ÉPAISSEURS SONT LES VRAIES : chaque tranche a été découpée dans le
 * fichier d'impression, à sa largeur exacte. C'est cette irrégularité qui fait
 * qu'une étagère ressemble à une étagère et non à un peigne.
 *
 * L'OUVERTURE : la tranche pivote autour de son bord gauche et s'efface, la
 * couverture arrive à sa place. C'est le geste de sortir un livre du rayon.
 * Au survol ET au focus clavier — sans le second, la couverture serait
 * réservée à la souris.
 */

.biblio { padding-inline: var(--gouttiere); }
.biblio-rayon {
	display: flex;
	align-items: flex-end;
	gap: 3px;
	border-bottom: 3px solid var(--navy);
	padding-bottom: 0;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: none;
	min-height: 380px;
}
.biblio-rayon::-webkit-scrollbar { display: none; }

.ouvrage {
	position: relative;
	flex: none;
	display: block;
	text-decoration: none;
	transform-style: preserve-3d;
	perspective: 1400px;
	transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.ouvrage-dos, .ouvrage-plat { display: block; backface-visibility: hidden; }
.ouvrage-dos img { display: block; height: 340px; width: auto; }

/* ── LA TRANCHE NUE ───────────────────────────────────────────────────────
 * `L'Encre et le Feu` n'a ni tranche ni couverture : il est en écriture,
 * parution annoncée 2028. Il laissait un trou dans la rangée (voir
 * `inc/livres.php`). Il reçoit ici un dos SANS JAQUETTE — la toile du
 * relieur, le titre poussé dessus — qui dit la vérité : le volume existe,
 * son habillage pas encore. Sa largeur est celle d'un livre mince, parce
 * qu'on ne connaît pas encore son épaisseur. */
.ouvrage-dos--nu {
	position: relative;
	width: 34px; height: 340px;
	background:
		linear-gradient(to right, rgba(0,0,0,.34), rgba(255,255,255,.06) 42%, rgba(0,0,0,.26));
	background-color: var(--navy);
	display: flex; align-items: center; justify-content: center;
}
.ouvrage-dos-titre {
	writing-mode: vertical-rl;
	font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
	text-transform: uppercase; color: var(--sur-navy-doux);
	white-space: nowrap; max-height: 300px; overflow: hidden;
}

/* La couverture attend, repliée sur le bord gauche de la tranche. */
.ouvrage-plat {
	position: absolute;
	left: 0;
	bottom: 0;
	transform-origin: left bottom;
	transform: rotateY(-92deg);
	transition: transform .45s cubic-bezier(.2,.7,.2,1);
	pointer-events: none;
}
.ouvrage-plat img { display: block; height: 340px; width: auto; }

/* 🔴 LE LIVRE SORT DU RAYON, IL NE S'OUVRE PLUS — 01.11.2026.
 * « Quand on fait un mouse over, ça fait une sorte d'artefact bizarre. »
 * C'était le livre qui s'OUVRAIT : la tranche pivotait de 88°, la couverture
 * revenait de −92°, et comme la tuile ne fait que quarante pixels de large,
 * la couverture sortait écrasée dans cette largeur-là — une bande illisible
 * coincée entre deux voisines. L'intention était belle et la place
 * n'existait pas.
 *
 * « Il y a le livre qui s'agrandit, comme si on le sortait de la
 * bibliothèque. Puis quand on clique dessus, ça tombe sur sa fiche. » C'est
 * un seul geste, et il tient en deux propriétés : il monte et il grandit,
 * depuis sa base, comme un volume qu'on tire vers soi. Le clic menait déjà
 * à la fiche — il n'y avait rien à changer là.
 *
 * ⚠️ L'ÉCHELLE PART DU BAS. `transform-origin: bottom` : un livre posé sur
 * une étagère grandit vers le haut, jamais vers le bas — sinon il traverse
 * la planche, et c'est précisément ce qui fait « artefact ». */
.ouvrage { transform-origin: bottom; }
.ouvrage:hover, .ouvrage:focus-visible {
	z-index: 3;
	transform: translateY(-18px) scale(1.14);
}
/* La couverture ne s'affiche jamais sur le rayon : elle ne sert plus qu'à
   l'aperçu, que `biblio.js` construit en lisant son `src` ici. `display:none`
   n'empêche pas de le lire — mais empêche la tuile de mesurer zéro pixel,
   qui était la cause du trou. */
.ouvrage-plat { display: none; }

/* ═══ LES OMBRES DE L'ÉTAGÈRE ═════════════════════════════════════════════ *
 * « Il manque un tout petit peu de réalisme. Est-ce qu'on arrive à rajouter
 * des ombres pour que ça fasse plus comme une vraie bibliothèque ? » — Yan,
 * le 02.11.2026.
 *
 * Ce qui manquait n'était pas une ombre mais TROIS, et elles ne disent pas la
 * même chose :
 *
 *   1. L'OMBRE ENTRE DEUX VOLUMES. Des livres serrés ne reçoivent pas la
 *      lumière sur leurs bords : chaque tranche est plus sombre à gauche et à
 *      droite qu'en son milieu. Sans elle, vingt et un aplats de couleur se
 *      touchent — c'est un camembert, pas une rangée.
 *   2. L'OMBRE DE CONTACT. Là où le livre pose sur la planche, la lumière
 *      n'entre plus : un trait sombre, court et serré, à la base. C'est elle
 *      qui pose les livres SUR quelque chose au lieu de les laisser flotter
 *      devant.
 *   3. L'OMBRE PORTÉE DU LIVRE TIRÉ. Un volume qu'on sort passe devant ses
 *      voisins et leur jette son ombre. Sans elle, il grandit sans avancer.
 *
 * ⚠️ TOUTES EN `rgba` DE LA PLAQUE, JAMAIS EN NOIR. Le noir pur sur un crème
 * fait une tache grise ; la couleur du navy désaturée fait une ombre. Et
 * elles tiennent dans les deux thèmes sans être réécrites, parce qu'elles
 * sont des SUPERPOSITIONS et non des couleurs.
 */

/* 1. Les bords, et le haut qui prend la lumière. */
.ouvrage-dos { position: relative; }
.ouvrage-dos::after {
	content: ""; position: absolute; inset: 0; pointer-events: none;
	background:
		linear-gradient(to bottom,
			rgba(255,255,255,.10), rgba(255,255,255,0) 14%,
			rgba(0,0,0,0) 72%, rgba(0,0,0,.26)),
		linear-gradient(to right,
			rgba(0,0,0,.40), rgba(0,0,0,.08) 26%,
			rgba(0,0,0,0) 52%, rgba(0,0,0,.12) 80%, rgba(0,0,0,.32));
}

/* 2. Le pied : court, serré, et il ne déborde pas sur la planche. */
.ouvrage::before {
	content: ""; position: absolute; z-index: -1;
	left: -5px; right: -5px; bottom: 0; height: 14px;
	background: radial-gradient(70% 120% at 50% 100%,
		rgba(16,20,29,.42), rgba(16,20,29,0) 72%);
	pointer-events: none;
}

/* 3. Le volume tiré passe devant, donc il porte son ombre. L'ombre grandit
      avec lui : c'est la même transition, sur la même courbe. */
.ouvrage { box-shadow: 0 0 0 rgba(16,20,29,0); transition:
	transform .35s cubic-bezier(.2,.7,.2,1), box-shadow .35s cubic-bezier(.2,.7,.2,1); }
.ouvrage:hover, .ouvrage:focus-visible {
	box-shadow: 0 16px 28px -10px rgba(16,20,29,.46), 0 2px 6px rgba(16,20,29,.22);
}

/* La planche elle-même a une épaisseur : le filet de 3 px la dessine, cette
   ombre lui donne le dessous. Sans elle, l'étagère est un trait. */
.biblio-rayon { box-shadow: 0 7px 16px -9px rgba(16,20,29,.55); }

/* Le titre n'apparaît qu'à l'ouverture : vingt et un titres affichés en
   permanence sous les tranches feraient une deuxième rangée de bruit. */
.ouvrage-nom {
	position: absolute;
	left: 0;
	top: calc(100% + 12px);
	width: max-content;
	max-width: 240px;
	font-family: var(--titre);
	font-size: 17px;
	line-height: 1.2;
	color: var(--navy);
	opacity: 0;
	transition: opacity .25s ease;
	pointer-events: none;
}
.ouvrage:hover .ouvrage-nom, .ouvrage:focus-visible .ouvrage-nom { opacity: 1; }

/* ── L'APERÇU : LE LIVRE S'OUVRE SUR LE RAYON ────────────────────────────
 * Un panneau posé sur l'étagère, pas dans la tranche. La couverture arrive
 * en pivotant depuis son bord gauche — la charnière — puis le texte suit.
 * C'est le geste d'un livre qu'on ouvre, et il a enfin la place de se faire :
 * la tentative d'avant le jouait DANS une tuile de quarante pixels.
 *
 * ⚠️ `pointer-events` RESTE ACTIF sur le panneau et nulle part ailleurs : le
 * rayon défile horizontalement derrière, et un panneau qui mangerait les
 * clics empêcherait de reprendre le rayon après avoir refermé. */
.biblio { position: relative; }
/* 🔴 IL NE PREND PAS TOUT LE RAYON, ET IL EST CENTRÉ.
 *
 * Première version : `inset: 0`, donc toute la largeur — le livre et son
 * texte tassés à gauche, un grand vide, et la croix à l'autre bout de
 * l'écran. « Ça fait hyper long, puis on doit chercher la petite croix. »
 *
 * Deuxième : borné à 880 px mais collé au bord GAUCHE de la fenêtre, sans
 * rapport avec la gouttière ni avec rien — « c'est un petit peu planté à
 * gauche, comme nulle part » (Yan, 02.11.2026). Une boîte posée sur un
 * bord qu'aucune colonne ne suit n'a pas l'air placée, elle a l'air tombée.
 *
 * Celle-ci est centrée sur le rayon, dans les deux axes, et prend la
 * HAUTEUR DE SON CONTENU au lieu de celle de l'étagère : c'est ce qui la
 * faisait paraître longue, plus que sa largeur. Elle ne touche plus aucun
 * bord — la gouttière est réservée des deux côtés.
 *
 * ⚠️ `transform` PORTE DEUX CHOSES : le centrage, qui ne bouge jamais, et
 * l'échelle, qui s'anime. Les écrire dans deux règles concurrentes ferait
 * perdre le centrage pendant la transition — la boîte partirait du coin. */
.biblio-apercu {
	position: absolute; z-index: 6;
	/* `--ancre` est posée par `biblio.js` : le bord gauche de la tranche
	   cliquée, bornée pour ne pas sortir du cadre. Sans script, 0 — le
	   panneau ouvre à gauche du rayon plutôt que nulle part. */
	top: 50%; left: var(--ancre, 0px);
	/* `border-box` OU LA BOÎTE DÉPASSE. En `content-box`, les 40 px de
	   padding s'ajoutent à la largeur : 960 px pour une borne à 880, et sur
	   un téléphone 398 px dans un rayon de 390 — quatre pixels dehors de
	   chaque côté, que seule une mesure voit. */
	box-sizing: border-box;
	/* 🔴 680 ET NON 880. Mesuré : dans un rayon de 1288 px utiles, un
	   panneau de 880 ne laisse que 400 px de jeu — l'ancrage au livre
	   n'avait plus que trois positions possibles, et dix livres sur vingt
	   et un rouvraient au même endroit. À 680 le jeu double et chaque
	   tranche retrouve sa place. Un ancrage qui ne distingue que trois
	   livres n'est pas un ancrage. */
	width: min(680px, calc(100% - var(--gouttiere) * 2));
	max-height: calc(100% - var(--e4) * 2);
	display: flex; align-items: center; gap: var(--e5);
	padding: var(--e5);
	background: var(--carte);
	box-shadow: 0 30px 70px rgba(0, 0, 0, .26);
	opacity: 0;
	/* 🔴 IL NE GRANDIT PLUS, IL S'OUVRE — 02.11.2026.
	   « Le carré qui s'ouvre, oui c'est bien, mais il manque d'originalité.
	   Trouve une meilleure idée. » Un `scale` de .97 à 1 est le geste de
	   n'importe quelle boîte de n'importe quel site ; il ne disait rien
	   d'une bibliothèque.
	   Le panneau est désormais une COUVERTURE : il part rabattu à 84° sur
	   le dos du livre et se déplie vers le lecteur. La charnière est le
	   bord de la tranche, le même point que celui d'où pivote la
	   couverture à l'intérieur — deux feuillets qui s'ouvrent l'un après
	   l'autre, et c'est le décalage entre les deux qui fait le livre.
	   Il attend 120 ms : le rayon doit avoir commencé à s'écarter, sinon
	   le panneau s'ouvre là où il y a encore des tranches. */
	transform-origin: left center;
	transform: translateY(-50%) rotateY(-84deg);
	transition: opacity .34s ease 120ms,
		transform .52s cubic-bezier(.2, .7, .2, 1) 120ms;
}
.biblio-apercu.est-ouvert { opacity: 1; transform: translateY(-50%) rotateY(0deg); }
/* Ouvert vers la gauche, il se rabat sur son bord DROIT — sinon la
   charnière serait du côté opposé à celui d'où il sort. */
.biblio-apercu.ouvre-a-gauche { transform-origin: right center;
	transform: translateY(-50%) rotateY(84deg); }
.biblio-apercu.ouvre-a-gauche.est-ouvert { transform: translateY(-50%) rotateY(0deg); }

/* ── LE RAYON S'ÉCARTE ─────────────────────────────────────────────────────
 * La moitié du geste, et celle qu'on ne voit nulle part ailleurs : les
 * tranches qui suivent le livre touché GLISSENT le long de la planche pour
 * lui faire de la place. Le panneau ne recouvre donc rien — il occupe un
 * vide qui vient de s'ouvrir.
 *
 * ⚠️ LES RÈGLES DE SURVOL SONT RECOPIÉES, PAS RENFORCÉES. `.ouvrage:hover`
 * pose un `transform` à (0,2,0) de spécificité. Une classe seule à (0,1,0)
 * perdrait, et une tranche écartée reviendrait se ranger sous la souris en
 * plein milieu du geste. On écrit donc le même poids, et c'est l'ordre du
 * fichier qui tranche. */
.biblio-rayon { --ecart: 0px; }
.ouvrage--pousse-g, .ouvrage--pousse-g:hover, .ouvrage--pousse-g:focus-visible {
	transform: translateX(calc(var(--ecart) * -1)); }
.ouvrage--pousse-d, .ouvrage--pousse-d:hover, .ouvrage--pousse-d:focus-visible {
	transform: translateX(var(--ecart)); }
/* Le livre qu'on a touché reste SORTI du rang tant que l'aperçu est ouvert :
   sans ça, on ne sait plus lequel des vingt-deux on regarde. */
.ouvrage--tire, .ouvrage--tire:hover {
	z-index: 5; transform: translateY(-22px) scale(1.1);
	box-shadow: 0 20px 34px -12px rgba(16,20,29,.5), 0 2px 8px rgba(16,20,29,.28); }
/* ⚠️ LE TITRE DU LIVRE TIRÉ RESTE CACHÉ, et c'est voulu : le panneau
   l'affiche en grand à trente pixels de là. Affiché aussi sous la tranche,
   il tombait sous la planche et se lisait comme une légende égarée. */

/* La perspective vit sur le cadre, pas sur le panneau : un élément ne peut
   pas être à la fois la scène et ce qui tourne dedans. */
.biblio { perspective: 1800px; }

.apercu-plat { flex: 0 0 auto; perspective: 1400px; }
.apercu-plat img {
	display: block; height: 300px; width: auto;
	transform-origin: left center;
	transform: rotateY(-62deg);
	/* Elle part APRÈS le panneau : le second feuillet. */
	transition: transform .58s cubic-bezier(.2, .7, .2, 1) 300ms;
	box-shadow: 0 10px 30px rgba(0, 0, 0, .3);
}
.biblio-apercu.est-ouvert .apercu-plat img { transform: none; }
/* Le dos nu, en grand, pour le livre qui n'a pas encore de couverture.
   Mêmes proportions qu'une couverture pour que le panneau garde sa mise en
   page, et la même matière que la tranche d'où il sort. */
.apercu-nu {
	display: flex; align-items: center; justify-content: center;
	width: 210px; height: 300px;
	background: var(--navy);
	background-image: linear-gradient(to right, rgba(0,0,0,.30), rgba(255,255,255,.05) 46%, rgba(0,0,0,.22));
	box-shadow: 0 10px 30px rgba(0, 0, 0, .3);
}
.apercu-nu span {
	font-family: var(--mono); font-size: 11px; letter-spacing: .16em;
	text-transform: uppercase; color: var(--sur-navy-doux);
	max-width: 15ch; text-align: center; line-height: 1.8;
}
.apercu-dit { flex: 1 1 auto; max-width: 52ch; }
.apercu-titre { font-family: var(--titre); font-size: 34px; line-height: 1.05; color: var(--navy); margin: 0; }
.apercu-sous { margin: var(--e2) 0 0; font-size: var(--t-mention); color: var(--texte-doux); }
.apercu-accroche { margin: var(--e3) 0 0; font-size: var(--t-corps); line-height: 27px; color: var(--texte); }
.apercu-aller { margin: var(--e4) 0 0; }
.apercu-aller a {
	font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--accent-texte);
	text-decoration: none; border-bottom: 2px solid var(--accent); padding-bottom: 3px;
}
.apercu-fermer {
	position: absolute; top: 10px; right: 12px;
	width: 40px; height: 40px; padding: 0; cursor: pointer;
	background: none; border: 0; color: var(--texte-doux);
	font: 26px/1 var(--mono);
}
.apercu-fermer:hover { color: var(--navy); }
/* `.ouvrage--tire` EST ÉCRIT PLUS HAUT, avec le rayon qui s'écarte — il y
   était redit ici, plus bas dans le fichier, donc c'est la version d'ici qui
   gagnait et le livre touché ne portait ni son ombre ni son titre. Un
   doublon de classe ne se voit pas : il annule en silence. */
@media (prefers-reduced-motion: reduce) {
	.biblio-apercu, .apercu-plat img { transition: none; }
	/* Le rayon s'écarte quand même — c'est la PLACE qui compte, pas le
	   glissement. Il le fait d'un coup. */
	.ouvrage--pousse-g, .ouvrage--pousse-d, .ouvrage--tire { transition: none; }
}
@media (max-width: 760px) {
	/* Sur un téléphone, la couverture et le texte ne tiennent pas côte à
	   côte : la couverture passe au-dessus, et elle ne pivote plus — une
	   rotation de trois quarts sur deux cents pixels est illisible. */
	/* 🔴 SUR UN TÉLÉPHONE IL SORT DE L'ÉTAGÈRE. En `absolute` dans le rayon,
	   sa hauteur maximale était celle du rayon : 215 px utiles pour 466 px de
	   contenu. La couverture passait, le TEXTE tombait dehors — titre,
	   accroche et « lire la fiche » simplement absents, sans rien pour le
	   signaler. Mesuré le 02.11.2026 sur un iPhone : « l'aperçu livre
	   pourrait être plus grand ». Il ne pouvait pas l'être.
	
	   En `fixed`, il se mesure à la FENÊTRE et non au rayon. C'est aussi le
	   bon registre : sur un écran de poche, un aperçu est une feuille qu'on
	   ouvre, pas une vignette posée dans une étagère. */
	.biblio-apercu {
		position: fixed;
		top: 50%; left: var(--gouttiere); right: var(--gouttiere);
		width: auto; max-height: 86vh;
		flex-direction: column; align-items: flex-start; gap: var(--e3);
		overflow-y: auto; padding: var(--e4);
		/* L'ancrage au livre n'a plus de sens : le panneau prend toute la
		   largeur, il n'y a plus de côté d'où sortir. */
		transform-origin: center;
		transform: translateY(-50%) scale(.97);
	}
	.biblio-apercu.est-ouvert { transform: translateY(-50%) scale(1); }
	.biblio-apercu.ouvre-a-gauche { transform-origin: center; }
	.apercu-plat { align-self: center; }
	.apercu-plat img { height: 230px; transform: none; }
}

/* « Toute la collection » À GAUCHE, comme tous les appels depuis le
   02.11.2026 — et plus BAS. À --e5 sous un rayon qui porte déjà sa ligne de
   3 px, l'appel et son soulignement d'accent se chevauchaient avec elle. */
.biblio-pied { display: flex; justify-content: flex-start; align-items: baseline;
	gap: var(--e4); margin-top: var(--e6); padding-inline: var(--gouttiere); }

@media (prefers-reduced-motion: reduce) {
	.ouvrage, .ouvrage-dos, .ouvrage-plat, .ouvrage-nom { transition: none; }
}
@media (max-width: 900px) {
	.biblio-rayon { min-height: 260px; }
	.ouvrage-dos img { height: 230px; }
	.ouvrage-dos--nu { height: 230px; }
	.ouvrage-dos-titre { max-height: 196px; }
}

/* `.ouvrage--debout` ET SES TROIS RÈGLES SONT PARTIES — 02.11.2026. Elles
   remettaient dans le flux une couverture `position: absolute` pour qu'un
   livre sans tranche se tienne de face. Deux choses ne marchaient pas : la
   règle qui la cachait avait une spécificité plus forte, et le seul livre
   concerné n'a pas de couverture non plus. D'où la TRANCHE NUE, plus haut. */

/* ═══ 21. LES CARRÉS ══════════════════════════════════════════════════════ *
 * Une liste de marques se lit de haut en bas et demande un effort de
 * comparaison ; des carrés se balaient du regard. Trois par ligne, format
 * carré strict, et UN carré sur trois en navy — c'est l'alternance qui donne
 * le rythme de la double page de magazine, pas la bordure.
 */

/* ── LE PAVAGE DES MAISONS ────────────────────────────────────────────────
   🔴 `.carres` ET `.rangee` SONT MORTS LE 30.10.2026. L'accueil posait neuf
   cases carrées identiques, l'univers neuf rangées pleine largeur : deux
   grilles pour les mêmes neuf objets, qui divergeaient à chaque retouche. Et
   neuf cases de taille identique disaient que les neuf maisons pèsent pareil.
   Elles ne pèsent pas pareil : le champ `rang` le dit maintenant, et c'est
   Lina qui le règle. */
/* ⚠️ LE PAVAGE NE POSE AUCUN REMBOURRAGE, et c'est le point de tout le
   système. Il l'a fait pendant une heure le 30.10.2026 : posé à l'intérieur
   d'un `gab--mur` qui portait déjà son air et sa gouttière, il les ajoutait
   une seconde fois. Un pavage est une GRILLE ; l'air autour appartient au
   gabarit qui le porte. Deux objets qui posent la même marge, c'est
   exactement la divergence que les gabarits existent pour empêcher. */
.mo-maison {
	justify-content: space-between;
	padding: var(--e5);
	background: var(--carte);
	border: 1px solid var(--trait);
	color: inherit;
	gap: var(--e4);
	transition: border-color .2s ease, background .2s ease;
}
.mo-maison:hover { border-color: var(--accent); }
/* ── TROIS TEINTES POUR TROIS RANGS ─────────────────────────
   Lina a demandé « des teintes claires ou foncées pour en mettre une en
   avant ». Trois rangs, donc trois fonds, du plus présent au plus discret :
   le navy avance, le blanc cassé tient le plan, le crème est celui de la
   page elle-même — une mention ne se détache pas du papier, elle y repose.
   C'est le seul moyen d'avoir une hiérarchie qui se voie sans qu'aucune
   maison paraisse déclassée : aucune n'est grise, aucune n'est barrée. */
.mo-tuile--mention.mo-maison { background: var(--creme); }
.mo-logo { display: block; }
/* TROIS EMPRISES POUR TROIS RANGS, et c'est la BOÎTE qui change, pas le
   logo : `contain` l'inscrit dedans sans jamais le déformer ni le recadrer.
   La tête porte le sien plus grand parce qu'elle a quatre fois la surface —
   le même logo au même corps dans une tuile double, c'est une tuile simple
   avec du vide autour. */
.mo-maison { --lk: 1; }
.mo-tuile--tete { --lk: 1.45; }
.mo-tuile--mention { --lk: .7; }
.mo-maison .code {
	font-variant-numeric: lining-nums tabular-nums;
	font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	color: var(--accent-texte); display: block; margin-bottom: var(--e2);
}
.mo-maison .nom { display: block; font-family: var(--titre); font-size: 26px; line-height: 1.08;
	color: var(--navy); }
.mo-tuile--tete .nom { font-size: 40px; }
.mo-tuile--mention .nom { font-size: 20px; }
.mo-maison .bl { display: block; margin-top: var(--e2);
	font-size: var(--t-mention); line-height: 24px; color: var(--texte-doux); }
.mo-maison .mo-texte { display: block; margin-top: var(--e3);
	font-size: var(--t-corps); line-height: 27px; color: var(--texte); max-width: 46ch; }

/* ── LE TEXTE NE SE LIT QU'AU SURVOL, SUR LA PAGE UNIVERS ─────────────────
 * « Le texte, on ne l'affiche pas. C'est quand on fait un mouse over sur une
 * des cartes qu'il y a le texte qui s'affiche. » Au repos la carte ne porte
 * plus que le logo, le nom et la baseline : neuf paragraphes alignés, c'était
 * une page de texte déguisée en mosaïque.
 *
 * 🔴 EN PANNEAU, ET PAS EN DÉPLIANT LA CARTE. Mesuré avant de choisir : les
 * rangées du pavage sont en `minmax(0, auto)`, donc dimensionnées par leur
 * contenu. Une carte qui grandit au survol pousse toute la rangée, et les
 * trois voisines sautent sous le curseur — on ne peut plus viser ce qu'on
 * voulait lire. Le texte se pose donc PAR-DESSUS le bas de sa propre carte :
 * la mosaïque ne bouge pas d'un pixel.
 *
 * Il couvre « Son histoire → », et c'est sans conséquence : la carte entière
 * est un lien, le clic tombe au même endroit. */
/* 🔴 LE TEXTE RESTE DANS LE FLUX, SIMPLEMENT INVISIBLE — et c'est la
   troisième écriture. Deux tentatives de PANNEAU superposé, mesurées et
   jetées toutes les deux :

     ancré en bas, hauteur libre    couvrait le nom sur 8 cartes sur 9
     ancré en bas, borné à 52 %     couvrait encore le nom sur 8

   La cause est géométrique et ne se négocie pas : le logo tient le haut de
   la carte, le nom est aux deux tiers, et un panneau ancré en bas qui porte
   quatre lignes remonte forcément jusqu'à lui. Borner sa hauteur ne le
   déplace pas, ça le tronque.

   Le texte garde donc sa place dans la carte et ne fait qu'apparaître. Ce
   qu'on perd : les cartes gardent la hauteur qu'elles ont aujourd'hui, avec
   du blanc sous le nom au repos. Ce qu'on gagne : la mosaïque ne bouge pas
   d'un pixel au survol, le nom n'est jamais couvert, et il n'y a plus de
   plan ni de fond à tenir. */
.pavage--lisante .mo-texte {
	opacity: 0;
	transition: opacity .22s ease;
}
.pavage--lisante .mo-maison:hover .mo-texte,
.pavage--lisante .mo-maison:focus-visible .mo-texte { opacity: 1; }
.mo-maison .aller { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--texte-doux); }
.mo-maison:hover .aller { color: var(--accent-texte); }
/* UNE MENTION NE PROMET PAS DE DESTINATION : « Son histoire → » répété neuf
   fois devient du bruit, et sur une case de 1 × 1 il prend la place du nom. */
.mo-tuile--mention .aller { display: none; }

/* ── LA TUILE DE TÊTE, EN NAVY ──────────────────────────────────────────────
   ⚠️ ELLE N'EST PAS OUVERTE À TOUTES LES MAISONS. Mesuré le 30.10.2026 :
   trois logos sur neuf se lisent sur le navy. Les six autres y disparaissent —
   leur encre est noire. `lha_marque_tient_sur_navy()` tient la liste, et une
   maison mise en tête sans y figurer reste en grand sur le crème. Le réglage
   de Lina ne peut donc pas produire une tuile illisible. */
.mo-maison--navy {
	background: var(--navy);
	border-color: var(--navy);
}
.mo-maison--navy .nom, .mo-maison--navy .mo-texte { color: var(--sur-navy); }
.mo-maison--navy .bl, .mo-maison--navy .aller { color: var(--sur-navy-doux); }
.mo-maison--navy .code { color: var(--accent); }
.mo-maison--navy:hover { border-color: var(--accent); }
/* LE LOGO N'EST PAS RETOUCHÉ. Celui de Mental Sofa est une illustration en
   couleurs : inversé, son canapé violet devient vert. On ne met pas un logo
   en négatif parce que le fond est foncé — on choisit un logo qui tient. */

/* ── L'UNIVERS LIT, L'ACCUEIL REPÈRE ────────────────────────────────────────
   Même grille, autre densité : sur la page Univers chaque tuile donne son
   texte entier, parce qu'on y vient pour lire. C'est la DENSITÉ qui change,
   jamais la grille. */
/* ⚠️ UNE TUILE QUI PORTE UN PARAGRAPHE SE COUCHE, elle ne se dresse pas.
   L'emprise par défaut d'une `pleine` est 1 colonne sur 2 rangées — un
   portrait, parfait pour une coupure de presse, catastrophique pour du texte :
   sur la capture du 30.10.2026, l'excerpt de Mecenda faisait dix lignes de
   trois mots dans une colonne de quart de page.

   Dans la mosaïque des maisons elle devient donc 2 colonnes sur 1 rangée. Le
   compte des cases ne bouge pas — une pleine vaut toujours deux cases — donc
   le garde-fou du pavage reste juste. */
.pavage--maisons .mo-tuile--pleine { grid-column: span 2; grid-row: span 1; }

/* 🔴 ET PAS DE PAVAGE DENSE ICI. `dense` remonte une petite tuile pour
   combler un trou, donc il RÉORDONNE. Sur un mur de coupures on parcourt, et
   c'est sans conséquence. Sur les maisons, l'ordre est celui que Lina a
   choisi — et le 30.10.2026 `dense` avait expédié Mental Sofa, sa maison de
   tête, en troisième rangée. Une mise en avant qu'un algorithme déplace n'est
   plus une mise en avant. */
.pavage--maisons { grid-auto-flow: row; }

.pavage--lisante .mo-maison { padding: var(--e5) var(--e5) var(--e4); }
/* 🔴 LE LOGO GRANDIT SUR LA PAGE UNIVERS — « j'aimerais que le logo soit plus
   grand ». Il le peut ici et pas sur l'accueil : la page lisante donne à
   chaque maison une tuile entière, et depuis que le texte est passé au
   survol, la carte au repos ne porte plus que trois choses — le logo, le nom,
   la baseline. Le logo peut donc tenir le haut de la carte au lieu de la
   signer discrètement. L'échelle est multipliée par l'emprise, donc TOUS les
   logos grandissent du même rapport : aucun ne se détache des autres. */
/* ⚠️ 1,2 ET NON 1,45, ET C'EST UN ARBITRAGE MESURÉ. À 1,45 le logo faisait
   138 px ; la carte en fait 281, le nom et la baseline en prennent 52, et il
   ne restait plus de place pour le panneau de survol — il grimpait sur le
   NOM, qui est précisément l'une des trois choses à garder visibles. À 1,2 le
   logo fait 114 px, soit vingt de plus qu'avant, et le panneau tient sous le
   nom. Le logo est plus grand ; il ne l'est pas au point de chasser le reste. */
.pavage--lisante .mo-maison { --lk: 1.2; }
.pavage--lisante .mo-tuile--tete { --lk: 1.55; }
/* La mesure de lecture : un paragraphe de pleine largeur dans une tuile
   étroite n'a pas besoin de borne, mais la tuile de tête, elle, en a une. */
.pavage--lisante .mo-texte { max-width: 52ch; }

/* ── LA JUSTIFICATION REVIENT, PARCE QUE LA TUILE A GRANDI ──────────────────
   Je l'avais retirée le 30.10.2026 : dans une colonne de quart de page elle
   donnait « l'ac-compagnement », « pré-sen-ta-tion » — un mot coupé toutes
   les deux lignes. Ce n'était pas la justification qui était fautive, c'était
   la LARGEUR. Les tuiles pleines font maintenant deux colonnes sur quatre :
   la mesure y est celle d'une colonne de magazine, où la justification est
   chez elle.

   Elle ne revient QUE là. Une mention — s'il en reste un jour — garde le fer
   à gauche : on ne justifie pas trois lignes, on fait des trous. */
.pavage--maisons .mo-tuile--pleine .mo-texte,
.pavage--maisons .mo-tuile--tete .mo-texte {
	/* 🔴 LA JUSTIFICATION REVIENT — 01.11.2026, demandée par Lina, et cette
	   fois la largeur la porte. Elle avait été retirée le 31.10 parce que
	   « sur une colonne de moins de quarante-cinq signes, le fer à droite
	   creuse des lézardes ». Le reproche visait la LARGEUR, pas le procédé :
	   mesuré aujourd'hui sur la page Univers, la colonne de texte fait
	   546 px, soit soixante-quatre signes — la mesure d'une colonne de
	   magazine, où la justification est chez elle.
	   La césure automatique reste : sans elle, justifier, c'est faire des
	   trous. */
	text-align: justify;
	hyphens: auto;
	-webkit-hyphens: auto;
}
/* ⚠️ SOUS 1100 px, DEUX COLONNES SUR DEUX : la tuile pleine occupe alors
   toute la largeur, ce qui va. Sous 700, une seule colonne, et la mesure
   retombe à celle d'un téléphone — où la justification refait des trous. */
@media (max-width: 700px) {
	.pavage--maisons .mo-texte { text-align: left; hyphens: manual; }
}

@media (max-width: 1100px) {
	.mo-tuile--tete { --lk: 1.19; }
	.mo-tuile--tete .nom { font-size: 32px; }
}
@media (max-width: 700px) {
	.mo-maison { padding: var(--e4); }
	.mo-tuile--tete, .mo-maison { --lk: .93; }
	.mo-tuile--tete .nom { font-size: 26px; }
	.mo-tuile--mention .aller { display: none; }
}

/* ═══ 22. LE JOURNAL EN MAÇONNERIE ════════════════════════════════════════ *
 * Trois colonnes égales alignent les cartes sur la plus haute et laissent du
 * vide sous les autres. En maçonnerie, chaque article prend la hauteur de son
 * texte et la colonne se remplit — c'est la page de sommaire d'un magazine.
 * `columns` et non une grille : c'est le seul mécanisme CSS qui laisse le
 * contenu couler de colonne en colonne sans script.
 */

.maconnerie .wp-block-post-template {
	columns: 3;
	column-gap: var(--e6);
	list-style: none;
	margin: 0;
	padding: 0;
}
.maconnerie .wp-block-post-template > li {
	break-inside: avoid;
	margin: 0 0 var(--e6);
	padding: var(--e5) var(--e4) var(--e4);
	background: var(--carte);
	border: 1px solid var(--trait);
	display: block;
}
/* Un article sur quatre passe en navy : c'est ce qui casse la régularité et
   fait respirer la page. */
.maconnerie .wp-block-post-template > li:nth-child(4n+2) {
	background: var(--navy);
	border-color: var(--navy);
}
.maconnerie li:nth-child(4n+2) h2,
.maconnerie li:nth-child(4n+2) h3,
.maconnerie li:nth-child(4n+2) h2 a,
.maconnerie li:nth-child(4n+2) h3 a { color: var(--sur-navy); }
.maconnerie li:nth-child(4n+2) p,
.maconnerie li:nth-child(4n+2) .wp-block-post-date { color: var(--sur-navy-doux); }

.maconnerie .wp-block-post-date { font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .14em; text-transform: uppercase; color: var(--accent-texte);
	margin: 0 0 var(--e3); }
.maconnerie h2, .maconnerie h3 { font-size: 25px; line-height: 1.12; margin-bottom: var(--e3); }
.maconnerie h2 a, .maconnerie h3 a { text-decoration: none; }
.maconnerie li:hover h2 a, .maconnerie li:hover h3 a { text-decoration: underline;
	text-decoration-color: var(--accent); text-underline-offset: 6px; }
.maconnerie p { margin: 0; font-size: var(--t-mention); line-height: 25px; }

@media (max-width: 1100px) { .maconnerie .wp-block-post-template { columns: 2; } }
@media (max-width: 700px)  { .maconnerie .wp-block-post-template { columns: 1; } }

/* ═══ 23. LES ENCADRÉS ════════════════════════════════════════════════════ *
 * Un texte long se coupe ou ne se lit pas. Trois objets pour ça, et pas un de
 * plus : l'encadré navy pour ce qui doit s'arrêter, la citation détachée pour
 * ce qui doit résonner, l'intertitre pour ce qui doit se retrouver.
 */

.encadre {
	background: var(--navy);
	color: var(--sur-navy);
	padding: var(--e5);
	margin: var(--e6) 0;
}
.encadre .filet-titre { color: var(--sur-navy-doux); border-bottom-color: rgba(236,230,218,.35); }
.encadre p { margin: 0; font-size: var(--t-corps); line-height: 27px; color: var(--sur-navy-doux); }
.encadre p + p { margin-top: var(--e3); }
.encadre strong { color: var(--sur-navy); font-weight: 400; }

.citation {
	margin: var(--e6) 0;
	font-family: var(--titre);
	font-size: clamp(24px, 2.6vw, 34px);
	line-height: 1.18;
	color: var(--navy);
	max-width: 24ch;
}
.citation--droite { margin-left: auto; text-align: right; }

/* UNE PHRASE QUI N'EST PAS UNE CITATION — 02.11.2026.
 * Elle prend le corps de la citation, et rien de son appareil : pas de
 * plaque, pas d'étiquette, pas de `cite`. Elle est plus large que `.citation`
 * (34ch contre 24) parce qu'elle doit tenir sur UNE ligne au grand écran :
 * une déclaration qui se replie en trois lignes redevient un paragraphe.
 * ⚠️ PAS DE GUILLEMETS, jamais. C'est l'autrice qui parle sur sa page ; des
 * guillemets en feraient le mot d'un tiers. */
.phrase-posee {
	/* 🔴 UNE GOUTTIÈRE EN `padding` PLUS UN `max-width` EN `ch` : la phrase
	   tombait à un mot par ligne — 02.11.2026, « bug texte au centre ».
	   Les deux sont justes séparément et faux ensemble. `box-sizing:
	   border-box` fait porter `max-width` sur la boîte ENTIÈRE, padding
	   compris : sur un écran de 1900, la gouttière vaut 310 px de chaque
	   côté, et d'un `max-width` de 34ch (≈ 730 px) il ne restait que 110 px
	   de texte. D'où la colonne d'un mot.
	   La marge fait le même travail sans entrer dans le calcul : le
	   `max-width` borne alors ce qu'il est censé borner, la MESURE. */
	margin: var(--e6) var(--gouttiere);
	font-family: var(--titre);
	font-size: clamp(24px, 2.4vw, 32px);
	line-height: 1.22;
	color: var(--navy);
	max-width: 34ch;
	text-wrap: balance;
}
.citation cite { display: block; font-family: var(--mono); font-style: normal;
	font-size: var(--t-etiquette); letter-spacing: .16em; text-transform: uppercase;
	color: var(--accent-texte); margin-top: var(--e3); }

/* Dans une colonne en maçonnerie, un encadré ne doit pas se couper. */
.colonnes .encadre, .colonnes .citation { break-inside: avoid; }


/* ═══ 24. LE MOT D'AFFICHE SE MESURE À SA CELLULE ═════════════════════════ *
 *
 * Ce piège m'a pris TROIS FOIS : « TRANSMETTRE » percutant un lien, « SI
 * QUELQUE » passant sous un bloc navy, « J'ÉCRIS POUR » recouvrant son propre
 * chapô. Chaque fois la même cause : le mot est en `nowrap`, sa taille venait
 * d'un modificateur choisi à la main, et le modificateur ne correspondait pas
 * au nombre de colonnes réellement occupées.
 *
 * Une taille qu'il faut accorder à la main se désaccorde au premier
 * déplacement. Elle se calcule donc sur la largeur de la CELLULE, par
 * requête de conteneur : le mot rétrécit tout seul quand la cellule rétrécit,
 * et les modificateurs ne servent plus qu'à brider un cas particulier.
 *
 * 11cqw : à douze signes, la ligne occupe environ trois quarts de sa cellule.
 *
 * ET LE PIÈGE DANS LE PIÈGE, mesuré le 19.10.2026 : UN CONTENEUR NE SE MESURE
 * PAS LUI-MÊME. `container-type` ouvre la mesure aux DESCENDANTS de l'élément,
 * jamais à l'élément lui-même. Un `<p class="geant c1-8">` posé directement
 * dans la grille EST le conteneur : son `cqw` cherche donc un conteneur plus
 * haut, n'en trouve aucun, et retombe silencieusement sur la largeur de la
 * FENÊTRE. Sur un écran de 1600 px, 11cqw valait 176 px au lieu de 94, et le
 * mot repassait par-dessus le texte voisin — la panne que ce bloc prétendait
 * avoir réglée.
 *
 * D'où la règle de pose : LE MOT D'AFFICHE EST TOUJOURS ENVELOPPÉ.
 *
 *     <div class="c1-8"><p class="geant">…</p></div>
 *
 * Le div porte le placement et devient le conteneur ; le mot, à l'intérieur,
 * se mesure enfin à la cellule. Le repli ci-dessous rattrape un mot resté nu :
 * il n'est pas joli, il évite seulement le débordement.
 */

.edito > *, .gab > * { container-type: inline-size; }
.edito > .geant, .gab > .geant { font-size: clamp(38px, 7vw, 120px); }
.edito .geant, .gab .geant { font-size: clamp(38px, 11cqw, 190px); }
.edito .geant--6col, .gab .geant--6col { font-size: clamp(34px, 9cqw, 130px); }
.edito .geant--5col, .gab .geant--5col { font-size: clamp(32px, 8cqw, 110px); }
.edito .chiffre, .gab .chiffre { font-size: clamp(80px, 34cqw, 260px); }

/* ═══ 25. LA SALLE D'UN LIVRE ═════════════════════════════════════════════ *
 * Une salle n'est pas une fiche illustrée : c'est la même image dans trois
 * états. Tenue sous une mosaïque de trente cases qui s'ouvre jour après jour,
 * découpée en trois fragments qui portent chacun une phrase, puis entière —
 * une seule fois, tout en bas.
 *
 * CE QUI FAIT LA PIÈCE, ET QUI N'EST PAS DE LA 3D. Quatre choses, mesurées sur
 * la maquette du 20.10.2026 : une lumière qui tombe d'en haut à gauche, un sol
 * aux quatre cinquièmes de la hauteur, une ombre portée sous l'œuvre, et du
 * vide autour. Retirez-en une et le mur redevient du papier. L'ombre portée est
 * la SEULE entorse à la règle « pas d'ombre au-delà de deux pixels » : elle est
 * réservée à l'œuvre accrochée, et nulle part ailleurs.
 *
 * AUCUN SCRIPT. L'état de la mosaïque est calculé en PHP d'après la date
 * d'ouverture. Deux visiteurs du même jour voient donc la même image, et un
 * navigateur sans JavaScript voit la salle entière. */

:root {
	--laiton-vif: #c08f3e;
	--nuit:       #0b1120;
	--sol-salle:  78%;
}

/* ─── le mur ─────────────────────────────────────────────────────────────── */
.salle-haut,
.salle-charpente {
	position: relative;
	isolation: isolate;
	overflow: hidden;
}
.salle-haut::before,
.salle-charpente::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	background:
		radial-gradient(112% 82% at 18% 0%, rgba(255,252,246,.98) 0%, rgba(246,243,236,.7) 34%, rgba(219,211,195,0) 76%),
		linear-gradient(180deg, var(--sol-haut) 0%, var(--sol-milieu) 58%,
			var(--sol-bord) var(--sol-salle),
			var(--sol-ombre) calc(var(--sol-salle) + .2%), var(--sol-bas) 100%);
}
.salle-haut > *,
.salle-charpente > * { position: relative; z-index: 1; }

.salle-haut {
	padding-block: var(--e6) var(--e6);
	padding-inline: var(--gouttiere);
}
.salle-titre {
	font-family: var(--titre);
	font-weight: 400;
	font-size: clamp(36px, 6vw, 72px);
	line-height: .98;
	letter-spacing: -.015em;
	margin: var(--e3) 0 0;
	max-width: 16ch;
}

/* ── LA QUATRIÈME DE COUVERTURE ───────────────────────────────────────────
 * Le texte d'éditeur à gauche, le colophon et l'achat à droite. C'est la
 * disposition d'un dos de livre : on lit, puis on vérifie, puis on achète.
 *
 * ⚠️ LE TEXTE N'EST PAS JUSTIFIÉ ICI. Une quatrième de couverture est
 * imprimée au fer à gauche ; justifiée dans sept colonnes elle prendrait
 * l'allure d'un paragraphe de site, et c'est précisément ce qu'elle n'est
 * pas. La règle générale de justification vise `.lecture p`, pas celle-ci. */
.quatrieme { padding-block: var(--e6); align-items: start; }
.quatrieme-texte {
	font-size: clamp(18px, 1.5vw, 21px); line-height: 1.62;
	color: var(--texte); margin: 0; text-align: left;
}
.quatrieme-bio {
	margin: var(--e4) 0 0; font-size: var(--t-mention); line-height: 26px;
	color: var(--texte-doux); text-align: left;
}
.quatrieme-colophon .coord { grid-template-columns: 15ch 1fr; }
.quatrieme-achat {
	margin: var(--e5) 0 0; display: flex; flex-wrap: wrap;
	align-items: center; gap: var(--e3) var(--e4);
}

/* ─── l'image tenue ──────────────────────────────────────────────────────── */
.salle-entree {
	display: grid;
	gap: var(--e5);
	align-items: start;
	margin-top: var(--e5);
}
@media (min-width: 880px) {
	.salle-entree { grid-template-columns: minmax(0, .8fr) minmax(0, 1fr); }
}
/* 🔴 LA COUVERTURE NE DÉPASSE PAS L'ÉCRAN — 02.11.2026. « Le livre en haut
   ne doit pas dépasser la hauteur du viewport. »
   Elle est en 2/3 et prend la largeur de sa colonne : sur un écran large,
   une colonne de 500 px donne 750 px de haut, plus le titre, plus la marge —
   et on arrivait sur une fiche dont le livre sortait par le bas. Un
   `max-height` ne suffit pas sur une grille en `aspect-ratio` : c'est la
   LARGEUR qu'il faut borner, sinon le rapport la rétablit. La borne se
   calcule donc depuis la hauteur disponible, et `margin-inline: 0 auto`
   garde l'image contre la gouttière. */
.mosaique {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	grid-template-rows: repeat(6, 1fr);
	gap: 2px;
	aspect-ratio: 2 / 3;
	/* 300 px, ET C'EST MESURÉ, PAS ESTIMÉ. Au-dessus de la mosaïque il y a
	   l'en-tête (que `--hd` porte), le padding de la salle, l'étiquette et
	   le titre — relevé au navigateur : 254 px du bas de l'en-tête au haut
	   de l'image sur un écran de 1440. On garde 46 px de respiration en
	   dessous, d'où 300. Un premier essai à 1,6 × --e7 laissait 36 px
	   dehors : la borne était calculée sans le titre. */
	max-width: calc((100svh - var(--hd) - 300px) * 2 / 3);
	margin-inline: 0 auto;
	background: var(--nuit);
	box-shadow: 0 34px 56px -30px rgba(44, 35, 21, .82);
}
.mosaique .case {
	background-image: var(--im);
	background-size: 500% 600%;
	filter: grayscale(.92) brightness(.34) contrast(1.15);
	transition: filter 900ms cubic-bezier(.16, 1, .3, 1);
}
/* L'AVIF de la couverture, et SEULEMENT si le navigateur sait le choisir.
   `--im2` n'est posé par `lha_mosaique()` que quand le fichier existe ; ce
   `@supports` est le second verrou. Sans lui, un navigateur qui ignore
   `image-set()` accepterait la propriete personnalisee puis la trouverait
   invalide a la substitution — et la couverture disparaîtrait au lieu de
   rester en JPEG. Mesure le 31.10.2026 : 21 couvertures sur 23 servies en
   JPEG sur `/livres/` alors que leurs AVIF etaient ecrits a cote. */
@supports (background-image: image-set(url("a.avif") type("image/avif"))) {
	.mosaique .case { background-image: var(--im2, var(--im)); }
}

.mosaique .case.est-ouverte { filter: contrast(1.08) saturate(1.2); }
.mosaique:hover .case:not(.est-ouverte):hover { filter: grayscale(.6) brightness(.56) contrast(1.1); }

.salle-compte {
	display: flex;
	gap: var(--e3);
	align-items: baseline;
	font-family: var(--mono);
	font-size: var(--t-mention);
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--accent-texte);
	margin: var(--e3) 0 0;
}
.salle-compte .j { margin-left: auto; color: var(--texte-doux); }
.salle-legende {
	font-family: var(--mono);
	font-size: var(--t-mention);
	letter-spacing: .06em;
	color: var(--texte-doux);
	margin: var(--e2) 0 0;
	max-width: 48em;
}
.salle-legende--apres { margin-top: var(--e4); }

.salle-etat {
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .2em;
	text-transform: uppercase;
	color: var(--accent-texte);
	margin: 0 0 var(--e3);
}
.salle-etat--paru { color: var(--navy); }
.salle-accroche {
	font-size: clamp(17px, 1.5vw, 20px);
	line-height: 1.52;
	max-width: 34em;
	margin: 0;
}
.salle-cartel {
	display: flex;
	gap: var(--e3);
	flex-wrap: wrap;
	align-items: baseline;
	font-family: var(--mono);
	font-size: var(--t-mention);
	letter-spacing: .16em;
	text-transform: uppercase;
	border-top: 2px solid var(--laiton-vif);
	padding-top: 11px;
	width: fit-content;
	max-width: 100%;
	margin: var(--e4) 0 0;
}
.salle-cartel .q { color: var(--texte-doux); }
.salle-cartel--clair { color: var(--blanc); }
.salle-cartel--clair .q { color: rgba(255, 255, 255, .72); }
.salle-lien { margin: var(--e4) 0 0; }
.salle-lien a {
	font-family: var(--mono);
	font-size: var(--t-mention);
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--accent-texte);
	text-decoration: none;
	border-bottom: 1px solid var(--trait);
	padding-bottom: 5px;
}
.salle-lien a:hover { border-color: var(--laiton-vif); }

/* ─── la présentation ────────────────────────────────────────────────────── */
.salle-presentation { padding-inline: var(--gouttiere); }
.salle-attaque {
	font-family: var(--titre);
	font-size: clamp(22px, 2.8vw, 32px);
	line-height: 1.16;
	max-width: 30em;
	margin: var(--e3) 0 var(--e4);
}
.salle-presentation p { max-width: var(--mesure); }

/* ─── les trois fragments ────────────────────────────────────────────────── */
.bloc--fragments { background: var(--navy); color: var(--sur-navy); }
.bloc--fragments .dedans-bloc {
	padding-block: var(--e6);
	padding-inline: var(--gouttiere);
}
.bloc--fragments .eti { color: var(--sur-navy-doux); }
.plateau {
	display: grid;
	gap: var(--e4);
	margin-top: var(--e4);
	grid-template-columns: 1fr;
}
@media (min-width: 640px) { .plateau { grid-template-columns: repeat(3, 1fr); } }
.fragment { margin: 0; }
.fragment-vue {
	position: relative;
	overflow: hidden;
	background: var(--nuit);
	aspect-ratio: 1 / 1;
}
.fragment-vue img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transform: scale(1.03);
	filter: contrast(.98) brightness(.9) saturate(.9);
	transition: filter 700ms cubic-bezier(.16, 1, .3, 1), transform 900ms cubic-bezier(.16, 1, .3, 1);
}
.fragment:hover .fragment-vue img { filter: contrast(1.12) saturate(1.28); transform: scale(1); }
.fragment-nom {
	display: block;
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--laiton-vif);
	margin-top: var(--e3);
}
.fragment blockquote {
	margin: var(--e2) 0 0;
	font-family: var(--titre);
	font-size: clamp(17px, 1.5vw, 19px);
	line-height: 1.32;
	color: var(--sur-navy);
}
.fragment-src {
	display: block;
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--sur-navy-doux);
	margin-top: var(--e2);
}

/* ─── ce qui se passe quand on passe dessus ──────────────────────────────── *
 * Les trois fragments sont trois découpes de la MÊME image. Le survol ne doit
 * donc pas être un effet de vignette : il doit dire ça. Quatre gestes, et pas
 * un de plus.
 *
 * LA LUMIÈRE QUITTE LES DEUX AUTRES. Dans une salle, on n'éclaire pas trois
 * œuvres pour en regarder une. Le fragment survolé monte à pleine lumière, les
 * deux autres retombent — c'est `:has()` sur le plateau qui le permet, sans une
 * ligne de script. Et rien n'est caché avant que le visiteur ait choisi : les
 * trois phrases restent lisibles en entier, seule l'image s'assombrit.
 *
 * LA PLAQUE SE DÉCROCHE. Six pixels vers le haut, et l'image recadre à sa place
 * exacte (1.03 → 1) : le fragment trouve sa position dans l'image entière au
 * moment où on le regarde. PAS D'OMBRE PORTÉE — elle est réservée à l'œuvre
 * accrochée, c'est écrit en tête de cette section et ça ne s'emprunte pas.
 *
 * LE FILET SE TIRE. Un trait de laiton se trace sous l'image, de gauche à
 * droite, et s'arrête au numéro. C'est lui qui donne une direction au
 * mouvement : sans lui, tout arrive partout en même temps.
 *
 * ET LE NUMÉRO. 01, 02, 03, par un compteur CSS — le rang d'un fragment se
 * déduit de sa place, il n'a rien à faire dans la base. Il est posé sur la
 * ligne du filet, avec le fond de la salle derrière lui : c'est ce fond qui
 * coupe le trait, comme le numéro d'une plaque sur une cimaise. Gris au repos,
 * laiton au survol.
 *
 * AU DOIGT, IL N'Y A PAS DE SURVOL. Sur un écran tactile, les trois fragments
 * sont à pleine lumière en permanence : un visiteur qui ne peut pas survoler ne
 * doit pas voir une salle à moitié éteinte. */
.plateau { counter-reset: fragment; }

.fragment {
	counter-increment: fragment;
	transition: transform 520ms cubic-bezier(.16, 1, .3, 1);
}
.fragment:hover { transform: translateY(-6px); }
.plateau:has(.fragment:hover) .fragment:not(:hover) .fragment-vue img {
	filter: contrast(.92) brightness(.58) saturate(.6);
}

.fragment figcaption { position: relative; margin-top: var(--e3); }
.fragment figcaption::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	width: 0;
	height: 1px;
	background: var(--laiton-vif);
	transition: width 560ms cubic-bezier(.16, 1, .3, 1);
}
.fragment:hover figcaption::before { width: 100%; }
.fragment figcaption::after {
	content: counter(fragment, decimal-leading-zero);
	position: absolute;
	top: 0;
	right: 0;
	transform: translateY(-50%);
	padding-inline: var(--e2);
	background: var(--navy);
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .12em;
	color: var(--sur-navy-doux);
	transition: color 420ms ease;
}
.fragment:hover figcaption::after { color: var(--laiton-vif); }

@media (hover: none) {
	.fragment-vue img { filter: contrast(1.12) saturate(1.28); transform: scale(1); }
	.plateau:has(.fragment:hover) .fragment:not(:hover) .fragment-vue img {
		filter: contrast(1.12) saturate(1.28);
	}
}

@media (prefers-reduced-motion: reduce) {
	.fragment:hover { transform: none; }
	.fragment,
	.fragment figcaption::before,
	.fragment figcaption::after { transition-duration: 1ms; }
}

/* ─── la charpente ───────────────────────────────────────────────────────── */
.salle-charpente { padding-block: var(--e6); padding-inline: var(--gouttiere); }
/* ⚠️ LES COLONNES SONT CELLES DU TABLEAU, PAS CELLES DE CHAQUE RANGÉE.
 * Chaque `.partie` portait sa propre grille, et sa première colonne était en
 * `auto` : « Partie un » est plus court que « Partie quatre », donc chaque
 * rangée plaçait son titre à une abscisse différente. Quatre titres décalés
 * les uns des autres, dans un bloc qui s'appelle « la charpente » — c'est
 * l'endroit du site où l'alignement DIT quelque chose.
 *
 * `subgrid` est la bonne réponse : les rangées empruntent les colonnes du
 * parent au lieu d'en inventer chacune les siennes. La ligne qui la précède
 * est le repli pour un navigateur qui ne la connaît pas — il garde une
 * première colonne de largeur FIXE, ce qui aligne aussi, en moins souple. */
.parties {
	display: grid;
	margin-top: var(--e4);
	grid-template-columns: auto minmax(0, 1fr);
}
.partie {
	display: grid;
	gap: 6px var(--e4);
	padding: var(--e3) 0;
	border-top: 1px solid var(--trait);
	grid-template-columns: 13ch minmax(0, 1fr);
	grid-template-columns: subgrid;
	grid-column: 1 / -1;
}
@media (min-width: 760px) {
	.parties { grid-template-columns: auto minmax(0, 1fr) 40%; }
	.partie { align-items: center; }
	.partie .part-barre { grid-column: 3; }
}
.part-n {
	font-family: var(--mono);
	font-size: var(--t-mention);
	letter-spacing: .14em;
	color: var(--texte-doux);
	white-space: nowrap;
}
.part-t {
	font-family: var(--titre);
	font-size: clamp(18px, 2vw, 24px);
	line-height: 1.14;
}
.part-t span {
	display: block;
	font-family: var(--texte-f);
	font-size: var(--t-mention);
	color: var(--texte-doux);
	margin-top: 4px;
	line-height: 1.4;
}
.part-barre {
	grid-column: 1 / -1;
	height: 10px;
	background: var(--creme-2);
	position: relative;
}
.part-barre i { position: absolute; inset: 0 auto 0 0; background: var(--navy); display: block; }
.partie--fort .part-barre i { background: var(--laiton-vif); }
.partie--fort .part-t { color: var(--accent-texte); }
.constat {
	margin: var(--e4) 0 0;
	border-left: 2px solid var(--laiton-vif);
	padding-left: var(--e3);
	font-family: var(--titre);
	font-size: clamp(18px, 2vw, 24px);
	line-height: 1.22;
	max-width: 28em;
}

/* ─── la salle ouverte ───────────────────────────────────────────────────── */
.salle-ouverte {
	position: relative;
	overflow: hidden;
	background: var(--nuit);
	min-height: min(74svh, 700px);
	display: grid;
	align-items: end;
}
.salle-fond { position: absolute; inset: 0; }
.salle-fond img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 42%;
	filter: contrast(1.08) saturate(1.2);
}
.salle-voile {
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(11,17,32,.18) 0%, rgba(11,17,32,.5) 55%, rgba(11,17,32,.92) 100%);
}
.salle-dessus {
	position: relative;
	z-index: 1;
	padding-block: var(--e6);
	padding-inline: var(--gouttiere);
}
.salle-phrase {
	font-family: var(--titre);
	color: var(--blanc);
	margin: 0 0 var(--e4);
	font-size: clamp(23px, 3.6vw, 46px);
	line-height: 1.1;
	max-width: 16em;
	text-shadow: 0 2px 24px rgba(0, 0, 0, .45);
}

/* ─── le mur des vingt et un ─────────────────────────────────────────────── */
.mur-livres {
	display: grid;
	gap: var(--e2);
	grid-template-columns: repeat(2, 1fr);
	margin-top: var(--e4);
}
@media (min-width: 560px) { .mur-livres { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 900px) { .mur-livres { grid-template-columns: repeat(7, 1fr); } }
.piece-mur { display: block; text-decoration: none; color: inherit; }
.piece-cadre {
	position: relative;
	display: block;
	overflow: hidden;
	aspect-ratio: 2 / 3;
	background: var(--nuit);
}
/* LA TUILE PORTE LA MÊME MOSAÏQUE QUE LA SALLE, en timbre-poste. C'est le mur
   qui donne l'état de la collection d'un coup d'œil : ce qui est paru est en
   clair, ce qui attend son tour est derrière ses volets, et la tuile du mois
   s'ouvre case par case. Montrer l'image entière ici revenait à tout dévoiler
   dix-huit mois à l'avance — et à faire du calendrier une décoration.

   Les ombres portées et le rapport de forme viennent de `.mosaique` ; on ne
   redéfinit ici que ce qui change à cette échelle : pas de relief, un filet
   d'un pixel au lieu de deux, et un éclaircissement au survol. */
.piece-cadre .mosaique {
	width: 100%;
	height: 100%;
	gap: 1px;
	box-shadow: none;
	transition: filter 620ms cubic-bezier(.16, 1, .3, 1);
}
.piece-cadre .mosaique .case { transition: filter 620ms cubic-bezier(.16, 1, .3, 1); }
.piece-mur:hover .piece-cadre .mosaique .case.est-ouverte,
.piece-mur:focus-visible .piece-cadre .mosaique .case.est-ouverte {
	filter: contrast(1.14) saturate(1.35);
}
/* Au survol, les volets encore clos s'entrouvrent sans s'ouvrir : on devine
   qu'il y a une image dessous, on ne la voit pas. */
.piece-mur:hover .piece-cadre .mosaique .case:not(.est-ouverte),
.piece-mur:focus-visible .piece-cadre .mosaique .case:not(.est-ouverte) {
	filter: grayscale(.86) brightness(.46) contrast(1.12);
}
.piece-sceau {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 6px 8px;
	background: rgba(11, 17, 32, .8);
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--laiton-vif);
}
.piece-nom {
	display: block;
	font-family: var(--titre);
	font-size: var(--t-mention);
	line-height: 1.22;
	margin-top: var(--e2);
}
.piece-mur:hover .piece-nom { color: var(--accent-texte); }

@media (prefers-reduced-motion: reduce) {
	.coupure { transition-duration: 1ms; }
	.coupure:hover, .coupure:focus-visible { transform: none; }
	.mosaique .case,
	.fragment-vue img,
	.piece-cadre img { transition-duration: 1ms; }
}

/* ─── un livre sans image : volets fermés ────────────────────────────────── *
 * Il reste sur le mur. Une case de la couleur du fond, un trait de laiton au
 * milieu comme la jointure de deux volets, et le mot « sans image ». Un livre
 * retiré du mur parce qu'il n'a pas encore de couverture serait un livre que
 * personne ne peut réclamer. */
.piece-mur--close .piece-cadre {
	background:
		linear-gradient(180deg, rgba(244, 241, 234, .07) 0%, rgba(244, 241, 234, 0) 62%),
		var(--nuit);
}
.piece-mur--close .piece-cadre::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 14%;
	bottom: 26%;
	width: 1px;
	background: rgba(192, 143, 62, .4);
}

/* ═══ 26. LE TRIPTYQUE D'UNE MAISON ═══════════════════════════════════════ *
 * Trois volets, toujours les mêmes, dans cet ordre : ce que c'est, la vision,
 * pourquoi je l'ai créée. C'est la MÊME FORME QUE LA TUILE, à une autre
 * échelle : une porte pour un livre, trois volets pour une maison.
 *
 * CE QUI FAIT LE TRIPTYQUE, et qui n'est pas la colonne : le filet vertical
 * entre les volets. Sans lui, trois paragraphes côte à côte se lisent comme un
 * texte coupé par la mise en page ; avec lui, ce sont trois réponses à trois
 * questions. Sur un écran étroit, le filet passe à l'horizontale — il ne
 * disparaît pas, sinon le triptyque redevient de la prose. */

.triptyque {
	display: grid;
	gap: var(--e4);
	margin-top: var(--e5);
}
@media (min-width: 820px) {
	.triptyque { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--e5); }
}
.volet {
	padding-top: var(--e3);
	border-top: 1px solid var(--trait);
}
@media (min-width: 820px) {
	.volet {
		padding-top: 0;
		padding-left: var(--e4);
		border-top: 0;
		border-left: 1px solid var(--trait);
	}
	.volet:first-child { padding-left: 0; border-left: 0; }
}
.volet-n {
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .18em;
	color: var(--accent-texte);
	margin: 0;
}
.volet-t {
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .18em;
	text-transform: uppercase;
	color: var(--texte-doux);
	margin: 4px 0 0;
}
.volet-c {
	font-family: var(--titre);
	font-size: clamp(17px, 1.6vw, 20px);
	line-height: 1.34;
	margin: var(--e2) 0 0;
}

/* ═══ 27. LE CURSEUR D'ESSAI ══════════════════════════════════════════════
   Il n'est servi que sur un site fermé au public. Volontairement discret et
   volontairement pas à la charte : c'est un outil, pas une pièce du site, et
   on doit voir d'un coup d'œil qu'il n'a rien à faire en ligne. */
.essai {
	position: fixed;
	right: var(--e3);
	bottom: var(--e3);
	z-index: 50;
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 10px 12px;
	background: var(--nuit);
	color: var(--sur-navy);
	border: 1px solid var(--laiton-vif);
	font-family: var(--mono);
	font-size: var(--t-etiquette);
	letter-spacing: .14em;
	text-transform: uppercase;
	max-width: 260px;
}
.essai label { color: var(--laiton-vif); }
.essai output { font-size: var(--t-action); letter-spacing: .06em; text-transform: none; }
.essai input[type="range"] { width: 100%; accent-color: var(--laiton-vif); }
.essai button {
	font: inherit;
	letter-spacing: .14em;
	text-transform: uppercase;
	background: none;
	border: 0;
	border-bottom: 1px solid var(--laiton-vif);
	color: var(--sur-navy);
	padding: 4px 0 2px;
	cursor: pointer;
	align-self: flex-start;
}
@media print { .essai { display: none; } }

/* ═══ 28. LES TRANSITIONS DE PAGE ═════════════════════════════════════════

   NATIVES, ET SANS UNE LIGNE DE SCRIPT. `@view-transition` demande au
   navigateur d'animer lui-même le passage d'un document à l'autre. Une
   bibliothèque de navigation aurait fait la même chose en quarante kilo-
   octets, en interceptant les clics, et en cassant le bouton « retour » le
   jour où elle aurait un défaut.

   LE CADRE NE BOUGE PAS, LE CONTENU GLISSE. C'est le parti pris : l'en-tête
   et le pied portent un nom de transition propre et ne sont pas animés, si
   bien qu'ils restent en place pendant que la page passe dessous. On change
   de salle sans sortir du bâtiment.

   Un navigateur qui ne connaît pas `@view-transition` ignore tout ce bloc et
   sert les pages comme avant : rien à charger, rien à replier, aucun écran
   blanc en attendant un script. */
@view-transition { navigation: auto; }

.hd   { view-transition-name: lha-entete; }
.pied { view-transition-name: lha-pied; }

/* Le cadre : aucun mouvement. Les deux états sont identiques, donc le
   remplacement sec ne se voit pas — c'est précisément l'effet voulu. */
::view-transition-group(lha-entete),
::view-transition-group(lha-pied) { animation-duration: 0s; }
::view-transition-old(lha-entete),
::view-transition-new(lha-entete),
::view-transition-old(lha-pied),
::view-transition-new(lha-pied) { animation: none; }

/* ── LE FEUILLET ─────────────────────────────────────────────────────────
 *
 * ⚠️ PREMIER ESSAI : LES DEUX PAGES SE FONDAIENT L'UNE DANS L'AUTRE. La
 * sortante s'effaçait vers la gauche pendant que l'entrante arrivait de la
 * droite en montant en opacité. Deux mouvements, mais un seul effet perçu —
 * un fondu enchaîné avec du déplacement dessus. On voyait à travers la page
 * qui arrive, et c'est précisément ce qui trahit l'écran : du papier n'est
 * pas translucide.
 *
 * CE QUI CHANGE TOUT : L'ENTRANTE N'A PLUS D'OPACITÉ ANIMÉE. Elle est
 * opaque du premier au dernier pixel, et elle GLISSE PAR-DESSUS. La
 * sortante, elle, ne s'en va pas : elle recule d'un cheveu et perd un peu de
 * lumière, comme une feuille qu'on couvre. Le geste devient « on pose une
 * page sur la pile », pas « une image se substitue à une autre ».
 *
 * L'OMBRE EST LE BORD DE LA FEUILLE, et c'est elle qui fait tout le travail.
 * Sans elle, la page entrante est un rectangle qui coulisse ; avec elle,
 * elle a une épaisseur et un bord d'attaque. Elle s'éteint en arrivant :
 * posée, la feuille ne projette plus rien.
 *
 * ET AUCUNE ROTATION. Un vrai tournage de page — en `rotateY`, avec une
 * perspective — est l'effet qu'on remarque, puis qu'on subit au troisième
 * clic. Il est gardé pour l'ouverture du site, une fois par visite, où il
 * annonce quelque chose. Entre deux pages, il serait un numéro.
 *
 * La courbe est très sortante : les trois quarts de la distance sont faits
 * dans le premier tiers du temps. C'est ce qui distingue un geste décidé
 * d'un glissement mou. */
::view-transition-old(root) {
	animation: lha-feuillet-dessous 440ms cubic-bezier(.22, 1, .3, 1) both;
}
::view-transition-new(root) {
	animation: lha-feuillet-dessus 440ms cubic-bezier(.22, 1, .3, 1) both;
}
@keyframes lha-feuillet-dessous {
	to { transform: translate3d(-1.1vw, 0, 0) scale(.995); filter: brightness(.965); }
}
@keyframes lha-feuillet-dessus {
	from {
		transform: translate3d(7vw, 0, 0);
		filter: drop-shadow(-16px 0 24px rgba(11, 17, 32, .28));
	}
	to {
		transform: none;
		filter: drop-shadow(-16px 0 24px rgba(11, 17, 32, 0));
	}
}

/* L'échappatoire. Qui demande moins de mouvement obtient un fondu court, pas
   un glissement — et surtout pas rien du tout : une coupe sèche entre deux
   pages est plus désorientante qu'un fondu de deux dixièmes. */
@media (prefers-reduced-motion: reduce) {
	::view-transition-old(root),
	::view-transition-new(root) {
		animation-name: lha-page-fondu;
		animation-duration: 180ms;
	}
	@keyframes lha-page-fondu { from { opacity: 0; } }
}

/* ═══ 29. LA COUVERTURE, ET LA PAGE QUI SE TOURNE ═════════════════════════ *
 * La couverture est COLLANTE et le récit glisse par-dessus : on soulève les
 * pages du magazine sans que la une s'en aille. La grille qui la voile est le
 * même geste que la mosaïque d'un livre — c'est ce geste répété qui fait la
 * marque, pas trois bonnes idées côte à côte.
 *
 * UNE CASE GARDE SA TAILLE, PAS SON NOMBRE — appris en construisant la
 * maquette. Trente cases sur une couverture de 1400 px font des pavés de 230
 * px, quand les mêmes trente sur une couverture de livre font des carrés de
 * 40. La couverture en porte donc quarante sur grand écran, et trente sur
 * téléphone : c'est la CASE qui est l'unité.
 *
 * LE FILET RESTE VISIBLE, cases ouvertes comprises : la grille ne disparaît
 * pas, elle s'ouvre. */

/* LA HAUTEUR DE LA BARRE, dont la couverture a besoin pour se coller dessous.
   Les deux valeurs se tiennent ici, ensemble : voir le bloc téléphone, où la
   barre est fixe et rend sa place au contenu par cette même variable. */
:root { --hd: 96px; }
@media (max-width: 900px) { :root { --hd: calc(2 * 10px + 44px + 1px); } }

/* 🔴 LA COUVERTURE NE RETIENT PLUS LA PAGE — 02.11.2026.
 *
 * « Quand on scrolle, il y a une sorte de blocage. Il faut vraiment scroller
 * pendant un petit bout de temps avant que ça commence réellement à
 * défiler. »
 *
 * La piste faisait 200svh pour une couverture collante de 100 : un écran
 * entier de défilement pendant lequel RIEN ne bougeait. C'était voulu au
 * départ — « elle est collante, et le récit glisse par-dessus » — et ça
 * tenait tant que la grille se refermait au défilement. Cette part a été
 * supprimée le 01.11 (voir `.couv-grille i`), et personne n'a repris la
 * piste : il restait la retenue, sans ce qu'elle retenait. Un effet dont on
 * a enlevé la cause ne devient pas neutre, il devient un blocage.
 *
 * La couverture occupe donc exactement sa hauteur et s'en va comme le reste
 * de la page. Elle garde `position: sticky` à zéro course — c'est ce qui la
 * laisse calée sous l'en-tête pendant qu'il rétrécit, sans rien retenir. */
.piste-couv { height: calc(100svh - var(--hd)); position: relative; }
.couv {
	position: sticky;
	top: var(--hd);
	height: calc(100svh - var(--hd));
	overflow: hidden;
	background: var(--nuit);
	display: grid;
	grid-template-rows: minmax(0, 1fr) auto;
}
.couv-image { position: relative; overflow: hidden; }

/* ── LA COUVERTURE EST UN TRIPTYQUE — 02.11.2026 ──────────────────────────
 *
 * « Je t'ai donné trois photos. Je veux vraiment que tu enlèves ces photos et
 * que tu remplaces. »
 *
 * CE QUI TOMBE AVEC L'ANCIENNE COMPOSITION. Un portrait entier posé à gauche
 * sur un détail en fond pleine largeur, et tout l'appareil qui allait avec :
 * le cadrage calculé du fond, l'ombre portée du portrait, le `contain` qui
 * l'empêchait d'être coupé, et la composition de téléphone où le portrait
 * couvrait 42 % de la clé. Six corrections successives pour faire tenir deux
 * images dans un cadre qui n'en voulait qu'une.
 *
 * TROIS VOLETS À PARTS ÉGALES règlent le problème au lieu de l'arbitrer :
 * chacun a sa colonne, aucun n'est posé sur l'autre, et aucun n'a besoin
 * d'être assourdi pour laisser voir le suivant. Les trois photographies sont
 * cadrées en 3:4 à la découpe — c'est le rapport d'un tiers de la bande —,
 * donc `cover` ne coupe presque rien.
 *
 * ⚠️ LE SUJET EST AU MILIEU, et la grille le sait : le foyer de la buée est
 * passé de .17 à .5 dans `inc/ouverture.php`. Une grille qui s'ouvre sur le
 * vide pendant que le visage reste couvert, c'est le défaut du 29.10 — il
 * revient à chaque fois qu'on déplace le sujet sans déplacer le foyer. */
.couv-triptyque {
	position: absolute; inset: 0;
	display: flex;
	/* Deux pixels, pas plus : c'est une reliure, pas une gouttière. Au-delà
	   les trois volets deviennent trois images côte à côte. */
	gap: 2px;
	background: var(--nuit);
}
.couv-volet { position: relative; flex: 1 1 0; min-width: 0; margin: 0; overflow: hidden; }
.couv-photo {
	display: block;
	width: 100%; height: 100%;
	/* `cover`, parce que chaque volet est déjà au rapport de sa colonne.
	   L'ancienne couverture avait besoin de `contain` pour ne pas décapiter
	   un portrait 2:3 dans une bande ; ici le fichier est taillé pour le
	   cadre, et c'est ce qui rend le réglage inutile. */
	object-fit: cover;
	object-position: 50% 28%;
}
/* Le portrait monte un peu : son visage est dans le tiers haut du fichier. */
.couv-volet--sujet .couv-photo { object-position: 50% 18%; }

/* ── LE TRIPTYQUE EST EN NOIR ET BLANC, ET LA COULEUR SE POSE ────────────
 * « Le triptyque devrait être en noir et blanc. Quand on passe la souris sur
 * une des photos, elle reste en couleur. Même si on ressort la souris. Quand
 * on remet la souris sur une autre, c'est celle-là qui prend la couleur.
 * Elle reste toujours sur la photo sur laquelle on est allé en dernier. »
 *
 * C'EST LA GRAMMAIRE DES BANDES, AVEC UNE MÉMOIRE EN PLUS. Sur `[bandes]`,
 * la couleur revient au survol et repart avec la souris : du CSS pur suffit.
 * Ici elle RESTE, donc il faut quelqu'un pour se souvenir — une classe posée
 * par `assets/ouverture.js`. Le CSS ne sait pas retenir ce qui vient de se
 * passer.
 *
 * ⚠️ LA COULEUR EST L'ÉTAT D'ARRIVÉE, PAS L'ÉTAT DE DÉPART. L'inverse — tout
 * en couleur, le gris au survol — dirait « vous abîmez ce que vous touchez ».
 * La même règle vaut ici que sur les bandes, et pour la même raison : le
 * geste doit RENDRE quelque chose.
 *
 * ⚠️ `filter` ET NON `mix-blend-mode`. Le bichrome des doubles pages passe
 * par un mélange avec le fond navy ; ici il n'y a pas de fond à mélanger,
 * les trois volets sont bord à bord. Une désaturation franche, et rien
 * d'autre. */
.couv-photo { filter: grayscale(1); transition: filter 520ms cubic-bezier(.2,.7,.2,1); }
.couv-volet--vif .couv-photo { filter: none; }
/* Le volet garde son anneau de focus : il reçoit le focus clavier, donc il
   doit le montrer. */
.couv-volet:focus-visible { outline: 2px solid var(--laiton-vif); outline-offset: -4px; }
@media (prefers-reduced-motion: reduce) {
	.couv-photo { transition: none; }
}

/* 🔴 LE VOLET DE GAUCHE EST DÉCALÉ — 02.11.2026. « La photo de gauche doit
   être décalée plus encore, un petit peu plus. »
   Le fichier porte la main ENTIÈRE, bagues comprises ; c'est la fenêtre de
   `cover` qui la coupait. Le volet fait 1000 × 1334 et s'affiche dans une
   colonne de 479 × 759 — plus étroite en proportion —, donc `cover` rogne
   les côtés à parts égales. En ramenant la fenêtre vers la gauche du
   fichier, la main rentre dans le cadre et la ceinture reste.
   ⚠️ CE N'EST PAS UN RECADRAGE DU FICHIER : le fichier ne change pas, c'est
   ce qu'on en montre qui bouge. Un recadrage perdrait les pixels. */
.couv-volet:first-child .couv-photo { object-position: 26% 28%; }

.couv-grille {
	position: absolute; inset: 0; z-index: 2;
	/* 🔴 ELLE NE PREND PAS LES CLICS NI LE POINTEUR — 02.11.2026. La grille
	   est posée PAR-DESSUS les trois volets, donc elle recevait tous les
	   `pointerenter` à leur place : la couleur ne revenait jamais au survol,
	   et aucune erreur ne le disait. Mesuré en envoyant l'événement à la
	   main sur un volet — la classe se posait — puis avec une vraie souris —
	   rien. Elle est décorative et `aria-hidden` : elle n'a aucune raison
	   d'intercepter quoi que ce soit. */
	pointer-events: none;
	display: grid; gap: 1px;
	grid-template-columns: repeat(8, 1fr);
	grid-template-rows: repeat(5, 1fr);
	/* 🔴 PLUS DE FOND ICI — 01.11.2026, et c'était LE voile. « Il y a
	 * toujours un voile sur le hero de la première page », quatrième fois
	 * que Lina le signale.
	 *
	 * Les trois premières fois, on a cherché au mauvais endroit : le filtre
	 * `brightness` de `.couv-fond`, retiré le 31.10 ; les cases, qui tombent
	 * bien à `opacity: 0` après l'arrivée. Personne n'a regardé le
	 * CONTENEUR, qui portait `rgba(236, 230, 218, .3)` — un lavis de crème à
	 * 30 % sur toute la photographie, en permanence. Les cases étant
	 * transparentes au repos, ce fond ne peignait pas les gouttières : il
	 * peignait TOUT.
	 *
	 * Vu côte à côte sur le même cadre, avec et sans : les noirs passent de
	 * gris à noirs. Rien n'est perdu au repos — les filets d'un pixel
	 * n'étaient pas perceptibles —, et pendant l'arrivée les gouttières
	 * laissent maintenant voir la photo entre les cases, ce qui est le motif
	 * même de la grille.
	 *
	 * ⚠️ Un lavis posé sur un conteneur ne se cherche pas où on cherche un
	 * voile. On regarde le filtre, puis les enfants ; le fond du parent est
	 * le dernier endroit, et c'était le bon. */
}
/* LA COUVERTURE SE DÉCOUVRE, ELLE N'EST PAS DÉJÀ DÉCOUVERTE.
 * Au repos elle s'arrête à un tiers de cases tombées — une couverture
 * entièrement voilée ne montre rien, et le premier écran doit se tenir tout
 * seul. Mais ce tiers ARRIVE : les cases tombent une à une en une seconde
 * sept, dans l'ordre de `--o`, et c'est le même geste que la porte et que la
 * mosaïque d'un livre.
 *
 * DEUX VARIABLES, DEUX RÔLES, ET ELLES S'ADDITIONNENT. `--p` est le
 * défilement, `--a` est l'arrivée : à `--a: 1` tout est voilé, à zéro on est
 * au repos. Les additionner dans la MÊME expression évite ce qui serait
 * arrivé avec deux mécaniques séparées — l'animation qui écrase le
 * défilement, ou l'inverse, selon celle qui a écrit la dernière.
 *
 * ⚠️ `--a` DOIT ÊTRE DÉCLARÉE PAR `@property`. Une propriété personnalisée
 * non enregistrée est un TEXTE pour le navigateur : il ne sait pas
 * l'interpoler, l'anime en deux paliers et la couverture saute au lieu de
 * s'ouvrir. L'enregistrer lui donne son type, et donc sa continuité.
 *
 * ELLE REJOUE EN REVENANT EN HAUT, et c'est demandé : la couverture n'est pas
 * un générique qu'on voit une fois, c'est l'état du haut de page. Le script
 * la relance quand `--p` retombe à zéro après en être parti. */
@property --a {
	syntax: "<number>";
	inherits: true;
	initial-value: 0;
}
.couv-grille { --a: 0; }
.couv-grille i {
	background: var(--creme);
	/* ⚠️ LE RANG PASSE PAR UNE VARIABLE INTERMÉDIAIRE, et ce détour n'est
	   pas décoratif. PHP écrit `--o` et `--m` dans l'attribut `style` de
	   chaque case : un style EN LIGNE bat toute règle de feuille, y compris
	   dans une requête de media. Une tentative d'écrire `--o: var(--m)` sous
	   900 px n'a donc rien changé du tout — silencieusement, comme toujours
	   avec les propriétés personnalisées. `--rang` est déclaré par la
	   feuille : elle peut le redéfinir où elle veut. */
	--rang: var(--o);
	/* 🔴 AU REPOS, PLUS UNE SEULE CASE. C'est la correction du 31.10.2026.
	 * L'ancien réglage laissait dix-huit cases crème sur quarante une fois
	 * l'arrivée jouée : la couverture ne s'ouvrait qu'à 55 %, et le reste du
	 * temps on voyait une photographie trouée de carrés beiges. « Les carrés
	 * doivent jamais rester comme ça. » Ils ne restent plus.
	 *
	 * `--c` est la part de voile voulue, et elle a maintenant UN seul sens :
	 * 0 montre l'image nue, 1 la couvre entièrement. Les deux sources
	 * s'additionnent dans cette variable plutôt que de s'écraser l'une
	 * l'autre.
	 *
	 * 🔴 ET LA PART DU DÉFILEMENT EST SUPPRIMÉE — 01.11.2026. Le terme
	 * `max(0, (--p − .62) × 2.63)` refermait la couverture après 62 % de
	 * course : « la couverture se referme derrière le lecteur », écrit ici
	 * même comme une intention. Lina l'a refusée autant de fois qu'elle l'a
	 * vue — « ces carrés ne doivent plus jamais apparaître sur le hero,
	 * c'est seulement à l'introduction, ensuite plus jamais, même avec un
	 * scroll ».
	 *
	 * Les corrections précédentes n'avaient touché que le REPOS : le
	 * 31.10 on a fait tomber les dix-huit cases qui restaient après
	 * l'arrivée, et le défilement continuait de les rappeler. Une intention
	 * écrite dans un commentaire se défend toute seule tant que personne ne
	 * la relit ; celle-ci a coûté quatre allers-retours.
	 *
	 * Il ne reste donc qu'une source, et `--c` vaut `--a` :
	 *   `--a` l'ARRIVÉE, de 1 à 0 : la buée qu'on essuie, UNE FOIS. */
	--c: var(--a);
	opacity: clamp(0, calc(var(--c) * (var(--n) + 1) - (var(--n) - var(--rang))), 1);
	transition: opacity 160ms linear;
}
/* La classe est posée PAR PHP, pas par le script : écrite au serveur, la
   couverture part voilée dès le premier pixel peint. Ajoutée après coup par
   JavaScript, on verrait le repos, puis le voile, puis l'ouverture — un
   clignotement à l'endroit exact où le site se présente. */
.couv--arrive .couv-grille {
	/* ⚠️ 900 ms, ET C'EST UN ALLER-RETOUR. 1700 ms d'origine : « il y a les
	   carrés, et puis ils s'enlèvent un à un » — j'ai allongé à 2400 pour
	   qu'on voie le geste. Réponse : « les carrés doivent partir tout de
	   suite, ils y restent pendant 2 secondes, ça va pas ». Les deux sont
	   vrais : le geste doit se VOIR, et il ne doit pas FAIRE ATTENDRE. À
	   900 ms sur quarante cases on lit encore la chute case par case, et la
	   photographie est nue avant qu'on ait eu le temps de s'impatienter. */
	/* 🔴 600 ms DEPUIS LE 02.11.2026 — « les carrés doivent disparaître plus
	   rapidement », et c'est la DEUXIÈME fois que Yan le demande après le
	   passage de 2400 à 900. Quand la même remarque revient, ce n'est plus un
	   réglage à affiner : c'est que le geste compte moins que l'attente. On
	   voit encore la chute case par case, mais la photographie est nue avant
	   qu'on ait eu le temps d'y penser. */
	animation: lha-couv-arrivee 600ms cubic-bezier(.33, 1, .68, 1) both;
}
/* Pendant que la page se tourne, la couverture attend DERRIÈRE elle. Sans ce
   délai, l'ouverture se joue sous le carton noir : elle a bien lieu, et
   personne ne la voit. Le marqueur est posé dans l'en-tête par trois lignes
   qui lisent `sessionStorage` avant le premier rendu. */
html.porte-a-jouer .couv--arrive .couv-grille { animation-delay: 4300ms; }
@keyframes lha-couv-arrivee { from { --a: 1; } to { --a: 0; } }
.couv-bandeau {
	background: var(--navy);
	border-top: 2px solid var(--laiton-vif);
	padding-block: var(--e4) var(--e5);
}
/* La gouttière du site, celle de `.ouverture .dedans` et des bandes : le
   bandeau du titre tombe sur le même bord que tout le reste de la page. */
.couv-bandeau .dedans { padding-inline: var(--gouttiere); }
.couv-bandeau .eti { color: var(--sur-navy-doux); margin: 0 0 var(--e3); }
.couv-nom {
	font-family: var(--titre); color: var(--sur-navy);
	font-size: clamp(38px, 8.6vw, 110px); line-height: .9;
	letter-spacing: -.022em; margin: 0 0 var(--e3);
	text-transform: uppercase;
}
.couv-roles {
	display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4); margin: 0;
	font-family: var(--mono); font-size: var(--t-action);
	letter-spacing: .2em; text-transform: uppercase; color: var(--laiton-vif);
}
.couv-roles span { display: flex; align-items: center; gap: var(--e4); }
.couv-roles span::after {
	content: ""; width: 5px; height: 5px; background: currentColor; border-radius: 50%;
}
.couv-roles span:last-child::after { display: none; }
/* 🔴 L'INVITE « LIRE » A ÉTÉ RETIRÉE — 02.11.2026. Ses trois règles et son
   animation décrivaient `.couv-lire`, qui n'existe NULLE PART : ni dans
   `inc/ouverture.php`, ni dans le HTML servi. Du CSS qui ne s'applique à
   rien, personne ne le voit — mais celui-ci coûtait cher, parce qu'il
   lisait `--p` : c'est pour cette seule règle morte que le script écrivait
   une propriété personnalisée sur la racine à chaque image du défilement,
   invalidant le style du document entier soixante fois par seconde. Une
   règle morte peut rester gratuite longtemps, puis se mettre à payer. */

@media (max-width: 760px) {
	/* ⚠️ HUIT RANGS, PAS SIX. PHP écrit toujours quarante cases — c'est la
	   CASE qui est l'unité, pas la grille. Six rangs sur cinq colonnes n'en
	   logent que trente : les dix dernières tombaient dans des rangs
	   implicites de hauteur nulle, hors de l'image, et le bas de la
	   couverture n'était jamais voilé sur téléphone. */
	.couv-grille { grid-template-columns: repeat(5, 1fr); grid-template-rows: repeat(8, 1fr); }
	/* ET L'ORDRE DE CHUTE SUIT LA GRILLE. `--o` est calculé pour huit
	   colonnes ; sur cinq, il désigne une case qui n'a rien à voir, et le
	   visage restait couvert pendant que des cases de décor s'ouvraient.
	   PHP écrit les deux rangs, la feuille choisit — par `--rang`, jamais en
	   réécrivant `--o`, qu'un style en ligne défend. */
	.couv-grille i { --rang: var(--m); }
}

/* 🔴 LE SEUIL DE LA COUVERTURE EST À 900, PAS À 760 — corrigé le 31.10.2026.
 * Il était dans le bloc des 760 px, et entre les deux se trouvait un trou que
 * personne ne regardait : à 808 px — un iPad en portrait, une fenêtre à demi
 * ouverte — le portrait gardait son réglage de bureau. Mesuré : 339 px de
 * large à 40 px du bord, 24 px de marge haute, son ombre portée, et le détail
 * de fond visible derrière, qui se lit comme un voile gris. « Cette photo
 * collée à gauche et pas de marge supérieure, enlève le voile. »
 *
 * LE CADRE EST HAUT, DONC LE PORTRAIT PREND TOUTE LA PLACE. Un portrait de
 * 42 % sur un écran de 390 px ferait 164 px : une vignette. À ces largeurs le
 * rapport du cadre est déjà proche de celui de la photographie, donc `cover`
 * ne coupe presque rien — et le détail de fond, entièrement recouvert,
 * s'efface au lieu de transparaître. */
/* 🔴 SUR TÉLÉPHONE, UN SEUL VOLET — 02.11.2026.
 *
 * Trois volets dans 390 px font trois bandes de 129 : ce n'est plus un
 * triptyque, c'est un peigne. Le portrait prend donc toute la largeur et les
 * deux détails s'effacent.
 *
 * ⚠️ `display: none` ET NON `opacity: 0` : un volet transparent garderait sa
 * colonne dans le flex, et le portrait n'aurait toujours qu'un tiers de la
 * place. C'est l'erreur symétrique de celle du 01.11, où un `display: none`
 * avait fait disparaître une photographie qu'on voulait voir — la règle
 * n'est pas « jamais `display: none` », c'est « savoir ce qu'on cache ».
 *
 * CE QUI A ÉTÉ RETIRÉ ICI : le cadrage calculé du fond, la largeur de 42 %
 * du portrait, et les notes qui expliquaient comment faire tenir la clé
 * derrière lui. Cette composition n'existe plus. */
@media (max-width: 900px) {
	.couv-triptyque { gap: 0; }
	.couv-volet:not(.couv-volet--sujet) { display: none; }
	.couv-volet--sujet .couv-photo { object-position: 50% 16%; }

	.couv-grille i { transition-duration: 1ms; }
	.couv--arrive .couv-grille,
	html.porte-a-jouer .couv--arrive .couv-grille {
		animation-duration: 1ms; animation-delay: 0ms;
	}
	.couv-lire i, .porte-grille i, .porte-roles,
	.porte.sort .porte-page { animation-duration: 1ms; }
}

/* ═══ 30. LES CHAPITRES D'« À PROPOS » ═══════════════════════════════════ *
 * Neuf écrans et demi de texte sans un seul jalon : on descendait la page
 * sans jamais savoir où on en était. Les chapitres numérotés donnent ce
 * repère, et c'est le seul endroit du site qui en ait besoin — c'est le seul
 * texte long. */
.chapitre {
	display: grid;
	grid-template-columns: var(--rail-chap, 120px) minmax(0, 1fr);
	gap: var(--e4);
	border-top: 1px solid var(--trait);
	padding-block: var(--e6);
}
.chapitre:first-of-type { border-top: 0; padding-top: var(--e4); }
/* 🔴 `--accent-texte`, PAS `--accent`. Mesuré : le laiton de marque (#b0915f)
   sur le crème ne rend que 2,64:1 À PLEINE OPACITÉ — il est fait pour des
   filets et des survols, pas pour porter du texte. À .55 il tombait à 1,64:1,
   et le repère de chapitre que ce bloc existe pour donner ne se lisait pas.
   `--accent-texte` est le même laiton rendu lisible, celui que le site emploie
   déjà pour les liens ; à .8 il tient 3,81:1 en clair et 4,69:1 en sombre,
   au-dessus du seuil des grands caractères, et le chiffre reste en retrait
   du titre qu'il accompagne. */
.chapitre-num {
	font-family: var(--titre); font-size: 52px; line-height: .8;
	color: var(--accent-texte); opacity: .8; margin: 0;
	font-variant-numeric: lining-nums tabular-nums;
}
.chapitre-corps h2 {
	font-family: var(--titre); font-weight: 400; color: var(--navy);
	font-size: clamp(26px, 3.6vw, 38px); line-height: 1.04;
	margin: 0 0 var(--e3);
}
.chapitre-corps h2 em { font-style: italic; }
.chapitre-corps p { max-width: var(--mesure); }
@media (max-width: 760px) {
	.chapitre { grid-template-columns: 1fr; gap: var(--e2); }
	.chapitre-num { font-size: 34px; }
}

/* Les archives : trois photographies de sa vie, à leur place — en bas d'un
   chapitre qui les annonce, et non en pleine page sur l'accueil.
   TROIS DE FRONT, TOUJOURS, et c'est le `auto-fit` qui a été retiré : il les
   empilait dès que la colonne passait sous quatre cents pixels, c'est-à-dire
   sur tablette, où elles devenaient trois grandes affiches l'une sous
   l'autre. Trois vignettes de front se lisent comme une planche-contact —
   ce qu'elles sont. Le rapport fixe les met d'aplomb : les trois originaux
   n'ont ni le même cadrage ni la même orientation. */
.archives {
	display: grid; gap: var(--e2);
	grid-template-columns: repeat(3, 1fr);
	margin-top: var(--e5);
	/* ⚠️ LE RAISONNEMENT S'EST TROMPÉ, ET IL EST CORRIGÉ LE 31.10.2026.
	   La version précédente bornait la planche à 760 px — trois vignettes de
	   250 — en écrivant : « ce sont des preuves, pas des photographies ».
	   C'était vrai de leur STATUT et faux de leur usage. Yan : « les petites
	   photos en bas de une passion, elles sont pas assez grandes, on ne les
	   voit pas assez. » Une preuve qu'on ne distingue pas ne prouve rien.
	   Elles prennent maintenant la largeur du chapitre ; la note qui les
	   suit continue de dire que ce sont des archives, et c'est elle qui
	   porte le statut, pas la taille. */
}
.archives figure { margin: 0; }
.archives img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.archives figcaption {
	font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .13em;
	text-transform: uppercase; color: var(--texte-doux); margin-top: var(--e2);
}
/* La note sous la planche : elle dit tout haut ce que la qualité dit tout
   bas. Les excuser serait pire — ce sont des preuves, pas des visuels. */
.archives-note {
	font-family: var(--mono); font-size: var(--t-mention);
	color: var(--texte-doux); margin: var(--e3) 0 0;
}

/* ═══ 31. LE FORMULAIRE A UNE CARTE ═══════════════════════════════════════ *
 * Sur la page Contact, deux masses se font face : les coordonnées en navy
 * plein, et le formulaire. Tant que celui-ci n'était qu'une suite de filets
 * sur le fond de page, la page montrait UNE carte et un bouton égaré. Elle
 * en montre deux, et le lecteur voit tout de suite laquelle on remplit.
 *
 * La carte est crème-foncé et non navy : deux blocs pleins de même valeur se
 * disputeraient, et c'est le formulaire qui doit gagner — c'est lui qui
 * attend quelque chose. */
.form-carte {
	background: var(--carte);
	border: 1px solid var(--trait);
	padding: var(--e5) var(--e5) var(--e6);
}
.form-carte .filet-titre { margin-bottom: var(--e5); }
@media (max-width: 760px) { .form-carte { padding: var(--e4) var(--e4) var(--e5); } }

/* Le curseur d'essai ne doit pas manger le titre sur un téléphone. */
@media (max-width: 560px) {
	/* ⚠️ IL TOMBAIT SUR LE NOM. Posé en bas à droite, il recouvrait
	   « LINA HADID » et deux des trois rôles sur la couverture d'un
	   téléphone — c'est-à-dire exactement la chose que la page doit dire en
	   premier. Il se range dans le coin, à moitié transparent tant qu'on ne
	   le touche pas. */
	/* ⚠️ IL RECOUVRAIT LE NOM. Posé en bas à droite, il tombait sur
	   « LINA HADID » et sur deux des trois rôles — c'est-à-dire exactement
	   ce que la page doit dire en premier. Le rendre transparent ne
	   suffisait pas : on lisait deux textes l'un sur l'autre.
	   Replié, il n'est plus qu'un onglet à hauteur de son titre, collé au
	   bord bas ; il se déplie au toucher. C'est un outil d'essai, il ne
	   dispute pas la page au contenu. */
	.essai {
		font-size: var(--t-mention);
		right: 0; left: 0; bottom: 0;
		max-width: none; padding: 9px var(--marge);
		max-height: 2.6em; overflow: hidden;
		transition: max-height .25s ease;
	}
	.essai:hover, .essai:focus-within { max-height: 60svh; }
	.essai .essai-titre { font-size: var(--t-etiquette); }
}

/* ═══ LE PAVAGE ════════════════════════════════════════════════════════
   Une grille d'emprises, partagée par l'univers et la presse. Le PHP qui la
   rend est dans `inc/mosaique.php` ; il n'y a qu'un seul des deux à lire pour
   comprendre l'autre.

   POURQUOI QUATRE COLONNES ET PAS TROIS. Avec trois, une tuile double occupe
   les deux tiers de la rangée et la mosaïque redevient une liste à gauche. Avec
   quatre, une tuile double laisse exactement deux cases à sa droite : c'est ce
   qui fait le pavage, et c'est pour ça que le garde-fou compte en multiples
   de quatre.

   `dense` COMBLE LES TROUS EN REMONTANT UNE PETITE TUILE, donc l'ordre n'est
   plus garanti. On parcourt un mur de coupures, on ne le lit pas de haut en
   bas : c'est acceptable ici, et ça ne le serait pas pour une suite qui
   raconte. */
.pavage {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	grid-auto-rows: minmax(0, auto);
	gap: var(--e4);
	grid-auto-flow: dense;
	align-items: stretch;
}
.mo-tuile {
	display: flex;
	flex-direction: column;
	gap: var(--e2);
	text-decoration: none;
	min-width: 0;
	position: relative;
}
.mo-tuile--tete    { grid-column: span 2; grid-row: span 2; }
.mo-tuile--pleine  { grid-column: span 1; grid-row: span 2; }
.mo-tuile--mention { grid-column: span 1; grid-row: span 1; }

/* LA TUILE MUETTE RESTE LISIBLE ET NE SE DONNE PAS L'AIR CLIQUABLE. C'est la
   même règle que pour une coupure sans lien : on ne cache pas ce qu'on ne peut
   pas ouvrir, on cesse seulement de le promettre. */
.mo-tuile--muette { cursor: default; }

/* LE REPLI SE FAIT EN DEUX TEMPS, PAS EN UN. À 1100 px, quatre colonnes
   deviennent deux et une tuile de tête occupe toute la largeur : la hiérarchie
   survit. À 700 px, une seule colonne, et toutes les emprises s'égalisent —
   un `grid-row: span 2` sur une colonne unique ne fait qu'un trou. */
@media (max-width: 1100px) {
	.pavage { grid-template-columns: repeat(2, 1fr); gap: var(--e3); }
	.mo-tuile--tete { grid-column: span 2; grid-row: span 2; }
}
@media (max-width: 700px) {
	.pavage { grid-template-columns: 1fr; }
	.mo-tuile--tete, .mo-tuile--pleine, .mo-tuile--mention {
		grid-column: span 1; grid-row: span 1;
	}
}

/* ── LES FILTRES EN RANGÉES ─────────────────────────────────────────────────
   Chaque rangée porte SON MOT à gauche et ses réponses à droite : la question
   se lit avant les réponses. La forme a été écrite pour trois rangées ; il
   n'en reste qu'une depuis le 02.11.2026 (voir `inc/presse.php`), et elle
   tient telle quelle — c'est ce qui permet d'en remettre une sans réécrire
   la mise en page. Le NOM a changé avec le nombre : `--trois` mentait. */
/* Deux classes, pas une : `.filtres` pose déjà `display: flex` avec la même
   spécificité, et seul l'ordre du fichier les départagerait. */
.filtres.filtres--rangees {
	display: block;
	padding: var(--e4) var(--marge) var(--e3);
	position: relative;
}
.filtres-rangee {
	display: flex; flex-wrap: wrap; gap: var(--e3) var(--e4);
	align-items: baseline;
	padding-block: var(--e2);
}
.filtres-rangee + .filtres-rangee { border-top: 1px solid var(--trait); }
/* LA COLONNE DU MOT EST FIXE, pour que les trois rangées de liens commencent
   au même endroit. Alignées sur leur mot, elles se liraient en escalier. */
.filtres-quoi {
	flex: 0 0 9ch;
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .18em; text-transform: uppercase;
	color: var(--accent-texte);
}
.filtres.filtres--rangees .compte {
	margin: 0; padding-top: var(--e3);
	border-top: 1px solid var(--navy);
	font-family: var(--mono); font-size: var(--t-mention);
	letter-spacing: .14em; color: var(--texte-doux);
}
@media (max-width: 700px) {
	/* Sur un téléphone, le mot passe au-dessus : neuf caractères de colonne
	   fixe, c'est un quart de l'écran donné à une étiquette. */
	.filtres-quoi { flex: 0 0 100%; }
}

/* ── LE MUR DE COUPURES, EN PAVAGE ────────────────────────────────────────
   La tuile de presse est une coupure : elle garde son inclinaison, son fond
   blanc et son filet. Ce que la mosaïque lui apporte, c'est son EMPRISE — une
   parution à la une tient deux colonnes sur deux rangées, une parution sans
   coupure une seule case. La taille dit ce que la tuile a à montrer. */

.pavage--presse .coupure { transform: none; }
/* LA SPÉCIFICITÉ EST ÉCRITE EXPRÈS. `.coupure .vign` pose déjà un rapport de
   3/4 avec deux classes ; une règle à deux classes ne le bat que parce
   qu'elle vient plus bas dans le fichier, ce qui tient jusqu'au jour où
   quelqu'un réordonne la feuille. Trois classes le battent pour de bon. */
.pavage--presse .coupure .vign { flex: 1 1 auto; aspect-ratio: auto; min-height: 0; }
/* LA TUILE DE TÊTE MONTRE SA COUPURE EN PAYSAGE. En portrait sur deux
   colonnes de large, la page imprimée devient une bande et on n'y lit plus
   rien. */
.pavage--presse .mo-tuile--tete .vign { aspect-ratio: 16 / 10; }
.pavage--presse .mo-tuile--mention .vign { aspect-ratio: 3 / 2; flex: 0 0 auto; }
/* OÙ MÈNE LA TUILE, écrit en bas, et seulement si elle mène quelque part. */
.mo-tuile .ou {
	margin-top: auto;
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .12em; text-transform: uppercase;
	color: var(--accent-texte);
}
a.mo-tuile:hover .ou { color: var(--navy); }
a.mo-tuile:hover .t { text-decoration: underline; text-decoration-color: var(--accent);
	text-underline-offset: 4px; }
/* UNE TUILE DE MENTION NE PORTE PAS LE TITRE EN ENTIER. Une case de 1 × 1
   avec un titre de douze mots devient un pavé illisible à côté de voisines
   qui respirent. Trois lignes, puis l'ellipse — et le titre entier reste
   dans l'attribut, donc dans la bulle du navigateur. */
.pavage--presse .mo-tuile--mention .t {
	display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
	line-clamp: 3; overflow: hidden;
}

/* ── LA RESPIRATION ─────────────────────────────────────────────────────────
   Une image pleine, bord à bord, sans un mot. C'est le gabarit qui répond au
   « beaucoup d'espace blanc » de Lina, et il y répond par l'inverse de ce
   qu'on attend : pas en retirant de l'air, en lui donnant quelque chose à
   porter. Une bande de 1212 px vide entre deux sections, c'est un défaut ;
   une photographie de 760 px entre deux sections, c'est un souffle.

   ELLE EST BASSE EXPRÈS. Une image pleine hauteur coupe la lecture et oblige
   à défiler pour retrouver le fil ; une bande se traverse. Le rapport est
   proche de 21/9, celui d'un panoramique.

   PAS DE LÉGENDE. Un texte sous une respiration en refait une section. Si
   l'image a besoin d'être expliquée, ce n'est pas une respiration. */
.respiration { margin: 0; display: block; }
.respiration img {
	display: block;
	width: 100%;
	height: clamp(220px, 34vw, 420px);
	object-fit: cover;
	object-position: 50% 50%;
}

/* 🔴 UNE RESPIRATION QUI NE COUPE RIEN — 02.11.2026.
   La hauteur bornée ci-dessus est ce qui fait qu'une respiration RESPIRE :
   une bande, pas une image. Mais `cover` sur une hauteur fixe est un zoom
   déguisé dès que l'écran s'élargit — à 1900 px, une bande 21/9 monte à
   822 px de haut et on n'en voit que la tranche du milieu.
   Quand le SUJET de l'image est un objet précis, c'est la bonne hauteur qui
   compte, pas la bonne bande : `--entiere` rend à l'image son rapport. */
.respiration--entiere img { height: auto; object-fit: fill; }

/* 05 · ÉCRIRE : les deux colonnes se centrent au lieu de s'aligner par le
   haut. Un mot d'affiche de trois lignes en face d'un bloc qui en fait huit
   laisse, aligné en haut, un rectangle blanc sous le titre — et c'est
   exactement ce qu'on voyait. Centrées, les deux masses se répondent. */
.gab--ecrire { align-items: center; }

/* ═══ LA FENÊTRE ════════════════════════════════════════════════
   Une fenêtre qui porte un encadrement vers un site tiers — et qui ne le
   porte qu'après le clic. Elle sert la visite virtuelle ET les trente-deux
   parutions de presse encadrables. Le pourquoi est dans `inc/fenetre.php` ;
   ici, seulement la forme.

   `<dialog>` NATIF, et c'est ce qui rend la fenêtre courte à écrire : la
   touche Échap, le piège de focus, le fond inerte et le retour du focus
   arrivent avec l'élément. */
/* 🔴 `display` NE SE POSE QUE SUR LA FENÊTRE OUVERTE.
   Un `<dialog>` fermé est en `display: none` par la feuille du navigateur.
   Lui donner `display: flex` sans condition ÉCRASE ce défaut : la fenêtre se
   dessine alors dans le flux de la page, après le pied, en un grand bloc
   navy vide. Relevé par Yan sur la page Contact le 31.10.2026 — mesuré
   ensuite : `open: false` et `display: flex`, 830 px de haut posés à 2934
   dans une page qui en fait 3764.

   C'est la troisième casse de la soirée du même genre : une règle écrite
   pour l'état visible, appliquée à tous les états. */
.fenetre[open] {
	display: flex;
}
.fenetre {
	width: min(96vw, 1400px);
	height: min(92vh, 900px);
	max-width: none; max-height: none;
	padding: 0;
	border: 1px solid var(--navy);
	background: var(--navy);
	color: var(--sur-navy);
	flex-direction: column;
	overflow: hidden;
}
.fenetre::backdrop { background: rgba(31, 43, 69, .86); }
/* LA BARRE DIT OÙ L'ON EST ET COMMENT SORTIR. Une fenêtre qui ne porte
   qu'une croix oblige à deviner ce qu'on regarde. */
.fenetre-barre {
	display: flex; align-items: center; gap: var(--e4);
	padding: var(--e3) var(--e3) var(--e3) var(--e4);
	border-bottom: 1px solid rgba(236, 230, 218, .22);
	flex: 0 0 auto;
}
.fenetre-quoi {
	margin: 0; flex: 1 1 auto;
	/* Le titre vient du contenu — « RTS · Les beaux parleurs · avril 2020 » —
	   et il peut dépasser. Il se coupe plutôt que de pousser la croix hors
	   de la barre. */
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .16em; text-transform: uppercase;
	color: var(--sur-navy-doux);
}
/* LA SECONDE PORTE : ouvrir chez Klapty, en grand. Elle est DANS la fenêtre
   et pas à côté du lien, parce que c'est là qu'on en a envie — une fois
   qu'on a vu que la visite valait le détour. */
.fenetre-dehors {
	font-family: var(--mono); font-size: var(--t-etiquette);
	letter-spacing: .12em; text-transform: uppercase;
	color: var(--sur-navy); text-decoration: none;
	border-bottom: 1px solid var(--accent); padding-bottom: 3px;
}
.fenetre-dehors:hover { color: var(--accent); }
.fenetre-fermer {
	flex: 0 0 auto;
	width: 44px; height: 44px;      /* la cible tactile de la maison */
	display: grid; place-items: center;
	background: none; border: 1px solid rgba(236, 230, 218, .3);
	color: var(--sur-navy); font-size: 18px; line-height: 1;
	cursor: pointer;
}
.fenetre-fermer:hover { border-color: var(--accent); color: var(--accent); }
.fenetre-cadre { flex: 1 1 auto; min-height: 0; background: var(--navy-presse); }
.fenetre-cadre iframe { display: block; width: 100%; height: 100%; border: 0; }

@media (max-width: 700px) {
	/* Sur un téléphone, la fenêtre prend tout : une visite à 360 degrés dans
	   un cadre de 80 % d'écran ne se visite pas. */
	.fenetre { width: 100vw; height: 100dvh; border: 0; }
	.fenetre-barre { gap: var(--e3); padding-inline: var(--e3); }
	.fenetre-quoi { font-size: 10px; }
}

/* ── LE JOURNAL, DANS LE MÊME PAVAGE ────────────────────────────────────────
   🔴 LA MAÇONNERIE ÉTAIT LA TROISIÈME GRILLE DU SITE, et c'est exactement ce
   que le pavage existe pour empêcher. « Le blog, il est monotone » — il
   l'était parce que ses notes avaient toutes la même taille dans une grille
   qui ne hiérarchisait rien. La plus récente ouvre maintenant en grand. */
.note {
	background: var(--carte);
	border: 1px solid var(--trait);
	padding: var(--e4);
	gap: var(--e3);
	color: inherit;
	transition: border-color .2s ease;
}
.note:hover { border-color: var(--accent); }
.note .vign {
	display: block; overflow: hidden; margin: calc(var(--e4) * -1) calc(var(--e4) * -1) 0;
	aspect-ratio: 4 / 3; background: var(--creme-2);
}
.mo-tuile--tete.note .vign { aspect-ratio: 21 / 9; }
.note .vign img { width: 100%; height: 100%; object-fit: cover; display: block; }
.note .x { font-family: var(--mono); font-size: var(--t-etiquette); letter-spacing: .14em;
	text-transform: uppercase; color: var(--accent-texte); }
.note .t { display: block; font-family: var(--titre); font-size: 24px; line-height: 1.1;
	color: var(--navy); }
.mo-tuile--tete.note .t { font-size: 38px; }
.mo-tuile--mention.note .t { font-size: 19px; }
.note .n { font-size: var(--t-mention); line-height: 25px; color: var(--texte-doux); }
/* UNE NOTE SANS IMAGE NE RÉSERVE PAS LA PLACE D'UNE IMAGE. Même règle que la
   coupure sans scan : un cadre vide se lit comme un chargement raté. */
.note--nue { border-top: 2px solid var(--navy); }
a.note:hover .t { text-decoration: underline; text-decoration-color: var(--accent);
	text-underline-offset: 4px; }
.pavage--journal .mo-tuile--tete .n { max-width: 56ch; }
@media (max-width: 700px) {
	.mo-tuile--tete.note .t { font-size: 26px; }
	.mo-tuile--tete.note .vign { aspect-ratio: 4 / 3; }
}

/* ── LE LOGO, EN SVG INLINE ─────────────────────────────────────────────────
   Il remplace le bloc « logo du site » et son PNG. Le pourquoi est dans
   `lha_logo_site()` ; ici, seulement la taille — qui suit la même variable
   que le bloc suivait, donc le resserrement au défilement marche à
   l'identique. */
.lha-logo-lien { display: block; line-height: 0; color: var(--navy); }
.lha-logo {
	display: block;
	height: var(--hd-logo);
	width: auto;
	transition: height 180ms ease;
}
@media (prefers-reduced-motion: reduce) { .lha-logo { transition-duration: 1ms; } }

/* ── LA MOSAÏQUE DE DÉTAILS ─────────────────────────────────────────────────
   Un détail en grand, quatre petits autour. Le pourquoi est dans
   `inc/macros.php` : quatre pages du site ne portaient aucune image, et un
   portrait souriant au-dessus d'une politique de confidentialité aurait été
   maladroit. Un détail donne la série sans donner un regard.

   🔴 PREMIÈRE VERSION : TROIS BANDES VERTICALES CÔTE À CÔTE. Lisible, mais
   c'était une rangée d'images, pas une mosaïque — et ce n'était pas l'idée.
   Les bandes sont parties avec leurs fichiers. */
.gab--macros { padding-block: 0 var(--e6); }
.pavage--macros { gap: var(--e2); }
.macro {
	margin: 0; overflow: hidden; background: var(--creme-2);
	aspect-ratio: 1; gap: 0;
	/* 🔴 `height: 100%` NE SUFFIT PAS QUAND LA HAUTEUR VIENT D'UN
	   `aspect-ratio`. Un pourcentage de hauteur exige une hauteur DÉFINIE
	   sur le parent ; celle que `aspect-ratio` calcule ne compte pas, et
	   l'image reprend alors son rapport naturel.
	   Le défaut est resté invisible tant que la mosaïque n'a porté que des
	   macros carrées de 900 × 900 : elles remplissaient la tuile par
	   coïncidence. Le 31.10.2026, une photographie 3:2 est entrée dans la
	   grande tuile et a laissé un tiers de crème en dessous ; une 2:3 dans
	   une petite a débordé de 157 px. Position absolue : l'image remplit sa
	   tuile quel que soit son rapport. */
	position: relative;
}
/* La tuile de tête est 2 × 2 : elle reste carrée, donc elle vaut exactement
   quatre petites. C'est ce qui ferme le pavage sans calcul. */
.macro img { position: absolute; inset: 0;
	width: 100%; height: 100%; object-fit: cover; display: block;
	transition: transform 700ms cubic-bezier(.16,1,.3,1); }
/* ⚠️ PAS DE NOIR ET BLANC ICI, contrairement aux bandes. Une macro vit de sa
   MATIÈRE — l'acier d'une montre, l'or d'un anneau, la laine brune. Les
   désaturer les rendrait toutes grises et interchangeables, ce qui est
   exactement le contraire du propos. */
.pavage--macros:hover .macro img { transform: scale(1.02); }
@media (prefers-reduced-motion: reduce) { .macro img { transition: none; } }
@media (max-width: 700px) {
	/* Deux colonnes : la tête occupe la largeur, les quatre autres se
	   rangent deux par deux dessous. */
	.pavage--macros { grid-template-columns: repeat(2, 1fr); }
}

/* UN PORTRAIT EN RESPIRATION NE SE TRAITE PAS COMME UNE BANDE. La bande se
   traverse ; un portrait se regarde, donc il lui faut de la hauteur et un
   cadrage haut — sinon `cover` coupe le visage, ce qui est arrivé deux fois
   ce soir sur d'autres images. */
.respiration--portrait img {
	height: clamp(420px, 68vw, 760px);
	object-position: 50% 22%;
}

/* ── LES CIBLES TACTILES ────────────────────────────────────────────────────
   Mesuré sur un iPhone 13 le 31.10.2026 : quarante-neuf liens sous 44 px de
   haut, et AUCUN n'était un lien dans un texte — ce sont des liens isolés,
   ceux qu'on vise au pouce. Les légendes du rail de livres faisaient 20 px.

   44 px est le minimum d'Apple et la recommandation du WCAG. On l'obtient
   par le rembourrage et non par la taille du texte : un libellé de menu
   grossi casserait la typographie pour régler un problème de doigt. */
@media (max-width: 900px) {
	/* `.pied li a` nommément : les liens du pied vivent dans des listes, et
	   `.pied a` seul ne les atteignait pas avec assez de poids pour battre
	   la règle de liste. Mesuré après coup : ils restaient à 30 px. */
	.lien, .livre-lien, .aller, .filtres a, .pied a, .pied li a, .coupure .m {
		display: inline-block;
		min-height: 44px;
		line-height: 1.6;
		padding-block: 10px;
	}
	/* Une légende de rail est sous l'image : le rembourrage haut la
	   décollerait. Il va en bas. */
	figcaption .livre-lien { padding-block: 4px 18px; min-height: 40px; }
	/* Dans une colonne de pied, les entrées se suivent : un rembourrage
	   symétrique les espacerait trop. Il est réparti. */
	.pied li a { min-height: 44px; padding-block: 11px; display: block; }
	.pied li { margin: 0; }
}


/* Le message de vide des filtres vit DANS la page, masqué tant qu'il reste
   une tuile : le script n'a qu'à le montrer, il n'a pas à l'écrire. */
.filtres-vide {
	padding-block: var(--e6);
	padding-inline: var(--gouttiere);
	font-size: var(--t-chapo);
	color: var(--texte-doux);
	display: flex; flex-wrap: wrap; gap: var(--e3); align-items: baseline;
}


/* ═══ LA PHOTOGRAPHIE EN BANDES ═══════════════════════════════════════════
 * Voir `inc/bandes.php` pour le pourquoi. Ici, trois choses seulement :
 *
 * 1. `background-size: calc(var(--n) * 100%) 100%` — chaque bande montre un
 *    N-ième de la largeur, donc l'image doit faire N fois la largeur d'une
 *    bande. Avec `cover`, chaque bande recadrerait l'image ENTIÈRE dans son
 *    tiers et on verrait trois fois le même sujet rétréci.
 * 2. La désaturation est l'état de REPOS, la couleur l'état d'arrivée : le
 *    geste rend quelque chose au lieu d'abîmer.
 * 3. Un filet de fond entre les bandes, pour qu'on voie qu'elles sont
 *    trois — sans lui, l'image paraît entière et le survol semble buggé. */
.bandes {
	margin: 0;
	display: grid;
	grid-template-columns: repeat(var(--n, 3), 1fr);
	gap: 2px;
	background: var(--creme);
	aspect-ratio: 21 / 9;
	overflow: hidden;
}
/* La bande BASSE : même largeur, moitié moins haute. Son image doit être
   taillée au MÊME rapport, sinon elle est écrasée et non recadrée. */
.bandes--basse { aspect-ratio: 42 / 9; }

.bande {
	background-image: var(--img);
	background-size: calc(var(--n, 3) * 100%) 100%;
	background-position: var(--pos, 0) center;
	background-repeat: no-repeat;
	filter: grayscale(1) contrast(1.06);
	transition: filter 420ms cubic-bezier(.16, 1, .3, 1);
	cursor: default;
}
.bande:hover, .bande:focus-visible { filter: grayscale(0) contrast(1.02); }
.bande:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
@media (prefers-reduced-motion: reduce) { .bande { transition: none; } }
/* Sur un téléphone il n'y a pas de survol, et trois bandes de 130 px ne
   montrent plus rien : l'image redevient une image. */
@media (max-width: 760px) {
	.bandes { grid-template-columns: 1fr; aspect-ratio: 16 / 9; }
	/* ⚠️ APRÈS `.bandes`, ET PAS AVANT. Les deux sélecteurs pèsent le même
	   poids : écrite plus haut, la bande basse était écrasée par le 16/9 du
	   repli, et mesurait exactement la même chose qu'une bande pleine. Une
	   borne qui ne mord jamais n'est pas un réglage. */
	.bandes--basse { aspect-ratio: 2 / 1; }
	.bande:not(:first-child) { display: none; }
	.bande { background-size: cover; background-position: center; filter: none; }
}

/* ═══ 99. `hidden` VEUT DIRE CACHÉ ════════════════════════════════════════ *
 *
 * 🔴 TROISIÈME FOIS QUE CE PIÈGE MORD, DONC ON LE FERME UNE FOIS.
 *
 * Le navigateur applique `[hidden] { display: none }` depuis SA feuille de
 * style. N'importe quelle règle d'auteur qui pose un `display` sur le même
 * élément gagne — une feuille d'auteur l'emporte toujours sur celle de
 * l'agent. Un élément du thème qui est `flex` ou `grid` ignore donc purement
 * et simplement l'attribut `hidden`.
 *
 * Deux rustines locales existaient déjà, `.porte[hidden]` et
 * `.filtres-vide[hidden]` : le défaut avait été trouvé deux fois et réparé
 * deux fois à l'endroit où il se voyait. Le 01.11.2026 il est revenu par les
 * FILTRES DE PRESSE. « Monde économique et LFM radio sont toujours affichés
 * et ne changent pas avec les filtres. » Mesuré : neuf tuiles portaient bien
 * `hidden`, `assets/presse.js` faisait son travail, le compteur annonçait
 * juste — et les tuiles mesuraient 618 px de haut, en `display: flex`, parce
 * que `.mo-tuile` le leur disait.
 *
 * ⚠️ UN COMPTEUR JUSTE NE PROUVE PAS UN AFFICHAGE JUSTE. La page disait
 * « 26 parutions » et en montrait 35. C'est le genre d'écart qu'aucune porte
 * ne regarde et que l'œil ne compte pas.
 *
 * ⚠️ `[hidden][hidden]` ET NON `!important`. Ce thème n'a aucun `!important`
 * et n'en veut pas — la première exception en appelle d'autres. Répéter
 * l'attribut porte la spécificité à (0,2,0) : assez pour battre toute règle
 * à une seule classe, et, placée en dernier dans la feuille, à deux classes
 * aussi. C'est une astuce, elle est écrite, et elle ne coûte rien à personne.
 *
 * Les deux rustines sont retirées : une règle générale qu'on double de cas
 * particuliers finit par ne plus être lue. */
[hidden][hidden] { display: none; }

/* ── UN LIBELLÉ QUI PASSE À LA LIGNE LE FAIT PROPREMENT ─────────────────── *
 * « Voir le lieu en 360° » tient sur 340 px ; la colonne des coordonnées en
 * fait 250 depuis que le panneau est passé de cinq colonnes à quatre. Deux
 * lignes sont donc inévitables — ce qui ne l'était pas, c'est la coupure :
 * « VOIR LE LIEU EN » puis « 360° » tout seul. Un orphelin de deux
 * caractères sous une ligne pleine se lit comme un défaut d'affichage.
 * `balance` répartit : « VOIR LE LIEU » / « EN 360° ». */
.visite-lien { text-wrap: balance; }
