/* ==========================================================================
   COMPOSANTS – Thème Rosa Alaimo (autonome, sans Divi)
   Portage en CSS vanilla des composants de l'ancien site (Tailwind/AMP compilé).
   S'appuie sur les variables de design-system.css.
   ========================================================================== */

/* ==========================================================================
   TRANSITIONS DE PAGE
   Chaque navigation produisait un flash blanc. Le fondu supprime la coupure, et
   la vignette d'une carte MORPHE en couverture d'article — le mouvement dit
   « cette carte est devenue cette page ».
   ⚠️ Sous `prefers-reduced-motion: no-preference` : c'est un `@view-transition`
   complet, la neutralisation globale des durées ne l'atteindrait pas.
   ⚠️ Les noms de vue sont posés en `style=` (blog-card.php, single.php) : ils
   dépendent de l'ID de l'article, donc du contenu.
   Non supporté = déclaration ignorée, navigation inchangée. */
@media (prefers-reduced-motion: no-preference) {
	@view-transition { navigation: auto; }

	/* ⚠️ LES RÉGLAGES PAR DÉFAUT NE SE VOIENT PAS SUR CE SITE, et il a fallu le
	   constater en usage : le fondu natif dure 250ms et enchaîne deux pages
	   blanches portant le même en-tête — il n'y a presque rien à voir changer.
	   Vérifié que la transition avait bien lieu (`pagereveal.viewTransition`
	   non nul) AVANT de conclure que c'était une question de réglage : le
	   symptôme « je ne vois rien » a deux causes possibles, et il fallait
	   éliminer la panne avant de toucher au calage.
	   420ms : au-delà, la navigation se met à sembler lente ; en deçà, l'œil ne
	   raccroche pas les deux états. */
	::view-transition-group(*) {
		animation-duration: 420ms;
		animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
	}
	/* Le corps de page glisse légèrement au lieu de se fondre sur place : c'est
	   le décalage qui donne le sens de la navigation, le fondu seul étant
	   indistinct entre deux pages de même facture. */
	::view-transition-old(root) {
		animation: ra-vt-sortie 260ms cubic-bezier(0.4, 0, 1, 1) both;
	}
	::view-transition-new(root) {
		animation: ra-vt-entree 380ms cubic-bezier(0, 0, 0.2, 1) 60ms both;
	}
}
@keyframes ra-vt-sortie { to { opacity: 0; transform: translateY(-1.5rem); } }
@keyframes ra-vt-entree { from { opacity: 0; transform: translateY(2rem); } }

/* --- Reset léger & base --- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; background-color: var(--ra-sombre); }
@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	/* Les états de survol restent, seule leur mise en mouvement est neutralisée. */
	*, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
body {
	margin: 0;
	background-color: var(--ra-clair);
	font-family: var(--ra-font-body);
	font-size: var(--ra-fs-courant);
	line-height: var(--ra-lh-courant);
	color: var(--ra-text);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}
img, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: inherit; }

h1, h2, h3, h4 {
	margin: 0;
	font-family: var(--ra-font-heading);
	letter-spacing: var(--ra-tracking-head);
	color: var(--ra-primaire);
}
h1 { font-size: var(--ra-fs-h1); line-height: 1.1; font-weight: 700; }
h2 { font-size: var(--ra-fs-h2); line-height: 1.05; font-weight: 700; margin-bottom: 1rem; }
h3 { font-size: var(--ra-fs-h3); line-height: 1.15; font-weight: 700; }
/* Accueil : titre héros bicolore (1ʳᵉ ligne fine, 2ᵉ ligne <span> en gras) — exception voulue. */
.hero-title { font-weight: 400; }
p  { margin: 0; font-size: var(--ra-fs-courant); line-height: var(--ra-lh-courant); }
@media (min-width: 1024px) { h2 { margin-bottom: 2rem; } }

/* Focus clavier visible sur tout élément interactif : aucune règle ne le
   prenait en charge, la navigation au clavier était donc aveugle. Encre plutôt
   qu'or : l'or (#99876c) ne tient pas le rapport de contraste 3:1 sur blanc. */
:focus-visible { outline: 3px solid var(--ra-primaire); outline-offset: 3px; }

/* Citation « guillemet suspendu » (titre serif italique, retrait négatif) */
.emphase {
	font-family: var(--ra-font-heading);
	font-style: italic;
	letter-spacing: var(--ra-tracking-head);
	text-indent: -0.75rem;
	font-size: var(--ra-fs-emphase);
	line-height: 1.2;
	margin: 0;
}
@media (min-width: 1280px) { .emphase { text-indent: -1.5rem; } }

/* ==========================================================================
   Conteneur « megabloc »
   ========================================================================== */
.megabloc {
	margin-inline: auto;
	max-width: var(--ra-container);
	padding-inline: 1.5rem;
}
.megabloc--full { margin-inline: auto; max-width: var(--ra-container); padding-inline: 0; }
/* Rythme vertical d'une page intérieure (haut ET bas). Remplace les
   `style="padding-block:…"` posés gabarit par gabarit. */
.page-rythme { padding-block: var(--ra-rythme-page); }
.page-rythme--bas { padding-bottom: var(--ra-rythme-page); }
/* Variante haute. Sur les pages domaine, la section qui suit le héros commence
   directement par les cartes : la citation de l'encart, calée en bas de sa boîte
   (padding-bottom: 0, voulu), venait donc TOUCHER leur cadre — 0px mesuré à
   toutes les largeurs. L'accueil et Contact ne montraient pas le défaut parce
   qu'un séparateur (margin 6rem) ouvre leur section suivante et fournit l'air
   par accident. Ici on le fournit explicitement, à la même valeur. */
.page-rythme--haut { padding-top: var(--ra-rythme-page); }
@media (min-width: 640px)  { .megabloc { padding-inline: 2rem; } .megabloc--full { padding-inline: 2rem; } }
@media (min-width: 1024px) { .megabloc { padding-inline: 3rem; } .megabloc--full { padding-inline: 3rem; } }

/* ==========================================================================
   En-tête : wordmark + bandeau téléphone/contact (« drap » noir + triangle)
   ========================================================================== */
/* Collant : les trois boutons drap SONT les points de contact du site, et ils
   quittaient l'écran au bout de 96px sur un article qui en fait 13 683 — le
   lecteur n'avait donc aucun moyen de joindre le cabinet pendant 99,3 % de sa
   lecture. Le fond opaque est indispensable : la barre n'en avait pas, le texte
   défilerait au travers du wordmark. `top: 0` conserve le dessin des boutons,
   dont le coin plié est calé sur le bord haut de la page. */
/* Le `padding-bottom` n'est pas décoratif : le wordmark finissait pile au bord
   bas de la barre (96px de haut, wordmark terminé à 96px), donc le contenu qui
   défile dessous venait le toucher. Il lui faut son propre dégagement, que la
   marge de la page ne peut pas fournir puisqu'elle défile, elle. */
.site-header { position: sticky; top: 0; z-index: 50; background-color: var(--ra-clair); padding-bottom: 1.5rem; }
/* FRONTIÈRE DE L'EN-TÊTE — elle n'existait pas : fond blanc sur page blanche,
   le contenu passait sous la barre sans séparation. Défaut d'orientation, pas
   manque d'ornement. Le filet n'apparaît QUE page défilée : en haut il n'y a
   rien à séparer.
   ⚠️ En `::after` et non en `border-bottom` : une bordure, même transparente,
   s'ajoute à la hauteur de la barre, dont dépend `--ra-entete-h` (décalage des
   ancres). Le pseudo-élément ne change aucune mesure.
   ⚠️ Piloté par le DÉFILEMENT : aucun script, aucun écouteur, et là où
   `animation-timeline` manque le filet reste simplement invisible.
   ⚠️ Volontairement NON neutralisé par `prefers-reduced-motion` : ce trait dit
   dans quel état est la page, il n'est pas décoratif. */
.site-header::after {
	content: "";
	position: absolute; inset-inline: 0; bottom: 0; height: 1px;
	background-color: var(--ra-vertparis);
	opacity: 0;
}
@supports (animation-timeline: scroll()) {
	/* ⚠️⚠️ L'ORDRE DES DÉCLARATIONS EST CRITIQUE : la forme raccourcie
	   `animation` RÉINITIALISE `animation-timeline` et `animation-range`. En les
	   posant avant elle — ce que j'avais fait en factorisant les deux
	   sélecteurs — l'animation retombait sur la timeline du document, donc à son
	   état final dès le chargement : le filet et l'ombre étaient visibles en
	   haut de page. Mesuré, pas deviné. La forme raccourcie d'abord, la
	   timeline ensuite, et jamais l'inverse. */
	/* Le filet se pose sur les 96 premiers pixels de défilement, soit à peu près
	   la hauteur de la barre : il est franc dès que le contenu passe dessous. */
	.site-header::after {
		animation: ra-entete-frontiere linear both;
		animation-timeline: scroll(root block);
		animation-range: 0 6rem;
	}
	/* ⚠️ UNE OMBRE EN PLUS DU FILET, ajoutée après coup. Le filet seul —
	   1px de vert-de-gris, 3,52 de contraste — était conforme au vocabulaire du
	   site et **imperceptible en usage** : l'utilisateur ne l'a pas vu.
	   L'ombre, elle, ne se lit pas comme un trait de plus mais comme un PLAN :
	   elle dit que la barre est au-dessus, ce qu'un filet ne dit pas. C'est
	   d'ailleurs la seule ombre du site — sa rareté fait qu'elle ne concurrence
	   aucun autre signal.
	   Très étalée et très transparente (18 %) pour rester une profondeur, pas un
	   contour. */
	.site-header {
		animation: ra-entete-ombre linear both;
		animation-timeline: scroll(root block);
		animation-range: 0 6rem;
	}
}
@keyframes ra-entete-frontiere { to { opacity: 1; } }
@keyframes ra-entete-ombre { to { box-shadow: 0 10px 24px -14px rgba(2, 6, 23, 0.55); } }
.site-header__inner {
	display: flex;
	align-items: flex-start;
	gap: 1rem;
}
/* Les boutons collent en haut de page (comme l'original) ; le wordmark garde
   sa marge haute et s'aligne donc plus bas que le bandeau. */
.wordmark { display: inline-block; padding-top: 2rem; }
@media (min-width: 768px)  { .wordmark { padding-top: 3rem; } }
@media (min-width: 1280px) { .wordmark { padding-top: 4rem; } }
.wordmark svg { height: 1.25rem; width: auto; fill: var(--ra-primaire); }
@media (min-width: 1280px) { .wordmark svg { height: 2rem; } }

/* Boutons « drap » : rectangle noir avec coin plié vert-de-gris en bas à droite,
   qui devient noir au survol (le pli disparaît → rectangle entièrement noir). */
/* Écart : à 0.5rem les trois boutons se lisaient comme un pavé compact. */
.drap-group { margin-left: auto; display: inline-flex; gap: 1rem; }
.drap-btn {
	display: inline-flex; flex-direction: column;
	color: var(--ra-clair); text-decoration: none;
}
.drap-btn__body {
	display: flex; align-items: flex-end; justify-content: center;
	background-color: var(--ra-sombre);
	font-family: var(--ra-font-heading); font-size: 1.25rem; font-weight: 700;
	/* Texte poussé vers le bas (comme l'ancien bandeau flush-top), mais sans
	   l'excès de vide : le padding haut était de 64px au-dessus d'un label de
	   24px, soit 122px de hauteur pour ~30px d'information. Ramené à 32px. */
	padding: 1.5rem 1.9rem 0.5rem;
	transition: background-color var(--ra-transition), color var(--ra-transition),
	            padding-top var(--ra-transition), padding-bottom var(--ra-transition);
}
@media (min-width: 768px)  { .drap-btn__body { padding-top: 1.75rem; } }
@media (min-width: 1280px) { .drap-btn__body { padding-top: 2rem; } }
/* Le numéro complet sur grand écran ; « Appeler » sous 768px, où la place manque.
   Toujours du texte : le bouton n'est jamais réduit à un pictogramme muet. */
.drap-btn__tel-court { display: none; }
/* Coin plié, repris À L'IDENTIQUE de l'ancien site : barre sombre en retrait à
   droite (.decodrap), et dans l'encoche carrée laissée libre à sa droite deux
   demi-triangles — ::after (vert-de-gris, visible : c'est le pli) et ::before
   (transparent au repos, donc invisible).

   SURVOL, deux gestes simultanés :
   1. les DEUX triangles passent à l'encre → l'encoche se remplit, le coin corné
      s'efface et le bouton devient un rectangle plein ;
   2. le libellé se lève de 12px. Ces 12px sont RETIRÉS EN HAUT ET REMIS EN BAS,
      si bien que le rembourrage total ne varie pas : la hauteur du bouton est
      constante par construction et la page ne saute pas au survol. */
.decodrap {
	position: relative; height: 1rem; width: calc(100% - 1rem);
	background-color: var(--ra-sombre);
	transition: background-color var(--ra-transition);
}
.decodrap::before {
	content: ""; position: absolute; bottom: 0; right: -1rem; width: 0; height: 0;
	border-bottom: 1rem solid transparent; border-left: 1rem solid transparent;
	transition: border-bottom-color var(--ra-transition);
}
.decodrap::after {
	content: ""; position: absolute; bottom: 0; right: -1rem; width: 0; height: 0;
	border-top: 1rem solid var(--ra-vertparis); border-right: 1rem solid transparent;
	transition: border-top-color var(--ra-transition);
}
.drap-btn:hover .decodrap::before { border-bottom-color: var(--ra-sombre); }
.drap-btn:hover .decodrap::after { border-top-color: var(--ra-sombre); }
/* Levée du libellé : 6px, retirés en haut et remis en bas (rembourrage total
   constant → hauteur constante). Réservée aux largeurs à souris : sous 768px le
   survol n'existe pas, et l'appliquer y ferait varier la hauteur pour rien. */
@media (min-width: 768px)  { .drap-btn:hover .drap-btn__body { padding-top: 1.375rem; padding-bottom: 0.875rem; } }
@media (min-width: 1280px) { .drap-btn:hover .drap-btn__body { padding-top: 1.625rem; } }
/* Drap « Blog » : couleur vert-de-gris (distincte) car ce n'est pas un drap de contact.
   Au repos = vert-de-gris + texte encre ; au survol = bascule en encre + texte clair. */
