@import url('../fonts/fonts.css');

/* =========================================================================
   Cynthia Bazile — Psychopraticienne & Coach en psychologie positive
   Feuille de style principale
   ========================================================================= */

/* ---------- 1. Variables de charte ---------- */
:root {
  /* Couleurs décoratives (fonds, bordures, aplats) */
  --rose:         #c9848c;
  --rose-clair:   #f2d7da;
  --rose-pale:    #faecee;
  --sauge:        #8b9b76;
  --sauge-clair:  #e4e8dc;
  --creme:        #fdf8f4;
  --creme-fonce:  #f7efe8;
  --blanc:        #ffffff;

  /* Couleurs de texte et d'action — contrastes vérifiés WCAG AA */
  /* ⚠️ Le seuil à tenir n'est PAS le blanc. Cette couleur sert aussi de
     texte sur --rose-pale (#faecee), fond des cartes et des étiquettes.
     L'ancienne valeur #a8535f donnait 5,16:1 sur blanc — d'où l'ancien
     commentaire, exact mais hors sujet — et 4,4985:1 sur le rose pâle,
     donc SOUS le seuil AA de 4,5, de 15 dix-millièmes. Mesuré dans un
     navigateur sur le fond réellement peint : 10 éléments en échec, dont
     les 8 étiquettes de thème de articles.html. Lighthouse n'en voyait
     qu'un seul, et seulement sur les pages qu'on pensait à lui donner.
     La valeur ci-dessous tient 4,76:1 sur le rose pâle et 5,46:1 sur blanc.
     Elle sert aussi de FOND sous du texte blanc (.bouton-rose, .filtre
     pressé) : l'assombrir y augmente le contraste, jamais l'inverse. */
  --rose-fort:    #a44f5b;   /* 4,76:1 sur --rose-pale ; 5,46:1 sur blanc */
  --rose-sombre:  #8f4551;   /* survol */
  --sauge-fort:   #647454;   /* 5,0:1 sur blanc */
  --sauge-sombre: #53603f;   /* survol */
  --texte:        #3a3330;
  --texte-doux:   #6b615c;

  /* Typographie */
  --titre:  'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --corps:  'Lato', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --plume:  'Sacramento', 'Segoe Script', cursive;

  /* Rythme */
  --contenu: 1180px;
  --etroit: 760px;
  --r-carte: 18px;
  --r-douce: 12px;
  --ombre: 0 2px 18px rgba(90, 66, 60, .07);
  --ombre-forte: 0 6px 28px rgba(90, 66, 60, .12);
  --transition: 180ms ease;

  --coeur-masque: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 21s-8-5.2-8-10.4A4.6 4.6 0 0 1 12 7a4.6 4.6 0 0 1 8 3.6C20 15.8 12 21 12 21z'/%3E%3C/svg%3E");
}

/* ---------- 2. Base ---------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 110px;
  /* Le panneau du menu mobile est replié hors écran par une translation :
     sans cette ligne il étire la page et provoque un défilement latéral.
     « clip » plutôt que « hidden » : hidden créerait un contexte de
     défilement qui désactiverait l'en-tête collant. */
  overflow-x: clip;
}

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

body {
  margin: 0;
  background: var(--creme);
  color: var(--texte);
  font-family: var(--corps);
  font-size: 1.0625rem;
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

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

/* Indispensable : sans cette règle, tout élément portant une classe
   display:grid ou display:flex reste visible malgré l'attribut hidden.
   C'est ce qui laissait s'afficher les témoignages non confirmés et les
   icônes de réseaux sociaux non renseignées. */
[hidden] { display: none !important; }

a { color: var(--rose-fort); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--rose-sombre); }

:focus-visible {
  outline: 3px solid var(--rose-fort);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Lien d'évitement pour la navigation au clavier */
.saut-contenu {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--rose-fort);
  color: #fff;
  padding: .75rem 1.25rem;
  z-index: 200;
  border-radius: 0 0 var(--r-douce) 0;
}
.saut-contenu:focus { left: 0; color: #fff; }

.visuellement-cache {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

/* ---------- 3. Typographie ---------- */
h1, h2, h3, h4 {
  font-family: var(--titre);
  font-weight: 500;
  line-height: 1.2;
  color: var(--texte);
  margin: 0 0 .6em;
  letter-spacing: .005em;
}

h1 { font-size: clamp(2.1rem, 5.2vw, 3.4rem); }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.5rem); }
h3 { font-size: clamp(1.25rem, 2.2vw, 1.55rem); }
h4 { font-size: 1.1rem; font-family: var(--corps); font-weight: 700; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

/* ══════════════════════════════════════════════════════════════════════════
   L'ÉCRITURE MANUSCRITE SE DIMENSIONNE PAR SA HAUTEUR D'X, PAS PAR SA TAILLE
   DE POLICE — et c'est une MESURE, faite le 2026-09-14 dans un navigateur
   contre la production, pas une appréciation.

   Sacramento n'occupe que 32-33 % de son cadre en hauteur d'x, là où Lato en
   occupe 53 %. Une déclaration en « rem » ment donc sur ce qu'on lit :

     .plume à 1,7 rem = 27,2 px  →  hauteur d'x  9 px  = celle du CORPS (17 px)
     .pied h3 à 1,55 rem = 24,8 px → hauteur d'x 8 px  = PLUS PETIT que les
                                                          liens de 17 px qu'il
                                                          est censé coiffer.

   ⚠️⚠️ CE N'EST NI UN PROBLÈME DE CONTRASTE NI D'ÉPAISSEUR, et je m'étais
   trompé avant de mesurer. À hauteur d'x ÉGALE, Sacramento dépose 94 % de
   l'encre de Lato 400 : les traits ne sont pas plus fins. Assombrir la couleur
   (déjà 5,46:1, conforme AA) n'aurait rien changé. Le texte était simplement
   trop PETIT, sous des nombres qui paraissaient grands.

   Facteur de compensation mesuré : 53/33 ≈ 1,6. Les valeurs ci-dessous visent
   une hauteur d'x de 12 à 14 px sur grand écran (corps : 9 px) et ne descendent
   jamais sous 10 px en dessous.

   ⚠️ `clamp()` et non une valeur fixe : c'est déjà l'idiome de cette feuille
   (h1, h2, h3) ; les neuf surcharges `style={{ fontSize }}` qu'elles
   remplacent étaient figées, donc seules à ne pas suivre la largeur.

   ⚠️ LE PLANCHER SE VÉRIFIE À 360 px, PAS SEULEMENT LE PLAFOND. Première
   version : `.sur-titre` en `clamp(1.8rem, …)` — sur mobile elle RAPETISSAIT
   (hauteur d'x 10 → 9 px), la correction faisait une régression. Mesurée,
   corrigée à 1,95 rem.
   ══════════════════════════════════════════════════════════════════════════ */
.plume {
  font-family: var(--plume);
  font-weight: 400;
  color: var(--rose-fort);
  /* ⚠️ LE PLAFOND EST À 2,1 rem, ET C'EST LA LONGUEUR DES PHRASES QUI L'A FIXÉ.

     Premier réglage : 2,4 rem. Lisible, mais le bloc de /a-propos
     (« Mon approche repose sur une conviction simple : … », un seul <p> avec
     deux <br />) occupait alors 336 px de haut sur 5 lignes — un pavé qui
     coupait la page en deux. Remarque de l'utilisateur, vérifiée à la mesure.

     La cause n'est pas l'interligne mais le REPLI : à 2,4 rem, « Mon approche
     repose sur une conviction simple : » fait 583 px dans une colonne de
     562 px, et retombe sur une deuxième ligne pour deux mots. À 2,1 rem elle
     tient (510 px) : le bloc passe à 4 lignes et 215 px, −36 %.

     ⚠️ NE PAS CHERCHER À SUPPRIMER TOUS LES REPLIS : la troisième phrase fait
     822 px à 2,4 rem et 719 px à 2,1 rem — elle ne tiendra sur une ligne à
     aucune taille lisible. Ce qu'on corrige est l'orpheline de la première,
     pas le principe du repli.

     Hauteur d'x à 2,1 rem : 11 px, contre 9 px pour le corps. La lisibilité
     gagnée est conservée. */
  font-size: clamp(1.9rem, 3.1vw, 2.1rem);
  /* ⚠️ 1,6 ET PAS 1,35 — MESURÉ, ET 1,35 ÉTAIT IMPOSSIBLE.

     L'encre de Sacramento (ascendantes + descendantes) mesure 1,46 fois sa
     taille de police. Un interligne de 1,35 donnait donc une boîte de ligne
     PLUS COURTE QUE L'ENCRE QU'ELLE CONTIENT : à 38,4 px, boîte 51,8 px pour
     56 px d'encre, soit −4,2 px. Les lignes successives se chevauchaient
     physiquement — les boucles d'une ligne dans les jambages de la suivante.

     Le défaut PRÉEXISTAIT (−3 px à l'ancienne taille) et l'agrandissement l'a
     aggravé : c'est en le regardant sur capture que je l'ai vu, après que les
     chiffres de hauteur d'x l'aient laissé passer.

     1,6 → +4,8 px de respiration à 33,6 px. Positif, donc sans collision.
     J'avais d'abord posé 1,75 (+11,2 px) : confortable, mais cumulé au repli
     décrit ci-dessus il donnait le pavé de 336 px. 1,6 tient les deux bouts.

     ⚠️ Toute modification de `font-size` ici doit revérifier CETTE ligne : les
     deux sont liées par le rapport encre/taille, qui ne dépend que de la
     police. Le plancher absolu est 1,46 ; en dessous, les lignes se touchent. */
  line-height: 1.6;
  display: inline-block;
}
/* L'accroche de l'accueil, seule à devoir tenir tête au titre principal. Les
   autres écarts d'origine (1,7 / 1,8 / 1,9 rem) valaient 6 % les uns des
   autres — invisibles : ils ne méritaient pas cinq valeurs. */
.plume-grand { font-size: clamp(2.1rem, 4.4vw, 2.85rem); }
.plume-sauge { color: var(--sauge-fort); }

.accent { color: var(--rose-fort); }
.doux { color: var(--texte-doux); }
.petit { font-size: .95rem; }
.centre { text-align: center; }
.gras { font-weight: 700; }

.sur-titre {
  font-family: var(--plume);
  /* Plancher à 1,95 rem : à 1,8 rem elle rapetissait sur mobile. Voir le bloc
     de .plume — la hauteur d'x est ce qui se lit. */
  font-size: clamp(1.95rem, 3vw, 2.3rem);
  color: var(--rose-fort);
  display: block;
  margin-bottom: -.2rem;
}

/* Séparateur au petit cœur, repris des maquettes */
.separateur {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: .8rem;
  margin: 1.1rem 0 1.6rem;
  color: var(--rose);
}
.separateur::before, .separateur::after {
  content: '';
  height: 1px;
  width: clamp(40px, 12vw, 110px);
  background: linear-gradient(90deg, transparent, var(--rose-clair), transparent);
}
.separateur svg { width: 17px; height: 17px; flex: none; }
.separateur--gauche { justify-content: flex-start; }
.separateur--gauche::before { display: none; }

/* ---------- 4. Mise en page ---------- */
.contenu {
  width: min(100% - 2.5rem, var(--contenu));
  margin-inline: auto;
}
.contenu-etroit { width: min(100% - 2.5rem, var(--etroit)); margin-inline: auto; }

section { padding: clamp(3rem, 7vw, 5.5rem) 0; }
section.serre { padding: clamp(2rem, 4vw, 3rem) 0; }

.fond-creme  { background: var(--creme-fonce); }
.fond-rose   { background: var(--rose-pale); }
.fond-sauge  { background: var(--sauge-clair); }
.fond-blanc  { background: var(--blanc); }

.grille { display: grid; gap: 1.5rem; }
/* Deux colonnes franches : avec auto-fit, un conteneur large en produisait
   trois et déséquilibrait les sections de quatre ou cinq cartes. */
.grille-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grille-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grille-4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

.entete-section { text-align: center; margin-bottom: 2.5rem; }
.entete-section p { max-width: 62ch; margin-inline: auto; color: var(--texte-doux); }

/* ---------- 5. Boutons ---------- */
.bouton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .55rem;
  padding: .85rem 1.6rem;
  min-height: 48px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  font-family: var(--corps);
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--transition), color var(--transition),
              border-color var(--transition), transform var(--transition);
}
.bouton:hover { transform: translateY(-1px); }
.bouton svg { width: 18px; height: 18px; flex: none; }