.drap-btn--blog .drap-btn__body { background-color: var(--ra-vertparis); color: var(--ra-primaire); }
.drap-btn--blog .decodrap { background-color: var(--ra-vertparis); }
.drap-btn--blog .decodrap::after { border-top-color: var(--ra-primaire); }
.drap-btn--blog:hover .drap-btn__body { background-color: var(--ra-sombre); color: var(--ra-clair); }
.drap-btn--blog:hover .decodrap { background-color: var(--ra-sombre); }
/* Mobile : les 3 boutons deviennent COMPACTS (hauteur réduite + tél en icône
   seule) pour tenir sans déborder ; flex-wrap en filet de sécurité. */
@media (max-width: 767px) {
	/* Mobile : écart laissé serré — l'en-tête tient tout juste à 390px, chaque
	   pixel compte. L'aération de 1rem ne vaut que pour le desktop. */
	.drap-group { gap: 0.35rem; flex-wrap: wrap; justify-content: flex-end; }
	/* Serré : « Appeler » est plus large que l'icône qu'il remplace, et les trois
	   boutons plus le wordmark doivent tenir dans 390px. */
	.drap-btn__body { font-size: 0.875rem; padding: 0.9rem 0.55rem 0.45rem; }
	.drap-btn__tel { display: none; }
	.drap-btn__tel-court { display: inline; }
	.wordmark svg { height: 1rem; }
	.wordmark { padding-top: 1.1rem; }
}

/* En-tête de page d'accueil : titre à gauche, menu domaines à droite */
.hero-head { padding-block: 4rem; }
/* ⚠️ SOUS 768px LE MENU COLLE AU TITRE — écart mesuré à 0px sur les 5 pages qui
   portent `.hero-head` (accueil, contact, les 3 domaines), à 320, 360, 390 et
   430px. Le menu se lisait comme la suite du H1 plutôt que comme une navigation.
   La cause : au-dessus de 768px c'est le `gap: 2rem` de la bascule en flex qui
   sépare les deux ; en dessous, `display: block` et aucune marge ne prend le
   relais. Le défaut était donc structurel, pas un oubli de valeur. */
@media (max-width: 767.98px) {
	.hero-head h1 + .cat-menu-nav,
	.hero-head h1 + .cat-menu { margin-top: 1.5rem; }
}
@media (min-width: 768px) {
	.hero-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 2rem; }
	/* Le menu ne cède plus devant le titre. Sans ça c'est LUI qui se comprimait
	   quand le H1 s'allongeait (412 → 379px selon la page), et « Droit du
	   dommage corporel » passait à la ligne. Le titre, lui, se replie très bien. */
	/* ⚠️ La règle porte sur le `<nav>` depuis le 2026-08-10 : c'est lui l'enfant
	   flex de `.hero-head`, le `<ul>` est passé d'un cran en profondeur quand le
	   repère de navigation a été ajouté. */
	.hero-head .cat-menu-nav { flex: none; }
	/* Un élément flex refuse par défaut de descendre sous la largeur de son mot
	   le plus long (`min-width: auto`) : il déborde au lieu de se replier. Le
	   plancher mesuré est de 653px sur la page au titre le plus contraint
	   (« Indemnisation », 281px à lui seul) — donc sans risque aujourd'hui, mais
	   la marge dépend d'un contenu que la cliente peut modifier. Avec 0, le pire
	   cas devient une césure au lieu d'une page cassée. */
	.hero-head h1 { min-width: 0; }
}
@media (min-width: 1280px) { .hero-head { padding-block: 8rem; } }

/* ==========================================================================
   Menu de catégories (nav services, soulignée, MAJUSCULES)
   ========================================================================== */
.cat-menu {
	list-style: none; margin: 0; padding: 0;
	font-size: var(--ra-fs-catmenu); line-height: 1.7;
	text-transform: uppercase;
	/* COULEUR DU TRAIT AU REPOS — le seul réglage qui distingue les deux
	   emplacements du composant. Transparent par défaut (héros) ; le pied de
	   page le rallume plus bas.
	   ⚠️ POURQUOI UNE VARIABLE ET PAS UNE RÈGLE SCOPÉE : `.site-footer
	   .cat-menu a` pèserait (0,2,1), exactement comme
	   `.cat-menu a[aria-current="page"]`. Seul l'ordre d'écriture les
	   départagerait, et la page courante du pied de page repasserait en
	   vert-de-gris à la première réorganisation du fichier. La variable
	   descend par héritage sans jamais entrer dans ce calcul : les états
	   survol et page courante gardent la main sur la propriété. */
	--ra-menu-trait: transparent;
}
@media (min-width: 768px)  { .cat-menu { text-align: right; } }
.cat-menu a, .alink {
	font-weight: 700;
	text-decoration: underline;
	text-decoration-color: var(--ra-vertparis);
	/* 2px : à 4px le trait écrasait le texte, dans le footer comme ailleurs.
	   Aligne `.alink` sur le menu des domaines, qui était déjà passé à 2px. */
	text-decoration-thickness: 2px;
	text-underline-offset: 4px;
	transition: text-decoration-color var(--ra-transition), color var(--ra-transition);
}
/* TROIS ÉTATS, TROIS DESSINS — repos : aucun trait · survol : 2px vert foncé ·
   page courante : 4px vert foncé.
   ⚠️ Défaut corrigé : le survol posait un trait de 4px encre, soit exactement
   le marqueur de page courante — deux « vous êtes ici » simultanés, mesurés.
   Le trait cesse donc de dire « lien » pour ne dire que « visé » ou « ici ».
   Il reste déclaré au repos mais TRANSPARENT plutôt que retiré : le survol se
   fond au lieu de surgir, et la transition de couleur retrouve un objet.
   ⚠️ Ce régime ne vaut que dans le HÉROS. Le pied de page garde son trait au
   repos (`--ra-menu-trait`) : le menu y côtoie les coordonnées, qui sont
   soulignées, et la colonne nue s'y lisait comme des étiquettes. Le cas se
   présente dans 4 contextes sur 8, partout où aucune entrée n'est courante. */
.cat-menu a {
	text-underline-offset: 3px;
	text-decoration-color: var(--ra-menu-trait);
	transition: text-decoration-color var(--ra-transition), color var(--ra-transition),
	            text-decoration-thickness var(--ra-transition);
}
/* ── ZONES TACTILES DES LIENS EN LIGNE ────────────────────────────────────────
   Mesuré à 390px : `.alink` 21px de haut, `.cat-menu a` 22 à 24px. Sous le
   seuil confortable de 44px (WCAG 2.5.5), même si l'espacement leur fait passer
   le minimum de 2.5.8.
   💡 Un `padding-block` sur un élément EN LIGNE n'entre pas dans le calcul de la
   hauteur de ligne : il agrandit la surface touchable SANS déplacer quoi que ce
   soit. (`inline-block` ne marche pas ici — sa hauteur remplacerait la
   contribution de la ligne et ferait grandir le bloc.)
   ⚠️⚠️ LA VALEUR EST BORNÉE PAR LE PAS ENTRE DEUX LIENS, jamais par la cible de
   44px : deux zones qui se chevauchent envoient le doigt sur le mauvais lien,
   ce qui est PIRE qu'une cible petite. D'où trois valeurs et non une seule —
   pas mesurés : liens du pied 95 à 198px (libre), menu du pied 40px,
   menu du héros 30px.
   Conséquence assumée : le menu du héros plafonne à 30px. L'amener à 44
   demanderait d'écarter ses entrées, donc de déplacer la mise en page. */
.alink { padding-block: 0.7rem; }                    /* 21 → 43px, écarts de 95 à 198px */
/* ⚠️⚠️ LE MENU DU HÉROS NE SE RÈGLE PAS AU `padding` — deux essais l'ont montré.
   Sa boîte de ligne (1,7em) dépasse à peine la boîte de contenu de la police
   (~1,45em en eskapade) : il ne reste que 2 à 3px de jeu de chaque côté. À
   `0.25rem` puis à `0.18em`, les zones se chevauchaient encore de 0,8 à 3,6px
   selon la largeur — et deux zones qui se chevauchent envoient le doigt sur le
   MAUVAIS lien, ce qui est pire que la cible étroite qu'on voulait corriger.
   💡 C'est la LARGEUR qui était le vrai gisement, pas la hauteur. Le `<li>`
   occupe déjà toute la colonne ; seul le `<a>`, en ligne, se limitait à son
   texte. En bloc, il prend toute la largeur du `<li>` et exactement sa boîte de
   ligne en hauteur — donc rien ne bouge.
   Surface mesurée à 390px : 98×22 = 2 156px² → 342×30 = 10 260px², soit ×4,8.
   ⚠️⚠️ CETTE RÈGLE N'EST NEUTRE QUE SANS `padding-block`. Sur un élément en
   ligne le rembourrage ne compte pas dans la hauteur ; sur un bloc, si. Les
   deux `padding-block` qui existaient sur ce sélecteur ont donc été retirés
   (voir plus bas) : avec eux, le menu du héros gagnait 30px et celui du pied 80.
   ⚠️ `display: block` et non `inline-block` : ce dernier remplace la
   contribution de la ligne par sa propre hauteur et ferait grandir le bloc. */
.cat-menu a { display: block; }

/* ⚠️ `:not([aria-current="page"])` n'est PAS une précaution de style : sans lui,
   survoler la page courante ferait maigrir son trait de 4 à 2px — le repère
   s'affaiblirait au moment précis où le curseur le désigne. Exclure l'entrée
   plutôt que de compter sur l'ordre des règles : les deux sélecteurs pèseraient
   (0,2,1) et le dernier écrit l'emporterait, ce qu'une réorganisation future
   casserait en silence. */
.cat-menu a:hover:not([aria-current="page"]) { text-decoration-color: var(--ra-vertparis-fonce); }
/* ⚠️ ANCIENNE VERSION DE CETTE CIBLE — `.service .cat-menu a { padding-block:
   0.3125rem }` — RETIRÉE le 2026-08-10. Elle avait été calibrée en desktop
   (34 → 44px pour un interligne de 44,2) et n'y posait aucun problème ; en
   mobile l'interligne tombe à 29,75px pour 22px de contenu, si bien que les
   5px de rembourrage produisaient des zones de 32px dans un pas de 30 :
   **les trois entrées se chevauchaient de 2px**, et un doigt posé dans le
   recouvrement partait sur le lien suivant. Défaut mesuré à 320, 360, 390 et
   430px. Une valeur fixe ne peut pas suivre un interligne qui est un `clamp`. */
/* Page en cours de lecture : trait vert foncé permanent. L'attribut est posé par
   template-parts/menu-domaines.php dans le héros, et par WordPress lui-même sur
   le menu du footer — une seule règle habille donc les deux. */
.cat-menu a[aria-current="page"] {
	text-decoration-thickness: 4px;
	text-decoration-color: var(--ra-vertparis-fonce);
}
/* `.cat-menu a:hover` a quitté cette règle : il y posait la même couleur que
   celle qu'on vient de lui donner plus haut, mais SANS l'exclusion de la page
   courante, et il l'emportait par l'ordre d'écriture — l'exclusion aurait été
   annulée sans que rien ne se voie. Ne restent ici que les liens de texte. */
.alink:hover { text-decoration-color: var(--ra-vertparis-fonce); }
.alink.is-plain { text-decoration: none; cursor: default; font-weight: 400; }

/* ==========================================================================
   Liste de services (filets vert-de-gris + survol décalé/teinté)
   ========================================================================== */
.services { list-style: none; margin: 0; padding: 0; }
.services li {
	padding: 0.75rem 0;
	border-top: 1px solid var(--ra-vertparis);
	font-size: var(--ra-fs-services); line-height: 1.3;
	transition: background-color var(--ra-transition), padding var(--ra-transition);
}
.services li:first-child { border-top: 0; }
.services li:hover { background-color: var(--ra-vertparis-10); padding-left: 0.375rem; }

/* Liste des distinctions (honneurs) */
.honneurs { list-style: none; margin: 0; padding: 0; width: 100%; }
.honneurs li {
	display: grid; grid-template-columns: auto 1fr; gap: 1.5rem;
	align-items: start;
	padding: 1.25rem 0;
	border-top: 1px solid var(--ra-sombre);
	font-size: var(--ra-fs-honneurs); line-height: 1.1;
}
.honneurs li:first-child { border-top: 0; padding-top: 0; }
.honneurs li:last-child { padding-bottom: 0; }
.honneurs .macaron { flex: none; }
.honneurs .macaron svg { height: 2.5rem; width: 2.5rem; max-width: none; fill: var(--ra-sombre); }
/* Le texte ACF est enveloppé dans un <p> : sans ça, la règle globale
   p{font-size:var(--ra-fs-body)} l'affichait en taille du CORPS (~30px). */
.honneurs p { font-size: inherit; line-height: inherit; margin: 0; }
/* le texte occupe toute la largeur restante (sinon il retombe à la ligne trop tôt) */
.honneurs li > span + span { flex: 1; min-width: 0; }

/* ==========================================================================
   Séparateur pointillé centré avec balance ⚖️
   ========================================================================== */
.separateur { position: relative; margin: 3rem 0; }
@media (min-width: 1024px) { .separateur { margin: 6rem 0; } }
.separateur::before {
	content: ""; position: absolute; inset: 0;
	display: block; top: 50%;
	border-top: 1px dotted var(--ra-secondaire);
}
.separateur--vertparis::before { border-top-color: var(--ra-vertparis); }
.separateur__icon {
	position: relative; display: flex; justify-content: center;
}
.separateur__icon span { background-color: var(--ra-clair); padding: 0 0.5rem; }
.separateur__icon svg { height: 1.5rem; width: 1.5rem; fill: var(--ra-primaire); }

/* ==========================================================================
   Blocs image + encart blanc superposé (hero, portrait)
   ========================================================================== */
.figure-encart { position: relative; padding-bottom: 3.5rem; }
/* ⚠️ SÉLECTEUR DESCENDANT ET NON ENFANT : Imagify enveloppe chaque image dans un
   `<picture>` pour servir du WebP. `.figure-encart > img` ne correspondait donc
   à RIEN sur les pages où l'image passe par `wp_get_attachment_image()` — règle
   morte, sans effet visible tant qu'aucune hauteur n'était contrainte, mais
   morte. Le `<picture>` est passé en bloc : inline, il ajoute une ligne de base
   et donc quelques pixels sous l'image. */
.figure-encart picture { display: block; }
.figure-encart img { width: 100%; object-fit: cover; }
/* ⚠️ Le rembourrage GAUCHE n'est pas décoratif : `.emphase` porte un
   `text-indent` négatif (le guillemet ouvrant « pend hors du texte, pour que la
   colonne s'aligne optiquement). Il faut donc de quoi le laisser pendre.
   Au-dessus de 640px, `.megabloc--full` décale la figure de 32 puis 48px et
   absorbe le débord ; en dessous il passe à `padding-inline: 0`, la boîte
   commençait à x=0 et le « sortait de l'écran — mesuré à −12px sur les trois
   pages, à 390, 480 et 600px de large. La citation était par ailleurs le seul
   bloc de la page sans gouttière, son texte collé au bord. */
.figure-encart__box {
	position: absolute; left: 0; bottom: 0;
	width: 80%;
	background-color: var(--ra-clair);
	padding: 1.5rem 1.5rem 0 1.5rem;
	display: flex; flex-direction: column; align-items: stretch;
}
@media (min-width: 640px)  { .figure-encart__box { width: 75%; padding-left: 0; } }
/* Largeur de l'encart calée sur l'ancien site : lg 32rem, xl 48rem (max-w-3xl) */
@media (min-width: 1024px) { .figure-encart__box { max-width: 32rem; padding: 1.5rem 1.5rem 0 0; } }
@media (min-width: 1280px) { .figure-encart__box { max-width: 48rem; } }

/* HAUTEUR DE L'IMAGE DU HÉROS — recadrée à 3:1 au-dessus de 1024px.
   Mesuré à 1440×900 : la figure occupait **728px, soit 81 % de la hauteur
   d'écran**, et le corps du texte ne commençait qu'après 2,4 écrans. À 3:1 elle
   tombe à 504px (56 %) et les deux cartes de synthèse remontent de 224px.
   ⚠️ `object-fit: cover` : l'image est RECADRÉE, jamais déformée. Le fichier
   d'origine est en 2:1, le recadrage est donc modéré et centré.
   ⚠️ SEULEMENT AU-DESSUS DE 1024px. Sous cette largeur la figure ne fait déjà
   que 30 % de l'écran (251px sur 844 à 390px de large) : la contraindre y
   rognerait une image déjà courte, sans rien gagner.
   ⚠️ SCOPÉ `.service` — l'accueil et Contact partagent le même composant, et
   leur image n'a pas le même format : celle de l'accueil est un 1343×895 (3:2),
   un recadrage en 3:1 lui retirerait la moitié de sa hauteur. Périmètre
   demandé : les trois pages domaine.
   Mesures des paliers essayés (hauteur / part d'écran / position des cartes) :
   actuel 728 / 81 % / 1333 · 21:9 632 / 70 % / 1237 · **3:1 504 / 56 % / 1109**
   · 40vh 416 / 46 % / 1021. Le `vh` a été écarté : une hauteur d'écran fait
   varier le recadrage d'un poste à l'autre, un rapport d'image non. */
@media (min-width: 1024px) {
	.service .figure-encart--hero img { aspect-ratio: 3 / 1; height: auto; }
}

/* ==========================================================================
   Grilles utilitaires locales (2 colonnes éditoriales)
   ========================================================================== */