/* Un bouton inactif doit se voir. Tant que la clé Web3Forms manque, le bouton
   d'envoi du formulaire est désactivé : il gardait pourtant le rose plein,
   l'opacité 1 et le curseur « main » d'un bouton actif. Le visiteur remplissait
   tout le formulaire, cliquait, et rien ne se passait — sans explication au
   moment du clic (l'avis jaune est 600 px plus haut). */
.bouton:disabled,
.bouton[aria-disabled="true"] {
  opacity: .55;
  cursor: not-allowed;
  filter: grayscale(.35);
}
.bouton:disabled:hover,
.bouton[aria-disabled="true"]:hover { transform: none; }

.bouton-rose { background: var(--rose-fort); color: #fff; }
.bouton-rose:hover { background: var(--rose-sombre); color: #fff; }

.bouton-sauge { background: var(--sauge-fort); color: #fff; }
.bouton-sauge:hover { background: var(--sauge-sombre); color: #fff; }

.bouton-contour {
  background: transparent;
  color: var(--rose-fort);
  border-color: var(--rose);
}
.bouton-contour:hover { background: var(--rose-pale); color: var(--rose-sombre); }

.bouton-blanc { background: #fff; color: var(--rose-fort); }
.bouton-blanc:hover { background: var(--creme); color: var(--rose-sombre); }

.boutons { display: flex; flex-wrap: wrap; gap: .9rem; }
.boutons-centre { justify-content: center; }

.lien-fleche {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-weight: 700;
  font-size: .95rem;
  text-decoration: none;
  color: var(--rose-fort);
}
.lien-fleche::after { content: '→'; transition: transform var(--transition); }
.lien-fleche:hover::after { transform: translateX(3px); }

/* ---------- 6. En-tête ---------- */
.entete {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(253, 248, 244, .96);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--creme-fonce);
}
.entete-interieur {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: .7rem 0;
}

.logo { display: flex; align-items: center; gap: .8rem; text-decoration: none; }
.logo-marque { width: 58px; height: 58px; flex: none; }
.logo-texte { display: flex; flex-direction: column; line-height: 1.25; }
.logo-nom {
  font-family: var(--titre);
  font-size: 1.5rem;
  letter-spacing: .09em;
  color: var(--texte);
  text-transform: uppercase;
  font-weight: 500;
}
.logo-role { font-size: .74rem; color: var(--rose-fort); letter-spacing: .01em; }

/* Le chevron « > » est indispensable : sans lui cette règle vise aussi le
   sous-menu, qui hérite alors d'un display:flex plus spécifique que son
   propre display:none et reste ouvert en permanence. */
.nav-principale > ul {
  display: flex;
  align-items: center;
  gap: clamp(.7rem, 1.8vw, 1.7rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-principale a {
  display: block;
  padding: .5rem .2rem;
  font-size: .97rem;
  color: var(--texte);
  text-decoration: none;
  border-bottom: 2px solid transparent;
}
.nav-principale a:hover { color: var(--rose-fort); }
.nav-principale a[aria-current="page"] {
  color: var(--rose-fort);
  border-bottom-color: var(--rose-fort);
}

/* Sous-menu Accompagnements */
.nav-deroulant { position: relative; }
.nav-deroulant > button {
  display: flex;
  align-items: center;
  gap: .35rem;
  padding: .5rem .2rem;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  font-family: var(--corps);
  font-size: .97rem;
  color: var(--texte);
  cursor: pointer;
}
.nav-deroulant > button:hover { color: var(--rose-fort); }
.nav-deroulant > button[aria-expanded="true"] { color: var(--rose-fort); }
.nav-deroulant > button .chevron { transition: transform var(--transition); }
.nav-deroulant > button[aria-expanded="true"] .chevron { transform: rotate(180deg); }

.sous-menu {
  position: absolute;
  top: calc(100% + .5rem);
  left: 50%;
  transform: translateX(-50%);
  min-width: 265px;
  padding: .6rem;
  background: #fff;
  border: 1px solid var(--creme-fonce);
  border-radius: var(--r-carte);
  box-shadow: var(--ombre-forte);
  list-style: none;
  margin: 0;
  display: none;
  flex-direction: column;
  gap: 1px;
}
.sous-menu[data-ouvert="true"] { display: flex; }
.sous-menu a {
  padding: .55rem .8rem;
  border-radius: var(--r-douce);
  border-bottom: 0;
  font-size: .93rem;
}
.sous-menu a:hover { background: var(--rose-pale); }

/* ══════════════════════════════════════════════════════════════════════════
   LES DEUX LIBELLÉS DU BOUTON DE RENDEZ-VOUS DU BANDEAU.

   Le composant `LienRendezVous` écrit les DEUX formes dans le HTML servi
   (« Prendre rendez-vous » et « RDV »), et c'est ici qu'on tranche laquelle
   s'affiche. Aucun JavaScript n'intervient : le HTML est déjà juste pour qui
   ne l'exécute pas.

   ⚠️ LA FORME COURTE EST MASQUÉE PAR DÉFAUT, et c'est le bon sens de la
   règle : un thème, une page ou un futur emplacement qui oublierait la règle
   de bascule afficherait le libellé COMPLET — lisible, simplement trop long.
   L'inverse laisserait un « RDV » énigmatique sur un grand écran. On choisit
   le défaut qui échoue du bon côté.

   ⚠️ `display: none` et non un masquage visuel : la forme courte ne doit pas
   non plus être ANNONCÉE en grand écran, sans quoi le lecteur d'écran lirait
   le libellé deux fois de suite. */
.rdv-libelle-court { display: none; }

.bouton-menu {
  display: none;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  background: none;
  border: 1.5px solid var(--rose);
  border-radius: 50%;
  color: var(--rose-fort);
  cursor: pointer;
}

/* ---------- 7. Bannière (hero) ---------- */
.banniere { position: relative; overflow: hidden; background: var(--creme-fonce); }
.banniere-grille {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  padding: clamp(2.5rem, 6vw, 4.5rem) 0;
}
.banniere h1 { margin-bottom: .3rem; }
.banniere-intro { max-width: 46ch; color: var(--texte-doux); }
.banniere-visuel { position: relative; }
.banniere-visuel .zone-photo { aspect-ratio: 4 / 5; border-radius: 200px 200px var(--r-carte) var(--r-carte); }

/* Médaillon « Chaque petit pas compte » */
.medaillon {
  position: absolute;
  right: -12px;
  bottom: 8%;
  width: 168px;
  height: 168px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .4rem;
  padding: 1.1rem;
  background: rgba(255, 255, 255, .95);
  border: 1px solid var(--rose-clair);
  border-radius: 50%;
  box-shadow: var(--ombre-forte);
  text-align: center;
  font-size: .78rem;
  line-height: 1.45;
  color: var(--texte-doux);
}
.medaillon svg { width: 16px; height: 16px; color: var(--rose); }

/* ---------- 8. Cartes ---------- */
.carte {
  background: #fff;
  border: 1px solid var(--creme-fonce);
  border-radius: var(--r-carte);
  padding: 1.7rem 1.5rem;
  box-shadow: var(--ombre);
}
.carte-creme { background: var(--creme); }
.carte h3 { margin-bottom: .5rem; }

/* La teinte douce est posée sur la carte, pas sur ses paragraphes : en
   ciblant « .carte p » elle l'emportait sur les classes utilitaires et
   affichait les prix en petit gris, les étoiles en gris et les phrases
   manuscrites sans leur couleur. Par héritage, chaque classe reprend
   la main. */
.carte { color: var(--texte-doux); font-size: .97rem; }
.carte h2, .carte h3, .carte h4 { color: var(--texte); }
.carte h2 { font-size: clamp(1.5rem, 2.6vw, 2rem); }

.carte-lien {
  display: flex;
  flex-direction: column;
  transition: transform var(--transition), box-shadow var(--transition);
}
.carte-lien:hover { transform: translateY(-3px); box-shadow: var(--ombre-forte); }
.carte-lien .lien-fleche { margin-top: auto; padding-top: 1rem; }

/* Pastille d'icône ronde */
.pastille {
  display: grid;
  place-items: center;
  width: 66px;
  height: 66px;
  margin-bottom: 1rem;
  border-radius: 50%;
  background: var(--rose-pale);
  color: var(--rose-fort);
}
.pastille svg { width: 30px; height: 30px; }
.pastille-sauge { background: var(--sauge-clair); color: var(--sauge-fort); }
.pastille-centre { margin-inline: auto; }

/* Bandeau des 4 piliers, à cheval sur la bannière */
.piliers {
  position: relative;
  z-index: 2;
  margin-top: -3rem;
  background: #fff;
  border-radius: var(--r-carte);
  box-shadow: var(--ombre-forte);
  padding: 2.2rem 1.5rem;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 1.5rem;
}
.pilier { text-align: center; padding-inline: 1rem; }
.pilier + .pilier { border-left: 1px solid var(--creme-fonce); }
/* h2 et non h3 : ces quatre piliers suivent directement le h1 de la bannière,
   le h3 sautait un niveau de titre (relevé par Lighthouse). L'apparence est
   inchangée, seule la hiérarchie annoncée aux lecteurs d'écran est corrigée. */
.pilier h2 { font-family: var(--corps); font-size: 1rem; font-weight: 700; }
.pilier p { font-size: .9rem; color: var(--texte-doux); margin: 0; }

/* Les quatre piliers sont des LIENS depuis le 12/09/2026. Ils constituent la
   seule accroche courte de l'accueil vers les pages dédiées, après le retrait
   des blocs qui rejouaient ces pages en entier.

   Sans ces règles, `a { color: var(--rose-fort); text-decoration: underline }`
   (section 3) s'appliquerait au titre ET au texte de chaque pilier : les
   quatre cartes deviendraient roses et soulignées. La règle rend donc la
   couleur au texte, et réserve le rose au survol du seul titre — l'indice
   qu'il s'agit d'un lien sans que la carte crie.

   ⚠️ `display: block` est nécessaire : un `a` est en ligne par défaut, et
   `text-align: center` comme `padding-inline` de `.pilier` n'auraient pas
   l'effet attendu sur une boîte en ligne. */
a.pilier {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: var(--r-carte);
  transition: background-color .2s ease;
}
a.pilier:hover { background: var(--creme); }
a.pilier:hover h2 { color: var(--rose-fort); }
/* Le focus clavier doit se voir : ces liens n'ont ni bordure ni fond au repos. */
a.pilier:focus-visible { outline: 3px solid var(--rose-fort); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { a.pilier { transition: none; } }

/* ---------- 9. Listes à cœurs ---------- */
.liste-coeurs { list-style: none; margin: 0 0 1.2rem; padding: 0; }
.liste-coeurs li {
  position: relative;
  padding-left: 1.9rem;
  margin-bottom: .65rem;
}
.liste-coeurs li::before {
  content: '';
  position: absolute;
  left: 0; top: .45em;
  width: 13px; height: 13px;
  background: var(--sauge);
  -webkit-mask: var(--coeur-masque) center / contain no-repeat;
  mask: var(--coeur-masque) center / contain no-repeat;
}
.liste-coeurs-rose li::before { background: var(--rose); }

/* Variante à deux colonnes, posée le 2026-09-12 sur l'accueil : la carte
   « Peut-être vous reconnaissez-vous » occupe toute la largeur depuis le
   retrait de la colonne voisine, et ses quatre questions n'en remplissaient
   qu'un tiers — beaucoup de vide à droite sur grand écran.

   `auto-fit` + `minmax` plutôt qu'une media query : le repli dépend alors de
   la largeur RÉELLE du conteneur et non de celle de la fenêtre — la liste
   reste correcte si elle est un jour placée dans une colonne étroite, ce
   qu'un point de rupture en pixels ne garantit pas.

   ⚠️ Le `max(19rem, 45%)` n'est pas une coquetterie. Avec `minmax(19rem, 1fr)`
   seul, `auto-fit` en a mis TROIS : la carte fait 1130 px de large et chaque
   colonne n'en exigeait que 304. Quatre questions sur trois colonnes, cela
   donne 3 + 1, déséquilibré. `auto-fit` place autant de colonnes qu'il peut,
   il ne s'arrête pas à deux — c'est le plancher à 45 % de la largeur du
   conteneur qui en interdit une troisième, tout en laissant le repli à une
   seule colonne opérer sous ~38rem.

   ⚠️ `margin-bottom` des <li> est remis à zéro. Conservé, il s'ajouterait au
   `gap` de la grille et creuserait un interligne double — c'est la grille qui
   espace, pas les éléments. */
.liste-coeurs--colonnes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(max(19rem, 45%), 1fr));
  gap: .65rem 2.5rem;
}
.liste-coeurs--colonnes li { margin-bottom: 0; }


/* ---------- 10. Parcours (frise) ---------- */
.frise {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 1.5rem;
  position: relative;
}
.frise-etape { text-align: center; position: relative; }
.frise-etape p { font-size: .92rem; color: var(--texte-doux); margin: 0; }
.frise-numero {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  margin: 0 auto .8rem;
  border-radius: 50%;
  background: var(--sauge-fort);
  color: #fff;
  font-weight: 700;
  font-size: .95rem;
}

/* ---------- 11. Tarifs ---------- */
.tarif { position: relative; text-align: center; display: flex; flex-direction: column; }
.tarif-prix {
  font-family: var(--titre);
  font-size: 2.7rem;
  font-weight: 600;
  color: var(--rose-fort);
  line-height: 1.1;
  margin: .4rem 0 .1rem;
}
.tarif-unite { font-size: .9rem; color: var(--texte-doux); margin-bottom: .9rem; }
.tarif-mise-en-avant { border: 2px solid var(--sauge); }
.tarif-etiquette {
  position: absolute;
  top: -14px; left: 50%;
  transform: translateX(-50%);
  padding: .28rem 1rem;
  background: var(--sauge-fort);
  color: #fff;
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 700;
  white-space: nowrap;
}

/* ---------- 12. Témoignages ---------- */
.temoignage { position: relative; padding-top: 2.2rem; }
.temoignage::before {
  content: '\201C';
  position: absolute;
  top: -.35rem; left: 1.2rem;
  font-family: var(--titre);
  font-size: 4.5rem;
  line-height: 1;
  color: var(--rose-clair);
}
.temoignage-etoiles { color: var(--rose); letter-spacing: .15em; margin: .8rem 0 .5rem; }
.temoignage-auteur { font-size: .92rem; color: var(--texte-doux); font-style: italic; }
.temoignage[hidden] { display: none; }

/* ---------- 13. Accordéon (FAQ) ---------- */
.accordeon { border: 1px solid var(--creme-fonce); border-radius: var(--r-carte); background: #fff; overflow: hidden; }
.accordeon + .accordeon { margin-top: .8rem; }
.accordeon-titre { margin: 0; }
.accordeon-bouton {
  display: flex;
  align-items: center;
  gap: .9rem;
  width: 100%;
  padding: 1.1rem 1.3rem;
  min-height: 56px;
  background: none;
  border: 0;
  font-family: var(--corps);
  font-size: 1rem;
  font-weight: 700;
  text-align: left;
  color: var(--texte);
  cursor: pointer;
}
.accordeon-bouton:hover { background: var(--creme); }
.accordeon-bouton .chevron { margin-left: auto; flex: none; transition: transform var(--transition); }
.accordeon-bouton[aria-expanded="true"] .chevron { transform: rotate(180deg); }
.accordeon-bouton .pastille-mini {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: none;
  border-radius: 50%;
  background: var(--rose-pale);
  color: var(--rose-fort);
}
.accordeon-bouton .pastille-mini svg { width: 17px; height: 17px; }
.accordeon-corps { padding: 0 1.3rem 1.3rem 4.2rem; color: var(--texte-doux); }
.accordeon-corps[hidden] { display: none; }

/* ---------- 14. Formulaire ---------- */
.champ { margin-bottom: 1.1rem; }
.champ label {
  display: block;
  margin-bottom: .35rem;
  font-size: .93rem;
  font-weight: 700;
  color: var(--texte);
}
.champ .indication { font-weight: 400; color: var(--texte-doux); }

input[type="text"], input[type="email"], input[type="tel"], select, textarea {
  width: 100%;
  padding: .8rem 1rem;
  min-height: 48px;
  font-family: var(--corps);
  font-size: 1rem;
  color: var(--texte);
  background: #fff;
  border: 1.5px solid var(--rose-clair);
  border-radius: var(--r-douce);
  transition: border-color var(--transition);
}
input:hover, select:hover, textarea:hover { border-color: var(--rose); }
input:focus, select:focus, textarea:focus { border-color: var(--rose-fort); }
textarea { min-height: 140px; resize: vertical; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b615c' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 18px;
  padding-right: 2.8rem;
}

.champ-case { display: flex; align-items: flex-start; gap: .7rem; margin-bottom: 1.3rem; }
.champ-case input { width: 20px; height: 20px; min-height: 0; margin-top: .28rem; flex: none; accent-color: var(--rose-fort); }
.champ-case label { font-weight: 400; font-size: .93rem; color: var(--texte-doux); margin: 0; }

.erreur-champ { display: block; margin-top: .35rem; font-size: .88rem; color: #a3272f; font-weight: 700; }
input[aria-invalid="true"], textarea[aria-invalid="true"], select[aria-invalid="true"] { border-color: #a3272f; }

.message-formulaire {
  padding: 1rem 1.2rem;
  border-radius: var(--r-douce);
  margin-bottom: 1.2rem;
  font-size: .96rem;
}
.message-formulaire[hidden] { display: none; }
.message-succes { background: var(--sauge-clair); border: 1px solid var(--sauge); color: #3d4a2e; }
.message-echec  { background: #fbe9e9; border: 1px solid #d99; color: #8a2129; }

/* Bandeau d'avertissement destiné à la propriétaire du site */
.avis-configuration {
  border: 2px dashed #c08a2e;
  background: #fdf4e2;
  color: #6b4a08;
  border-radius: var(--r-douce);
  padding: 1rem 1.2rem;
  margin-bottom: 1.2rem;
  font-size: .93rem;
}
.avis-configuration strong { display: block; margin-bottom: .25rem; }

/* ---------- 15. Filtres et articles ---------- */
.filtres { display: flex; flex-wrap: wrap; gap: .6rem; margin-bottom: 2.2rem; }
.filtre {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem 1.1rem;
  min-height: 42px;
  background: #fff;
  border: 1.5px solid var(--rose-clair);
  border-radius: 999px;
  font-family: var(--corps);
  font-size: .9rem;
  color: var(--texte);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), border-color var(--transition);
}
.filtre:hover { border-color: var(--rose); }
.filtre[aria-pressed="true"] { background: var(--rose-fort); border-color: var(--rose-fort); color: #fff; }

.etiquette {
  display: inline-block;
  padding: .25rem .8rem;
  background: var(--rose-pale);
  color: var(--rose-fort);
  border-radius: 999px;
  font-size: .78rem;
  font-weight: 700;
}
.etiquette-sauge { background: var(--sauge-clair); color: var(--sauge-fort); }

.article-carte { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.article-carte .zone-photo { aspect-ratio: 16 / 10; border-radius: 0; border: 0; border-bottom: 1px solid var(--rose-clair); }
.article-carte-corps { padding: 1.3rem; display: flex; flex-direction: column; flex: 1; }
.article-carte h3 { font-size: 1.2rem; margin: .7rem 0 .5rem; }
.article-carte[hidden] { display: none; }

.article-mis-en-avant {
  display: grid;
  grid-template-columns: minmax(0, .8fr) minmax(0, 1fr);
  gap: 0;
  background: #fff;
  border: 1px solid var(--creme-fonce);
  border-radius: var(--r-carte);
  overflow: hidden;
  box-shadow: var(--ombre);
}
.article-mis-en-avant .zone-photo { height: 100%; min-height: 280px; border-radius: 0; border: 0; }
.article-mis-en-avant-corps { padding: clamp(1.5rem, 3vw, 2.6rem); }

/* Corps d'un article */
.article-texte { max-width: 68ch; }
.article-texte h2 { margin-top: 2.2rem; }
.article-texte ul { padding-left: 1.3rem; }
/* `ol` est autorisée par lib/assainir.ts depuis le lot 1b (une liste numérotée
   est la mise en forme la plus banale d'un article ; la jeter laissait des
   `li` orphelins et perdait la numérotation). Elle n'avait aucune règle : le
   navigateur lui donnait son retrait par défaut, plus large que celui de `ul`
   juste au-dessus. Une seule ligne les aligne. */
.article-texte ol { padding-left: 1.3rem; }
.article-texte li { margin-bottom: .5rem; }
.article-meta { color: var(--texte-doux); font-size: .92rem; margin-bottom: 1.6rem; }

/* ---------- 16. Emplacements photo ---------- */
.zone-photo {
  position: relative;
  display: grid;
  place-items: center;
  width: 100%;
  background:
    repeating-linear-gradient(45deg, var(--creme-fonce) 0 12px, var(--creme) 12px 24px);
  border: 1px solid var(--rose-clair);
  border-radius: var(--r-carte);
  color: var(--texte-doux);
  overflow: hidden;
}
.zone-photo span {
  padding: .5rem 1rem;
  background: rgba(255, 255, 255, .9);
  border-radius: 999px;
  font-size: .8rem;
  letter-spacing: .02em;
  text-align: center;
}
/* ══════════════════════════════════════════════════════════════════════════
   ⚠️⚠️ `position: absolute` N'EST PAS UN ORNEMENT : SANS LUI, `object-fit` ET
   `object-position` NE FONT RIEN. Mesuré le 2026-09-14 en plaçant les premières
   photographies.

   `.zone-photo` est une grille avec `place-items: center`, ce qui donne à son
   enfant `align-self: center` — l'image se dimensionne alors sur son contenu et
   `height: 100%` ne la contraint plus. Une image de 1024×1536 posée dans un
   cadre 4/3 de 562 px de large était rendue en 562×844 : elle DÉBORDAIT de
   420 px, invisiblement, parce que `.zone-photo` porte `overflow: hidden`.

   Le symptôme est sournois : le cadre a l'air rempli, l'image a l'air recadrée.
   Mais ce n'est pas `object-fit` qui recadre, c'est le débordement masqué — donc
   la partie visible est toujours le MILIEU, et `object-position` est sans effet.
   Impossible de choisir ce que l'image montre.

   ⚠️ Ce défaut ne touchait pas que les bannières : `.article-carte .zone-photo`
   porte le même mécanisme, donc les illustrations que Cynthia attache à ses
   articles débordaient de la même façon.

   `position: absolute; inset: 0` rend l'image exactement de la taille du cadre
   (`.zone-photo` est déjà `position: relative`), et `object-fit: cover` reprend
   son office. */
.zone-photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* ---------- 17. Appel à l'action ---------- */
/* Fond en --rose-fort et non --rose : le rose clair (#c9848c) sous du texte
   blanc ne donnait que 2,93:1, sous les 4,5:1 exigés pour du texte courant
   et même sous les 3:1 des grands titres (mesuré, et confirmé par Lighthouse
   sur les 17 pages). C'est le bloc qui invite à prendre rendez-vous : il doit
   rester lisible en plein soleil sur un téléphone. --rose-fort donne 5,2:1,
   et les boutons blancs à texte rose qu'il contient y ressortent mieux. */
.appel {
  background: var(--rose-fort);
  color: #fff;
  padding: clamp(2rem, 5vw, 3.2rem);
  border-radius: var(--r-carte);
}
.appel h2, .appel .plume { color: #fff; }
.appel p { color: rgba(255, 255, 255, .95); }
.appel a:not(.bouton) { color: #fff; }
.appel-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 2rem;
  align-items: center;
}
.appel .separateur { color: rgba(255, 255, 255, .8); }
.appel .separateur::before, .appel .separateur::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .6), transparent);
}

.liste-formats { list-style: none; margin: 0; padding: 0; }
.liste-formats li { display: flex; align-items: center; gap: .8rem; margin-bottom: .8rem; }
.liste-formats svg { width: 20px; height: 20px; flex: none; }

/* ---------- 18. Pied de page ---------- */
.pied {
  background: var(--creme-fonce);
  padding: 3rem 0 0;
  font-size: .92rem;
}
.pied-grille {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 2rem;
  padding-bottom: 2.5rem;
}
/* ⚠️ C'ÉTAIT LE PIRE CAS DU SITE : à 1,55 rem, ces en-têtes avaient une
   hauteur d'x de 8 px, soit MOINS que les liens de 17 px (9 px) qu'ils
   coiffent — un titre visuellement plus petit que sa propre liste. Voir le
   bloc de .plume. */
.pied h3 { font-family: var(--plume); font-size: clamp(1.85rem, 2.6vw, 2.1rem); color: var(--rose-fort); margin-bottom: .6rem; }
.pied ul { list-style: none; margin: 0; padding: 0; }
.pied li { margin-bottom: .2rem; }
/* Zone tactile d'au moins 24 px de haut (critère WCAG 2.5.8). */
.pied li a { display: inline-block; padding: .35rem 0; min-height: 26px; }
.pied a { color: var(--texte-doux); text-decoration: none; }
.pied a:hover { color: var(--rose-fort); text-decoration: underline; }
.pied-avertissement { color: var(--texte-doux); font-size: .87rem; }

.reseaux { display: flex; gap: .7rem; }
.reseaux a {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1.5px solid var(--rose-clair);
  border-radius: 50%;
  color: var(--rose-fort);
}
.reseaux a:hover { background: var(--rose-pale); border-color: var(--rose); }
.reseaux svg { width: 20px; height: 20px; }

.pied-bas {
  background: var(--sauge-fort);
  color: #fff;
  text-align: center;
  padding: .9rem 0;
  font-size: .87rem;
}

/* Crédit d'auteur dans la barre basse, posé le 2026-09-12.

   ⚠️ COLLISION DE CASCADE. `.pied a` (plus haut) impose
   `color: var(--texte-doux); text-decoration: none` — et `.pied-bas` vit
   À L'INTÉRIEUR de `<footer class="pied">`. Sans cette règle, le lien
   s'afficherait en gris foncé (#6b615c) sur le bandeau sauge (#647454),
   soit un contraste de 1,2:1, et sans soulignement. Les deux sélecteurs ont
   la même spécificité (une classe + un élément) : c'est l'ordre dans le
   fichier qui tranche, d'où la position de ce bloc APRÈS `.pied-bas`.

   ⚠️ Le soulignement est OBLIGATOIRE, pas décoratif. Ce lien est INLINE dans
   une phrase de la même couleur (« Site réalisé par … ») : la couleur seule
   ne peut donc pas signaler qu'il est cliquable (WCAG 1.4.1). Les liens des
   listes du pied de page, eux, sont autonomes et n'en ont pas besoin.

   Le contour de focus est BLANC : sur le bandeau sauge, le rose de la charte
   tomberait sous le seuil. */
.pied-bas a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pied-bas a:hover { text-decoration-thickness: 2px; }
.pied-bas a:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---------- 19. Fil d'Ariane ---------- */
.fil { padding: 1rem 0 0; font-size: .9rem; color: var(--texte-doux); }
.fil ol { display: flex; flex-wrap: wrap; gap: .5rem; list-style: none; margin: 0; padding: 0; }
.fil li + li::before { content: '›'; margin-right: .5rem; color: var(--rose); }
.fil a { color: var(--texte-doux); }

/* ---------- 20. Éléments décoratifs ---------- */
.feuillage {
  position: absolute;
  pointer-events: none;
  user-select: none;
  opacity: .5;
  z-index: 0;
}
.feuillage-hg { top: 1rem; left: -2rem; width: 130px; }
.feuillage-bd { bottom: 1rem; right: -1rem; width: 150px; }
.relatif { position: relative; }
.au-dessus { position: relative; z-index: 1; }

/* ---------- 21. Adaptation aux petits écrans ---------- */
@media (max-width: 820px) {
  .grille-2 { grid-template-columns: 1fr; }
}

@media (max-width: 980px) {
  .banniere-grille { grid-template-columns: 1fr; }
  .banniere-visuel { order: -1; }
  .banniere-visuel .zone-photo { aspect-ratio: 3 / 2; border-radius: var(--r-carte); }
  .medaillon { width: 132px; height: 132px; font-size: .72rem; right: 8px; }
  .article-mis-en-avant { grid-template-columns: 1fr; }
  .article-mis-en-avant .zone-photo { min-height: 210px; }
  .pilier + .pilier { border-left: 0; }
  .piliers { margin-top: 0; }
}

@media (max-width: 860px) {
  .bouton-menu { display: flex; }

  /* Le panneau replié ne sort JAMAIS du viewport.
     Un translateX(100%) le plaçait hors écran à droite : comme il est en
     position:fixed, ni overflow-x:clip sur html ni un clip sur body ne le
     rognent (un élément fixed a le viewport pour bloc conteneur, il échappe
     au contexte de rognage de ses ancêtres). Mesuré : scrollWidth de 690
     pour 360 de viewport, et la page se faisait glisser latéralement de
     330 px au doigt, sur les 17 pages.
     On le laisse donc à sa place et on le masque par visibility + opacité :
     visibility:hidden retire aussi ses 5 liens du parcours de tabulation,
     qui restaient atteignables au clavier alors qu'ils étaient hors écran.
     Le léger glissement de 12 px se fait vers l'intérieur, jamais au-delà
     du bord droit. */
  .nav-principale {
    position: fixed;
    inset: 0 0 0 auto;
    width: min(88vw, 380px);
    padding: 5.5rem 1.6rem 2rem;
    background: var(--creme);
    box-shadow: -8px 0 30px rgba(90, 66, 60, .18);
    transform: translateX(-12px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease, transform 240ms ease, visibility 0s linear 240ms;
    overflow-y: auto;
    z-index: 120;
  }
  .nav-principale[data-ouvert="true"] {
    transform: translateX(0);
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms ease, transform 240ms ease, visibility 0s;
  }
  .nav-principale > ul { flex-direction: column; align-items: stretch; gap: .2rem; }
  .nav-principale a, .nav-deroulant > button {
    padding: .85rem .4rem;
    min-height: 48px;
    font-size: 1.05rem;
    border-bottom: 1px solid var(--creme-fonce);
    width: 100%;
  }
  .nav-principale a[aria-current="page"] { border-bottom-color: var(--rose-fort); }
  .nav-deroulant { position: static; }
  .sous-menu {
    position: static;
    transform: none;
    min-width: 0;
    box-shadow: none;
    border: 0;
    background: var(--creme-fonce);
    border-radius: var(--r-douce);
    margin: .3rem 0 .6rem;
  }
  .sous-menu a { border-bottom: 0; font-size: .97rem; }

  .voile {
    position: fixed;
    inset: 0;
    background: rgba(58, 51, 48, .45);
    z-index: 110;
    border: 0;
    padding: 0;
  }
  .voile[hidden] { display: none; }

  /* ══════════════════════════════════════════════════════════════════════════
     LE BOUTON DE RENDEZ-VOUS RESTE OFFERT SOUS 860px — CORRIGÉ LE 2026-09-15.

     ⚠️ CETTE RÈGLE PORTAIT `display: none`, ET C'ÉTAIT LE DÉFAUT. Transcrite
     telle quelle du site statique d'origine, elle retirait le bouton de la
     barre sans que rien ne le remette ailleurs : `MenuMobile` n'a jamais eu
     d'entrée « rendez-vous ». Sur téléphone, la seule façon d'atteindre la
     prise de rendez-vous était de deviner qu'elle se trouve au milieu de la
     page « Contact ».

     Gardé par `e2e/non-regression.spec.ts` (« le rendez-vous est atteignable
     depuis l'en-tête »), qui CLIQUE dans un vrai navigateur à 360 et 768px —
     seul endroit où cette règle existe. Un test unitaire n'applique aucune
     feuille de style et ne pouvait donc rien voir.

     ── CE QUE CHAQUE LIGNE ACHÈTE, ET CE QU'ELLE COÛTE ──────────────────────

     ⚠️ `justify-content` repasse à `flex-start` : en `space-between`, trois
     éléments au lieu de deux laissent le bouton FLOTTER AU MILIEU dès qu'il y
     a de la place (visible à 768px, pas à 360px — le piège classique d'un
     réglage vérifié sur un seul téléphone). Le `margin-left: auto` regroupe
     donc le bouton et le menu à droite, logo à gauche.

     ⚠️ `order: 1` sur le bouton de menu, et non `order: -1` sur celui-ci :
     le logo n'a pas d'`order`, il vaut donc 0 — un `-1` ici le ferait passer
     AVANT le logo.

     ⚠️⚠️ ET CE `order` A UN COÛT, ASSUMÉ : dans le DOM, le bouton de menu
     précède celui de rendez-vous ; à l'écran c'est l'inverse. La tabulation
     visite donc le menu avant « RDV », alors que « RDV » est à sa gauche.
     C'est une entorse à l'ordre de lecture, limitée à DEUX commandes voisines
     de la même barre, indépendantes l'une de l'autre. L'alternative —
     réordonner le DOM — déplacerait la même entorse sur le grand écran, entre
     la navigation entière et le bouton, ce qui serait pire.

     ⚠️ L'ICÔNE DISPARAÎT : mesurée à 26px, pour un budget total d'environ
     91px à 360px. La garder ne laissait que 3px de marge — assez pour qu'une
     police de repli ou un zoom de texte fasse déborder les 17 pages d'un
     coup. La pastille rose porte déjà le sens « action ».

     ⚠️ `white-space: nowrap` : sans lui, « RDV » tient, mais le libellé
     complet d'un futur emplacement se casserait en trois lignes et ferait
     grandir la barre en silence. */
  .entete-interieur { gap: .6rem; justify-content: flex-start; }
  .bouton-menu { order: 1; }

  .entete-bouton-rdv {
    margin-left: auto;
    flex: 0 0 auto;
    white-space: nowrap;
    padding: .55rem .9rem;
    font-size: .9rem;
  }
  .entete-bouton-rdv .rdv-libelle-long { display: none; }
  .entete-bouton-rdv .rdv-libelle-court { display: inline; }
  .entete-bouton-rdv svg { display: none; }

  body.menu-ouvert { overflow: hidden; }
}

@media (max-width: 560px) {
  .logo-marque { width: 46px; height: 46px; }
  .logo-nom { font-size: 1.2rem; }
  .logo-role { font-size: .68rem; }
  .boutons .bouton { width: 100%; }
  .medaillon { position: static; margin: 1rem auto 0; }
  .accordeon-corps { padding-left: 1.3rem; }
  .feuillage { display: none; }
}

/* ---------- 22. Impression ---------- */
@media print {
  .entete, .pied-bas, .bouton, .filtres, .voile { display: none !important; }
  body { background: #fff; font-size: 11pt; }
  .zone-photo { display: none; }
}

/* ---------- 22. Correctifs de l'audit du 09/09/2026 ---------- */

/* CRITIQUE 1 — le menu mobile était tronqué à la hauteur de l'en-tête (~120 px)
   sur les 17 pages, sous 860 px. Cause : `backdrop-filter` sur `.entete` crée un
   CONTAINING BLOCK pour ses descendants `position: fixed`. Le panneau
   `.nav-principale`, qui vit dans le <header>, calait donc son `inset: 0` sur
   l'en-tête au lieu du viewport. Seul le premier lien restait visible.
   Le flou est retiré uniquement là où le panneau devient fixed : le fond de
   l'en-tête est déjà opaque à 96 %, la perte visuelle est imperceptible.
   Ni le scrollWidth ni le compte de liens focusables ne pouvaient détecter ce
   défaut — un panneau trop court ne déborde pas et ne rend rien focusable. */
@media (max-width: 860px) {
  .entete { backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* CRITIQUE 2 — deux grilles à deux colonnes ne repassaient jamais en une seule
   colonne sur mobile, dont celle du formulaire de contact (cartes réduites à
   127 px de large à 360 px). Cause : `grid-template-columns` posé en style EN
   LIGNE, qui l'emporte sur toute règle de feuille de style. Le ratio est donc
   déplacé ici, où la media query peut le surcharger.
   Cas particulier de contact.html : le bloc ne portait même pas `.grille-2`,
   donc la règle mobile ne l'atteignait pas, style en ligne ou non. */
.grille-contact { grid-template-columns: minmax(0, .75fr) minmax(0, 1fr); }
.grille-piliers { grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr); }

@media (max-width: 820px) {
  .grille-contact,
  .grille-piliers { grid-template-columns: 1fr; }
}

/* ---------- 23. Back-office : la liste des articles (lot 1b, tâche 9) ---------- */

/* ⚠️ `list-style: none` retire la sémantique de liste dans Safari : la liste
   porte `role="list"` dans le JSX pour la rendre. Les deux vont ensemble. */
.liste-admin {
  list-style: none;
  margin: 0 0 2.5rem;
  padding: 0;
  display: grid;
  gap: 1.2rem;
}
.liste-admin > li { margin: 0; }

/* `.carte h2` vaut jusqu'à 2rem — la taille d'un titre de section. Dans une
   liste de dix articles, dix titres de section ne hiérarchisent plus rien. */
.liste-admin h2 { font-size: clamp(1.2rem, 2.2vw, 1.45rem); margin: .15rem 0 .55rem; }

.etat-article { margin: 0; }
.meta-article { color: var(--texte-doux); font-size: .88rem; margin: .9rem 0 1.1rem; }

/* Trois teintes, trois MOTS. La couleur ne porte jamais l'information seule.
   Contrastes mesurés sur le fond réellement peint, seuil AA 4,5:1 (texte de
   .78rem en gras : en dessous des 18,66 px du « grand texte ») :
     · sauge sombre #53603f sur sauge clair #e4e8dc → 5,42:1
     · rose fort   #a44f5b sur rose pâle   #faecee → 4,76:1 (valeur de la charte)
     · brun        #6b4a08 sur crème ambré #fdf4e2 → 7,37:1 (paire de .avis-configuration)
   ⚠️ `.etiquette-sauge`, la classe de la charte, n'est PAS reprise ici : son
   #647454 sur ce même fond ne donne que 4,05:1 — sous le seuil. Elle n'est
   aujourd'hui rendue par aucune page (composants/EtatVideArticles.tsx n'est
   appelé nulle part), donc ce n'est pas un défaut en ligne ; c'en serait devenu
   un en la réutilisant ici. */
.etiquette-en-ligne  { background: var(--sauge-clair); color: var(--sauge-sombre); }
.etiquette-brouillon { background: var(--rose-pale);   color: var(--rose-fort); }
.etiquette-alerte    { background: #fdf4e2;            color: #6b4a08; }

/* L'adresse citée dans l'avis d'incohérence. Sans `overflow-wrap`, un slug long
   déborde de la carte à 360 px de large. */
.avis-configuration code { font-size: .92em; overflow-wrap: anywhere; }

/* ---------- 24. Back-office : l'éditeur d'article (lot 1b, tâche 10) ---------- */

/* L'étiquette d'un groupe qui n'est pas un champ unique (la zone d'écriture,
   l'adresse publique). `<label>` ne conviendrait pas : il désigne UN contrôle,
   et l'associer à une zone `contenteditable` demanderait un `for` sur un
   élément que ProseMirror recrée. C'est un `<span>` nommé par
   `aria-labelledby`, avec l'allure d'un `.champ label`. */
.etiquette-champ {
  display: block;
  /* ⚠️ `margin` COMPLET, et non le seul `margin-bottom` : cette classe habille
     aussi un `<h2>` (la zone d'écriture, voir composants/admin/FormulaireArticle.tsx),
     qui porte une marge HAUTE de titre de section. Sans ce zéro, l'étiquette
     « Votre article » se détachait du champ qu'elle nomme. */
  margin: 0 0 .35rem;
  /* ⚠️ La police du CORPS, explicitement. Un `<h2>` hérite sinon de
     `var(--titre)` et de `font-weight: 500` (section 3) : l'étiquette « Votre
     article » serait apparue en serif légère au milieu de cinq étiquettes en
     sans-serif grasse. Les deux éléments qui portent cette classe — un `<h2>`
     et un `<span>` — doivent être INDISCERNABLES à l'œil : leur différence est
     sémantique, pas visuelle. */
  font-family: var(--corps);
  font-size: .93rem;
  font-weight: 700;
  line-height: 1.4;
  letter-spacing: normal;
  color: var(--texte);
}

.editeur {
  border: 1.5px solid var(--rose-clair);
  border-radius: var(--r-douce);
  background: #fff;
  /* ⚠️⚠️ `clip` ET NON `hidden`, ET CE N'EST PAS UN DÉTAIL DE GOÛT — 2026-09-15.

     `overflow: hidden` fait de cet élément un CONTENEUR DE DÉFILEMENT. La barre
     d'outils en `position: sticky` se serait alors accrochée à LUI — un
     conteneur qui ne défile jamais — au lieu de la page. Le résultat : une
     propriété correctement posée, aucune erreur, aucune trace, et une barre qui
     ne colle pas. C'est la panne la plus traître de `sticky`, et elle se
     diagnostique toujours trop tard parce qu'on relit la règle `sticky`, jamais
     l'ancêtre.

     `clip` rogne exactement pareil — c'est ce qu'on veut, pour que les coins
     arrondis coupent le contenu — mais ne crée AUCUN conteneur de défilement.
     La barre s'accroche donc à la page.

     ⚠️ NE PAS « SIMPLIFIER » EN REVENANT À `hidden` : les deux se ressemblent à
     la lecture et n'ont pas le même effet ici. Le garde est
     `e2e/admin-editeur.spec.ts` (« elle reste sous le bandeau après
     défilement »), qui fait défiler un VRAI navigateur — aucun test unitaire ne
     peut voir cette différence. */
  overflow: clip;
}

/* ══════════════════════════════════════════════════════════════════════════
   LA BARRE D'OUTILS SUIT LE DÉFILEMENT — 2026-09-15.

   Avant, elle restait clouée en haut du bloc de texte : sur un article un peu
   long, mettre un mot en gras au milieu obligeait à remonter jusqu'en haut,
   cliquer, puis redescendre retrouver l'endroit.

   ⚠️ `top` VIENT D'UNE MESURE, PAS D'UNE CONSTANTE. Le bandeau du site est
   `sticky` et surplombe aussi le back-office ; sa hauteur VARIE avec le retour
   à la ligne de son logo — mesuré 83 px à 1440 et 768, 99 px à 390, 112 px à
   360. Aucun palier ne la décrit : elle dépend du moment où « CYNTHIA BAZILE »
   se casse en deux lignes. `composants/admin/Editeur.tsx` la mesure donc à
   l'exécution et pose `--hauteur-entete`.

   ⚠️ LA VALEUR DE REPLI EST LA PLUS GRANDE MESURÉE (112 px), jamais une
   moyenne : trop bas laisse un ruban de texte défiler sous le bandeau, trop
   haut CACHE la barre derrière lui. Entre les deux, on choisit le défaut qui se
   voit.

   ⚠️ `z-index: 90` < le 100 du bandeau : si l'un devait recouvrir l'autre,
   c'est le bandeau qui gagne. Il porte la navigation du site ; la barre
   d'outils n'est qu'un accessoire de la page.

   ⚠️ LE FOND DOIT RESTER OPAQUE (`--creme`) : une barre translucide laisserait
   le texte de l'article défiler visiblement au travers de ses boutons. */
.editeur-barre {
  position: sticky;
  top: var(--hauteur-entete, 112px);
  z-index: 90;
  display: flex;
  flex-wrap: wrap;
  gap: .4rem;
  padding: .55rem;
  background: var(--creme);
  border-bottom: 1.5px solid var(--rose-clair);
}

/* ⚠️ Des MOTS, pas des icônes : voir l'en-tête de composants/admin/Editeur.tsx.

   ⚠️⚠️ 44 px, ET LE COMMENTAIRE D'ORIGINE SE CONTREDISAIT LUI-MÊME : il
   énonçait le seuil (« en dessous de 44 px on vise mal sur un téléphone ») deux
   lignes avant de régler la hauteur à 40. Trouvé en revue. C'est la forme de
   défaut la plus traître d'une feuille de style : la règle est ÉCRITE, donc on
   la croit tenue, et personne ne relit le chiffre.

   Le seuil vient du critère WCAG 2.5.8 (Target Size, Minimum). Il compte
   doublement ici : ces sept boutons sont serrés les uns contre les autres, et ils
   sont manipulés pendant qu'on rédige — c'est-à-dire sans regarder où l'on
   appuie. */
.editeur-bouton {
  min-height: 44px;
  padding: .4rem .8rem;
  font-family: var(--corps);
  font-size: .88rem;
  color: var(--texte);
  background: #fff;
  border: 1.5px solid var(--rose-clair);
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--transition), color var(--transition),
              border-color var(--transition);
}
.editeur-bouton:hover { border-color: var(--rose); }

/* ⚠️ L'état enfoncé se voit par la COULEUR **et** par `aria-pressed`, qui est
   ce que lit un lecteur d'écran. La couleur ne porte jamais l'information
   seule sur ce site. Contraste mesuré : #fff sur #a44f5b (--rose-fort) →
   5,46:1, au-dessus du seuil AA de 4,5:1 pour du texte de .88rem. */
.editeur-bouton[aria-pressed="true"] {
  background: var(--rose-fort);
  border-color: var(--rose-fort);
  color: #fff;
}

/* La zone d'écriture elle-même (`contenteditable`, posée par ProseMirror).
   `min-height` généreux : un cadre haut de trois lignes dit « écris une note »,
   un cadre haut de vingt dit « écris un article ». */
.editeur-zone {
  padding: 1rem 1.1rem;
  min-height: 22rem;
  font-size: 1rem;
  line-height: 1.7;
  color: var(--texte);
}
.editeur-zone:focus { outline: 3px solid var(--rose-fort); outline-offset: -3px; }
.editeur-zone > :first-child { margin-top: 0; }
.editeur-zone > :last-child { margin-bottom: 0; }
.editeur-zone h3 { font-size: 1.15rem; margin: 1.4rem 0 .5rem; }
.editeur-zone p { margin: 0 0 .9rem; }
.editeur-zone ul, .editeur-zone ol { margin: 0 0 .9rem 1.4rem; }
.editeur-zone li { margin-bottom: .3rem; }
.editeur-zone a { color: var(--rose-fort); }

/* ⚠️ Un paragraphe vide n'a AUCUNE hauteur visible dans un `contenteditable` :
   sans cette invite, la page présente un rectangle blanc de 22 rem entièrement
   vide, et rien ne dit qu'on peut y écrire. Constaté en REGARDANT l'écran, pas
   par un test.

   ⚠️ Le TEXTE de l'invite n'est pas ici : il vit dans
   `composants/admin/extensions.ts`, où l'extension `Placeholder` le pose en
   attribut `data-placeholder`. Une phrase destinée à être LUE n'a pas sa place
   dans un `content:` de feuille de style, où aucun outil de traduction ne la
   trouve. Cette règle ne fait que la rendre visible. */
.editeur-zone p.is-empty:first-child::before {
  content: attr(data-placeholder);
  float: left;
  height: 0;
  pointer-events: none;
  color: var(--texte-doux);
}

.editeur-lien {
  margin-top: .8rem;
  padding: 1rem 1.1rem;
  background: var(--creme);
  border: 1.5px solid var(--rose-clair);
  border-radius: var(--r-douce);
}
.editeur-lien .champ { margin-bottom: .8rem; }

/* Un avertissement qui apparaît PENDANT la frappe : il doit se voir sans
   arrêter la lecture. Ni le rouge d'une erreur, ni le vert d'un succès —
   l'ambre déjà employé par `.avis-configuration`, qui est la teinte de « ceci
   vous concerne » sur ce site. Contraste #6b4a08 sur #fdf4e2 → 7,37:1. */
.avis-champ {
  display: block;
  margin-top: .35rem;
  padding: .5rem .7rem;
  font-size: .88rem;
  color: #6b4a08;
  background: #fdf4e2;
  border-radius: var(--r-douce);
}

/* L'adresse publique de l'article : elle se lit, elle se copie, elle ne se
   perd pas au bout d'une carte. */
.adresse-article { margin: 0 0 .4rem; }
.adresse-article code {
  font-size: .95rem;
  color: var(--texte-doux);
  overflow-wrap: anywhere;
}

.details-adresse { margin-top: .6rem; }
.details-adresse > summary {
  cursor: pointer;
  font-size: .9rem;
  color: var(--rose-fort);
  min-height: 44px;
  display: flex;
  align-items: center;
}
.details-adresse .indication { display: block; margin-bottom: .5rem; }

/* ⚠️ UN CHAMP DÉSACTIVÉ DOIT SE VOIR — constaté en REGARDANT l'écran, pas par
   un test. La règle générale des champs de ce site pose `background: #fff`, ce
   qui ÉCRASE le gris que le navigateur applique de lui-même à un champ
   désactivé : le champ « Description de l'image », éteint jusqu'à la tâche des
   illustrations, avait exactement l'allure d'un champ qu'on peut remplir.
   Cynthia aurait cliqué dedans, tapé, et rien ne serait apparu.
   C'est le même défaut, à la même cause, que celui déjà payé sur le bouton
   d'envoi du formulaire de contact (section 2 de ce fichier). */
input:disabled, textarea:disabled, select:disabled {
  background: var(--creme-fonce);
  color: var(--texte-doux);
  border-color: var(--rose-clair);
  cursor: not-allowed;
}
input:disabled:hover, textarea:disabled:hover, select:disabled:hover {
  border-color: var(--rose-clair);
}

/* ⚠️ `display: flex` sur un `<summary>` SUPPRIME le triangle de repli (le
   `::marker` n'existe que pour un `display: list-item`). Le repli « Modifier
   l'adresse » ressemblait alors à un simple lien qui ne mène nulle part. On le
   redessine, et on l'oriente selon l'état ouvert. */
.details-adresse > summary::before {
  content: "";
  width: 0; height: 0;
  margin-right: .5rem;
  border-left: 6px solid currentColor;
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
  transition: transform var(--transition);
}
.details-adresse[open] > summary::before { transform: rotate(90deg); }
.details-adresse > summary::marker,
.details-adresse > summary::-webkit-details-marker { content: ""; display: none; }

/* ⚠️ UNE INSTRUCTION N'EST NI UN SUCCÈS NI UN ÉCHEC. « Sélectionnez d'abord les
   mots qui doivent devenir un lien » portait le vert de `.message-succes` :
   rien ne s'était passé, et la couleur disait le contraire. Le vert sur une
   consigne non suivie apprend à ne plus lire le vert.
   Teinte neutre de la charte (crème ambré / brun), contraste #6b4a08 sur
   #fdf4e2 → 7,37:1, la même paire que `.avis-configuration`. */
.message-instruction {
  background: #fdf4e2;
  border: 1px solid #e0c896;
  color: #6b4a08;
}

/* ---------- 25. Back-office : publier, dépublier, supprimer (lot 1b, tâche 11) ---------- */

/* La section qui suit le formulaire d'écriture. Un filet en haut, parce que ce
   qui s'y décide n'est plus du texte mais ce que le monde voit : la séparation
   visuelle dit « on change de sujet » avant qu'on ait lu le titre. */
.cycle-article {
  margin-top: 2.8rem;
  padding-top: 1.8rem;
  border-top: 1px solid var(--rose-clair);
}
.cycle-article h2 { font-size: clamp(1.15rem, 2.2vw, 1.35rem); margin: 1.8rem 0 .6rem; }
.cycle-article h2:first-child { margin-top: 0; }
.cycle-article form { margin-top: 1rem; }
.cycle-article code { overflow-wrap: anywhere; }

/* ⚠️ LE SEUL BOUTON ROUGE DU SITE, ET IL N'EN EXISTE QU'UN SEUL USAGE :
   « Supprimer définitivement ». La charte n'avait aucune teinte de danger — et
   c'est normal, rien n'était destructeur avant cette tâche. Réemployer
   `.bouton-contour` (rose de la charte) aurait donné au geste irréversible
   exactement l'allure du bouton « Retour à mes articles » qui le côtoie.

   Contraste MESURÉ, pas supposé : #8a2129 (déjà la couleur de texte de
   `.message-echec`, donc pas une teinte de plus dans la charte) sur blanc
   donne 8,99:1 ; blanc sur #8a2129, la même valeur. Seuil AA pour du texte
   ordinaire : 4,5:1. */
.bouton-danger { background: #8a2129; color: #fff; }
.bouton-danger:hover { background: #6f1a20; color: #fff; }

/* Le titre de l'article qu'on s'apprête à effacer, dans le bandeau de
   confirmation. Il est GROS parce que c'est la seule chose qui distingue cette
   page de la même page pour un autre article : une confirmation identique dix
   fois de suite ne se lit plus. */
.titre-a-supprimer {
  font-family: var(--titre);
  font-size: clamp(1.15rem, 2.6vw, 1.5rem);
  line-height: 1.3;
  margin: .4rem 0 0;
}