.grid-2 { display: grid; grid-template-columns: 1fr; gap: 4rem; }
@media (min-width: 1024px) { .grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.pl-lg { padding-left: 0; }
@media (min-width: 1024px) { .pl-lg { padding-left: 3rem; } }

/* ==========================================================================
   Blocs domaine de l'accueil
   Le titre EST la porte d'entrée vers la page du domaine : sans habillage il
   se lisait comme un simple titre de section, et les trois pages principales
   n'étaient atteignables que par le petit menu du haut. Colonne de titre
   resserrée pour ne pas laisser un vide à côté des listes courtes.
   ========================================================================== */
@media (min-width: 1024px) {
	/* Même structure que .bio-grid — colonnes égales, gouttière de 80px — pour
	   que les listes démarrent exactement là où démarre le paragraphe de
	   présentation. L'alignement tient à la construction, pas à une valeur
	   ajustée à la main : il reste vrai quelle que soit la largeur du conteneur. */
	.domaine { column-gap: 5rem; align-items: start; }
}
/* Trait à 4px : ces titres font 48px, un filet de 2px y pesait optiquement
   moitié moins que sous le menu du héros à 26px. Survol = passage au vert foncé. */
.domaine h2 a {
	text-decoration: underline;
	text-decoration-color: var(--ra-vertparis);
	text-decoration-thickness: 4px;
	text-underline-offset: 6px;
	transition: text-decoration-color var(--ra-transition);
}
.domaine h2 a:hover { text-decoration-color: var(--ra-vertparis-fonce); }

/* ==========================================================================
   Pages service (domaines)
   ========================================================================== */
.hero-kicker { display: block; font-weight: 400; font-size: 0.55em; margin-bottom: 0.35em; }

/* ==========================================================================
   Contextes de lecture
   Redéclarer les deux variables suffit : paragraphes, listes et titres
   imbriqués suivent par héritage, y compris sur du contenu WYSIWYG ajouté plus
   tard. L'accueil, lui, garde la voix éditoriale à 30px.

   Deux régimes, selon la longueur de ce qu'on lit d'affilée :
   — COURANTE (22px / 1.7) : blocs courts, dans une colonne déjà étroite.
   — ÉLARGIE (26px / 1.6) : contenus longs, avec colonne resserrée à 46rem.
     Mesuré à 74-75 caractères par ligne, contre 113 auparavant.
   ========================================================================== */
.cartes .carte,
.contact-intro,
.contact-form-wrap,
.cta-contact {
	--ra-fs-courant: var(--ra-fs-lecture);
	--ra-lh-courant: 1.7;
	font-size: var(--ra-fs-courant);
	line-height: var(--ra-lh-courant);
}

.service-corps,
.faq-item,
.article-body {
	--ra-fs-courant: var(--ra-fs-lecture-large);
	--ra-lh-courant: 1.6;
	/* Titres remontés AVEC le corps : à 26px de texte, un h3 laissé à 26px
	   repasserait au niveau de ce qu'il annonce et la hiérarchie s'aplatirait. */
	--ra-fs-rich-h2: clamp(2rem, 1.70rem + 1.30vw, 2.625rem);      /* 32 → 42px */
	--ra-fs-rich-h3: clamp(1.625rem, 1.50rem + 0.55vw, 2rem);      /* 26 → 32px */
	font-size: var(--ra-fs-courant);
	line-height: var(--ra-lh-courant);
	max-width: var(--ra-mesure-lecture);
}

/* Contenu riche (WYSIWYG ACF) : rythme vertical & listes */
.rich { text-align: justify; hyphens: auto; }   /* parti pris cliente : contenu justifié.
                                                   La césure (lang="fr-FR") évite les lézardes. */

/* ── CÉSURE BRIDÉE SOUS 1024px ────────────────────────────────────────────────
   Mesuré à 390px, lignes pleines seules : 31,4 % des lignes d'un article
   finissaient sur un mot coupé, 26,9 % dans le bloc « En résumé » (une ligne
   sur trois, jusqu'à 3 sur 5 dans un paragraphe). Cause : `hyphens: auto` sans
   borne coupe des mots courts (« si-tuation », « convo-cation », « rapi-dement »).
   `hyphenate-limit-chars: 10 5 5` = ne couper qu'un mot d'au moins 10 lettres,
   avec 5 lettres de part et d'autre.

   ⚠️ LA JUSTIFICATION N'EST PAS TOUCHÉE — c'est un parti pris de la cliente.
   Mesuré au passage : `text-align: left` ne changeait RIEN au taux de césure
   (31,4 % dans les deux cas). Le fer à gauche n'était donc pas le remède, et la
   justification n'était pas la cause.

   Réglages comparés à 390px (césure · espace médiane · p90 · max) :
     actuel      31,4 % · 6,41 · 9,77 · 14,95
     8 4 4       13,9 % · 6,91 · 11,98 · 21,31
   **10 5 5       7,2 % · 7,03 · 12,47 · 24,44  (retenu)**
     hyphens:none 0 %   · 8,31 · 16,75 · 36,67 → lézardes visibles
   Le nombre de lignes ne bouge pas (137 avant, 138 après) : le gain est gratuit
   en hauteur de page.
   ⚠️ Borné au mobile : au-delà de 1024px la colonne est assez large pour que la
   césure serve vraiment à égaliser les blancs. */
@media (max-width: 1023.98px) {
	.rich,
	.article-body,
	.blog-card__excerpt {
		hyphenate-limit-chars: 10 5 5;
	}
}
.rich > * + * { margin-top: 1.25rem; }          /* gap > interligne, sinon les § se collent */
.rich h2, .rich h3, .rich h4 { margin-top: 2.5rem; margin-bottom: 0.75rem; text-align: left; } /* titres non justifiés */

/* Séparation des paragraphes dans les contenus LONGS (articles, pages domaine).
   ⚠️ Le `1.25rem` ci-dessus est une valeur FIXE écrite quand le corps était à
   22px, et elle n'a pas suivi le passage à 26px/1.6 : mesuré dans un article,
   l'écart entre deux paragraphes (20px) était devenu DEUX FOIS PLUS PETIT que
   l'écart entre deux lignes d'un même paragraphe (41,6px). Le texte se lisait
   comme un pavé continu — le commentaire « gap > interligne » ne décrivait plus
   ce que faisait le code.
   En `em`, donc proportionnel au contexte, comme `.rich li + li` : l'air suit la
   taille du texte sans qu'aucune règle ait à être refaite si l'échelle bouge. */
/* ⚠️ `.service-corps .rich >` et non `.service-corps >` : sur une page domaine le
   `.rich` est un ENFANT de `.service-corps`, alors qu'un article porte les deux
   classes sur le même élément. Le sélecteur en enfant direct de `.service-corps`
   ne touchait que le `.rich` lui-même, et les paragraphes restaient à 20px. */
/* ⚠️ La liste des contextes doit suivre celle des « Contextes de lecture » plus
   haut : la FAQ et les cartes en étaient absentes et restaient donc sur le
   `1.25rem` générique, soit 20px FIXES. Mesuré : dans une réponse de FAQ (26px,
   interligne 41,6) l'écart entre deux paragraphes valait 0,48 fois l'écart
   entre deux lignes du MÊME paragraphe ; dans une carte (22px, interligne 37,4)
   0,53. C'est exactement le défaut corrigé ici pour le corps et les articles,
   jamais propagé. Et 20px était la même valeur absolue dans deux corps de
   tailles différentes, au milieu d'un système entièrement relatif. */
/* ⚠️ Les trois conteneurs de `rosa_structurer_corps()` sont listés en plus de
   `.rich` : depuis que le corps est regroupé en blocs, les paragraphes ne sont
   plus enfants directs de `.rich` et ce rythme ne les atteignait plus. */
.service-corps .rich > * + *,
.corps-bloc > * + *,
.corps-bloc__chapo > * + *,
.corps-cas__corps > * + *,
.faq-item .rich > * + *,
.carte .rich > * + *,
.cta-contact__texte > * + *,
.article-body > * + * { margin-top: 1.4em; }

/* Un titre appartient à ce qui le SUIT. Sans cette règle, la marge du paragraphe
   suivant (1,4em) fusionne avec celle du titre et l'emporte : le titre se
   retrouvait à égale distance de la section qu'il ferme et de celle qu'il ouvre,
   donc rattaché à rien. Même intention que la liaison amorce/liste des pages
   domaine, appliquée ici à la paire titre/texte. */
.service-corps .rich :is(h2, h3, h4) + *,
.faq-item .rich :is(h2, h3, h4) + *,
.carte .rich :is(h2, h3, h4) + *,
.article-body :is(h2, h3, h4) + * { margin-top: 0.6em; }
/* Sauf quand c'est un titre qui suit un titre : à 0,6em, les jambages du h2
   venaient frôler le h3 qui ouvre sa première section. Ils restent un bloc de
   titraille, mais respirent. */
.service-corps .rich :is(h2, h3) + :is(h3, h4),
.faq-item .rich :is(h2, h3) + :is(h3, h4),
.carte .rich :is(h2, h3) + :is(h3, h4),
.article-body :is(h2, h3) + :is(h3, h4) { margin-top: 1.1em; }
/* Titres DANS le corps de texte, calés sur la voix de LECTURE (22px) :
   h2 34 > h3 26 > h4 22 gras > corps 22. Chaque palier doit rester au-dessus
   du corps, sinon la page cesse d'être parcourable (cf. --ra-fs-lecture). */
.rich h2 { font-size: var(--ra-fs-rich-h2); }
.rich h3 { font-size: var(--ra-fs-rich-h3); }
.rich h4 { font-size: var(--ra-fs-courant); }                        /* = corps, en gras */
/* Listes du corps de texte : puce carrée or & numéros or serif (charte angulaire). */
.rich ul,
.rich ol { list-style: none; margin: 1.25rem 0; padding-left: 0.5rem; }
/* Les items sont trop courts pour être justifiés : le justifié y creuse des
   trous entre les mots. Le texte courant, lui, reste justifié (parti pris cliente). */
.rich li { position: relative; text-align: left; }
/* En em : l'air entre items suit la taille du contexte, sans règle dédiée. */
.rich li + li { margin-top: 0.45em; }
.rich li > ul,
.rich li > ol { margin: 0.5rem 0 0; }

.rich ul > li { padding-left: 1.5em; }
.rich ul > li::before {
	content: "";
	position: absolute; left: 0; top: 0.62em;
	width: 0.45em; height: 0.45em;
	background: var(--ra-vertparis);
}

.rich ol { counter-reset: ra-item; }
.rich ol > li { padding-left: 2em; counter-increment: ra-item; }
.rich ol > li::before {
	content: counter(ra-item) ".";
	position: absolute; left: 0; top: 0;
	width: 1.4em; text-align: right;
	font-family: var(--ra-font-heading); font-weight: 700;
	color: var(--ra-vertparis);
}
.rich a { color: var(--ra-primaire); text-decoration: underline; text-decoration-color: var(--ra-vertparis); text-decoration-thickness: 2px; text-underline-offset: 3px; }
.rich a:hover { text-decoration-color: var(--ra-vertparis-fonce); }

/* Cartes « En résumé » / « Ce que je fais » — le diptyque de synthèse.
   ⚠️ Corps à 22px quand la page est à 26, et c'est VOULU : dans une colonne de
   633px, 22px donnent 67 caractères par ligne, en plein dans la fourchette ;
   24px → 61 pour 21 % de hauteur en plus ; 26px → 56, SOUS la fourchette, pour
   30 % en plus. **Ne pas « harmoniser » cette taille.**
   Le fond, et non la taille, est ce qui sépare les deux registres : un filet
   fin sur blanc laisse la même matière que la page, et l'œil compare alors des
   tailles au lieu de lire deux fonctions. Teinte du bandeau d'appel à l'action
   en plus léger — même famille, intensité graduée. */
.cartes .carte { background-color: var(--ra-vertparis-20); padding: 2.5rem 2.25rem; }

/* ⚠️⚠️ PLANCHER RELEVÉ SUR TÉLÉPHONE — la carte gardait la voix « courante »
   (`--ra-fs-lecture`, 18 → 22px) alors que le corps voisin est en « élargie »
   (20 → 26px). L'écart est voulu et documenté plus haut : « ne pas harmoniser ».
   Mais les deux clamps ont des PLANCHERS différents, et sur téléphone ils y sont
   tous les deux : il ne restait que 2px (18 contre 20) pour porter une
   distinction qui en vaut 4 en desktop — pendant que la carte payait 36px de
   marge interne de chaque côté sur 342px de large.
   Mesuré avant : colonne de 270px, 39 caractères par ligne, 26,9 % de césure.
   C'était le plus petit texte du site dans la plus étroite de ses colonnes.
   Après : 294px et 20px.

   💡 UN `max()` PLUTÔT QU'UNE MEDIA QUERY, et c'est le point important. Mon
   premier essai bornait la règle à 768px : le texte de la carte passait alors de
   23,3px à 19,7px EN AGRANDISSANT la fenêtre — il rapetissait au franchissement.
   Un `max()` n'a pas de frontière : le plancher tient jusqu'à ce que le clamp
   d'origine le dépasse de lui-même (vers 836px), puis la voix « courante »
   reprend seule. La hiérarchie des deux voix est intacte partout où elle a de
   quoi s'exprimer.
   Le `clamp` de la marge interne suit la même logique : 24px sur téléphone,
   36px dès que la carte s'élargit, sans marche d'escalier. */
.cartes .carte {
	--ra-fs-courant: max(var(--ra-fs-lecture), 1.25rem);
	padding: 2.5rem clamp(1.5rem, 0.7rem + 3.17vw, 2.25rem);
}
/* Ces deux cartes sont les premières sections de la page : leur titre est donc un
   h2, sinon le plan sautait du h1 directement au h3. La TAILLE reste celle d'un
   h3 — un titre de carte à 48px écraserait sa carte. Même principe que le h1 de
   /blog calé sur l'échelle h2 : le niveau porte la sémantique, la classe porte
   la taille. Le `margin-bottom` est repris parce que la règle globale des h2
   passe à 2rem au-delà de 1024px. */
.cartes .carte .carte__titre {
	font-size: var(--ra-fs-h3);
	line-height: 1.15;
	margin-bottom: 1rem;
}

/* Corps long-forme des pages domaine (taille & colonne : cf. Contextes de lecture). */
.service-corps > h2 { margin-bottom: 1.5rem; }

/* ==========================================================================
   Pages domaine : colonne de lecture (corps + FAQ + appel à l'action)
   Chaque bloc porte déjà sa propre largeur (`--ra-mesure-lecture`) : cette
   grille à une colonne ne sert plus qu'à porter le rythme vertical entre eux.
   ========================================================================== */
/* L'écart entre deux blocs empilés de la colonne (corps, FAQ, contact) est le
   rythme de la page, pas une valeur de grille propre. Sans ça, corps → FAQ ne
   valait que le `gap` (64px en ≥1280, 40px en dessous) : c'était le plus petit
   écart de toute la page — plus petit que les 96px qui séparent tous les autres
   blocs, et plus petit que les 104px qui séparent deux chapitres À L'INTÉRIEUR
   du corps. La FAQ ouvre pourtant une nouvelle partie, sous le plus grand titre
   de la page (48px). */
/* ⚠️ Le `row-gap` est la seule chose qui sépare ces blocs : `.cta-contact`
   voit sa marge propre annulée plus bas (.service-lecture .cta-contact). */
/* LARGEUR — `--ra-mesure-lecture` est redéclarée ICI, pas dans `:root` : la
   variable est partagée avec les articles et le bloc contact, et c'est la
   colonne des pages domaine seule qu'on règle. FAQ et bloc contact la
   consomment par héritage via leur propre `max-width` : une seule valeur pour
   les deux. 54rem = la largeur retenue pour les articles, donc une mesure de
   lecture commune à tout le texte long du site. */
.service-lecture { --ra-mesure-lecture: 54rem; display: grid; grid-template-columns: 1fr; row-gap: var(--ra-rythme-page); }

/* ⚠️ LE CORPS EST LE SEUL BLOC À DEUX LARGEURS, et c'est tout l'intérêt de la
   mise en page. Mesuré sur droit pénal : les listes font **44 % de la hauteur
   du corps** (3 492px sur 8 022) pour environ 30 % des mots, mais leurs 55
   items — tous d'une seule ligne — n'utilisaient que **38 % de la largeur** ;
   pendant ce temps les paragraphes couraient sur **135 caractères** au lieu des
   60-75 confortables. La largeur profitait donc à ce qui n'en avait pas besoin.
   Le bloc s'étend, le TEXTE COURANT garde sa mesure, et les LISTES prennent la
   largeur en deux colonnes. Résultat : 86 caractères par ligne, césure 27,3 →
   21,7 %, page raccourcie de 1,3 écran.
   Le sélecteur `.service-lecture .service-corps` (0,2,0) est nécessaire pour
   passer devant le `max-width` du groupe des contextes de lecture (0,1,0). */
.service-lecture .service-corps { max-width: none; }
/* ⚠️ Les TITRES ne sont pas du texte courant : ils n'ont pas de mesure de
   confort à respecter, et les borner à la colonne de lecture les cassait pour
   rien — mesuré : **7 titres sur 10 passaient sur deux lignes** contre 3 en
   pleine largeur, et une deuxième ligne courte est le blanc le plus visible de
   la page. Ils gardent donc la largeur du bloc. Seul le texte courant est borné. */
/* Justifié + français : la césure évite les lézardes, mais par défaut le
   navigateur coupe des mots courts et laisse des fragments de deux lettres.
   En n'autorisant la coupe qu'à partir de 8 caractères, avec 4 de chaque côté,
   les coupures passent de 5 à 3 sur le corps entier sans que les lézardes
   reviennent. Les items de liste, eux, ne se coupent jamais — inutile de les
   traiter à part. */
.service-corps .rich,
.faq-item .rich { hyphenate-limit-chars: 8 4 4; }

/* ==========================================================================
   TROIS FONCTIONS ÉDITORIALES, TROIS MISES EN PAGE
   Le corps enchaîne trois choses qui ne se lisent pas de la même façon, et qui
   recevaient pourtant le même traitement du début à la fin. Mesuré sur les 3
   pages : 46 à 61 % des mots sont dans des listes, et rien ne signalait au
   lecteur qu'il changeait de registre.
   Les blocs sont qualifiés par leur STRUCTURE dans rosa_structurer_corps() —
   jamais par leur texte : la mise en page ne dépend pas des mots de Rosa.
   ========================================================================== */
/* ⚠️ `var(--ra-rythme-page)` et non une valeur propre : un chapitre est une
   partie de premier niveau, il se sépare donc du précédent comme la FAQ se
   sépare du corps ou les cartes du séparateur — 96px en ≥1024, 48 en dessous.
   J'avais posé 5,5rem (88px), un nombre magique qui ne dérivait de rien et qui
   avait au passage fait glisser l'ouverture de chapitre de 104 à 120px sans
   décision. L'échelle reste monotone : 72px entre deux cas < 128 entre deux
   chapitres (96 + les 2rem de rembourrage du h2). */
.corps-bloc + .corps-bloc { margin-top: var(--ra-rythme-page); }
.corps-bloc > h2 { max-width: none; }

/* ── PROSE : on lit. Colonne unique, aucun artifice. ─────────────────────── */
.corps-bloc--prose > * { max-width: var(--ra-mesure-lecture); }
/* CHAPÔ — le premier paragraphe d'un chapitre de prose, à la taille « lead »
   déjà employée pour l'entrée de la bio de l'accueil. Deux raisons :
   1. il marque l'entrée dans le texte, ce qu'aucun signal ne faisait ;
   2. c'est le seul moyen d'occuper la largeur SANS allonger la ligne — le corps
      à 26px ne peut pas dépasser ~86 caractères sur 864px, alors qu'à 36px une
      colonne de 70rem (1 120px) n'en fait que 77, sans une seule césure.
      Mesuré : 92,5 car. en pleine largeur, 85,5 à 76rem, 77 à 70rem, 69 à 64rem.
   La prose reste le bloc le moins « mis en page » de la page — c'est voulu, on
   y lit — mais elle ne s'ouvre plus sur une colonne étroite dans un bloc large. */
.corps-bloc--prose > h2 + p {
	max-width: 70rem;
	font-size: var(--ra-fs-lead);
	line-height: 1.25;
	text-align: left;   /* une amorce courte n'a rien à justifier */
}

/* ── CATALOGUE : on cherche. C'est le SEUL bloc où le titre quitte le fil du
      texte, parce que c'est le seul qu'on balaie : alignés dans leur colonne,
      les titres forment la liste des cas traités. Le numéro en or reprend
      l'idiome des listes numérotées du site. ─────────────────────────────── */
.corps-bloc--catalogue { counter-reset: corps-cas; }
.corps-bloc__chapo > * { max-width: var(--ra-mesure-lecture); }
/* ⚠️ PAS DE FILET ENTRE LES CAS, et c'est délibéré. Il y en avait un : retiré
   après comptage — la page portait 29 traits horizontaux, dont 12 ajoutés en
   même temps que cette mise en page. Deux raisons de le supprimer :
   1. il doublait un signal déjà donné trois fois (le numéro en or, le titre
      dans sa propre colonne, et 72px d'écart) — vérifié en le retirant, la
      frontière entre deux cas reste évidente ;
   2. il faisait 1 329px, exactement comme le filet or des chapitres. Deux
      niveaux de structure, deux traits pleine largeur que seule une nuance de
      couleur distinguait. Un trait qui apparaît à tous les niveaux cesse de
      signifier quelque chose : sans lui, le filet or redevient exclusif à
      l'ouverture d'un chapitre. */
.corps-cas {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
	column-gap: 4rem;
	margin-top: 4.5rem;
}
.corps-bloc--catalogue > .corps-cas:first-of-type { margin-top: 3rem; }
/* NUMÉROTATION — le chiffre joue sur la TAILLE, pas sur la densité : grand, mais
   en valeur faible, il ne dispute rien au titre. C'est ce qui permet de le
   mettre en valeur sur une page qu'on cherche à garder épurée, là où un pavé
   plein aurait réintroduit de la matière sombre.
   Même dessin ici et sur les principes (même format `01`, même taille, même
   teinte) : les deux séries disaient « 1 sur 6 » avec trois différences —
   18 vs 26px, `01` vs `1.`, or vs vert-de-gris.
   ⚠️ La teinte est celle du bandeau d'appel à l'action : les deux forment une
   famille. Contraste avec la page 1,65 — c'est délibérément faible, le chiffre
   est un repère de composition, l'ordre étant déjà porté par la structure. */
/* ── CHIFFRE EN FILIGRANE ────────────────────────────────────────────────────
   Posé à CÔTÉ du titre, il lui imposait 6rem de retrait : 96px prélevés sur une
   colonne de 596. Derrière le texte il ne coûte rien.
   Mesuré : largeur utile du titre 500 → 596px (+19 %), le plus long passe de
   3 lignes à 2, hauteur cumulée des six titres 478 → 441px, tous réalignés sur
   l'axe x=48. Titre par-dessus le filigrane : contraste 9,76 (seuil 4,5) ; le
   chiffre est à 1,65 — repère de composition, pas information.
   ⚠️ `align-self: start` est INDISPENSABLE, et le défaut n'apparaît qu'en mise
   en page réelle : une cellule de grille s'étire sur la hauteur de sa rangée,
   ici celle du corps (des centaines de px), et `top: 50%` centrait le chiffre
   ~300px sous son titre. Une simulation aux corps masqués ne le montre pas.
   ⚠️ Sans empilement explicite, un `::before` positionné se peint AU-DESSUS du
   flux : d'où `z-index: 0` ici et `z-index: 1` sur le h3.
   ⚠️ Les six principes gardent leur chiffre EN LIGNE : les rôles diffèrent —
   l'un ponctue une grille d'unités courtes, l'autre habille un titre.
   ────────────────────────────────────────────────────────────────────────── */
.corps-cas__titre { counter-increment: corps-cas; position: relative; align-self: start; }
.corps-cas__titre::before {
	content: counter(corps-cas, decimal-leading-zero);
	position: absolute; left: -0.05em; top: 50%; transform: translateY(-50%);
	z-index: 0;
	font-family: var(--ra-font-heading);
	/* 13rem (208px). ⚠️ NE PAS RAISONNER SUR L'ÉCART DE 72px ENTRE DEUX CAS pour
	   borner cette taille : c'est ce que j'avais fait d'abord, et c'est faux.
	   La colonne de gauche ne contient QUE le titre — le corps occupe la colonne
	   de droite, qui commence à x=708 — si bien que le chiffre déborde
	   verticalement sur du VIDE, et jamais sur du texte. Mesuré : même à 20rem
	   il s'arrête à x=408, soit 300px avant la colonne de corps. La borne est
	   donc esthétique, pas structurelle.
	   💡 Le piège venait de ma simulation : j'y masquais les corps pour
	   rapprocher les six cas, ce qui créait une contrainte verticale que la vraie
	   page n'a pas. Deuxième fois dans la journée qu'une simulation compactée
	   invente un défaut ou en cache un — la valider en page réelle. */
	font-size: 13rem; line-height: 1; font-weight: 700; letter-spacing: 0.04em;
	/* ⚠️ TEINTE ALLÉGÉE DE 45 À 20 % (2026-08-10, après rendu). À 45 % — la
	   valeur qu'il avait quand il était POSÉ À CÔTÉ du titre — le chiffre
	   accrochait le regard une fois passé DESSOUS : sa panse venait couper les
	   jambages du titre. Un même contraste ne se juge pas de la même façon selon
	   qu'une forme est à côté du texte ou derrière lui.
	   Les cinq teintes ont été comparées en rendu, contraste avec la page :
	   45 % → 1,65 (accroche) · 30 % → 1,38 · **20 % → 1,23 (retenu)** ·
	   15 % → 1,17 · 10 % → 1,11 (le chiffre disparaît).
	   Le titre par-dessus passe de 9,76 à **13,01**.
	   Conséquence assumée : le chiffre ne partage plus sa teinte avec le bandeau
	   d'appel à l'action (45 %), écho voulu le 07/08 — mais cet écho supposait un
	   chiffre posé sur la page, pas un filigrane sous du texte. */
	color: var(--ra-vertparis-20);
}
.corps-cas__titre > h3 { position: relative; z-index: 1; }
/* Les marges d'ouverture de chapitre n'ont plus lieu d'être : c'est le filet de
   la ligne qui sépare deux cas. */
.corps-cas__titre > h3 { margin-top: 0; max-width: none; }
.corps-cas__corps > :first-child { margin-top: 0; }

/* ── PRINCIPES : six unités courtes. Une grille, pas un empilement. ──────── */
/* ⚠️ `h2` est exclu de la liste, pas seulement `.corps-principes` : un `:not()`
   emprunte la spécificité de son argument, donc ce sélecteur pesait (0,2,0) et
   battait `.corps-bloc > h2` (0,1,1) — le titre du bloc, et surtout SON FILET,
   se retrouvaient bornés à 864px au lieu de traverser toute la largeur comme
   les autres filets de chapitre. */
.corps-bloc--principes > :not(.corps-principes, h2, h3) { max-width: var(--ra-mesure-lecture); }
/* Titre des six principes. Rendu en `<h3>` par `rosa_nc_marquer_principes()`,
   il hérite du dessin des sous-sections : aucun traitement inventé pour lui.
   Il traverse la largeur parce que c'est la grille qu'il annonce, pas la
   colonne de lecture — d'où son exclusion du `:not()` ci-dessus.
   ⚠️ Préfixé `.rich` : sans ça `.rich h3 { margin-top: 2.5rem }` (0,1,1)
   l'emportait sur (0,1,0) et le titre ouvrait à 40px au lieu de 72.
   ⚠️ `4.5rem` et non `2.4em` : ce titre et les cas du catalogue sont au MÊME
   niveau et s'ouvraient à 77 contre 72px. En `em`, la valeur suivrait la taille
   du titre — ce qui n'a pas de sens pour une séparation entre deux parties. */
.rich .corps-principes__titre { margin-top: 4.5rem; }
/* ⚠️ La liaison titre→texte de 0,6em (16px) ne convient PAS ici : elle est faite
   pour un titre suivi d'un paragraphe, alors que chaque cellule de la grille
   s'ouvre elle-même sur un libellé en gras. Deux gras à 16px se disputaient, et
   le titre se lisait comme un morceau de la première rangée.
   L'échelle du bloc doit rester monotone : libellé→texte 4px < **titre→grille
   31px** < entre rangées 44px < gouttière 56px. Au-delà de 44 le titre
   cesserait d'être rattaché à la grille qu'il annonce ; à 16 il en faisait
   partie. (Essais mesurés : 0,6em→16 · 0,9em→23 · **1,2em→31** · 1,4em→36.) */
.rich .corps-principes__titre + .corps-principes { margin-top: 1.2em; }
.corps-principes {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	column-gap: 3.5rem; row-gap: 2.75rem;
	margin-top: 2.5rem;
}
/* Même arbitrage que pour les cas : chaque cellule est déjà délimitée par son
   numéro en or, son libellé en gras et les 3,5rem de gouttière. Le filet n'y
   ajoutait rien — et les six s'alignant deux par deux dans la grille, ils se
   lisaient de toute façon comme deux longs traits de plus. */
/* ⚠️ `.rich .corps-principes` et non `.corps-principes` seul : l'air entre deux
   items de liste vient de `.rich li + li` (0,1,2), qui battait `.corps-principes
   > li` (0,1,1). Les items 2 à 6 recevaient donc 11,7px de marge et le premier
   non — les trois cellules d'une rangée ne s'alignaient pas. Dans une grille,
   l'écart est porté par `row-gap`, pas par les items. */
.rich .corps-principes > li {
	margin-top: 0;
	break-inside: avoid;
	padding-left: 4.5rem;
}
/* ⚠️ `.rich .corps-principes > li::before` (0,2,2) et non `.corps-principes >
   li::before` (0,1,2) : cette dernière ne bat PAS `.rich ol > li::before`
   (0,1,3), et ni le format `01` ni la taille ne s'appliquaient. Piège de
   cascade déjà rencontré ailleurs sur ce projet — interroger la feuille, ne
   jamais estimer une spécificité de tête. */
.rich .corps-principes > li::before {
	content: counter(ra-item, decimal-leading-zero);
	top: -0.08em;
	width: auto; text-align: left;
	font-size: 3rem; line-height: 1;
	color: var(--ra-vertparis-45);
}

@media (max-width: 1023px) {
	/* Deux colonnes n'ont plus de sens : le titre repasse au-dessus de son
	   contenu, et les principes s'empilent. */
	.corps-cas { grid-template-columns: 1fr; row-gap: 1rem; }
	.corps-principes { grid-template-columns: 1fr; }
	/* (L'écart entre chapitres suit `--ra-rythme-page`, qui vaut déjà 3rem
	   ici : aucune surcharge à prévoir.) */
	/* ⚠️ LE FILIGRANE NE PEUT PAS SUIVRE L'AGRANDISSEMENT DU GRAND ÉCRAN, et
	   l'écart (13rem là-bas, 6 ici) n'est pas une timidité : la grille repasse à
	   UNE colonne, le corps n'est plus à droite du titre mais dessous, et il ne
	   reste que le `row-gap: 1rem` sous le titre. Le vide dans lequel le chiffre
	   déborde librement sur grand écran n'existe tout simplement plus.
	   Mesuré à 390px, écart entre le bas du chiffre et la première ligne du
	   corps : 9rem → **-14px** · 7rem → 2px · **6rem → 10px (retenu)**. À 768px
	   le 9rem venait franchement buter contre le paragraphe, vérifié en rendu
	   agrandi — le chevauchement de boîtes ne suffisait pas à conclure, il
	   fallait regarder l'encre.
	   Il n'y a plus de retrait à annuler ici : depuis le passage en
	   arrière-plan, le chiffre ne prélève aucune largeur. */
	/* ⚠️⚠️ FILIGRANE RETIRÉ SOUS 1024px (2026-08-10, après rendu à 390px).
	   Il ne s'agit plus de le dimensionner : à cette largeur il change de NATURE.
	   Mesuré à 390px : chiffre de 96px contre un titre de 3 lignes / 90px — deux
	   objets de même taille, donc le chiffre passe SOUS LES MOTS et se lit comme
	   une tache, non comme un fond. À 1440px le rapport est inverse (208px de
	   chiffre pour 73px de titre sur 2 lignes) : il redevient un aplat derrière
	   le texte, ce pour quoi il a été dessiné.
	   💡 Ce n'est pas la taille du chiffre qui décide, c'est son RAPPORT à la
	   hauteur du titre — et ce rapport bascule parce que le titre gagne des
	   lignes en mobile pendant que le chiffre en perd en taille.
	   La numérotation reste portée par l'ordre de lecture, qui suffit ici.
	   Retour arrière : rétablir `font-size: 6rem` à la place de `content: none`. */
	.corps-cas__titre::before { content: none; }
	.rich .corps-principes > li { padding-left: 3.5rem; }
	.rich .corps-principes > li::before { font-size: 2.25rem; }
}

/* Interligne propre aux items de liste. Un item de liste n'est pas un
   paragraphe : la très grande majorité tient sur UNE ligne (50 sur 61 dans le
   corps, 46 sur 48 dans la FAQ), et sur ceux-là le 1,6 du texte courant ne sert
   à rien — il ne fait que gonfler la boîte de 15,6px, si bien que l'air entre
   deux puces venait d'une hauteur morte plutôt que d'une valeur choisie.
   1,30 n'est pas une invention : c'est déjà l'interligne de la liste de
   services de l'accueil, même nature d'items courts.
   ⚠️ Scopé aux pages domaine : sur `.rich` nu, la règle toucherait les listes
   des articles et de l'accueil. */
.service-corps .rich li,
.faq-item .rich li { line-height: 1.3; }

/* (Le SOMMAIRE ANCRÉ a été retiré le 2026-08-10 : gabarit, script et habillage
   supprimés après décision de ne pas en afficher. `inc/sommaire.php` reste, car
   `rosa_ancrer_titres()` y pose les ancres des titres, utilisées par les liens
   de saut de Google et par le décalage ci-dessous. Copie dans
   Local Sites/rosa-alaimo-avocat/sauvegardes/.) */

/* Les ancres ne doivent pas se coller au bord haut de la fenêtre. */
/* Décalage d'ancrage : l'en-tête étant collant, un titre visé par le sommaire
   atterrirait derrière la barre. Posé sur tout élément ancrable du site, pas
   seulement sur les pages domaine — les liens de saut de Google visent aussi
   les titres d'articles. */
[id] { scroll-margin-top: calc(var(--ra-entete-h) + 1.5rem); }

/* Ouverture de section : un filet or discret marque les 4-5 chapitres de la
   page, qui se noyaient dans le flux. Écho léger aux séparateurs à la balance.
   Pas sur le premier titre : il ouvre déjà le corps, le filet y ferait doublon
   avec le séparateur du dessus.
   Le filet reste propre aux pages domaine : sur les articles, seul l'ÉCART est
   repris (4,5rem), pas le trait — l'ajout d'un élément graphique n'entrait pas
   dans la demande d'homogénéisation typographique. */
/* ⚠️ Depuis le regroupement en blocs, c'est `.corps-bloc + .corps-bloc` qui
   porte l'écart entre chapitres : le h2 ne garde que son filet et son
   rembourrage, sinon les deux s'additionneraient. */
/* ⚠️ OR PLEIN, et non l'or à 15 % d'origine : mesuré, ce filet contrastait à
   **1,17** avec la page — le trait le MOINS visible de tous, alors qu'il marque
   le niveau le plus élevé. Les filets de la FAQ, qui ne séparent que deux
   questions, sont à 3,52. La hiérarchie était donc inversée, et le retrait des
   filets de cas s'appuyait sur un argument — « le filet or redevient exclusif à
   l'ouverture d'un chapitre » — qui ne tenait que si ce filet se voyait.
   À 3,48 il rejoint le niveau des séparateurs et des filets de FAQ ; c'est sa
   COULEUR, pas son épaisseur, qui dit qu'il ouvre un chapitre. */
.service-corps .rich h2 { padding-top: 2rem; border-top: 1px solid var(--ra-secondaire); }
.corps-bloc:first-child > h2 { padding-top: 0; border-top: 0; }
/* La frontière entre deux sous-sections est désormais le filet de `.corps-cas` :
   le h3 n'a plus d'écart propre à porter. (Auparavant il héritait du `1.4em` de
   l'écart courant, calculé sur SA taille — 31,9 × 1,4 = 44,7px — une valeur
   jamais pensée pour un titre, plus faible que l'écart amorce/liste de 52px à
   l'intérieur même de la sous-section.) */
/* Ouverture de chapitre dans un article : même respiration que les pages
   domaine, sans le filet. */
.article-body h2 { margin-top: 4.5rem; }

/* Amorce suivie de sa liste, ≈13 fois par page. Sans liaison elle flottait à
   égale distance du § précédent et de la liste qu'elle annonce : on l'écarte de
   l'un, on la colle à l'autre.
   ⚠️ En `em` : les 2rem d'origine (32px) valaient MOINS que l'écart entre
   paragraphes porté à 1,4em (36,4px), l'amorce cessait d'être écartée.
   DEUX SÉLECTEURS. `.rich-amorce`, posée par `rosa_normaliser_wysiwyg()` sur
   tout paragraphe qui ANNONCE le suivant, en gras ou non — reconnaissance par
   le RÔLE, là où `:has(> strong:only-child)` ne voyait que la forme et laissait
   13 amorces sur 32 sans liaison. Le `:has()` reste sur `.rich` pour les pages
   où la normalisation n'est pas branchée ; double emploi sans conflit. */
.rich p.rich-amorce,
.rich p:has(> strong:only-child) { margin-top: 2em; }
/* Une liste se distingue d'elle-même (puces, retrait) : 0,4rem suffit à la
   rattacher. Un paragraphe annoncé, lui, demande la même respiration qu'un
   texte sous son titre — l'amorce joue exactement ce rôle. */
.rich p.rich-amorce + :is(ul, ol),
.rich p:has(> strong:only-child) + :is(ul, ol) { margin-top: 0.4rem; }
.rich p.rich-amorce + p { margin-top: 0.6em; }
/* ⚠️ FAUX POSITIFS DU `:has()`, neutralisés là où la classe fait autorité.
   Dans le corps des pages domaine, rosa_structurer_corps() marque les amorces
   par leur RÔLE. Le `:has()` ci-dessus, gardé pour les pages qui ne passent pas
   par la normalisation, y continuait pourtant de s'appliquer aux paragraphes
   entièrement en gras qui n'annoncent rien : mesuré sur Droit des étrangers,
   deux d'entre eux recevaient les 52px d'ouverture d'une amorce SANS la liaison
   de 6px en dessous — ils flottaient donc à égale distance de ce qui précède et
   de ce qui suit, exactement le défaut que la reconnaissance par le rôle avait
   corrigé. Ils reprennent l'écart courant.
   Spécificité (0,4,2), au-dessus de `.rich p:has(...)` (0,2,2). */
.service-corps .rich p:has(> strong:only-child):not(.rich-amorce) { margin-top: 1.4em; }
/* Un titre garde la main sur ce qui le suit, amorce comprise : sans cette
   règle, une amorce placée juste après un titre reprenait ses 2em et le titre
   se retrouvait détaché de sa propre section. Spécificité (0,2,2), au-dessus
   des deux règles ci-dessus. */
.rich :is(h2, h3, h4) + p.rich-amorce { margin-top: 0.6em; }

/* Un premier enfant n'a rien au-dessus de quoi s'écarter. Sans ça, une réponse
   de FAQ qui commence par une amorce se décollait de sa question de 52px, alors
   que les six autres réponses de la page la touchaient — un écart dicté par la
   première phrase de la réponse, pas par une intention.
   ⚠️ Volontairement NON global : sur `.rich` nu, la règle remonterait aussi de
   72px le premier titre des articles et des mentions légales, qui commencent
   par un h2 ou un `<hr>` selon l'article. C'est un vrai défaut d'homogénéité,
   mais il appartient aux articles — signalé, pas corrigé ici.
   Spécificité (0,3,0) : passe devant `.rich p.rich-amorce` (0,2,1). */
.service-corps .rich > :first-child,
.faq-item .rich > :first-child,
.carte .rich > :first-child { margin-top: 0; }

/* Items « <strong>Libellé</strong> puis explication » (les 6 principes de
   défense, sur les trois pages). Le libellé était séparé de son explication
   par un `<br>`, donc par un écart NUL, quand deux items voisins en ont 0,45em.
   Le saut est retiré à la normalisation et le libellé passe en bloc : l'écart
   interne (0,2em) reste bien inférieur à celui qui sépare deux items, l'ordre
   de lecture est préservé. */
.rich li.li-libelle > strong:first-child { display: block; margin-bottom: 0.2em; }

/* Articles liés (« Les derniers articles » / « À lire aussi ») : dernier bloc des
   pages service & single → padding bas pour ne pas coller au footer (rythme de la home). */
.service-articles { padding-bottom: 6rem; }
@media (min-width: 1024px) { .service-articles { padding-bottom: 8rem; } }

/* FAQ (accordéon natif <details>)
   La FAQ courait sur toute la largeur du conteneur : ses réponses faisaient
   173 caractères par ligne, le pire endroit de la page — invisible au premier
   regard puisque l'accordéon est fermé par défaut. Elle rejoint la colonne de
   lecture, calée sur le corps (même bord gauche, même largeur, même taille). */
/* ⚠️ LA FAQ SUIT LE MÊME PRINCIPE QUE LE CORPS : le BLOC prend la largeur de la
   page, le TEXTE garde sa mesure. Elle était restée bornée à 54rem — ce qui se
   justifiait quand l'appel à l'action l'était aussi ; depuis qu'il est devenu un
   bandeau pleine largeur, elle était **le seul bloc de la page à 864px** contre
   1 329 partout ailleurs, et le décrochement sautait aux yeux juste avant le
   bandeau. Ses filets s'alignent désormais sur ceux des chapitres, et le `+`
   se pose au bord droit : la question devient une vraie ligne d'accordéon.
   Il faut relâcher `.faq-item` en plus de `.service-faq` : la première est dans
   le groupe des « contextes de lecture », qui lui impose la mesure. */
.service-faq,
.service-faq .faq-item { max-width: none; }
.service-faq .faq-item .rich > * { max-width: var(--ra-mesure-lecture); }
.service-faq .faq-list { border-bottom: 1px solid var(--ra-vertparis); }
.faq-item { border-top: 1px solid var(--ra-vertparis); }
.faq-item summary {
	cursor: pointer; list-style: none;
	font-family: var(--ra-font-heading); font-weight: 700;
	font-size: var(--ra-fs-courant); padding: 1rem 0;
	display: flex; justify-content: space-between; align-items: center; gap: 1rem;
	color: var(--ra-primaire);
}
.faq-item summary::-webkit-details-marker { display: none; }
/* La question est un `<h3>` (plan de titres) mais garde EXACTEMENT l'aspect
   qu'elle avait en texte nu : le style d'accordéon est porté par `summary`, le
   `<h3>` ne fait que se taire. `font: inherit` reprend d'un coup taille, graisse
   et interligne ; `letter-spacing` doit être repris à part, il n'est pas dans le
   raccourci `font` et `h3` en pose un (`--ra-tracking-head`). */
.faq-item summary > h3 { font: inherit; letter-spacing: inherit; color: inherit; margin: 0; }
/* MARQUEUR — le `+` PIVOTE de 45° pour devenir une croix, au lieu d'être
   remplacé par un `−`.
   ⚠️ La transition déclarée ici était du CODE MORT : elle portait sur
   `transform`, alors qu'aucun `transform` n'était jamais appliqué — le
   changement se faisait par échange de `content`, une propriété discrète qui ne
   s'interpole pas. Le marqueur sautait donc d'un glyphe à l'autre.
   Le `−` disparaît au passage : on ne peut pas interpoler un `+` vers un `−`,
   et la croix dit « refermer » aussi clairement. */
.faq-item summary::after {
	content: "+";
	font-size: 1.5rem; line-height: 1;
	color: var(--ra-secondaire);
	transition: transform var(--ra-transition-panneau);
}
.faq-item[open] summary::after { transform: rotate(45deg); }
/* OUVERTURE DÉPLIÉE — un `<details>` s'ouvre d'un coup ; sur une réponse
   longue, le lecteur perd sa ligne.
   ⚠️ TROIS PROPRIÉTÉS NÉCESSAIRES, aucune n'est un confort :
   — `::details-content` désigne le panneau, sans sélecteur jusque-là ;
   — `interpolate-size: allow-keywords` (sur `:root`) autorise l'animation VERS
     `auto` — sinon il faudrait figer une hauteur, donc casser dès qu'une
     réponse s'allonge ;
   — `transition-behavior: allow-discrete` fait durer `content-visibility` le
     temps de la transition, sans quoi seule l'OUVERTURE s'animerait.
   Propriétés absentes = accordéon d'aujourd'hui : rien de cassé, rien de
   caché. */
.faq-item::details-content {
	block-size: 0;
	overflow: hidden;
	transition: block-size var(--ra-transition-panneau),
	            content-visibility var(--ra-transition-panneau);
	transition-behavior: allow-discrete;
}
.faq-item[open]::details-content { block-size: auto; }
.faq-item .rich { padding-bottom: 1.25rem; }

/* Articles liés */

/* ==========================================================================
   Article de blog
   ========================================================================== */
/* En-tête (H1 + méta) et couverture : plus larges que le corps pour l'impact éditorial.
   L'air au-dessus du H1 vient du rythme de page commun (il était à 2rem : un titre
   de 60px se retrouvait collé sous le bandeau des boutons). */
.article-header { max-width: 72rem; margin: var(--ra-rythme-page) auto 1.5rem; text-align: center; }
/* Variante pleine largeur, fer à gauche (mentions légales & pages simples). */
.article-header--plein { text-align: left; margin-inline: 0; }
.article-meta { font-size: 1.25rem; color: var(--ra-text-muted); margin-top: 1rem; }
.article-meta .sep { margin: 0 0.4rem; color: var(--ra-secondaire); }
.article-cover { max-width: 72rem; margin: 0 auto 2.5rem; }
.article-cover img { width: 100%; aspect-ratio: 3 / 1; object-fit: cover; display: block; }
/* Corps d'article : taille et colonne viennent du contexte de lecture élargie.
   Centré, contrairement aux pages domaine calées à gauche sur leur FAQ.
   ⚠️ La variable est redéclarée ICI et non dans `:root`, sinon les pages
   domaine et la FAQ suivraient — leur colonne à 46rem est calée autrement.
   LARGEUR ARBITRÉE entre césure et caractères par ligne, mesuré sur un article
   entier à 1280px, **dernière ligne de chaque paragraphe exclue** (ragged et
   jamais coupée : l'inclure faussait moyenne ET taux). Caractères / césure :
   46rem → 73,8 / 27,2 % · 50rem → 80,5 / 27,1 % · 52rem → 83,4 / 34,6 % ·
   56rem → 90,4 / 31,0 % · 60rem → 96,7 / 25,5 %. ⚠️ Le taux n'évolue PAS
   linéairement avec la largeur.
   54rem retenu sur un troisième critère, décisif : le RETOUR À LA LIGNE DES
   TITRES — sur 4 articles (90 titres), 26 débordaient à 50rem contre 20 à
   54rem, dont un h2 passant de 3 lignes à 2. Le décrochement avec l'en-tête
   (resté à 72rem) tombe de 176 à 144px.
   Contrepartie assumée : 86,7 car./ligne (au-dessus des 60-75) et 29,4 % de
   césure contre 27,1 % à 50rem. */
.article-body { --ra-mesure-lecture: 54rem; margin-inline: auto; }
/* Déclaré APRÈS .article-body, sinon son `margin-inline:auto` recentrait le
   corps et le décalait de son titre resté fer à gauche (mentions légales). */
.article-body--plein { margin-inline: 0; }

/* Bloc « prendre contact » — articles ET pages domaine, une seule forme : le
   bandeau décrit plus bas. Écart d'ouverture identique à celui d'un chapitre. */
/* Marge d'ouverture, commune aux deux contextes. Le reste du dessin est plus
   bas — il n'y a plus qu'UNE forme. */
.cta-contact { margin-top: 4.5rem; }
/* ARTICLES — le bandeau se cale sur l'axe de l'EN-TÊTE ET DE LA COUVERTURE
   (72rem), pas sur celui du corps. L'article a trois axes là où la page domaine
   n'en a qu'un : 72rem pour l'en-tête et l'image, 54rem pour le corps. Choisir
   72rem n'ajoute donc AUCUN alignement nouveau — le bandeau retombe exactement
   sous l'image vue en haut de page.
   ⚠️ Les deux autres largeurs ont été essayées en rendu : à 54rem (la colonne de
   lecture) le titre se casse en deux lignes, le bouton est comprimé et le bloc
   monte à 333px contre 261 ; en pleine largeur il introduit un QUATRIÈME axe
   (x=48) qui n'existe nulle part ailleurs dans l'article. */
.article .cta-contact { max-width: 72rem; margin-inline: auto; }
/* Dans la colonne de lecture des pages domaine, c'est le `row-gap` de la grille
   qui porte le rythme (cf. .service-lecture) : la marge propre du bloc s'y
   ajouterait. Elle est donc annulée — et le CTA se sépare de la FAQ exactement
   comme la FAQ se sépare du corps. Auparavant un `margin-top: 2rem` corrigeait
   le cas ≥1280 (64+32=96) mais laissait 72px en dessous, contre 48 de rythme :
   la compensation était trop forte là où le rythme est plus serré. */
.service-lecture .cta-contact { margin-top: 0; max-width: none; }

/* ══ BANDEAU D'APPEL À L'ACTION ══════════════════════════════════════════════
   Sur une longue surface blanche de lecture, ce bloc est le seul moment qui
   doit interrompre. Changer le FOND est le différenciateur le plus fort et le
   plus sobre : aucun ornement ajouté, la matière est inversée. Le bloc
   raccourcit au passage (296 → 272px), le bouton passant à droite.
   ⚠️ COULEURS — mesuré sur le fond #768e84 : blanc = 3,52 (sous le seuil 4,5),
   encre = 4,57, sombre = 5,74, d'où le texte en `--ra-sombre`. Le bouton reste
   le drap encre (écart bouton/fond 4,57, au-dessus des 3:1 d'un composant) et
   son pli passe à l'or, sans quoi il disparaîtrait sur ce fond.
   Une seule forme pour les pages domaine ET les articles : il ne reste aux deux
   contextes qu'une différence de LARGEUR (pleine largeur / 72rem centré). */
.cta-contact {
	padding: 3.5rem 3rem;
	background-color: var(--ra-vertparis-45);
	color: var(--ra-sombre);
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	column-gap: 4rem;
	align-items: center;
}
/* ⚠️ PAS de taille propre : le titre garde le `--ra-fs-h3` (30px) du composant,
   celui des titres de carte. Les deux sont des titres de BLOC — un encadré, un
   bandeau — et n'ont aucune raison de différer. J'avais posé `--ra-fs-lead`
   (36px), ce qui ajoutait une cinquième taille de titre à la page ET détournait
   une variable de TEXTE pour un titre. Vérifié à 30px : le titre tient, et le
   bandeau perd 7px de hauteur.
   La couleur, elle, est reprise explicitement : les titres portent
   `--ra-primaire`, qui ne descend pas du bandeau et tombe à 4,57 sur ce fond
   quand le texte courant est à 5,74. Conforme au seuil des grands textes, mais
   il n'y a aucune raison que le titre soit le moins lisible du bloc. */
.cta-contact__titre { color: var(--ra-sombre); grid-column: 1; }
/* Le texte garde une mesure de lecture même si le bandeau traverse la page. */
.cta-contact__texte { max-width: 44rem; grid-column: 1; }
.cta-contact .drap-btn { grid-column: 2; grid-row: 1 / span 2; align-self: center; }
.cta-contact .decodrap::after { border-top-color: var(--ra-secondaire); }
/* ⚠️ SANS CETTE LIGNE LE SURVOL EST CASSÉ. Le geste du drap consiste à faire
   passer les DEUX triangles à l'encre pour que l'encoche se remplisse et que le
   bouton devienne un rectangle plein. En repeignant le pli en or au repos, la
   règle ci-dessus (0,3,1) l'emporte aussi au survol sur `.drap-btn:hover
   .decodrap::after` (0,2,1) : le triangle restait or et le coin ne se refermait
   plus. Repeindre une couleur d'état de repos oblige à vérifier les AUTRES
   états du composant. */
.cta-contact .drap-btn:hover .decodrap::after { border-top-color: var(--ra-sombre); }
@media (max-width: 900px) {
	/* Le bouton repasse sous le texte : à cette largeur, deux colonnes le
	   réduiraient à une étiquette écrasée contre le bord. */
	.cta-contact { grid-template-columns: 1fr; padding: 2.5rem 1.75rem; }
	.cta-contact .drap-btn { grid-column: 1; grid-row: auto; justify-self: start; margin-top: 2rem; }
}

.cta-contact__titre {
	font-size: var(--ra-fs-h3);
	line-height: 1.15;
	margin-bottom: 0.75rem;
}
.cta-contact__texte { margin-bottom: 1.75rem; }

/* ==========================================================================
   Grille du blog
   ========================================================================== */
/* h1 sémantique (la page n'en avait plus), calé sur l'échelle h2 pour rester au même niveau visuel que « Le blog » de l'accueil. */
.blog-title { font-size: var(--ra-fs-h2); line-height: 1.05; margin-bottom: 3rem; }

/* Section blog sur l'accueil */
.home-blog { margin-top: 6rem; }
@media (min-width: 1024px) { .home-blog { margin-top: 7rem; } }
.home-blog__head {
	display: flex; justify-content: space-between; align-items: baseline;
	gap: 1rem 2rem; flex-wrap: wrap;
	/* 40px sous un titre de 50px, avant un pavé de cartes : la section démarrait
	   sans respiration. Les autres h2 du site ont 32px, mais ils précèdent du
	   texte, pas un bloc. */
	margin-bottom: 3.5rem;
}
.home-blog__head h2 { margin-bottom: 0; }
.home-blog__head .alink { font-family: var(--ra-font-heading); font-size: var(--ra-fs-catmenu); white-space: nowrap; }

.blog-grid { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 640px)  { .blog-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .blog-grid { grid-template-columns: repeat(3, 1fr); } }

/* Carte article — fond gris, titre en tête (accueil + page blog) */
.blog-card {
	position: relative;   /* référence du lien étiré, cf. .blog-card__title a::after */
	display: flex; flex-direction: column;
	background: var(--ra-gris-carte);
	padding: 2rem;
	transition: background-color var(--ra-transition);
}
.blog-card:hover { background: var(--ra-gris-carte-hover); }

/* 30px pour 21px d'extrait, soit un rapport de 1,43 : à 27,2px le titre n'était
   qu'à 1,30 du texte et se lisait comme « du texte un peu plus gros ». */
.blog-card__title { font-size: clamp(1.5rem, 1.25rem + 1.00vw, 1.875rem); line-height: 1.18; margin-bottom: 1.25rem; }
/* Pas de soulignement au survol du titre : c'est la CARTE qui répond au survol
   (fond creusé + léger zoom de l'image), pas chacun de ses éléments séparément. */
.blog-card__title a { color: var(--ra-primaire); text-decoration: none; }
/* Lien étiré : le lien du titre couvre toute la carte, qui devient cliquable
   d'un bout à l'autre sans HTML invalide (un <a> ne peut pas en contenir un
   autre). Le nom accessible du lien reste le titre de l'article. */
.blog-card__title a::after { content: ""; position: absolute; inset: 0; z-index: 1; }

.blog-card__img { display: block; margin: 0 0 1.25rem; overflow: hidden; }
.blog-card__img img { width: 100%; aspect-ratio: 3/2; object-fit: cover; display: block; transition: transform 450ms cubic-bezier(0.4, 0, 0.2, 1); }
.blog-card:hover .blog-card__img img { transform: scale(1.04); }

.blog-card__cat {
	/* Au-dessus de la surface étirée : la pastille mène à l'archive de la
	   catégorie, pas à l'article — elle doit rester cliquable pour elle-même. */
	position: relative; z-index: 2;
	align-self: flex-start;
	background-color: var(--ra-sombre); color: var(--ra-clair);
	font-family: var(--ra-font-heading); font-size: 1rem; font-style: italic;
	line-height: 1.2; letter-spacing: 0.01em;
	padding: 0.45rem 1rem; margin-bottom: 1.2rem;
}
.blog-card__cat:hover { background-color: var(--ra-primaire); }
/* Colonne étroite + justifié = lézardes : la césure les résorbe. */
.blog-card__excerpt { font-size: 1.3125rem; line-height: 1.35; color: var(--ra-text); margin-bottom: 1.5rem; text-align: justify; hyphens: auto; }
.blog-card__more { margin-top: auto; text-align: right; margin-bottom: 0; }
/* « Lire la suite » n'est plus un lien mais un libellé : toute la carte l'est.
   Il garde son soulignement d'affordance, qui s'assombrit avec le survol de la
   carte plutôt qu'avec le sien propre. */
.blog-card__more span {
	font-family: var(--ra-font-heading); font-weight: 700; font-size: 1.0625rem;
	color: var(--ra-primaire);
	text-decoration: underline; text-decoration-color: var(--ra-vertparis);
	text-decoration-thickness: 3px; text-underline-offset: 4px;
	transition: text-decoration-color var(--ra-transition), color var(--ra-transition);
}
.blog-card:hover .blog-card__more span { text-decoration-color: var(--ra-vertparis-fonce); }

/* Carrousel du blog (accueil) — piste scroll-snap + flèches + pastilles */
.blog-carousel { position: relative; }
.blog-carousel__track {
	display: flex; gap: 2rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;            /* Firefox : masquer la barre */
	padding-bottom: 0.25rem;
}
.blog-carousel__track::-webkit-scrollbar { display: none; } /* WebKit : masquer la barre */
.blog-carousel__track > .blog-card { scroll-snap-align: start; flex: 0 0 100%; }
@media (min-width: 640px)  { .blog-carousel__track > .blog-card { flex-basis: calc((100% - 2rem) / 2); } }
@media (min-width: 1024px) { .blog-carousel__track > .blog-card { flex-basis: calc((100% - 4rem) / 3); } }

.blog-carousel__nav { display: flex; gap: 0.25rem; }
.blog-carousel__nav[hidden] { display: none; }
/* Boutons à contour : deux chevrons filiformes sans fond ni contour ne se
   lisaient pas comme des commandes, alors que le carrousel d'images du bas de
   page a des flèches pleines de 52px. Cible tactile portée de 40 à 44px. */
.blog-carousel__arrow {
	display: grid; place-items: center;
	width: 2.75rem; height: 2.75rem;
	background: transparent; border: 1px solid var(--ra-primaire);
	padding: 0; cursor: pointer;
	color: var(--ra-primaire);
	transition: background-color var(--ra-transition), color var(--ra-transition), border-color var(--ra-transition);
}
.blog-carousel__arrow svg { width: 1.4rem; height: 1.4rem; }
.blog-carousel__arrow:hover:not(:disabled) { background: var(--ra-primaire); color: var(--ra-clair); }
/* Désactivé : atténué en vert-de-gris plutôt qu'en opacité (0.3 tombait à 1,54
   de contraste, la flèche disparaissait). Le bouton reste lisible comme
   présent-mais-indisponible au lieu de s'effacer. */
.blog-carousel__arrow:disabled { color: var(--ra-vertparis); border-color: var(--ra-vertparis); cursor: default; }

/* Puces rapprochées des cartes : ce sont les commandes du carrousel, pas un
   élément autonome. Elles étaient à équidistance des cartes (36px) et du lien
   « Voir tous les articles » (35px), donc rattachées visuellement à ni l'un ni
   l'autre. */
/* `margin-top` ramené de 1.25 à 0.75rem : le bouton fait maintenant 24px de haut
   pour un point de 9px centré dedans, soit 7,5px de marge interne au-dessus.
   0.75rem + 7,5px replace le point visible à 19,5px des cartes — l'écart de 20px
   décidé plus haut est conservé au demi-pixel près. */
.blog-carousel__dots { display: flex; justify-content: center; gap: 0; margin-top: 0.75rem; }
.blog-carousel__dots[hidden] { display: none; }
/* ⚠️ ZONE TACTILE DE 24px, POINT VISIBLE DE 9px. Mesuré avant correctif : le
   bouton faisait 9×9px avec 18px entre deux centres — sous le minimum de WCAG
   2.2 AA (2.5.8), et l'exception d'espacement ne rattrapait pas non plus
   (elle demande 24px entre les centres, il y en avait 18).
   Le point reste petit : c'est le BOUTON qui grandit, en transparent autour de
   lui. Le dessin ne bouge pas d'un pixel, seule la surface touchable change.
   ⚠️ Le `gap` du conteneur passe donc à 0 : les zones de 24px se touchent déjà
   bord à bord, l'écart entre les points visibles vient de leur marge interne. */
.blog-carousel__dot {
	width: 1.5rem; height: 1.5rem;
	display: grid; place-content: center;
	background: none; border: 0; padding: 0; cursor: pointer;
}
.blog-carousel__dot::before {
	content: ""; display: block;
	width: 0.55rem; height: 0.55rem; border-radius: 50%;
	background: var(--ra-vertparis); opacity: 0.4;
	transition: opacity var(--ra-transition), background-color var(--ra-transition);
}
.blog-carousel__dot:hover::before { opacity: 0.7; }
.blog-carousel__dot.is-active::before { opacity: 1; background: var(--ra-primaire); }

/* Détaché des puces : « Voir tous les articles » n'est pas une commande du
   carrousel, c'est l'action qui fait quitter l'accueil. */
.home-blog__foot { margin-top: 3rem; text-align: center; }
.home-blog__foot .alink { font-family: var(--ra-font-heading); font-size: var(--ra-fs-catmenu); }
.blog-pagination { margin-top: 4rem; display: flex; gap: 0.75rem; justify-content: center; font-family: var(--ra-font-heading); }
.blog-pagination .page-numbers { padding: 0.4rem 0.8rem; border: 1px solid var(--ra-vertparis); }
.blog-pagination .current { background-color: var(--ra-primaire); color: var(--ra-clair); border-color: var(--ra-primaire); }

/* ==========================================================================
   Contact
   ========================================================================== */
/* La photo remplit sa colonne au lieu de s'arrêter à sa hauteur naturelle :
   elle mesurait 876px face à 1200px de formulaire, laissant 324px de blanc en
   bas de page, à gauche du bouton d'envoi. `cover` recadre latéralement (le
   sujet est centré), la hauteur suit celle du formulaire. */
.contact-photo { width: 100%; height: 100%; object-fit: cover; }
.contact-intro { margin-bottom: 1rem; }
.contact-requis { font-size: var(--ra-fs-lecture); color: var(--ra-text-muted); margin-bottom: 1.5rem; }

/* ==========================================================================
   Formulaire Formidable — habillage à la charte

   Formidable expose sa mise en forme sous forme de variables CSS déclarées sur
   `.with_frm_style`, et ses propres règles les consomment. On reprend donc la
   main PAR LES VARIABLES plutôt qu'en réécrivant les règles : c'est le point
   d'extension prévu, et ça évite une surenchère de spécificité (les règles du
   plugin sont préfixées `.frm_style_style-formidable.with_frm_style`, plus
   spécifiques que tout ce qu'on écrirait raisonnablement ici).
   ========================================================================== */
.contact-form-wrap .frm_forms.with_frm_style {
	max-width: none;

	/* Champs : anguleux, filet vert-de-gris, à l'échelle du texte autour.
	   Les tailles consomment `--ra-fs-courant` (voix de lecture, 22px) au lieu
	   d'un nombre à elles : le formulaire est le point de conversion de la page,
	   il n'a aucune raison d'être le plus petit texte du site. Il tournait à
	   16,8px juste sous une intro à 22px — 24 % d'écart, sans intention. */
	--field-font-size: var(--ra-fs-courant);
	--field-height: auto;
	--field-pad: 0.6rem 0.8rem;
	--field-margin: 1.5rem;
	--border-radius: 0;
	--border-color: var(--ra-vertparis);
	--border-color-active: var(--ra-primaire);
	--bg-color: var(--ra-clair);
	--bg-color-active: var(--ra-clair);
	--text-color: var(--ra-text);

	/* Libellés & choix */
	--font-size: var(--ra-fs-courant);
	--label-color: var(--ra-primaire);
	/* Encre et non or : #99876c sur blanc plafonne à 3,48:1, sous le seuil AA
	   pour du texte de cette taille. Même arbitrage que pour `:focus-visible`. */
	--required-color: var(--ra-primaire);
	--check-font-size: var(--ra-fs-courant);
	--check-label-color: var(--ra-text);

	/* Bouton d'envoi : encre pleine, anguleux, inversé au survol (comme .btn).
	   Seuls le survol et l'état actif lisent ces variables — l'état AU REPOS est
	   codé en dur par Formidable et se reprend plus bas. */
	--submit-font-size: var(--ra-fs-courant);
	--submit-weight: 700;
	--submit-bg-color: var(--ra-primaire);
	--submit-border-color: var(--ra-primaire);
	--submit-text-color: var(--ra-clair);
	--submit-padding: 0.7em 1.8em;
	--submit-hover-bg-color: transparent;
	--submit-hover-color: var(--ra-primaire);
	--submit-hover-border-color: var(--ra-primaire);
	--submit-active-bg-color: var(--ra-primaire);
	--submit-active-color: var(--ra-clair);
	--submit-active-border-color: var(--ra-primaire);
}
/* Ce que les variables ne couvrent pas : les familles de polices. */
.contact-form-wrap .frm_primary_label { font-family: var(--ra-font-heading); font-weight: 400; }
.contact-form-wrap input,
.contact-form-wrap textarea,
.contact-form-wrap select,
.contact-form-wrap .frm_radio label,
.contact-form-wrap .frm_checkbox label { font-family: var(--ra-font-body); }
/* Marque du champ obligatoire. Six champs sur sept le sont, et rien ne le
   montrait : Formidable pose bien `aria-required` (le lecteur d'écran l'annonce)
   mais laisse le `<span class="frm_required">` VIDE tant qu'aucun indicateur
   n'est réglé dans son style — un visiteur voyant ne découvrait la contrainte
   qu'après avoir envoyé. On remplit ce span plutôt que d'ajouter une marque à
   côté : `:empty` fait que la règle se retire d'elle-même si l'indicateur est
   renseigné un jour côté plugin, sans jamais doubler l'astérisque.
   ⚠️ Le `.frm_required_field` du parent n'est pas décoratif : Formidable pose le
   span vide sur TOUS les champs, y compris facultatifs — sans lui, « Téléphone »
   se retrouve marqué obligatoire à tort. */
.contact-form-wrap .frm_required_field .frm_required:empty::after { content: "\00a0*"; font-weight: 700; }
/* Cible tactile des choix : 29px de haut, soit le strict minimum. Le label
   couvre déjà toute la largeur ; il ne lui manquait que de la hauteur. */
.contact-form-wrap .frm_radio label,
.contact-form-wrap .frm_checkbox label { padding-block: 0.4rem; align-items: center; }

/* Focus clavier. Formidable neutralise le contour du site — son `outline:none`
   sur les champs pèse (0,2,1) contre (0,1,0) pour la règle `:focus-visible`
   globale — et le remplace par un halo bleu #4199FD codé en dur : couleur
   étrangère à la charte, et trop diffuse (5px de flou, aucune propagation) pour
   situer le clavier. Le formulaire était donc le seul composant du site sans
   focus visible.
   Deux règles distinctes, parce que les états ne se recouvrent pas : le halo
   part sur `:focus` (un clic souris sur une case ne déclenche pas
   `:focus-visible`, le bleu resterait), le contour n'apparaît qu'au clavier.
   `!important` uniquement là où le plugin en pose un lui-même, sur les cases. */
.contact-form-wrap .frm_forms.with_frm_style :is(input, select, textarea):focus { box-shadow: none !important; }
.contact-form-wrap .frm_forms.with_frm_style :is(input, select, textarea):focus-visible {
	outline: 3px solid var(--ra-primaire);
	outline-offset: 3px;
}
/* Bouton au repos : la seule règle où il faut battre Formidable en spécificité.
   Sa règle de base code les valeurs EN DUR (#4199FD, radius 8px, 14px, ombre)
   au lieu de lire ses propres variables, sous un sélecteur à 3 classes — d'où
   les 4 classes ici. Le survol et l'état actif, eux, lisent bien les variables. */
.contact-form-wrap .frm_forms.with_frm_style .frm_submit button {
	font-family: var(--ra-font-heading); letter-spacing: 0.02em;
	font-size: var(--submit-font-size); font-weight: var(--submit-weight);
	background: var(--submit-bg-color); color: var(--submit-text-color);
	border: 1px solid var(--submit-border-color); border-radius: 0;
	padding: var(--submit-padding); margin-inline: 0;
	box-shadow: none; cursor: pointer;
	transition: background-color var(--ra-transition), color var(--ra-transition);
}
.contact-form-wrap .frm_message { background: var(--ra-vertparis-20); border-left: 4px solid var(--ra-vertparis); padding: 1rem; font-family: var(--ra-font-heading); }

/* Espacement des paragraphes de bio sur l'accueil */
.stack-bio > * + * { margin-top: 1.25rem; }
/* Pas de max-width sur ce bloc : le texte occupe toute sa colonne (600px).
   ⚠️ La contraindre relance la césure du justifié, et pas linéairement — mesuré
   19 % de lignes coupées à 600px, 22 % à 595 et 590, 37 % à 580, 41 % à 560,
   28 % à 540. À 46 caractères par ligne, ce paragraphe est déjà bien en dessous
   de la mesure de confort : tout pixel retiré se paie en mots coupés. */
/* Chapô de la présentation : le premier paragraphe passe à 36px pour se
   détacher du corps à 30px. Ciblé par sa POSITION et non par une classe —
   le contenu vient d'un WYSIWYG ACF, l'éditrice n'a donc rien à baliser.
   Mesuré : 36px ne coûte pas une césure de plus que 34px (50 caractères par
   ligne dans les deux cas), autant prendre l'écart le plus lisible. */
.stack-bio > p:first-child { font-size: var(--ra-fs-lead); line-height: max(1.16em, 2.05rem); }
/* Interlignage resserré : à 30px, l'interligne général de 1.4 (hérité de la
   règle `p`) laissait trop d'air entre les lignes d'un même paragraphe et
   diluait les blocs. Le chapô descend un cran plus bas encore : plus le corps
   est gros, moins il a besoin d'interligne.
   Plancher : en dessous de ~1.15, les capitales accentuées (É, À) commencent à
   toucher la ligne du dessus — vérifié, on est juste au-dessus. */
/* ⚠️⚠️ D'OÙ LE `max()` : LE RAISONNEMENT CI-DESSUS EST JUSTE, ET C'EST LUI QUI
   INTERDIT UN RATIO FIXE. « Plus le corps est gros, moins il a besoin
   d'interligne » implique l'inverse quand le corps rétrécit — or le `clamp` de
   la taille descend le texte à 20px en mobile, où 1,2 donnait **20/24px**.
   Mesuré à 390px avant correctif : c'était le SEUL texte courant du site sous
   ×1,5 (domaine, FAQ, article et mentions sont tous à ×1,60, le bandeau de
   contact à ×1,70), et le bloc long au plus fort taux de césure (12 % contre
   10 et 7 %). Trois mots coupés sur un seul écran.
   La borne est une LONGUEUR, pas un ratio : elle ne mord qu'en dessous de 26px
   de corps (et 28px pour le chapô), donc le desktop garde exactement ses
   36px/1,16 et 30px/1,2 — vérifié après coup, aucun pixel bougé au-delà de
   1024px. Même mécanisme que le bloc « En résumé » du 2026-08-10, et pour la
   même raison : une media query aurait posé une frontière là où le texte, lui,
   varie continûment. */
.stack-bio p { line-height: max(1.2em, 1.95rem); }
/* Écart portrait / texte de présentation : 80px, portés par la seule gouttière
   de la grille. Auparavant l'écart cumulait le gap de .grid-2 (64px) et le
   padding de .pl-lg (48px), soit 112px répartis sur deux règles partagées avec
   le contact, le footer et les blocs domaine — d'où cette classe dédiée. */
@media (min-width: 1024px) { .bio-grid { column-gap: 5rem; } }

/* ==========================================================================
   Carrousel d'images (bande horizontale, bas d'accueil)
   ========================================================================== */
.carousel-strip {
	position: relative;
	overflow: hidden;                 /* la piste défile à l'intérieur, pas la page */
	margin-top: 6rem;
}
@media (min-width: 1024px) { .carousel-strip { margin-top: 12rem; } }
.carousel-strip__track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;            /* Firefox : masquer la barre */
}
.carousel-strip__track::-webkit-scrollbar { display: none; } /* WebKit : masquer la barre */
.carousel-strip__img {
	height: 340px;
	width: auto;
	flex: none;
	object-fit: cover;
	display: block;
	scroll-snap-align: start;
}

/* Flèches en overlay (défilement manuel, aucun auto) */
.carousel-strip__arrow {
	position: absolute; top: 50%; transform: translateY(-50%);
	z-index: 2;
	display: grid; place-items: center;
	width: 3.25rem; height: 3.25rem;
	background: rgba(2, 6, 23, 0.7); color: var(--ra-clair);
	border: 0; cursor: pointer;
	box-shadow: 0 2px 12px rgba(2, 6, 23, 0.35);
	transition: background-color var(--ra-transition), opacity var(--ra-transition);
}
.carousel-strip__arrow:hover:not(:disabled) { background: var(--ra-primaire); }
.carousel-strip__arrow:disabled { opacity: 0; pointer-events: none; } /* masquée en bord de piste */
.carousel-strip__arrow svg { width: 1.5rem; height: 1.5rem; }
.carousel-strip__arrow--prev { left: 1rem; }
.carousel-strip__arrow--next { right: 1rem; }

/* ==========================================================================
   Page introuvable (404)
   Zéro composant neuf : héros et wordmark viennent de l'accueil, l'en-tête
   collant et le pied de page portent toute la navigation. Ne reste qu'une
   mesure de lecture sur l'unique paragraphe — sans elle il traverse les
   1 329px du conteneur, soit près de 90 caractères par ligne à 30px.
   (Le menu des domaines et la liste des recours ont été retirés le 2026-08-10 :
   comptés dans le HTML rendu, Contact y figurait déjà 4 fois, le blog 3,
   l'accueil 3 et chaque domaine 2. Ils ne servaient qu'à répéter.)
   ========================================================================== */
.introuvable__texte { max-width: 34rem; }

/* ==========================================================================
   APPARITION AU DÉFILEMENT — les pages domaine font ~13 000px.
   ⚠️ EN CSS PUR, et c'est ce qui rend le procédé acceptable : sans
   `animation-timeline` la règle est ignorée et **rien n'est masqué**. Un reveal
   en JS cache d'abord et révèle ensuite ; script en échec = page blanche.
   ⚠️ `animation-range` en PIXELS : un pourcentage se calcule sur la hauteur de
   l'élément, un bloc de 5 000px mettrait 5 000px à apparaître.
   ⚠️ Les blocs visibles au chargement ne sont PAS masqués — leur timeline est
   au-delà de sa fin et `both` retient l'état final.
   ⚠️ Sous `prefers-reduced-motion: no-preference` : une timeline de défilement
   ignore `animation-duration`, la neutralisation globale ne suffirait pas.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
	@supports (animation-timeline: view()) {
		.blog-card,
		.cartes .carte,
		.corps-cas,
		.faq-item,
		.cta-contact,
		.grid-2.domaine,
		.honneurs li {
			animation: ra-apparition linear both;
			animation-timeline: view();
			/* ⚠️⚠️ CE CALAGE A DÛ ÊTRE REFAIT : le premier (`entry 0% entry 240px`)
			   fonctionnait parfaitement et NE SE VOYAIT PAS. Mesuré, le bloc
			   atteignait l'opacité 1 alors que son sommet était encore à **70 %
			   de la hauteur d'écran** — tout se jouait dans la bande basse, là où
			   l'œil ne lit pas. Le geste existait sans être perçu.
			   Avec `100px → 560px`, le bloc finit d'apparaître quand son sommet
			   est à **28 % de la hauteur d'écran**, c'est-à-dire dans la zone de
			   lecture. Essais mesurés (hauteur du sommet à l'opacité 1) :
			   0→240px = 70 % · **100→560px = 28 %** · 150→700px = 13 % ·
			   0→entry 100% = 6 % (le bloc n'est net qu'arrivé en haut).
			   💡 Une animation au défilement ne se règle pas sur sa durée mais
			   sur L'ENDROIT DE L'ÉCRAN où elle se termine. */
			animation-range: entry 100px entry 560px;
		}
	}
}
/* 2rem de course et non 1,25 : à 20px le mouvement se confondait avec le
   défilement lui-même. */
@keyframes ra-apparition {
	from { opacity: 0; transform: translateY(2rem); }
}

/* ==========================================================================
   Pied de page (fond vert-de-gris 20 %)
   ========================================================================== */
.site-footer { background-color: var(--ra-vertparis-20); font-size: 1.125rem; }
.site-footer__inner { padding-block: 4rem; }
/* Signature du footer : elle était figée à 16px par un style inline, soit la
   moitié de celle de l'en-tête. Elle suit désormais la règle du thème, et le
   padding haut de .wordmark (prévu pour coller les boutons en haut de page)
   n'a pas lieu d'être ici. */
/* ⚠️ CIBLE TACTILE — mesuré à 105×16px, la plus petite du site (celui de
   l'en-tête atteint 34px grâce à son `padding-top`, qui est retiré ici). Le
   rembourrage l'amène à 44px et les marges négatives le RENDENT à la mise en
   page : le logotype ne bouge pas d'un pixel, seule la surface cliquable
   grandit. La marge basse absorbe la moitié du rembourrage (1,5rem − 0,875rem)
   pour que l'écart visuel avec les coordonnées reste celui d'avant.
   ⚠️ `inline-block` est conservé : les marges verticales comptent sur un
   inline-block, ce qui est précisément ce qui permet de compenser. Sur un `<a>`
   resté en ligne, elles seraient ignorées et le rembourrage seul aurait suffi. */
/* `padding-block` remplace au passage le `padding-top: 2rem` de `.wordmark`,
   prévu pour coller les boutons en haut de page et sans objet ici. */
.site-footer .wordmark {
	padding-block: 0.875rem;
	margin-top: -0.875rem;
	margin-bottom: 0.625rem;
}
/* Menu du footer ramené à la taille du texte qui l'entoure. Il partageait
   --ra-fs-catmenu avec le menu du héros, calé à 26px sur la hauteur du H1 de
   l'accueil : une valeur qui n'a aucun sens ici, où le reste est à 18px. Les
   capitales suffisent à le distinguer des coordonnées. */
.site-footer .cat-menu {
	font-size: 1.125rem; line-height: 2.2;
	/* Le trait revient AU REPOS ici, contrairement au héros : ce menu partage sa
	   bande avec les coordonnées, qui sont soulignées (`.alink`). Nu, il se
	   lisait comme une liste d'étiquettes en face d'une colonne de liens. La
	   correction du jour tient quand même — le survol passe au vert foncé sans
	   épaissir, l'épaisseur reste l'exclusivité de la page courante. */
	--ra-menu-trait: var(--ra-vertparis);
}
/* Interligne 2.2 des deux côtés du footer, sans gouttière de ligne : c'est ce
   qui donne aux coordonnées et au menu le MÊME pas vertical (39,6px). Avec un
   interligne de 25,2px plus 16px de gouttière à gauche contre 36px à droite,
   les deux colonnes dérivaient de 5,2px par ligne. */
.site-footer dl { margin: 0; font-family: var(--ra-font-heading); line-height: 2.2; }
.site-footer dl > div { padding: 0.5rem 0; }
/* Le libellé occupe la largeur de son texte, pas un tiers de la colonne : avec
   `repeat(3, 1fr)` il se voyait attribuer 203px pour « Fax », d'où 150 à 177px
   de vide avant la valeur.
   UNE SEULE grille portée par le <dl>, pas une par ligne : les lignes passent en
   `display: contents` pour que leurs <dt>/<dd> deviennent les items de cette
   grille commune. Sans ça, chaque ligne dimensionne son libellé isolément et les
   valeurs cessent d'être alignées entre elles (« Fax » 25px vs « Adresse » 55px). */
@media (min-width: 640px) {
	.site-footer dl { display: grid; grid-template-columns: auto 1fr; column-gap: 1.5rem; row-gap: 0; }
	.site-footer dl > div { display: contents; }
}
.site-footer dt { font-style: italic; margin: 0; }
.site-footer dd { margin: 0; }
/* Ligne légale. Son rembourrage propre (24px) ne correspondait pas à celui du
   conteneur du footer (48px) : le lien débordait de 24px vers la droite, au-delà
   du bord du menu. Il reprend donc le même rembourrage que .megabloc, et passe
   de 14 à 16px — 14 était deux fois plus petit que tout le reste du footer. */
.site-footer .mentions {
	max-width: var(--ra-container); margin-inline: auto; text-align: right;
	font-size: 1rem; padding-inline: 1.5rem; padding-bottom: 1.5rem;
}
@media (min-width: 640px)  { .site-footer .mentions { padding-inline: 2rem; } }
@media (min-width: 1024px) { .site-footer .mentions { padding-inline: 3rem; } }
