/* =============================================
   ORGATYPIK - LE CSS DU THÈME

   CE FICHIER N'EST PLUS UNE COPIE DE LA MAQUETTE.

   Il l'était : theme/assets/composants.css était maquette/style.css, à l'octet près.
   Cela paraissait élégant - « décalquer sans traduire », disait le guide - et c'était
   l'erreur qui a tout faussé. Un fond posé en CSS est INVISIBLE À L'ÉDITEUR : le
   rédacteur ne le voit pas, ne peut pas le changer, et l'aperçu ment.

   Désormais : CE QUE WORDPRESS SAIT EXPRIMER, WORDPRESS L'EXPRIME.

     - les fonds, dégradés, espacements, tailles et couleurs de texte  -> theme.json
       (presets) et attributs de blocs, dans theme/patterns/
     - les composants (carte, tuile, témoignage…)                      -> register_block_style()
     - et ICI, seulement ce que WordPress ne sait PAS dire :
         · un dégradé sur du TEXTE (background-clip: text)
         · les pseudo-éléments (les puces, la flèche, le guillemet, le « + »)
         · les survols et les transitions
         · les sélecteurs de CONTEXTE (.section-dark a:where(:not(.btn, .wp-element-button)))
         · les media queries
         · position: fixed, backdrop-filter, z-index

   maquette/style.css reste la RÉFÉRENCE VISUELLE - on compare les rendus - mais elle
   n'est plus la source du style. Ce fichier part d'elle, et s'élague à mesure que le
   natif reprend le travail.
   ============================================= */

/* =============================================
   BASE
   ============================================= */

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

html { scroll-behavior: smooth; font-size: 16px; }

body {
  font-family: var(--font-body);
  color: var(--text);
  line-height: 1.7;
  background: var(--white);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  line-height: 1.2;
  color: var(--navy);
  /* Garde-fou : un mot ne déborde jamais du viewport. Un mot qui tient va simplement à
     la LIGNE SUIVANTE ; overflow-wrap ne coupe un mot QUE s'il est trop long pour tenir
     seul sur une ligne (dernier recours). PAS de hyphens: auto : il césurait trop, pour
     « remplir » les lignes centrées, alors qu'un renvoi à la ligne suffit presque
     toujours. */
  overflow-wrap: break-word;
}

h1 { font-size: clamp(2.2rem, 5vw, 3.4rem); font-weight: 800; }
h2 { font-size: clamp(1.8rem, 3.5vw, 2.6rem); font-weight: 700; }
h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); font-weight: 700; }
h4 { font-size: 1.15rem; font-weight: 600; }

p { margin-bottom: 1rem; }
a { color: var(--navy); text-decoration: none; transition: var(--transition); }
img { max-width: 100%; height: auto; }

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--space-6);
}

/* =============================================
   UTILITAIRES
   ============================================= */

.narrow { max-width: 800px; margin-left: auto; margin-right: auto; }
.narrow-sm { max-width: 720px; margin-left: auto; margin-right: auto; }
.mt-xl { margin-top: var(--space-12); }

/* Note de section : commentaire d'auteur sous un bloc, plus discret qu'un paragraphe
   de corps. Sert notamment aux clauses explicatives (« pourquoi ça marche »). */
.is-style-note-section {
  max-width: 720px;
  margin: var(--space-10) auto 0;
  text-align: center;
  color: var(--gray-600);
  font-size: 0.95rem;
}

/* Pied de section : rappel de CTA sous une grille */
.is-style-pied-de-section { text-align: center; margin-top: var(--space-12); }
.is-style-pied-de-section .btn { margin-top: var(--space-4); }

.section-footer-lead {
  font-family: var(--font-heading);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--navy);
}


/* Rangée de pastilles */
.is-style-rangee-etiquettes { display: flex; flex-wrap: wrap; gap: var(--space-2); margin-top: var(--space-4); }

/* =============================================
   LOGO
   ============================================= */

/* Le logo associe le SYMBOLE (image) et le WORDMARK (texte).
   Le wordmark reste du texte : il est net à toute taille, sélectionnable, et
   son dégradé suit les tokens. Le dégradé porte sur .logo-word et non sur
   .logo, faute de quoi background-clip: text masquerait l'image.
   Les fichiers source d'origine sont en 4480x5440 : ne jamais les servir tels
   quels, employer les dérivés de assets/. */
/* Le logo est un GROUPE FLEX de deux images (wp:image) : le symbole et le wordmark.
   Le flex, l'alignement vertical et le gap viennent du bloc groupe (layout flex,
   verticalAlignment:center, blockGap:10px) ; le CSS ne fait que dimensionner les images
   et annuler la marge par défaut des figures wp:image. C'est ce qui retire le wp:html
   du logo : le wordmark étant une image, le bloc image natif suffit. */
.logo { align-items: center; }

.logo-mark { margin: 0; flex-shrink: 0; }
.logo-mark img { width: 34px; height: 34px; display: block; }

/* Le wordmark est une IMAGE (wordmark-light.png / -dark.png), plus un dégradé sur texte
   qui ne se rendait pas de façon fiable dans l'éditeur. Hauteur = l'ink de l'ancienne
   taille (133/144 × 1.5rem = 1.386rem) ; la variante claire/sombre vient du src. */
.logo-word { margin: 0; line-height: 0; }
/* Chaque image du logo (symbole ET wordmark) est enveloppée d'un <a> vers l'accueil : le
   logo entier est cliquable. Ce lien, inline par défaut, porte un talon de line-height
   qui pousserait l'image vers le haut (le centre du wordmark passait ~4 px au-dessus de
   celui du symbole). On le passe en bloc, line-height nulle : chaque image se cale sur le
   centre du flex .logo. */
.logo-mark a, .logo-word a { display: block; line-height: 0; }
.logo-word img { height: 1.386rem; width: auto; display: block; }

/* En ligne dans le contenu (tableau comparatif, carte visuelle), le wordmark reste une
   image simple, pas un bloc wp:image. */
.brand-word,
.brand-word-on-dark {
  display: inline-block;
  height: 1.386rem;
  width: auto;
  vertical-align: middle;
}

/* 0.65 rem faisait 10,4 px : sous le seuil de lisibilité confortable, et la baseline
   se lisait mal. 0.75 rem (12 px) la rend lisible sans qu'elle concurrence le wordmark,
   qui reste trois fois plus grand. */
.logo-tagline {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--gray-400);
  letter-spacing: 0.03em;
  display: block;
  /* Collée au wordmark. Le line-height du wordmark (1.7, hérité du corps) laissait un
     talon sous les lettres : la baseline flottait à distance. On le ramène à 1 sur le
     wordmark - il n'a qu'une ligne - et la marge négative absorbe ce qui reste. */
  margin-top: -2px;
  /* PLUS DE RETRAIT. Les 44 px valaient exactement la largeur du symbole (34) plus
     l'écart du logo (10) : ils alignaient la baseline sur le wordmark, à droite du
     symbole. Le symbole ayant quitté l'en-tête, ce retrait n'alignait plus rien -
     il décalait la phrase de 44 px vers la droite du wordmark. */
}

.site-footer .logo-mark img { width: 40px; height: 40px; }

/* LE LOGO DU PIED : SYMBOLE AU-DESSUS DU WORDMARK, ET CENTRÉ SUR LUI.

   Ailleurs (en-tête), le logo est une ligne : symbole à gauche, mot à droite. Dans le
   pied il s'empile, et le symbole se centre sur la largeur du mot - pas sur celle de la
   colonne. D'où « width: fit-content » : sans lui, align-items centrerait le symbole
   dans toute la colonne de marque, qui est bien plus large que le wordmark, et le
   symbole partirait à droite du mot au lieu de le coiffer.

   Le bloc, lui, reste calé à gauche comme le reste de la colonne. */
.site-footer .logo {
  flex-direction: column;
  align-items: center;
  width: fit-content;
  gap: var(--space-2);
}

/* =============================================
   HEADER / NAVIGATION

   Le CTA « Diagnostic gratuit » est volontairement HORS de .nav-links :
   il était auparavant à l'intérieur, si bien qu'il disparaissait avec le
   menu sous 960px et qu'aucune conversion n'était possible sur mobile.

   Le menu mobile est un <details>/<summary> natif : accessible, sans
   JavaScript, et la maquette reste ouvrable au double-clic. Les liens y
   sont dupliqués - c'est assumé ici, car dans WordPress le bloc Navigation
   fournit un seul markup et son propre panneau responsive.
   ============================================= */

.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  background: var(--surface-header);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--gray-200);
  transition: var(--transition);
}

.nav-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--space-6);
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--header-height);
}

.nav-brand { display: flex; flex-direction: column; justify-content: center; }

.nav-desktop { display: flex; align-items: center; gap: var(--space-8); }



.nav-links a:hover,
.nav-links a.active { color: var(--navy); }


.nav-links a:hover::after,
.nav-links a.active::after { width: 100%; }

.nav-cta {
  font-family: var(--font-heading);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--white);
  background: var(--violet);
  padding: 10px var(--space-6);
  border-radius: var(--radius-md);
  letter-spacing: 0.01em;
  white-space: nowrap;
}

.nav-cta:hover {
  background: var(--violet-dark);
  color: var(--white);
  transform: translateY(-1px);
}









.nav-panel a:hover,
.nav-panel a.active { color: var(--navy); }

.nav-panel .nav-cta {
  color: var(--white);
  text-align: center;
  border-bottom: none;
  margin-top: var(--space-3);
  padding: var(--space-3) var(--space-6);
}

/* =============================================
   BOUTONS
   ============================================= */

.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 14px var(--space-8);
  border-radius: var(--radius-md);
  border: none;
  cursor: pointer;
  transition: var(--transition);
  text-decoration: none;
  letter-spacing: 0.01em;
}

.btn-block { width: 100%; justify-content: center; }

.btn-primary {
  background: var(--violet);
  color: var(--white);
  box-shadow: var(--shadow-violet);
}

.btn-primary:hover {
  background: var(--violet-dark);
  color: var(--white);
  transform: translateY(-2px);
  box-shadow: var(--shadow-violet-lg);
}





.btn-arrow::after { content: '→'; transition: var(--transition); }
.btn-arrow:hover::after { transform: translateX(4px); }

/* Boutons sur fond sombre. Le sélecteur :not(.btn) plus bas empêche les
   règles de couleur de lien d'atteindre les boutons - c'est ce qui rend
   inutiles les !important et la couche de correctifs de l'ancienne v2. */
.hero-home .is-style-secondaire .wp-block-button__link,
.hero-page .is-style-secondaire .wp-block-button__link,
.section-dark .is-style-secondaire .wp-block-button__link,
.cta-band .is-style-secondaire .wp-block-button__link {
  color: var(--white);
  border-color: var(--white);
}

.hero-home .is-style-secondaire .wp-block-button__link:hover,
.hero-page .is-style-secondaire .wp-block-button__link:hover,
.section-dark .is-style-secondaire .wp-block-button__link:hover,
.cta-band .is-style-secondaire .wp-block-button__link:hover {
  background: var(--white);
  color: var(--navy);
}

/* =============================================
   HERO
   ============================================= */

.hero { padding: 160px 0 var(--space-25); position: relative; overflow: hidden; }

/* .hero-home ne porte plus ni fond, ni couleur, ni padding : le pattern les pose en
   ATTRIBUTS (gradient « hero », textColor « on-navy-body », presets d'espacement), et
   l'editeur les montre. Ne reste ici que ce que WordPress ne sait pas dire. */

/* Le h1 porte sa couleur en attribut (« on-navy-title ») et sa marge en preset. Sa
   largeur de lecture reste ici : le layout « constrained » la donnerait, mais il
   centrerait le titre. */
.hero-home h1 { max-width: 800px; }

/* .hero-highlight est morte : Gutenberg ne garde pas les <span> d'un titre. La mise
   en valeur passe par <strong>, style plus bas. */

/* Le max-width de l'accroche a ete RETIRE : dans un layout « constrained », WordPress
   centre tout enfant qui porte une largeur propre - l'accroche se retrouvait au milieu
   au lieu de rester a gauche. La taille vient du preset « large », la marge d'un preset
   d'espacement, la couleur du groupe parent. */
/* La largeur de lecture de l'accroche. Le layout « constrained » de WordPress la
   donnerait, mais il centrerait le texte : il pose un margin auto !important sur tout
   enfant. La maquette l'aligne a gauche. */
.hero-home .hero-sub { max-width: 640px; line-height: 1.8; }

/* Le fond est un violet à 15 % composé sur le dégradé : --violet-light n'y
   atteint que 4.17:1. --on-navy-accent donne 6.59:1 au même endroit. */
.is-style-badge {
  /* BLOC (et non inline-flex) qui enveloppe son contenu : la pastille se centre alors
     par sa PROPRE marge auto (voir .hero-page .is-style-badge), et non par le text-align
     de son parent. Un centrage porté par la pastille elle-même résiste à un reset de
     text-align sur un conteneur intermédiaire de l'éditeur - ce que l'héritage ne fait
     pas. Sur l'accueil (hero-home), pas de marge auto : la pastille reste à gauche. */
  display: flex;
  width: fit-content;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--on-navy-accent);
  background: var(--on-navy-badge-bg);
  border: 1px solid var(--on-navy-badge-border);
  padding: 6px var(--space-4);
  border-radius: var(--radius-pill);
  /* L'AIR ENTRE LA PASTILLE ET LE TITRE (48px) N'EST PLUS ICI : c'est un ATTRIBUT de
     bloc (style.spacing.margin.bottom = preset 12) porté par le groupe .is-style-badge,
     et non une règle de cette feuille. La raison est la parité de l'éditeur : le canevas
     écrase le margin-bottom d'une feuille chargée par add_editor_style (styles par défaut
     des blocs), et la pastille se collait au <h1> en édition. Un style inline, né de
     l'attribut, bat cet écrasement. Le blockGap du hero reste coupé côté thème ; les deux
     retombent sur la même hauteur, par construction. Voir convertir.py (icone_puis_texte)
     et parts/hero.php. */
  letter-spacing: 0.03em;
  text-transform: uppercase;
}


.hero-stats {
  display: flex;
  gap: var(--space-12);
  margin-top: var(--space-14);
  padding-top: var(--space-10);
  border-top: 1px solid var(--on-navy-border);
}

/* --on-navy-accent plutôt que --violet-light (3.14:1 en fin de dégradé),
   et cohérent avec les grands chiffres de la page résultats. */
.hero-stat-number {
  font-family: var(--font-heading);
  font-size: 2.4rem;
  font-weight: 800;
  color: var(--on-navy-accent);
  display: block;
}

.hero-stat-label {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 500;
  color: var(--on-navy-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: var(--space-1);
}

/* Hero des pages internes.

   Le FOND et la COULEUR DU TEXTE ne sont plus ici : les blocs les posent en ATTRIBUTS
   (dégradé « hero-page », textColor « on-navy-body »), donc l'éditeur les montre et le
   rédacteur peut en changer. C'était le reproche fait au thème, et il était fondé.

   Le PADDING reste en CSS, et c'est délibéré : 140 px n'est sur aucun barreau de
   l'échelle d'espacement. Inventer un preset pour une seule valeur serait pire que de
   la garder ici. La variante --brand reste en CSS pour la même raison : c'est un choix
   d'auteur, pas un réglage à exposer. */
.hero-page {
  padding: 140px 0 var(--space-20);
  text-align: center;
}

/* La pastille se centre par SA marge (elle est un bloc en fit-content) : le text-align
   ci-dessus centre le texte des titres et accroches, mais pas un bloc. Scopé à
   .hero-page : sur l'accueil (hero-home), la pastille garde sa marge nulle, à gauche. */
.hero-page .is-style-badge { margin-inline: auto; }
/* Sauf dans le hero scindé, dont la colonne de texte s'aligne à gauche. Le nom de
   classe diffère de celui de la maquette (is-style-badge / hero-badge) : c'est le
   prix du style de bloc, et il impose d'écrire la règle DEUX fois, une par feuille. */
.hero-page--split .is-style-badge { margin-inline: 0; }

/* Le dégradé finit sur --violet (8.23:1 sous du blanc) et non sur --navy-light,
   qui n'offrait que 2.75:1. */
/* LE HERO EN DEUX COLONNES : le discours à gauche, la marque à droite.

   .hero-page centre son texte, et c'est juste pour un hero pleine largeur. Dès qu'il
   se scinde, le centrage devient un défaut : deux colonnes centrées chacune sur
   elle-même ne s'alignent sur rien. La variante rétablit donc l'alignement à gauche.

   La colonne de marque EMPILE le symbole au-dessus du mot, centrés l'un sur l'autre.
   Même disposition que le pied de page, et même raison : le symbole se centre sur la
   largeur du MOT, pas sur celle de la colonne, d'où width: fit-content.

   Côté WordPress, le paragraphe et le titre portent des classes d'alignement posées
   par leurs attributs de bloc : c'est convertir.py qui cesse de les centrer dans ce
   contexte (voir NON_CENTRE), pas ce CSS - un attribut rend un style inline, qu'une
   feuille ne bat pas sans !important. */
.hero-page--split { text-align: left; }

.hero-split {
  display: flex;
  align-items: center;
  gap: var(--space-16);
}

.hero-split-texte { flex: 1; min-width: 0; }

/* Sans colonne de marque, c'est l'ILLUSTRATION qui occupe la droite : le texte se
   borne donc à la moitié gauche, sinon il court dessous. 52 % et non 50 : le motif
   des illustrations laisse le tiers gauche vide, on peut donc mordre un peu. */
/* Pas « > .container » : côté WordPress, la Bannière glisse un
   .wp-block-cover__inner-container entre la section et le conteneur. Le sélecteur
   descendant couvre les deux rendus. */
.hero-page--split .container > * { max-width: 64%; }
/* LE TITRE DU HERO SCINDÉ EST PLUS PETIT, ET C'EST UNE CONTRAINTE DE LARGEUR.
   Mesuré au rendu : à 3.4rem (54.4 px), « de vingt-cinq ans de terrain » demande 803 px.
   La colonne n'en a que 650 - au-delà, le texte court sous la partie pleine de
   l'illustration, qui commence à 724 px du bord. À 2.6rem (41.6 px) la même ligne tombe
   à 614 px : les trois lignes voulues tiennent, et aucune ne se recasse.
   Le titre reste du TEXTE LARGE au sens WCAG (seuil 3:1) : les 6.46:1 mesurés tiennent. */
.hero-page--split h1 { font-size: clamp(2rem, 4vw, 3.1rem); }

.hero-page--split .hero-badge { margin-left: 0; margin-right: 0; }
/* (0,2,1) et non (0,1,1) : « .hero-page p:where(…) » pèse autant et vient plus bas
   dans le fichier, donc gagnerait par l'ordre. On qualifie par la colonne. */
.hero-page--split .container p:where(:not(.overline)) {
  margin-left: 0;
  margin-right: 0;
  max-width: 34rem;
}

.hero-split-marque {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  width: fit-content;
}

.marque-symbole { width: 148px; height: auto; display: block; }
/* LE COUPLE SYMBOLE + MOT DANS LA BANDE FINALE. Empilé et centré, comme au pied de
   page. C'est le seul endroit de la page où la marque SIGNE au lieu de se présenter :
   le lecteur y est invité à partir vers pylotik.com, et le logotype est ce qu'il
   retrouvera en arrivant. Dans le hero, il aurait redit le h1, qui commence déjà par
   « pylotik, ». */
.cta-marque {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  width: fit-content;
  margin: 0 auto var(--space-8);
}
.cta-marque .marque-symbole { width: 76px; }
.cta-marque .marque-mot { width: 152px; }

.marque-mot { width: 232px; height: auto; display: block; }
/* En blocs, chaque image est enveloppée d'une <figure>. */
.marque-symbole img, .marque-mot img { width: 100%; height: auto; display: block; }
.marque-symbole, .marque-mot { margin: 0; }

/* .hero-page--brand : dégradé « hero-brand » en attribut. */

/* LE HERO ILLUSTRÉ EST UNE BANNIÈRE (core/cover), et core/cover arrive avec ses propres
   règles : « display: flex », « min-height: 430px » et « padding: 1em ». Le hero a les
   siennes - et surtout son POINT DE RUPTURE mobile, qu'un min-height figé écraserait.
   On rend donc la boîte au flux normal et on lui redonne son padding.

   Le sélecteur porte les DEUX classes (0,2,0) volontairement : à égalité de spécificité
   avec « .wp-block-cover », c'est l'ordre de chargement qui trancherait, et l'ordre des
   feuilles de blocs du cœur n'est pas quelque chose sur quoi on veut parier.

   L'image et le voile sont des attributs du bloc (url, gradient, dimRatio) : rien de tout
   cela n'est ici, et c'est voulu - un fond posé en CSS serait invisible à l'éditeur. */
.wp-block-cover.hero-page {
  display: block;
  min-height: 0;
  padding: 140px 0 var(--space-20);
}

/* L'accueil pose SON padding en attribut de bloc (style inline) : on ne lui redonne donc
   que le flux normal et l'annulation du min-height du cœur. */
.wp-block-cover.hero-home {
  display: block;
  min-height: 0;
}

/* LE HERO N'A AUCUN GAP DE FLUX, et cette règle est là parce qu'on ne peut PAS s'en
   remettre à l'attribut seul.

   Le blockGap est bien posé à 0 sur la Bannière ET sur son .container (l'attribut est
   dans le markup, l'éditeur le voit). Mais la règle qu'il génère,
   « .wp-container-…-is-layout-xxx > * », pèse (0,1,0) - exactement comme la règle globale
   « :root :where(.is-layout-flow) > * { margin-block-start: 24px } ». À égalité, c'est
   l'ORDRE D'ÉMISSION qui tranche, et cet ordre dépend de quel bloc de la page emploie la
   classe de layout en premier : /resultats/ gagnait, l'accueil perdait. Un espacement qui
   dépend de la composition de la page n'est pas un espacement, c'est un tirage au sort.

   (0,2,0) tranche la question une fois pour toutes. Dans le hero, l'espacement vient des
   marges des composants - comme dans la maquette, qui n'a jamais eu de gap de flux. */
.hero-page .container > *,
.hero-home .container > * {
  margin-block-start: 0;
}

/* L'IMAGE DE LA BANNIÈRE : « contain », calée à droite - le pendant exact du
   background-size de la maquette, et pour les mêmes raisons (cover recadre le sujet et
   agrandit l'image au-delà de 1424px de viewport).

   Le sélecteur porte TROIS classes (0,3,0) volontairement : la règle du cœur pèse (0,2,0)
   (« .wp-block-cover .wp-block-cover__image-background { object-fit: cover } »). À
   spécificité égale, c'est l'ordre de chargement des feuilles de blocs qui trancherait -
   et ce n'est pas quelque chose sur quoi on veut parier. */
.wp-block-cover.hero--visuel .wp-block-cover__image-background {
  /* L'<img> est ramenée à la BOÎTE DE L'IMAGE (calée à droite) au lieu de couvrir tout le
     bloc : sans quoi le masque fondrait les 22 % du HERO alors que l'image ne commence
     qu'à ~27 %, et son bord resterait net. C'est le pendant du dimensionnement de la
     maquette, obtenu ici par la géométrie - une <img> étant un élément remplacé.

     ⚠ HAUTEUR EXPLICITE, ET NON « auto » AVEC top/bottom : un élément remplacé reprend son
     ratio intrinsèque et IGNORE la contrainte bottom. L'image sortait en 1280x676.

     ⚠ L'IMAGE EST CENTRÉE DANS LA PARTIE VISIBLE : l'en-tête est fixed et recouvre les
     72 premiers pixels du hero. Sa boîte démarre donc sous l'en-tête. */
  left: auto;
  right: 0;
  top: var(--header-height);
  bottom: 0;
  /* Le calage vertical est réglable PAR PAGE. Par défaut l'illustration est centrée dans
     la partie visible du hero ; l'accueil la veut en bas (« margin-bottom: 0 » l'y pousse,
     le « margin-top: auto » absorbant tout le reste). Le calage horizontal, lui, est
     toujours à droite : c'est la composition même des illustrations. */
  margin-block: auto;
  height: calc(100% - var(--header-height));
  width: auto;
  max-width: 100%;
  object-fit: contain;
  object-position: right bottom;

  /* Le fondu porte sur TOUS les bords : les illustrations ont un fond navy proche du nôtre
     sans lui être égal, et tout bord qui ne coïncide pas avec un bord du hero se voit. */
  /* LE FONDU ESTOMPE LES BORDS DE L'IMAGE. Les illustrations portent un fond navy opaque
     proche du nôtre sans lui être égal : tout bord qui ne coïncide pas avec un bord du
     hero se verrait. Le bord DROIT ne fond jamais - il touche toujours celui du hero. */
  -webkit-mask-image: linear-gradient(to right, transparent 0%, #000 22%),
                      linear-gradient(to bottom, transparent 0%, #000 26%, #000 74%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, #000 22%),
              linear-gradient(to bottom, transparent 0%, #000 26%, #000 74%, transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}


/* LA BASE OPAQUE SOUS L'IMAGE. Même raison que dans la maquette : en « contain », l'image
   ne couvre plus que la droite du hero, et le voile de core/cover se retrouverait posé sur
   le fond de la page - une couture verticale franche au bord de l'image.

   C'est la SEULE déclaration de fond que le thème reprend en CSS, et l'exception se
   justifie : le voile reste l'attribut du bloc (gradient + dimRatio, réglables dans
   l'inspecteur) ; ceci n'est que la base sur laquelle il se compose. Le côté gauche vaut
   alors exactement le dégradé nu, et la jonction disparaît par construction. */
.wp-block-cover.hero-page.hero--visuel { background-image: var(--gradient-hero-page); }
.wp-block-cover.hero-page--brand.hero--visuel { background-image: var(--gradient-hero-brand); }
.wp-block-cover.hero-home.hero--visuel { background-image: var(--gradient-hero); }

/* Le hero de l'accueil est très haut : à pleine largeur, l'illustration passait sous tout
   le texte. On la borne - le pendant du --hero-illustration-max de la maquette. */

.hero-page h1 { margin-bottom: var(--space-4); }

/* L'ACCROCHE DU HERO. Elle seule.

   Le surtitre est un <span> dans la maquette, le badge un <div> : « .hero-page p » ne les
   atteint pas. Dans WordPress, Gutenberg ne garde aucun <span> - les deux sont devenus des
   PARAGRAPHES, et la règle les attrapait. Le badge sortait à 1.15 rem, énorme, là où la
   maquette le veut petit et discret.

   C'est le prix du changement de balise, et il se paie ici : chaque règle qui vise « p »
   dans un contexte doit exclure ce qui n'en était pas un. Le :where(:not()) exclut SANS
   ajouter de spécificité - :not() seul en ajouterait, et la règle se mettrait à battre
   celles des composants. */
.hero-page p:where(:not(.is-style-surtitre, .is-style-badge, .badge-texte)) {
  font-size: 1.15rem;
  max-width: 600px;
  margin: 0 auto;
}

/* Le texte d'une pastille (hero, épingle du pied) : il vit désormais dans un
   <p class="badge-texte"> à côté du bloc icône, dans un groupe flex. Il n'hérite
   que de son conteneur (mono, casse, couleur de .is-style-badge ; 0.85rem de
   .footer-location) : aucune règle propre, seulement l'exclusion ci-dessus pour
   qu'il échappe à la mise en forme des paragraphes de hero. */

/* =============================================
   SECTIONS
   ============================================= */

.section { padding: var(--section-padding); }
/* .section-alt : le fond est un ATTRIBUT (backgroundColor « off-white »). */

.section-dark {
  color: var(--on-navy-body);
}

.section-dark h2,
.section-dark h3 { color: var(--on-navy-title); }
.section-dark .is-style-surtitre { color: var(--on-navy-overline); }
/* LE SURTITRE D'UN HERO SOMBRE. Il manquait, et c'était un défaut de contraste ANCIEN,
   antérieur aux heros illustrés : « .section-dark .is-style-surtitre » recevait bien une teinte
   lisible, mais rien n'existait pour « .hero-page .is-style-surtitre ». Le surtitre y restait donc
   en --violet sur navy, soit 1.46:1 - un ratio que le projet documente lui-même plus bas.
   L'illustration de fond ne l'a pas causé : elle l'a rendu visible. */
.hero-page .is-style-surtitre { color: var(--on-navy-overline); }
.section-dark p { color: var(--on-navy-body); }

.is-style-entete-section { text-align: center; max-width: 700px; margin: 0 auto var(--space-16); }

.is-style-surtitre {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--violet);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-3);
  display: block;
}

.overline--left { text-align: left; }

.is-style-entete-section h2 { margin-bottom: var(--space-4); }

/* Le :not(.is-style-surtitre) n'est pas une precaution oiseuse : c'est ce qui rend la regle
   independante de la BALISE qui porte le surtitre.
   Ici, l'overline est un <span>, que « .is-style-entete-section p » n'atteint pas. Mais dans
   WordPress, un surtitre est forcement un PARAGRAPHE - Gutenberg n'a pas de bloc
   <span> - et il tombait alors sous cette regle, dont la specificite (0,1,1) bat
   celle de .is-style-surtitre (0,1,0). Le surtitre y passait a 1.1rem et au gris, au lieu de
   0.75rem et du violet. Le defaut est apparu au portage, la faute etait ici.
   Aucun changement de rendu dans la maquette : elle n'a pas de p.is-style-surtitre. */
.is-style-entete-section p:where(:not(.is-style-surtitre)) { font-size: 1.1rem; color: var(--text-light); line-height: 1.8; }

/* .is-style-entete-section p et .section-dark p ont la même spécificité (0,1,1) : sans
   cette règle, le gris clair l'emporte par ordre de déclaration et tombe à
   2.24:1 sur navy.
   Même :not(.is-style-surtitre), et pour la même raison : (0,2,1) battrait
   « .section-dark .is-style-surtitre » (0,2,0), et le surtitre perdrait sa teinte lisible sur
   fond sombre - celle qui donne 6.97:1 là où le violet n'en donne que 1.46. */
.section-dark .is-style-entete-section p:where(:not(.is-style-surtitre)) { color: var(--on-navy-body); }

/* Liens sur fonds sombres.

   LE GARDE DOIT CONNAÎTRE LES DEUX MONDES. Dans la maquette, un bouton porte « .btn ».
   Dans WordPress, il porte « .wp-element-button » - et « :not(.btn) » ne le voyait pas.
   La règle attrapait donc le bouton du hero et lui donnait la couleur d'un lien : son
   texte virait au violet clair là où la maquette le veut blanc.

   Le garde est en :where(), et c'est capital : :not() AJOUTE de la spécificité, :where()
   n'en ajoute AUCUNE. Avec « a:where(:not(.btn, .wp-element-button)) », le sélecteur pesait (0,2,1) et battait la
   règle du bouton (0,2,0). Avec « a:where(:not(...)) », il pèse (0,1,1) et lui cède la
   place - sans cesser d'habiller les vrais liens. */
.section-dark a:where(:not(.btn, .wp-element-button)),
.cta-band a:where(:not(.btn, .wp-element-button)),
.hero-home a:where(:not(.btn, .wp-element-button)),
.hero-page a:where(:not(.btn, .wp-element-button)) { color: var(--on-navy-overline); }

.section-dark a:where(:not(.btn, .wp-element-button)):hover,
.cta-band a:where(:not(.btn, .wp-element-button)):hover,
.hero-home a:where(:not(.btn, .wp-element-button)):hover,
.hero-page a:where(:not(.btn, .wp-element-button)):hover { color: var(--white); }

/* =============================================
   GRILLES
   ============================================= */

.is-style-grille-2, .is-style-grille-3, .is-style-grille-4 { display: grid; gap: var(--grid-gap, var(--space-10)); }
.is-style-grille-2 { grid-template-columns: repeat(2, 1fr); align-items: center; }
.is-style-grille-3 { grid-template-columns: repeat(3, 1fr); }
.is-style-grille-4 { grid-template-columns: repeat(4, 1fr); }

.gap-sm { --grid-gap: var(--space-4); }
.gap-md { --grid-gap: var(--space-6); }
.gap-lg { --grid-gap: var(--space-8); }
.gap-xl { --grid-gap: var(--space-12); }
.gap-2xl { --grid-gap: var(--space-16); }

.grid--top { align-items: flex-start; }

/* =============================================
   CARTES
   ============================================= */

.is-style-carte {
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-10) var(--space-8);
  box-shadow: var(--shadow);
  transition: var(--transition);
  border: 1px solid var(--gray-200);
}

/* Le soulèvement au survol est commun à toutes les cartes, tarifs compris. Il est
   déclaré ICI, et une seule fois : le -4px est une valeur, pas un token, et deux
   copies auraient fini par diverger. */
.is-style-carte:hover,
.is-style-tarif:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }

/* =============================================
   ICÔNES
   =============================================

   Les icônes étaient des emoji, ce sont désormais des images du thème. Leur
   taille ne se règle donc plus par `font-size` : les conteneurs en portent
   encore un, sans effet sur elles, mais il sert toujours à aligner le texte
   voisin.

   L'icône est un `<span class="icone icone--nom">` VIDE, dont l'illustration est
   une image de FOND (assets/icones.css, généré). Elle était un `<img alt="">` :
   correct au sens de WCAG pour une image décorative, mais les audits d'images
   comptaient 67 « images sans alternative », ne distinguant pas un alt vide d'un
   alt absent. Un fond CSS sort de leur inventaire sans rien changer à
   l'accessibilité. Voir theme/inc/bloc-icone.php.

   width/height, et non plus max-width/max-height : un <span> n'a aucune dimension
   intrinsèque à borner, il se réduirait à zéro. La boîte est donc CARRÉE et
   explicite, et « background-size: contain » y inscrit l'illustration sans en
   déformer aucune - les 44 n'ont pas le même rapport (de 101x150 à 241x169). Seule
   différence avec l'ancien rendu : la boîte ne se rétracte plus à la largeur réelle
   de l'illustration. Dans une vignette ou une ligne de flex, elle est centrée : le
   rendu est identique à l'oeil.

   La valeur par défaut vaut pour les icônes posées dans un titre. */

.icone {
  display: inline-block;
  vertical-align: middle;
  margin: 0;
  width: 1.5rem;
  height: 1.5rem;
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* La TAILLE d'une icône vient de son CONTENEUR quand le bloc orgatypik/icone ne
   la fixe pas lui-même (attribut « taille », prioritaire en style inline). Un
   même bloc fait donc 34 px dans une carte, 26 px dans un verbatim, 104 px dans
   une grande vignette - sans réglage, par le seul contexte. */
.card-icon .icone { width: 34px; height: 34px; }
.value-tile-icon .icone { width: 34px; height: 34px; }
.value-tile-icon--lg .icone { width: 46px; height: 46px; }
.visual-card-icon .icone { width: 104px; height: 104px; }
.visual-card-icon--md .icone { width: 84px; height: 84px; }
.is-style-titre-glyphe .icone { width: 32px; height: 32px; }

/* Ces deux emplacements portaient un glyphe de 12 à 14 px, illisible pour une
   illustration. Ils sont agrandis, ce que leur conteneur absorbe sans casse.
   L'icône est un enfant DIRECT du groupe flex (plus de <span> glyphe) : le
   dimensionnement est le même, le sélecteur descend juste d'un cran. */
.is-style-badge .icone { width: 22px; height: 22px; }
.footer-location .icone { width: 18px; height: 18px; }

/* La vignette carrée d'une carte (l'aplat teinté qui entoure l'icône). C'était un
   style de bloc dédié ; c'est désormais un conteneur ordinaire, le bloc
   orgatypik/icone se posant dedans. L'aplat teinté reste un ATTRIBUT
   (backgroundColor « surface-tint-* » + textColor), montré par l'inspecteur. */
.card-icon {
  width: 56px;
  height: 56px;
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-5);
}

/* Les trois aplats teintés des icônes sont des ATTRIBUTS (backgroundColor
   « surface-tint-* » + textColor). Les presets étaient DÉFINIS dans theme.json et
   JAMAIS EMPLOYÉS : ils le sont enfin, et l'inspecteur les montre. */

.is-style-carte h3 { margin-bottom: var(--space-3); }
/* Le :not() rend la règle indépendante de la BALISE. .is-style-lien-carte (le
   « En savoir plus ») est un PARAGRAPHE dans WordPress et tombait sous cette
   règle, dont la spécificité (0,1,1) bat la sienne (0,1,0), le faisant passer de
   0.85 à 0.95rem. L'icône, elle, n'est plus un paragraphe mais un bloc : la règle
   ne l'atteint plus, un seul :not() suffit désormais. */
.is-style-carte p:where(:not(.is-style-lien-carte)) { color: var(--text-light); font-size: 0.95rem; }

.is-style-lien-carte {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-heading);
  font-size: 0.85rem;
  font-weight: 700;
  color: var(--violet);
  margin-top: var(--space-4);
}

.is-style-lien-carte:hover { gap: 10px; }

/* LE LOGOTYPE D'UNE CARTE DE MARQUE. Les deux mots de marque n'ont pas le même rapport
   (orgatypik 4.55, pylotik 3.46) : on borne la HAUTEUR, jamais la largeur, sinon l'un
   paraîtrait deux fois plus gros que l'autre. 30 px les met à la même présence optique.

   En blocs, l'image est enveloppée d'une <figure> : la règle porte donc sur les deux. */
.card-logo { margin-bottom: var(--space-5); }
.card-logo img { height: 30px; width: auto; display: block; }

/* Carte à vignette (articles de blog) */
.card--media { padding: 0; overflow: hidden; }



.card-body { padding: var(--space-7) var(--space-6); }
/* Le titre de carte est dimensionne par son ROLE, pas par sa balise : le bloc
   « Titre de l'article » sort en h2 (hierarchie correcte sous le h1 de la page),
   mais garde la taille compacte d'une vignette. */
.card-body h3,
.card-body .wp-block-post-title { font-size: 1.05rem; margin: var(--space-3) 0 var(--space-2); }
.card-body p { font-size: 0.85rem; color: var(--gray-400); }

/* =============================================
   VERBATIMS
   ============================================= */

/* Flex plutôt que grille : la grille aligne les orphelins de la dernière rangée à
   gauche, sans moyen de les centrer. En flex, `justify-content: center` centre la
   rangée incomplète, et le `max-width` à un tiers empêche les deux cartes de la
   dernière rangée de s'étirer sur toute la largeur. Les rangées pleines, elles,
   remplissent exactement (3 × un tiers + 2 gouttières = 100 %). */
.is-style-miroir {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5);
}

.is-style-verbatim {
  flex: 1 1 280px;
  max-width: calc((100% - 2 * var(--space-5)) / 3);
  margin: 0;                       /* le verbatim est un bloc Citation : on ôte sa marge par défaut */
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-7) var(--space-6);
  /* Filet fin et transparent sur tout le pourtour, plutôt qu'une barre latérale
     colorée : au repos il ne se voit pas mais réserve la place, si bien que le
     survol ne décale rien. */
  border: 1px solid transparent;
  box-shadow: var(--shadow);
  font-size: 0.95rem;
  color: var(--gray-600);
  font-style: italic;
  line-height: 1.7;
  transition: var(--transition);
}

/* Au survol : le filet passe en violet et la carte grossit légèrement. */
.is-style-verbatim:hover { border-color: var(--violet); transform: scale(1.03); }

/* =============================================
   ÉTAPES DE MÉTHODE
   ============================================= */

.is-style-etape {
  display: flex;
  gap: var(--space-10);
  align-items: flex-start;
  padding: var(--space-12) 0;
  border-bottom: 1px solid var(--gray-200);
}

.is-style-etape:last-child { border-bottom: none; }

.is-style-numero-etape {
  font-family: var(--font-heading);
  font-size: 4rem;
  font-weight: 900;
  background: var(--gradient-brand-text);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  opacity: 0.15;
  line-height: 1;
  flex-shrink: 0;
  width: 100px;
  text-align: center;
}

.step-content h3 { margin-bottom: var(--space-3); display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }


/* =============================================
   TÉMOIGNAGES
   ============================================= */

.is-style-temoignage {
  margin: 0;                       /* le témoignage est un bloc Citation : on ôte sa marge par défaut */
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-10);
  box-shadow: var(--shadow);
  position: relative;
  border: 1px solid var(--gray-200);
}

.is-style-temoignage::before {
  content: '❝';
  font-size: 4rem;
  color: var(--violet);
  opacity: 0.15;
  position: absolute;
  top: var(--space-4);
  left: var(--space-6);
  line-height: 1;
}

.is-style-temoignage p {
  font-size: 1rem;
  line-height: 1.8;
  color: var(--gray-600);
  margin: 0 0 var(--space-5);
}

/* L'auteur et son rôle vivent dans le <cite> de la citation : l'auteur en gras
   (le <strong>), le rôle sur la ligne suivante (après le <br>). */
.is-style-temoignage cite {
  display: block;
  font-style: normal;
  font-size: 0.8rem;
  color: var(--gray-400);
}

.is-style-temoignage cite strong {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--navy);
}

/* Les études de cas ne portent plus de témoignage imbriqué : nommer un client
   à côté de la description de ses difficultés relèverait du secret des affaires.
   Les avis clients restent sur la page d'accueil, publiés avec leur accord. */

/* =============================================
   TARIFS
   ============================================= */

.is-style-tarif {
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-10) var(--space-8);
  border: 2px solid var(--gray-200);
  text-align: center;
  transition: var(--transition);
}

.is-style-tarif.featured { border-color: var(--violet); position: relative; }

.is-style-tarif.featured::before {
  content: 'Populaire';
  position: absolute;
  top: -12px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--violet);
  color: var(--white);
  font-family: var(--font-mono);
  font-size: 0.7rem;
  font-weight: 600;
  padding: var(--space-1) var(--space-4);
  border-radius: var(--radius-pill);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Le survol de .is-style-tarif est déclaré avec celui de .is-style-carte, section CARTES. */

.pricing-title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--navy);
  margin-bottom: var(--space-2);
}

.pricing-price {
  font-family: var(--font-heading);
  font-size: 1.8rem;
  font-weight: 800;
  color: var(--navy);
  margin: var(--space-4) 0 var(--space-1);
}

.pricing-price small { font-size: 0.9rem; font-weight: 500; color: var(--gray-400); }
.pricing-desc { font-size: 0.85rem; color: var(--gray-400); margin-bottom: var(--space-6); }
.pricing-note { text-align: center; color: var(--gray-400); font-size: 0.85rem; margin-top: var(--space-6); }

.is-style-cochee { list-style: none; text-align: left; margin-bottom: var(--space-8); }

.is-style-cochee li {
  padding: var(--space-2) 0;
  font-size: 0.9rem;
  color: var(--gray-600);
  border-bottom: 1px solid var(--gray-100);
  display: flex;
  align-items: center;
  gap: 10px;
}

.is-style-cochee li::before { content: '✓'; color: var(--violet); font-weight: 700; flex-shrink: 0; }

/* =============================================
   TABLE COMPARATIVE
   ============================================= */

/* La marge HAUTE n'est plus ici : elle est un ATTRIBUT de bloc (style.spacing.margin),
   posé par convertir.py et par la composition. WordPress écrit
   « :root :where(.is-layout-flow) > :first-child { margin-block-start: 0 } », de
   spécificité (0,2,0) : aucune règle raisonnable ne la bat, et le tableau collait au
   texte dès qu'il ouvrait son conteneur. Un attribut rend un style inline, qui gagne
   toujours - et que l'inspecteur montre. */
.is-style-comparatif {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}

/* AUCUN TRAIT SOUS L'EN-TÊTE. L'aplat pastel suffit à le séparer des lignes : un trait
   par-dessus ferait double emploi. La règle est écrite en NÉGATIF, et c'est délibéré -
   WordPress, lui, pose « thead { border-bottom: 3px solid } » sur son bloc Tableau, à la
   couleur du texte. Sans cette ligne, un trait noir de 3 px barrait le tableau sur le
   site, là où la maquette n'en avait aucun. */
.is-style-comparatif thead { border-bottom: none; }

/* L'en-tête est un APLAT CLAIR - le pastel navy de la charte, --surface-table-head.

   Il était navy foncé, ce qui obligeait le wordmark à sa variante « fond sombre ».
   Or le wordmark d'orgatypik EST le dégradé navy -> violet : le montrer sur clair,
   c'est le montrer tel qu'il est. Le fond clair n'est donc pas un choix esthétique,
   c'est ce qui rend le logotype fidèle.

   Contrastes vérifiés sur le pastel (#D4D9EC) : navy 8.55:1, et l'arrêt violet du
   wordmark 5.85:1 - AA en texte courant l'un comme l'autre, sans avoir à invoquer
   la clause du texte large. Le point gris, lui, change de gris : voir .brand-word.

   L'aplat se distingue du zébrage des lignes paires (--off-white), bien plus clair :
   l'en-tête se lit comme un en-tête. */
.is-style-comparatif th {
  font-family: var(--font-heading);
  font-weight: 600;   /* un cran au-dessus des lignes (400), sans l'excès du 700 */
  padding: var(--space-3) var(--space-5);
  text-align: left;
  vertical-align: middle;   /* centre « Cabinet classique » et l'image du wordmark : sinon
                               l'alignement se fait sur la baseline et le texte remonte. */
  background: var(--surface-table-head);
  color: var(--navy);
  width: 50%;
}

.is-style-comparatif th:first-child { border-radius: var(--radius-md) 0 0 0; }
.is-style-comparatif th:last-child { border-radius: 0 var(--radius-md) 0 0; }

/* 1.2rem en graisse 800 font 19.2px gras : « texte large » au sens WCAG, seuil 3:1.
   Le wordmark y est très au-dessus (5.85:1 au pire arrêt), donc contrairement à la
   variante sur fond sombre, le réduire ne le mettrait pas en défaut. line-height: 1
   empêche la ligne de grandir : sans lui, l'en-tête gagnerait 8px pour rien. */
.is-style-comparatif th .brand-word { height: 1.109rem; }   /* wordmark plus petit dans le tableau (ink de 1.2rem) */

.is-style-comparatif td { padding: 14px var(--space-5); border-bottom: 1px solid var(--gray-200); }
.is-style-comparatif tr:last-child td { border-bottom: none; }
.is-style-comparatif tr:nth-child(even) { background: var(--off-white); }

/* LA LIGNE MISE EN ÉVIDENCE : LA DERNIÈRE DU CORPS, ET C'EST STRUCTUREL.

   Aucune classe sur le <tr>, et ce n'est pas une préférence : le save() de core/table
   ne conserve d'une cellule que « content », « tag », « align », « colspan » et
   « rowspan ». Une rangée porteuse de classe rendrait le bloc INVALIDE dans l'éditeur.
   Le repère est donc positionnel - la ligne mise en avant est la dernière -, ce qui est
   la seule forme que WordPress sait reproduire à l'identique.

   L'aplat est le PASTEL VIOLET de la charte (#E2DAF0, aplat only) : il se distingue du
   pastel navy de l'en-tête sans sortir de la palette. Contrastes mesurés dessus :
   navy 8.89:1, et le wordmark 7.12:1 sur son segment bleu - le segment terracotta
   (3.19:1) et le point (2.36:1) relèvent du logotype, exempté par WCAG 1.4.11.

   Le zébrage des lignes paires est battu SANS !important : (0,2,1) contre (0,2,0). Le
   « border-bottom: none » de tr:last-child, lui, est à égalité - d'où la position de
   ce bloc APRÈS lui dans le fichier, qui est ce qui tranche. */
.is-style-comparatif tbody tr:last-child td {
  background: var(--pastel-violet);
  color: var(--navy);
  font-weight: 500;
  border-top: 2px solid var(--violet);
  border-bottom: none;
}
.is-style-comparatif tbody tr:last-child td:first-child { border-radius: 0 0 0 var(--radius-md); }
.is-style-comparatif tbody tr:last-child td:last-child { border-radius: 0 0 var(--radius-md) 0; }

/* =============================================
   BANDE D'APPEL À L'ACTION
   ============================================= */

.cta-band {
  color: var(--white);
  padding: var(--space-20) 0;
  text-align: center;
  position: relative;
  overflow: hidden;
}

/* .cta-band--deep : dégradé « cta-deep » en attribut. */

.cta-band h2 { color: var(--on-navy-title); margin-bottom: var(--space-4); }
.cta-band p { color: var(--on-navy-body); font-size: 1.1rem; max-width: 560px; margin: 0 auto var(--space-8); }

/* =============================================
   FORMULAIRE
   ============================================= */

.form-heading { margin-bottom: var(--space-2); }
.form-intro { color: var(--gray-600); margin-bottom: var(--space-8); }

.form-group { margin-bottom: var(--space-6); }

.form-group label {
  display: block;
  font-family: var(--font-heading);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: var(--space-2);
}

.form-group input,
.form-group textarea,
.form-group select {
  width: 100%;
  padding: 14px var(--space-4);
  font-family: var(--font-body);
  font-size: 0.95rem;
  border: 2px solid var(--gray-200);
  border-radius: var(--radius-md);
  transition: var(--transition);
  background: var(--white);
  color: var(--text);
}

.form-group input:focus,
.form-group textarea:focus,
.form-group select:focus {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 4px var(--ring-focus);
}

.form-group textarea { resize: vertical; min-height: 140px; }

/* Champ de téléversement : le remplissage vertical du sélecteur natif diffère
   d'un navigateur à l'autre, on l'aligne sur les autres champs. */
.form-group input[type="file"] { padding: 11px var(--space-4); font-size: 0.9rem; cursor: pointer; }


/* États de validation.
   :required   - n'annote que les champs contraints, pas les champs optionnels.
   :not(:placeholder-shown) - n'annote qu'un champ déjà saisi, pas un champ vierge.
   Les champs requis portent donc tous un placeholder, même un simple espace. */
.form-group input:required:not(:placeholder-shown):invalid,
.form-group textarea:required:not(:placeholder-shown):invalid { border-color: var(--error); }

.form-group input:required:not(:placeholder-shown):valid,
.form-group textarea:required:not(:placeholder-shown):valid { border-color: var(--success); }

/* Les modificateurs .form-hint--error / --success / --attention ont été RETIRÉS.
   Ils n'étaient posés sur aucun élément, et .form-hint doublait exactement
   .form-hint-inline, plus haut. Leur commentaire prétendait « donner un usage aux
   tokens d'état » : c'est faux, --error et --success colorent les bordures
   :invalid et :valid ci-dessus, et --attention colore .legal-todo. Ils vivent
   sans ces classes.

   Le formulaire de production apportera son propre balisage, et donc ses propres
   classes. Écrire un contrat que personne ne signera, c'est du code mort qui a
   l'air d'une intention. */

.form-consent {
  font-size: 0.8rem;
  color: var(--gray-400);
  margin-top: var(--space-3);
  text-align: center;
}

/* --link (6.58:1) plutôt que --navy : dans un paragraphe déjà gris,
   le navy manque d'affordance de lien. */
.form-consent a { color: var(--link); text-decoration: underline; }
.form-consent a:hover { color: var(--violet); }

::placeholder { color: var(--gray-400); opacity: 1; }

/* Espace réservé au formulaire. convertir.py ne génère plus le formulaire (CF7
   s'insère à la main) : il pose ce marqueur à la place du <form>, que le rédacteur
   remplace par le shortcode [contact-form-7 …]. */
.form-placeholder {
  padding: var(--space-8);
  border: 2px dashed var(--gray-200);
  border-radius: var(--radius-md);
  color: var(--gray-400);
  text-align: center;
  font-size: 0.9rem;
}

/* --- CONTACT FORM 7 À L'HABIT ORGATYPIK ---

   La production emploie CF7 (+ WP Armour, honeypot LOCAL : sans cookie ni service
   tiers, vérifié). CF7 a son propre balisage - le formulaire du thème l'avait prévu
   (plus haut : « le formulaire de production apportera ses propres classes »). On
   reporte donc, via les mêmes tokens que .form-group, le style sur les classes CF7. */

/* L'espace ENTRE champs vient du <p> que CF7 pose autour de chacun (le reset global
   l'a mis à 0). C'est le bon porteur : il vaut pour le champ texte (label enveloppant)
   comme pour le champ à cases (label séparé). */
.wpcf7-form p { margin-bottom: var(--space-6); }
.wpcf7-form p:last-of-type { margin-bottom: 0; }
/* Le <br> que CF7 glisse entre un label séparé et sa liste de cases : inutile,
   l'espace vient du margin-top du wrap. */
.wpcf7-form p > br { display: none; }

/* Le libellé de champ, en DM Sans. Pas de marge basse : l'espace vers le champ vient
   du wrap, l'espace vers le champ suivant vient du <p>. */
.wpcf7-form label {
  display: block;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--navy);
  margin-bottom: 0;
}
.wpcf7-form .wpcf7-form-control-wrap { display: block; margin-top: var(--space-2); }

/* La case de consentement : discrète, comme .form-consent (pas un libellé de champ). */
.wpcf7-form .wpcf7-acceptance { display: block; margin-top: var(--space-3); }
.wpcf7-form .wpcf7-acceptance .wpcf7-list-item { margin: 0; }
.wpcf7-form .wpcf7-acceptance label {
  display: flex;
  gap: var(--space-2);
  align-items: flex-start;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--gray-400);
  margin-bottom: 0;
}
/* La case à cocher : la case native de CF7 est laide. On la remplace par une case
   à l'habit orgatypik - contour gris, violet une fois cochée, coche blanche. */
.wpcf7-form input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin: 2px 0 0;
  border: 2px solid var(--gray-200);
  border-radius: var(--radius-sm);
  background: var(--white);
  cursor: pointer;
  transition: var(--transition);
  position: relative;
}
.wpcf7-form input[type="checkbox"]:hover { border-color: var(--violet); }
.wpcf7-form input[type="checkbox"]:checked {
  background: var(--violet);
  border-color: var(--violet);
}
.wpcf7-form input[type="checkbox"]:checked::after {
  content: '';
  position: absolute;
  left: 5px;
  top: 1px;
  width: 4px;
  height: 9px;
  border: solid var(--white);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.wpcf7-form input[type="checkbox"]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--ring-focus);
}

/* Les LISTES de cases (champ checkbox/radio) - PAS le consentement RGPD, qui est
   multi-ligne et reste aligné en haut. Ici les items sont courts : la case et son
   libellé sur une ligne, centrés verticalement. Sans ça, le libellé hérite de la
   règle d'étiquette générale (bloc, grande marge) et se désaligne de la case. */
.wpcf7-form .wpcf7-checkbox .wpcf7-list-item,
.wpcf7-form .wpcf7-radio .wpcf7-list-item { display: block; margin: 0 0 var(--space-2); }
.wpcf7-form .wpcf7-checkbox .wpcf7-list-item label,
.wpcf7-form .wpcf7-radio .wpcf7-list-item label {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  font-family: var(--font-body);
  font-size: 0.9rem;
  font-weight: 400;
  color: var(--text);
  margin-bottom: 0;
}
.wpcf7-form .wpcf7-checkbox input[type="checkbox"] { margin: 0; }

/* Les champs de saisie - PAS le bouton, ni les cases (acceptation, cases à cocher,
   radios), qui sont aussi des .wpcf7-form-control mais ne veulent pas de cadre. */
.wpcf7-form .wpcf7-form-control:not(.wpcf7-submit):not(.wpcf7-acceptance):not(.wpcf7-checkbox):not(.wpcf7-radio) {
  width: 100%;
  padding: 14px var(--space-4);
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 400;
  border: 2px solid var(--gray-200);
  border-radius: var(--radius-md);
  transition: var(--transition);
  background: var(--white);
  color: var(--text);
}
.wpcf7-form .wpcf7-form-control:not(.wpcf7-submit):not(.wpcf7-acceptance):not(.wpcf7-checkbox):not(.wpcf7-radio):focus {
  outline: none;
  border-color: var(--violet);
  box-shadow: 0 0 0 4px var(--ring-focus);
}
.wpcf7-form .wpcf7-textarea { resize: vertical; min-height: 140px; }

/* Le champ de téléversement (le CV) : le bouton natif « Choisir un fichier » est
   laid. On refait ce pseudo-élément en petit bouton teinté, façon bouton secondaire. */
.wpcf7-form input[type="file"] { padding-top: 9px; padding-bottom: 9px; cursor: pointer; }
.wpcf7-form input[type="file"]::file-selector-button,
.wpcf7-form input[type="file"]::-webkit-file-upload-button {
  margin-right: var(--space-4);
  padding: 8px var(--space-4);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.85rem;
  color: var(--violet);
  background: var(--surface-tint-violet);
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: var(--transition);
}
.wpcf7-form input[type="file"]::file-selector-button:hover,
.wpcf7-form input[type="file"]::-webkit-file-upload-button:hover {
  background: var(--violet);
  color: var(--white);
}

/* Le champ fautif et son message (CF7 pose .wpcf7-not-valid). */
.wpcf7-form .wpcf7-not-valid { border-color: var(--error); }
.wpcf7-form .wpcf7-not-valid-tip { color: var(--error); font-size: 0.85rem; margin-top: var(--space-2); }

/* Le bouton d'envoi, calé sur .btn-primary. */
.wpcf7-form .wpcf7-submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  padding: 14px var(--space-8);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  border: none;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: var(--transition);
  background: var(--violet);
  color: var(--white);
  box-shadow: var(--shadow-violet);
}
.wpcf7-form .wpcf7-submit:hover {
  background: var(--violet-dark);
  transform: translateY(-2px);
  box-shadow: var(--shadow-violet-lg);
}

/* Le message de retour, calé sur .form-succes / .form-erreur. */
.wpcf7-form .wpcf7-response-output {
  margin: var(--space-6) 0 0;
  padding: var(--space-5) var(--space-6);
  border: none;
  border-left: 4px solid var(--gray-200);
  border-radius: var(--radius-md);
  background: var(--off-white);
  font-size: 0.95rem;
}
.wpcf7-form.sent .wpcf7-response-output { border-left-color: var(--success); color: var(--success); }
.wpcf7-form.invalid .wpcf7-response-output,
.wpcf7-form.failed .wpcf7-response-output,
.wpcf7-form.spam .wpcf7-response-output { border-left-color: var(--error); color: var(--error); }

/* =============================================
   PIED DE PAGE
   ============================================= */

.site-footer {
  background: var(--gradient-footer);
  color: var(--on-navy-body);
  padding: var(--space-16) 0 var(--space-8);
}

.footer-grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--space-12); margin-bottom: var(--space-12); }

.footer-brand p { font-size: 0.9rem; line-height: 1.7; color: var(--on-navy-muted); margin-top: var(--space-3); }
.footer-brand a { color: var(--on-navy-muted); }

/* Les survols emploient --on-navy-accent (5.88:1) et non --violet-light,
   qui ne donne que 3.72:1 sur navy - un état de survol reste soumis à l'AA. */
.footer-brand a:hover { color: var(--on-navy-accent); }

/* L'épingle du pied : un groupe flex [bloc icône + texte], et non plus un
   paragraphe à icône en ligne (invalide sous Gutenberg). Le flex remet l'icône à
   côté du texte, là où le CSS de la maquette l'avait en ligne. */
.footer-location { display: flex; align-items: center; gap: var(--space-2); margin-top: var(--space-4); font-size: 0.85rem; }

/* Titres de colonnes. Ce sont des <h2> et non des <h4> : après le <h2> de
   la bande d'appel à l'action, un <h4> créait un saut de niveau. */
.footer-col-title {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--on-navy-muted);
  margin-bottom: var(--space-5);
}

.footer-col a { display: block; font-size: 0.9rem; color: var(--on-navy-muted); padding: var(--space-1) 0; }
.footer-col a:hover { color: var(--on-navy-accent); }

/* Les colonnes de liens sont un bloc Liste : on ôte puces et marges de la liste, le
   lien reste en display:block ci-dessus - le rendu est celui des <a> nus de la maquette. */
.footer-col ul { list-style: none; margin: 0; padding: 0; }
.footer-col li { margin: 0; }

.footer-bottom {
  border-top: 1px solid var(--on-navy-border-subtle);
  padding-top: var(--space-6);
  display: flex;
  justify-content: space-between;
  font-size: 0.8rem;
  font-family: var(--font-mono);
}

.footer-bottom a { color: var(--on-navy-muted); }
.footer-bottom a:hover { color: var(--on-navy-accent); }

/* Le copyright était un <span> ; en bloc c'est un paragraphe, dont on ôte la marge. */
.footer-copy { margin: 0; }

/* Les liens légaux sont un bloc Liste : rangée horizontale, sans puces ni marges. */
.footer-legal { display: flex; gap: var(--space-6); flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.footer-legal li { margin: 0; }

/* =============================================
   RANGÉE DE PRÉSENTATION
   ============================================= */

.is-style-rangee { display: flex; align-items: center; gap: var(--space-16); padding: 60px 0; }
.is-style-rangee.reverse { flex-direction: row-reverse; }
.feature-visual { flex: 1; min-width: 0; }
.feature-content { flex: 1; min-width: 0; }

.is-style-accroche { font-size: 1.05rem; margin: var(--space-4) 0 var(--space-5); }

/* Ligne de crédibilité sous un titre : une affirmation courte, pas un paragraphe. */
.feature-credential {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--violet);
  letter-spacing: 0.02em;
  border-left: 3px solid var(--violet);
  padding-left: var(--space-3);
  margin-top: var(--space-4);
  margin-bottom: 0;
}

.feature-visual-box {
  border-radius: var(--radius);
  padding: var(--space-12);
  text-align: center;
  border: 1px solid var(--gray-200);
  min-height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 4rem;
}

/* Le conteneur porte font-size: 4rem pour les glyphes décoratifs posés
   directement dedans. Toute carte de contenu doit donc remettre à l'échelle. */
.is-style-carte-visuelle { text-align: center; font-size: 1rem; }

/* Panneau de marque CLAIR : le fond pastel navy → violet vient d'un attribut de
   bloc (gradient « panel-soft »), pas du CSS, pour rester pilotable dans
   l'éditeur. Le CSS ne pose que la bordure, accordée au pastel. */
.feature-visual-box--brand {
  border-color: var(--pastel-navy);
}

/* LES DEUX EMBLÈMES DE SOUVERAINETÉ. Une seule image pour les deux : ils se lisent
   ensemble - le lieu d'hébergement et le périmètre de conservation - et les séparer
   en deux fichiers aurait laissé leur alignement à la merci du conteneur. */
.emblemes {
  display: block;
  width: 100%;
  max-width: 480px;
  height: auto;
  margin: 0 auto var(--space-8);
}

/* Illustration servie en fichier .svg via <img> : porte un alt, contrairement
   à un <svg> inline. Ses couleurs sont figées, elles ne suivent pas les tokens. */
/* LA CLASSE N'EST PLUS SUR L'IMAGE, MAIS SUR LA <figure>.
   Gutenberg pose le className d'un bloc Image sur son <figure>, jamais sur son <img> :
   c'est le conteneur qu'il enveloppe. La règle vise donc les deux - le cadre sur la
   figure, la taille sur l'image qu'elle contient. */
.is-style-figure {
  display: block;
  margin: 0;
  border-radius: var(--radius);
  border: 1px solid var(--gray-200);
  background: var(--white);
  overflow: hidden;
}

.is-style-figure img,
img.is-style-figure {
  display: block;
  width: 100%;
  height: auto;
}

/* Variante posée à même un fond sombre : le SVG y est transparent. */
.feature-figure--bare { border: none; background: transparent; overflow: visible; }

/* Citation d'une source externe. À distinguer d'un témoignage client :
   ici on cite un tiers, pas un client. */
.is-style-source {
  max-width: 760px;
  margin: var(--space-12) auto 0;
  padding: var(--space-6) var(--space-8);
  border-left: 4px solid var(--violet);
  background: var(--white);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}

.is-style-source p {
  font-size: 1rem;
  line-height: 1.8;
  color: var(--gray-600);
  font-style: italic;
  margin-bottom: var(--space-3);
}

.is-style-source cite {
  font-family: var(--font-heading);
  font-style: normal;
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--navy);
}

.visual-card-icon { font-size: 5rem; margin-bottom: var(--space-4); }
.visual-card-icon--md { font-size: 4rem; margin-bottom: var(--space-4); }

/* La carte de marque : un GROUPE [libellé + wordmark] et non plus un <p> à image
   en ligne (invalide). La police et la couleur, posées ici, sont héritées par le
   libellé interne ; l'image du wordmark est dimensionnée juste en dessous. */
.visual-card-title {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--navy);
  font-size: 1rem;
  margin: 0;
}

/* Le wordmark est désormais un BLOC image. On neutralise l'habit inline de
   .brand-word sur son figure et on dimensionne l'image dedans, centrée sous le
   libellé (le .visual-card centre déjà le texte). */
.visual-card-title .brand-word { display: block; height: auto; }
.visual-card-title .brand-word img { height: 1.386rem; width: auto; margin: 0 auto; display: block; }

.visual-card-sub { color: var(--violet); }

.visual-card--on-dark { color: var(--white); }
.visual-card--on-dark .visual-card-title { color: var(--white); font-size: 1.2rem; }
/* Sur navy, --violet ne donne que 1.46:1. --on-navy-overline donne 6.97:1. */
.visual-card--on-dark .visual-card-sub { color: var(--on-navy-overline); font-size: 0.9rem; }

/* Le schéma silo/transversal était construit en CSS. Il est désormais servi
   comme fichier assets/silo-transversal.svg, via <img class="feature-figure">,
   afin de porter un attribut alt exploitable. */

/* =============================================
   LISTE À PUCES
   ============================================= */

.is-style-billes { list-style: none; margin: var(--space-5) 0; }

/* Surtout PAS `display: flex` sur le <li>. Il transformait chaque enfant en
   élément flex : dans « <strong>Exploration simultanée</strong> de toutes les
   pistes », le <strong> et le texte qui suit devenaient DEUX éléments, et le
   `gap` s'insérait entre eux. D'où l'espace étrange après chaque terme en gras.
   La puce est donc détachée du flux, en position absolue. */
.is-style-billes li {
  position: relative;
  padding: 3px 0 3px var(--space-6);
  font-size: 0.95rem;
  line-height: 1.6;
}

/* Une bille, pas un glyphe : un caractère aurait sa propre chasse et son propre
   calage vertical, impossibles à centrer proprement.

   Le centrage vertical porte sur la PREMIÈRE ligne, pas sur le bloc : sur une
   puce qui passe à la ligne, la bille doit rester en face du début du texte.

   Attention au piège : une boîte en `position: absolute` se cale sur la
   PADDING-BOX du parent. `top: 0` vise donc le bord du <li>, pas le début du
   texte, qui commence 3 px plus bas (le padding-top). Le calcul doit les ajouter :
     3px (padding) + 0.8em (demi-hauteur de ligne) - 3.5px (rayon de la bille)
   Sans le padding, la bille remonte de 3 px.

   Le +0.5px final est mesuré, pas devine : la demi-hauteur de ligne vise le milieu
   de l'INTERLIGNE, or l'encre du texte n'y est pas centree (les jambages la tirent
   vers le bas). Le rendu montrait la bille 1 px trop haut. */
.is-style-billes li::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(0.8em + 0.5px);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--violet);
}

/* Sur fond sombre, le violet de la bille tombe à 1.46:1 sur --navy-mid : elle
   disparaîtrait. La lavande y tient 4.96:1. Le texte des <li>, lui, hérite
   déjà de --on-navy-body via .section-dark. */
.section-dark .is-style-billes li::before { background: var(--on-navy-accent); }

/* =============================================
   COMPTEURS ET STATISTIQUES
   ============================================= */

.counter-row { display: flex; justify-content: center; gap: var(--space-20); text-align: center; flex-wrap: wrap; }

.is-style-compteur .counter-value {
  font-family: var(--font-heading);
  font-size: 3rem;
  font-weight: 900;
  background: var(--gradient-brand-text);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.is-style-compteur .counter-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--gray-400);
  margin-top: var(--space-1);
}

/* Les grands chiffres d'engagement étaient composés en CSS. Ils sont désormais
   servis par assets/engagement-gallup.svg, qui porte un attribut alt exploitable.
   Les tokens --on-navy-stat-* restent la référence des couleurs de ce SVG :
   toute modification du fichier doit reprendre leurs valeurs. */

/* p.stat-caption : porte le même poids (0,1,1) que .section-dark p, et le
   suit dans la feuille - sans le sélecteur de type, la couleur serait écrasée. */
p.stat-caption {
  text-align: center;
  color: var(--on-navy-muted);
  margin: var(--space-10) auto 0;
  max-width: 600px;
}

.stat-caption strong { color: var(--on-navy-body); }

/* Encart de note statistique sous une grille sombre */
.stat-note {
  text-align: center;
  margin-top: var(--space-12);
  padding-top: var(--space-10);
  border-top: 1px solid var(--on-navy-divider);
}

.stat-note p { color: var(--on-navy-muted); font-size: 0.9rem; font-family: var(--font-heading); }

  /* 3.72:1 sur navy-mid - TEXTE LARGE */ /* 5.87:1 sur navy-mid */

/* =============================================
   TUILES DE VALEUR
   ============================================= */

.is-style-tuile { padding: var(--space-6) 0; }
.value-tile--center { text-align: center; padding: var(--space-6) var(--space-4); }

.is-style-tuile h3 { color: var(--on-navy-title); margin-bottom: var(--space-2); font-size: 1.1rem; }
.value-tile--center h3 { font-size: 1rem; }
/* L'icône de tuile n'est plus un paragraphe mais un bloc : « .is-style-tuile p »
   ne l'atteint pas, un :not() de moins. */
.is-style-tuile p { color: var(--on-navy-muted); font-size: 0.9rem; }
.value-tile--center p { font-size: 0.85rem; }

/* =============================================
   PANNEAUX
   ============================================= */

.is-style-panneau {
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-10);
  border: 1px solid var(--gray-200);
  text-align: center;
}

.is-style-panneau h3 { margin-bottom: var(--space-4); }
.is-style-panneau p { max-width: 640px; margin: 0 auto; color: var(--gray-600); }

/* Un .is-style-panneau garde son fond blanc à l'intérieur d'une section sombre. Sans ces
   trois règles, la cascade de .section-dark y repeindrait le texte en blanc :
   `.section-dark h3` et `.section-dark h3` ont la même spécificité que
   `.is-style-panneau h3`, et le second perdrait à l'ordre d'apparition. On qualifie donc,
   plutôt que de forcer. Ratios sur blanc : navy 12.03:1, gray-600 7.04:1,
   link 6.58:1. */
.section-dark .is-style-panneau h3 { color: var(--navy); }
.section-dark .is-style-panneau p { color: var(--gray-600); }
/* LE PANNEAU EST UNE ÎLE CLAIRE DANS UNE SECTION SOMBRE, et ses liens doivent suivre
   la règle du fond CLAIR - sans quoi « .section-dark a:where(:not(.btn, .wp-element-button)) » leur donnerait la
   couleur du fond sombre, illisible sur ce blanc.

   Le sauvetage se faisait avec --link, et c'était le mauvais bleu : --link est réservé
   aux textes DÉJÀ GRIS, où le navy manque d'affordance (CLAUDE.md §3). Le texte du
   panneau n'est pas gris. On obtenait donc un lien bleu vif au milieu d'une page dont
   tous les autres liens de corps sont navy. C'est --navy qu'il faut, comme partout
   ailleurs sur fond clair : 12.03:1 sur blanc. */
.section-dark .is-style-panneau a:where(:not(.btn, .wp-element-button)) { color: var(--navy); }

.panel--sm { padding: var(--space-8); text-align: left; }

/* PANNEAU DE MARQUE : LE PANNEAU BLANC DISPARAISSAIT SUR SECTION BLANCHE.

   .panel est blanc bordé de gris ; posé sur .section (blanc lui aussi), il ne se
   détachait plus - seul son filet le signalait. Cette variante lui donne l'aplat
   PASTEL VIOLET de la charte (#E2DAF0, aplat only), le même que la ligne mise en
   avant du tableau comparatif : sur cette page, tout ce qui parle de pylotik porte
   la même teinte, et c'est ce qui en fait un repère plutôt qu'une décoration.

   Le gradient --gradient-panel-soft a été écarté, et pour une raison mesurée : son
   premier arrêt est le pastel navy #D4D9EC, sur lequel --gray-600 (la couleur de
   .panel p) ne donne que 4.44:1 - sous le seuil AA de 4,5:1. Sur le pastel violet
   seul, les trois encres du panneau passent : gris 4.62:1, navy 8.89:1, lien 4.87:1.
   Un aplat plat vaut mieux qu'un dégradé dont une extrémité échoue. */
.panel--brand {
  background: var(--pastel-violet);
  border-color: var(--pastel-navy);
}

/* LE MOT DE MARQUE pylotik AU FIL DU TEXTE.

   Le wordmark composé (trois segments colorés) ne peut pas être du texte : il faudrait
   trois <span> imbriqués, et Gutenberg n'en conserve aucun. C'est donc une IMAGE, comme
   celui d'orgatypik - mais posée EN LIGNE, à la taille du texte qui l'entoure, et non
   en logotype de bloc (.brand-word, qui est fixe à 1.386rem).

   Deux fichiers, et le choix se fait par le FOND, jamais par le CSS : -light sur fond
   clair, -dark sur fond sombre. Un background-image aurait permis de basculer par
   sélecteur de contexte, mais le mot de marque est du TEXTE au sens du lecteur d'écran :
   il lui faut un alt, donc un <img>. C'est l'inverse du choix fait pour les icônes, et
   pour la raison inverse - elles sont décoratives, lui ne l'est pas.

   Sans point final : le point appartient au logotype composé, pas à la marque citée dans
   une phrase, où il se lirait comme une fin de phrase (convention pylotik).

   1.05em et non 1em : la hauteur du fichier couvre l'ascendante ET la descendante du
   « p », là où la capitale d'une police n'occupe qu'une part du cadratin. Sans cette
   correction le mot paraissait rétréci au milieu du texte. Le décalage de baseline
   compense la descendante.

   Contraste : aucune exigence. WCAG 1.4.3 exempte explicitement « le texte qui fait
   partie d'un logo ou d'un nom de marque ». Pour mémoire, les valeurs mesurées : sur
   blanc, segment bleu 9.64:1 et terracotta 4.31:1 ; sur --navy-mid (le stop le plus
   clair de nos fonds sombres), la variante sombre donne 3.29:1 sur ses trois segments. */
.wm-pylotik {
  display: inline-block;
  height: 1.05em;
  width: auto;
  vertical-align: -0.19em;
}

/* DANS UN TITRE, LE MOT DE MARQUE MONTE D'UN CRAN.

   La hauteur est en em, donc il suit déjà la taille du titre. Mais un logotype composé
   paraît plus petit qu'un texte de même corps : sa hauteur d'x est basse et ses lettres
   sont bas-de-casse, là où un titre aligne des capitales. À 1.05em il se lisait comme un
   mot en retrait au milieu de son propre titre. 1.45em le remet au niveau de ce qui
   l'entoure. Le décalage de baseline suit la même proportion. */
h1 .wm-pylotik {
  /* EN BLOC, ET C'EST CE QUI LUI DONNE DE L'AIR. Une image en ligne ne peut pas
     écarter les lignes : ses marges verticales n'entrent pas dans le calcul de la
     hauteur de ligne, seuls line-height et vertical-align y entrent. Le mot de marque
     se retrouvait donc collé au titre qui le suit, jambe du « p » contre capitale.
     Passé en bloc, il crée sa propre ligne et sa marge s'applique enfin. Le <br> qui
     le suivait dans le markup devient inutile, et il a été retiré. */
  display: block;
  height: 1.45em;
  width: auto;
  margin: 0 auto var(--space-5);
}
.panel--sm h3 { margin-bottom: var(--space-4); font-size: 1rem; }

/* Panneau d'appel à candidature, bordure pointillée */
.is-style-panneau-appel {
  text-align: center;
  margin-top: var(--space-12);
  padding: var(--space-10);
  background: var(--surface-accent-soft);
  border-radius: var(--radius);
  border: 1px dashed var(--violet);
}

.is-style-panneau-appel p { color: var(--gray-600); max-width: 500px; margin: 0 auto var(--space-5); }

/* Encarts latéraux de la page contact */
.is-style-encart {
  background: var(--off-white);
  border-radius: var(--radius);
  padding: var(--space-8);
  margin-bottom: var(--space-8);
  border: 1px solid var(--gray-200);
}

.is-style-encart h3 { margin-bottom: var(--space-5); }

.info-panel--dark {
  border: none;
  color: var(--white);
}

.info-panel--dark h3 { color: var(--white); margin-bottom: var(--space-4); }
.info-panel--dark p { color: var(--on-navy-body); font-size: 0.9rem; margin: 0; }
.info-panel--dark a { color: var(--on-navy-overline); font-weight: 600; }
.info-panel--dark a:hover { color: var(--white); }

.info-panel--accent {
  background: var(--surface-accent-soft);
  border: 1px solid var(--border-accent-soft);
  padding: var(--space-6);
}

.info-panel--accent h3 { color: var(--violet); margin-bottom: var(--space-3); font-size: 1rem; }
.info-panel--accent p { font-size: 0.9rem; color: var(--gray-600); margin: 0; }

.info-field { margin-bottom: var(--space-4); }
.info-field:last-child { margin-bottom: 0; }

.info-field-label {
  font-family: var(--font-heading);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--on-navy-muted);
  text-transform: uppercase;
  margin-bottom: var(--space-1);
}

.info-note { color: var(--on-navy-muted); font-size: 0.85rem; }

/* Sous-cartes d'une grille de présentation */
.is-style-sous-carte h3 { font-size: 1rem; margin-bottom: var(--space-2); }
.is-style-sous-carte p { font-size: 0.9rem; color: var(--gray-600); }

/* Titre précédé d'un glyphe : un GROUPE FLEX [bloc icône + titre]. L'icône est un
   <img> de taille bornée (32px), non plus un glyphe de police - deux titres côte à
   côte s'alignent donc d'eux-mêmes, sans la boîte fixe qu'imposaient jadis les
   métriques divergentes de l'emoji et du symbole texte. Le groupe porte la marge
   basse ; son titre interne, remis à zéro par le reset, ne la double pas. */
.is-style-titre-glyphe { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-6); }

/* =============================================
   ÉTUDES DE CAS
   ============================================= */

.is-style-etude-de-cas {
  background: var(--white);
  border-radius: var(--radius);
  padding: var(--space-12);
  margin-bottom: var(--space-8);
  border: 1px solid var(--gray-200);
}

.is-style-etude-de-cas:last-child { margin-bottom: 0; }
.is-style-etude-de-cas h3 { margin-bottom: var(--space-4); }
/* Dans la maquette, l'étiquette est un <span> que « .case-study p » n'atteint pas.
   Dans WordPress, convertir.py en fait un <p class="is-style-pastille"> : sans
   l'exclusion, cette règle (0,1,1) battrait « .is-style-pastille » (0,1,0) et
   gonflerait l'étiquette à 0.95rem. On l'écarte, comme pour les cartes plus haut. */
.is-style-etude-de-cas p:where(:not(.is-style-pastille)) { font-size: 0.95rem; color: var(--gray-600); }
.is-style-etude-de-cas .is-style-rangee-etiquettes { margin-top: 0; margin-bottom: var(--space-6); align-items: center; }

.is-style-libelle-cas { color: var(--violet); margin-bottom: var(--space-3); }
.case-label--spaced { margin-top: var(--space-5); }
.case-label--result { color: var(--navy); margin-bottom: var(--space-3); }

/* =============================================
   ACCORDÉON

   <details>/<summary> natif : le composant est accessible et fonctionne
   sans JavaScript. L'ancienne version employait des <button aria-expanded="true">
   figés, sans script : tous les panneaux restaient ouverts et les boutons
   étaient inertes.
   ============================================= */

.is-style-accordeon { border-bottom: 1px solid var(--gray-200); }




.is-style-accordeon[open] > .accordion-trigger::after { transform: rotate(45deg); }

.accordion-content {
  padding: 0 0 var(--space-6);
  color: var(--gray-600);
  line-height: 1.8;
  font-size: 0.95rem;
}

/* =============================================
   PAGES LÉGALES

   Contenu rédactionnel long, une seule colonne. Les liens y sont en --link
   plutôt qu'en --navy : dans un texte dense, le navy se confond avec les
   titres et perd son affordance de lien.
   ============================================= */

.legal { max-width: 760px; margin: 0 auto; }
.legal h2 { font-size: clamp(1.4rem, 2.4vw, 1.8rem); margin: var(--space-12) 0 var(--space-4); }
.legal h2:first-of-type { margin-top: 0; }
.legal h3 { font-size: 1.05rem; margin: var(--space-6) 0 var(--space-3); }
.legal p { color: var(--gray-600); }
.legal a { color: var(--link); text-decoration: underline; text-underline-offset: 2px; }
.legal a:hover { color: var(--violet); }

.legal ul { list-style: none; margin: var(--space-4) 0; }

.legal ul li {
  padding: var(--space-2) 0 var(--space-2) var(--space-6);
  position: relative;
  color: var(--gray-600);
  font-size: 0.95rem;
}

/* Même bille que .is-style-billes, pour ne pas avoir deux puces différentes dans le
   site. Le `top` diffère parce que le padding diffère : ici 8px (--space-2), là
   3px. Il vaut padding + demi-hauteur de ligne - rayon, plus la correction de
   0.5px mesurée au rendu (l'encre n'est pas centrée dans l'interligne). */
.legal ul li::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(8px + 0.85em - 3px);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--violet);
}

/* Le sélecteur porte le type `p` et le contexte : `.hero-page p` a une
   spécificité supérieure à `.legal-updated` seul, et lui imposait sa
   font-size de 1.15rem ainsi que sa couleur. On qualifie, on ne force pas.
   --gradient-hero-page se termine sur --navy : c'est ce stop qui contraint.
   --on-navy-muted y donne 5.37:1, au-delà du seuil AA de 4.5:1 exigé par
   ce texte de 0.72rem. */
.hero-page p.legal-updated {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--on-navy-muted);
  margin-top: var(--space-4);
}


/* =============================================
   PASTILLES
   ============================================= */

.is-style-pastille {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* La CATÉGORIE d'un article (core/post-terms) porte aussi ce style, mais elle rend son
   propre <a> : les classes utilitaires « has-…-background-color » qu'un paragraphe
   reçoit ne s'y appliquent pas. Le style porte donc sa couleur PAR DÉFAUT - le pastel
   navy de la charte, comme les tags de la maquette. Un paragraphe qui pose un
   backgroundColor en attribut l'emporte, lui, sur cette valeur. */
.wp-block-post-terms.is-style-pastille a {
  background: var(--surface-tint-navy);
  color: var(--navy);
  text-decoration: none;
}

/* Les deux étiquettes teintées sont des ATTRIBUTS (backgroundColor + textColor). */

/* LES COMPOSANTS CONTENEURS NE VEULENT PAS DU blockGap DE FLUX.
   Ils gèrent leur espacement interne par les marges de leurs éléments (h3, p, listes),
   exactement comme la maquette. Le blockGap de WordPress s'y ajouterait, décalant chaque
   enfant sauf le premier de 24 px. On le remet à zéro par la variable que WordPress lit
   lui-même pour ses marges de flux. */
.is-style-carte,
.is-style-verbatim,
.is-style-tuile,
.is-style-temoignage,
.is-style-tarif,
.is-style-etape,
.is-style-etude-de-cas,
.is-style-panneau,
.is-style-panneau-appel,
.is-style-encart,
.is-style-sous-carte,
.is-style-carte-visuelle,
.is-style-compteur {
  --wp--style--block-gap: 0;
}

/* La variable ne suffit pas : WordPress fige « :root :where(.is-layout-flow) > * {
   margin-block-start: 24px } » en dur, sans relire la variable. On coupe donc la marge de
   flux directement sur les enfants de ces conteneurs. Le sélecteur « .is-style-X > * »
   pèse (0,2,0) et bat la règle du cœur (0,1,0). C'est la seule façon de rendre à ces
   composants l'espacement de la maquette, qui vient de leurs marges internes. */
.is-style-carte > *,
.is-style-verbatim > *,
.is-style-tuile > *,
.is-style-temoignage > *,
.is-style-tarif > *,
.is-style-etape > *,
.is-style-etude-de-cas > *,
.is-style-panneau > *,
.is-style-panneau-appel > *,
.is-style-encart > *,
.is-style-sous-carte > *,
.is-style-carte-visuelle > *,
.is-style-compteur > * {
  margin-block-start: 0;
}

/* =============================================
   RESPONSIVE
   ============================================= */

@media (max-width: 960px) {
  /* PAS D'ILLUSTRATION SOUS 960px. Elle est composée pour occuper la DROITE d'un hero
     large, le texte tenant à gauche. Sur un écran étroit, le hero se resserre et
     s'allonge : l'image, dont la largeur suit la hauteur, finit par le couvrir
     entièrement et passe sous le titre - elle cesse d'être un décor pour devenir du
     bruit. 960px et non 600 : c'est là que la navigation passe au burger, donc là que
     le site entre en mode mobile.

     Le voile reste : posé sur le dégradé de fond, il redonne exactement le dégradé nu.
     Le hero retrouve donc son rendu d'avant les Bannières, sans règle de rattrapage. */
  .wp-block-cover.hero--visuel .wp-block-cover__image-background { display: none; }

  .is-style-grille-2, .is-style-grille-3, .is-style-grille-4 { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: var(--space-8); }
  .is-style-rangee, .is-style-rangee.reverse { flex-direction: column; gap: var(--space-10); }
  .hero-stats { flex-wrap: wrap; gap: var(--space-8); }
  .counter-row { gap: var(--space-10); }
  .is-style-etape { flex-direction: column; gap: var(--space-4); }
  .is-style-numero-etape { width: auto; font-size: 2.5rem; text-align: left; }

  .nav-desktop { display: none; }

  /* Deux cartes par rangée : le max-width passe à une demie largeur. */
  .is-style-verbatim { max-width: calc((100% - var(--space-5)) / 2); }
}

@media (max-width: 600px) {
  /* La baseline « Performance opérationnelle & organisationnelle » débordait sur deux
     ou trois lignes sous le wordmark, cassant la hauteur fixe de l'en-tête : le symbole
     et le wordmark suffisent sur mobile. */
  .logo-tagline { display: none; }
  .hero-home { padding: 130px 0 var(--space-20); }
  .hero-page { padding: 120px 0 var(--space-16); }
  .wp-block-cover.hero-page { padding: 120px 0 var(--space-16); }
  /* Le min du clamp (2.2rem = 35px) était trop grand sur un téléphone étroit, surtout
     avec un mot long. On le ramène à 1.9rem sous 600px. */
  h1 { font-size: 1.9rem; }
  .section { padding: var(--space-16) 0; }
  .is-style-entete-section { margin-bottom: var(--space-10); }
  .is-style-verbatim { max-width: 100%; }
  .footer-grid { grid-template-columns: 1fr; }
  .footer-bottom { flex-direction: column; gap: var(--space-2); }
  .is-style-etude-de-cas { padding: var(--space-8) var(--space-6); }
  .feature-visual-box { padding: var(--space-8); min-height: 260px; }
  .counter-row { gap: var(--space-8); }
}
/* =============================================
   LE PONT WORDPRESS

   La seule feuille de style écrite POUR le thème. Les deux autres sont des copies :
   tokens.css vient du design system, composants.css de la maquette. Ni l'une ni
   l'autre ne doit être retouchée ici - la synchro les écraserait.

   Elle ne contient que ce que la maquette ne pouvait pas prévoir : les classes que
   WORDPRESS génère lui-même, et qu'il faut raccorder aux composants existants.

   Le cas central est la navigation. maquette/style.css l'annonce d'ailleurs, en
   commentaire de sa propre section HEADER : « dans WordPress le bloc Navigation
   fournit un seul markup et son propre panneau responsive ». Nous employons donc ce
   bloc - accessible, traduit, avec son menu mobile - plutôt que de porter le
   <details> de la maquette, qui n'existait que parce qu'elle n'a pas de JavaScript.
   Mais il produit .wp-block-navigation-item__content là où la maquette écrit
   .nav-links a. Ce fichier fait le raccord, et rien d'autre.

   AUCUNE VALEUR DE COULEUR ICI : que des alias. Le vérificateur le contrôle.
   ============================================= */

/* --- Navigation --- */

/* L'équivalent de .nav-links : la liste des liens du bloc Navigation. */
.site-header .wp-block-navigation__container {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  list-style: none;
}

/* PAS DE RETOUR À LA LIGNE dans l'en-tête.

   Le bloc Groupe en layout flex, comme le bloc Navigation, enveloppe par défaut
   (flex-wrap: wrap). À 1000 px, « Blog » passait donc SOUS le header, à moitié coupé.
   La maquette n'enveloppe jamais : sous 960 px, elle bascule en menu burger, et
   au-dessus tout tient sur une ligne. On lui rend ce comportement. */
.site-header .nav-desktop,
.site-header .wp-block-navigation,
.site-header .wp-block-navigation__container {
  flex-wrap: nowrap;
}

/* Le gap du groupe vient de blockGap, qui n'est pas celui de la maquette. */
.site-header .nav-desktop {
  gap: var(--space-8);
}

/* L'équivalent de « .nav-links a ». Le soulignement animé est repris à
   l'identique : il naît sous le lien et s'étend au survol. */
.site-header .wp-block-navigation-item__content {
  font-family: var(--font-heading);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--gray-600);
  letter-spacing: 0.02em;
  text-decoration: none;
  position: relative;
  padding: var(--space-1) 0;
  /* Sans lui, la compression du flex casse « Notre approche » sur deux lignes dès que
     la fenêtre se resserre. Un libellé de navigation ne se coupe jamais. */
  white-space: nowrap;
}

.site-header .wp-block-navigation-item__content:hover,
.site-header .current-menu-item .wp-block-navigation-item__content {
  color: var(--navy);
}

.site-header .wp-block-navigation-item__content::after {
  content: '';
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--violet);
  transition: var(--transition);
}

.site-header .wp-block-navigation-item__content:hover::after,
.site-header .current-menu-item .wp-block-navigation-item__content::after {
  width: 100%;
}

/* LE MENU MOBILE = LE PANNEAU DÉROULANT DE LA MAQUETTE (.nav-panel), et non le modal
   plein écran de WordPress.

   La maquette ouvre son menu mobile JUSTE SOUS l'en-tête : position: absolute,
   top: header-height, pleine largeur, hauteur automatique, fond blanc et ombre. Le
   bloc Navigation, lui, ouvre un modal position: fixed plein écran. Et comme
   .site-header porte un backdrop-filter - qui fait de lui le bloc conteneur de ses
   descendants en position: fixed -, ce plein écran se retrouvait borné à la HAUTEUR de
   l'en-tête, avec un défilement interne (le bug signalé). On lui rend le comportement
   de .nav-panel ; le backdrop-filter devient alors un allié, l'ancrage absolu se calant
   pile sous l'en-tête. */
.site-header .wp-block-navigation__responsive-container.is-menu-open {
  display: block;              /* et non le flex centré du modal WordPress */
  /* fixed, et non absolute : absolute se calerait sur le plus proche ancêtre
     POSITIONNÉ (le bloc Navigation, étroit), d'où un panneau riquiqui. fixed, lui, se
     cale sur l'ancêtre à backdrop-filter (.site-header, pleine largeur) : le panneau
     prend toute la largeur, juste sous l'en-tête. */
  position: fixed;
  top: var(--header-height);
  right: 0;
  bottom: auto;
  left: 0;
  width: auto;
  height: auto;
  /* visible, et non le overflow du modal WordPress : la croix est posée AU-DESSUS du
     panneau, dans l'en-tête - un overflow: hidden la découperait. Le menu est court, il
     n'a pas besoin de défiler. */
  overflow: visible;
  background: var(--white);
  border-bottom: 1px solid var(--gray-200);
  box-shadow: var(--shadow);
  padding: var(--space-4) var(--space-6) var(--space-6);
}

/* WordPress étire ces conteneurs sur toute la hauteur du modal (min-height: 100vh,
   flex centré). On les laisse épouser leur contenu, comme le panneau de la maquette. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close,
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-dialog,
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content {
  display: block;
  width: 100%;
  min-width: 0;
  height: auto;
  min-height: 0;
  max-width: none;
}

/* La croix REMPLACE le hamburger, à sa place dans l'en-tête - comme la maquette, où le
   burger s'anime en croix. On masque le burger à l'ouverture (via :has), et on pose la
   croix pile où il était : centre vertical de l'en-tête, calée à droite. Le position:
   fixed se cale sur .site-header, l'ancêtre à backdrop-filter. */
.site-header .wp-block-navigation:has(.wp-block-navigation__responsive-container.is-menu-open) .wp-block-navigation__responsive-container-open {
  display: none;
}
/* Le panneau ouvert porte un transform (animation WordPress), il devient donc le bloc
   conteneur de la croix en position: fixed. La croix se mesure donc depuis le HAUT du
   panneau (à top: --header-height). Pour la remonter au centre de l'en-tête, il faut un
   décalage NÉGATIF d'une demi-hauteur d'en-tête : le panneau et l'en-tête se décalent
   ensemble (barre d'admin comprise), le calage reste juste. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-close {
  position: fixed;
  top: calc(var(--header-height) / -2);
  right: var(--space-6);
  transform: translateY(-50%);
}

/* Les liens en colonne, à l'habit de .nav-panel : séparateurs discrets entre eux. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
  flex-direction: column;
  align-items: stretch;
  gap: 0;
}

.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
  display: block;
  width: 100%;
  padding: var(--space-3) 0;
  border-bottom: 1px solid var(--gray-100);
}

/* Le soulignement animé du desktop n'a pas de sens dans le panneau empilé. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content::after {
  display: none;
}

/* LE CTA existe en deux exemplaires, comme dans la maquette : le bouton d'en-tête
   (.nav-cta, un wp:html) sert le DESKTOP, l'entrée de menu (.nav-cta-menu, une entrée
   de navigation) sert le PANNEAU MOBILE. Ils sont exclusifs, jamais les deux ensemble.
   C'est ce montage qui met le CTA dans le menu sur mobile, et non dans l'en-tête. */
@media (max-width: 960px) {
  .site-header .nav-cta { display: none; }
}
@media (min-width: 961px) {
  .site-header .nav-cta-menu { display: none; }
}

/* L'entrée CTA du panneau : un bouton violet en bas de la liste, comme
   .nav-panel .nav-cta de la maquette. */
.site-header .wp-block-navigation__responsive-container.is-menu-open .nav-cta-menu {
  margin-top: var(--space-4);
}
.site-header .wp-block-navigation__responsive-container.is-menu-open .nav-cta-menu .wp-block-navigation-item__content {
  display: block;
  text-align: center;
  color: var(--white);
  background: var(--violet);
  border-bottom: none;
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-6);
  font-family: var(--font-heading);
  font-weight: 700;
}

/* LE BURGER BASCULE À 960 px, PAS À 600.

   WordPress fait apparaître le sien à 600 px. La maquette, elle, passe en menu mobile
   dès 960 px - et pour cause : à 700 px, les cinq liens et le bouton d'appel ne
   tiennent plus sur une ligne, ils débordaient du header et retombaient dessous.

   On reprend donc les deux règles que WordPress applique à 600 px, en les portant à
   960. La spécificité est volontairement plus forte que la sienne (.site-header en
   tête), sans quoi elles ne gagneraient pas.

   960 px est le point de rupture de composants.css, pas une valeur choisie ici : s'il
   change là-bas, il doit changer ici. C'est la seule valeur que ces deux fichiers
   partagent sans qu'un token les relie. */
@media (max-width: 960px) {
  .site-header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
    display: none;
  }

  .site-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
    display: flex;
  }
}

/* --- La barre d'administration ---

   Elle est en position: fixed, avec un z-index de 99999. Notre .site-header l'est
   aussi, à top: 0 : la barre noire se posait donc PAR-DESSUS le logo et la navigation,
   dès qu'on était connecté.

   WordPress décale bien le flux du document (html { margin-top: 32px }), mais un
   élément fixed se positionne par rapport au VIEWPORT, pas au flux : ce décalage ne
   l'atteint jamais. Il faut le descendre nous-mêmes.

   La classe .admin-bar n'existe sur le <body> que pour un utilisateur connecté : le
   visiteur, lui, ne voit rien de tout ceci. La barre passe à 46 px sous 783 px, seuil
   fixé par WordPress - le reprendre à l'identique, il ne se déduit pas de nos points
   de rupture. */
.admin-bar .site-header {
  top: 32px;
}

@media screen and (max-width: 782px) {
  .admin-bar .site-header {
    top: 46px;
  }
}

/* --- La boucle de requête ---

   Le bloc « Boucle » rend un <ul>, et enveloppe CHAQUE carte dans un <li>. La grille
   posée sur le <ul> traite donc le <li> comme son item, et la carte n'en est plus
   qu'un enfant : elle ne remplit plus sa cellule, et les trois cartes d'une rangée
   partent à des hauteurs différentes. On rend le <li> transparent à la mise en page. */
.wp-block-post-template {
  margin: 0;
  padding: 0;
  list-style: none;
}

.wp-block-post-template > .wp-block-post {
  display: flex;
  margin: 0;
}

.wp-block-post-template > .wp-block-post > .is-style-carte {
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* Le corps prend la hauteur restante : les cartes d'une rangée finissent alignées,
   quelle que soit la longueur des titres. */
.wp-block-post-template > .wp-block-post > .is-style-carte > .card-body {
  flex: 1;
}

/* --- Cartes à vignette ---

   La maquette posait un <div class="card-media"> de 200 px de haut, parce qu'elle
   choisissait ses images. Le bloc « Image mise en avant » ne connaît pas cette classe,
   et rend l'image à sa taille naturelle : les trois cartes d'une rangée prenaient donc
   des hauteurs différentes, et la grille se disloquait. On lui rend la contrainte. */
.card--media .wp-block-post-featured-image {
  margin: 0;
}

.card--media .wp-block-post-featured-image img {
  display: block;
  width: 100%;
  height: 200px;
  object-fit: cover;
}

/* --- Compensation du header fixe ---

   .site-header est en position: fixed. Dans la maquette, c'est le hero qui absorbe
   la hauteur, par son padding-top de 160px. Les gabarits qui n'ont PAS de hero -
   l'article, l'archive, la recherche, la 404 - retomberaient donc sous l'en-tête.
   Ils portent cette classe, et elle seule. Ne pas la mettre sur une page à hero :
   le décalage serait compté deux fois. */
.sous-header {
  padding-top: var(--header-height);
}

/* --- Le contenu que WordPress rend lui-même ---

   Le corps d'un article est écrit par un rédacteur, dans l'éditeur. Il n'y a donc
   pas de classe de composant à y poser : ces règles habillent le HTML nu. */
.article-body {
  max-width: 760px;
  margin: 0 auto;
  /* Sur mobile, la colonne de lecture occupe toute la largeur du viewport : sans
     gouttières, le texte de l'article collait aux deux bords de l'écran. On lui rend
     une marge intérieure, comme .nav-inner en donne à l'en-tête. */
  padding-left: var(--space-6);
  padding-right: var(--space-6);
}

.article-body > * {
  margin-bottom: var(--space-6);
}

.article-body h2 {
  margin-top: var(--space-14);
}

.article-body h3 {
  margin-top: var(--space-10);
}

.article-body img,
.article-body figure {
  border-radius: var(--radius);
}

/* L'image mise en avant, posée par le gabarit HORS de .article-body : elle ne
   reçoit donc ni la largeur de lecture ni le rayon. On les lui rend, pour
   qu'elle s'affiche comme une image du corps (largeur du contenu, coins
   arrondis) et non pleine largeur à angles vifs. */
.wp-block-post-featured-image.article-cover {
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
  /* Gouttières mobiles, comme .article-body : sans elles, l'image mise en avant
     touchait les deux bords de l'écran. */
  padding-left: var(--space-6);
  padding-right: var(--space-6);
}
.wp-block-post-featured-image.article-cover img {
  border-radius: var(--radius);
}

/* Les gabarits à boucle (blog, archive, recherche) posent la grille de cartes
   directement dans une section, hors .container : sur mobile - et au-delà, sous la
   largeur de contenu - elle touchait les deux bords. On lui rend la colonne de
   lecture de .container. */
.wp-block-query {
  max-width: var(--max-width);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--space-6);
  padding-right: var(--space-6);
}

/* --- Les tableaux de l'article, à l'habit orgatypik ---

   Le rédacteur pose un bloc Tableau (souvent laissé au style core « Stripes »),
   dont l'en-tête est en <td><strong> et non en <th>. On lui rend l'esthétique de
   la charte - en-tête en aplat pastel, zébrage discret, coins arrondis - SANS
   dépendre du style choisi : le thème « convertit » le tableau au rendu.

   C'est le pendant générique de .is-style-comparatif (lui, réservé au comparatif
   à deux colonnes de la maquette, en-tête <th> et wordmark). */
.article-body .wp-block-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.article-body .wp-block-table thead { border-bottom: none; }
.article-body .wp-block-table thead td,
.article-body .wp-block-table thead th {
  font-family: var(--font-heading);
  font-weight: 500;   /* medium, pas gras : coherent avec .is-style-comparatif */
  text-align: left;
  padding: var(--space-3) var(--space-5);
  background: var(--surface-table-head);
  color: var(--navy);
  border: none;
}
.article-body .wp-block-table thead tr :first-child { border-radius: var(--radius-md) 0 0 0; }
.article-body .wp-block-table thead tr :last-child { border-radius: 0 var(--radius-md) 0 0; }
.article-body .wp-block-table td {
  padding: 14px var(--space-5);
  border: none;
  border-bottom: 1px solid var(--gray-200);
}
.article-body .wp-block-table tbody tr:last-child td { border-bottom: none; }
/* Le zébrage de la charte, et on éteint celui du style core « Stripes ». */
.article-body .wp-block-table.is-style-stripes tbody tr { background-color: transparent; }
.article-body .wp-block-table tbody tr:nth-child(even) td { background: var(--off-white); }

/* Les listes du corps d'article.

   Le reset global (ligne 33 : *, *::before, *::after { padding: 0 }) prive les
   <ul>/<ol> de leur retrait. Sans lui, les puces et les numéros débordent à
   gauche de la colonne de lecture. On rend le retrait, et on habille les puces
   nues des billes de la charte.

   ON NE VISE QUE .wp-block-list, la liste ÉCRITE PAR LE RÉDACTEUR dans l'éditeur.
   Les listes posées par une extension (les boutons de partage Jetpack, un <ul>
   nu ; l'EXIF du carrousel…) n'ont pas cette classe : elles gardent leur propre
   habillage, on n'y touche pas.

   Le :not([class*="is-style-"]) épargne en plus les listes qui portent déjà leur
   style (billes, cochée…) : pas de SECONDE puce. */
.article-body ul.wp-block-list:not([class*="is-style-"]) { list-style: none; }
.article-body ul.wp-block-list:not([class*="is-style-"]) > li {
  position: relative;
  padding-left: var(--space-6);
}
/* La bille. Même géométrie que .is-style-billes, mais un calage vertical PROPRE :
   là-bas le <li> porte un padding-top de 3px, ici il n'en a pas. On ne peut donc
   pas reprendre son top : le repère n'est pas le même.

   Ici le texte commence à top:0. Le centre de la première ligne est à 0.8em
   (demi-hauteur de la ligne, line-height 1.6). Pour y centrer une bille de 7px,
   on remonte de son rayon : 0.8em - 3.5px. Le +1px final reprend le décalage
   optique de la charte (l'encre n'est pas centrée dans l'interligne) : -2.5px. */
.article-body ul.wp-block-list:not([class*="is-style-"]) > li::before {
  content: '';
  position: absolute;
  left: 0;
  top: calc(0.8em - 2.5px);
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--violet);
}

.article-body ol.wp-block-list { padding-left: var(--space-7); }

.article-body .wp-block-list li { line-height: 1.6; }
.article-body .wp-block-list li + li { margin-top: var(--space-2); }

/* --- Byline et catégories, dans le hero de l'article ---

   Le hero-page est centré : ces deux blocs le suivent. L'auteur est une signature
   discrète (« Par … » posé au pseudo-élément, le bloc ne rend que le nom) ; les
   catégories sont des pastilles cliquables, aux teintes de la charte. */
/* Byline et catégories vivent dans le hero d'article, qui est SOMBRE : leurs
   couleurs sont donc des teintes on-navy, pas les gris/navy du fond clair. */
.wp-block-post-author-name.article-author {
  font-size: 0.9rem;
  color: var(--on-navy-muted);
  margin-top: var(--space-3);
}
.wp-block-post-author-name.article-author::before { content: 'Par '; }

.wp-block-post-terms.article-cats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.wp-block-post-terms.article-cats a {
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--on-navy-accent);
  background: var(--on-navy-badge-bg);
  border: 1px solid var(--on-navy-badge-border);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  text-decoration: none;
}
.wp-block-post-terms.article-cats a:hover { color: var(--white); }


/* =============================================
   LES COMPOSANTS, VUS PAR GUTENBERG

   Tout le contenu du site est composé de BLOCS NATIFS. Aucun bloc « HTML
   personnalisé » : un tel bloc n'est pas un composant, c'est du code collé, que le
   rédacteur ne peut ni éditer ni dupliquer.

   Les compositions posent les classes de la maquette (.is-style-carte, .is-style-verbatim, .btn…) via
   l'attribut className des blocs. Le CSS de composants.css s'applique alors sans
   retouche - c'est tout l'intérêt. Mais Gutenberg produit un HTML qui n'est pas tout
   à fait celui de la maquette, et ce qui suit comble l'écart.

   TROIS ÉCARTS, ET TROIS PARADES.

   1. Gutenberg ne conserve pas les <span class="…"> dans son texte enrichi. Les
      icônes deviennent donc des BLOCS à part entière (le rédacteur peut changer
      l'emoji), et les mises en valeur inline passent par <strong>, format natif, que
      l'on style ici selon son contexte.

   2. Un bloc s'enveloppe : wp:button rend <div class="wp-block-button"><a>. La classe
      atterrit sur le div, jamais sur le lien. Il faut la redescendre.

   3. Les blocs portent des marges par défaut, que la maquette ne connaît pas.
      ============================================= */

/* --- Le conteneur de section ---

   IL N'Y A RIEN À FAIRE ICI, et c'est le point : composants.css commence par un reset
   « *, *::before, *::after { margin: 0 } », qui neutralise déjà les marges que
   Gutenberg pose entre blocs.

   Une règle « .container > * { margin: 0 } » avait été écrite ici. Elle avait la même
   spécificité que « .is-style-entete-section { margin: 0 auto var(--space-16) } », mais le pont
   est chargé APRÈS composants.css : elle l'écrasait, et tous les espacements entre le
   titre d'une section et son contenu disparaissaient. Ne pas la remettre. */

/* --- LE blockGap : coupe A LA SOURCE ---

   WordPress posait « margin-block-start: 24px » sur tout bloc qui n'est pas le premier
   de son parent. Ces 24px s'AJOUTAIENT aux espacements de la maquette, qui gère les
   siens par des règles explicites : chaque section dérivait d'un cran, et l'écart se
   cumulait sur toute la page.

   On a d'abord tenté de le neutraliser ici, conteneur par conteneur. Mauvaise idée : la
   règle « .is-style-carte > * { margin-top: 0 } » écrasait du même coup les marges VOULUES, comme
   « .is-style-lien-carte { margin-top: --space-4 } ». Chaque parade en appelait une autre.

   La vraie réponse tient en une ligne, et elle est dans theme.json :

       "styles": { "spacing": { "blockGap": "0px" } }

   WordPress n'émet plus rien, composants.css redevient seul maître de ses espacements,
   et tout l'échafaudage disparaît. Voir design-system/generer.py.

   Le contenu rédactionnel libre - le corps d'un article - retrouve ses espacements par
   .article-body, plus bas : lui n'a pas de composant pour les lui donner. */

/* --- Surtitre --- */
.is-style-entete-section p.is-style-surtitre {
  margin-bottom: var(--space-3);
}

/* --- Boutons ---

   La maquette pose .btn sur le lien lui-même. Gutenberg le pose sur le conteneur, et
   le lien en dessous est .wp-block-button__link. On redescend donc le composant d'un
   cran, et on annule le conteneur.

   Les valeurs sont celles de .btn dans composants.css. C'est la seule duplication du
   pont, et elle est inévitable : on ne peut pas faire hériter une classe d'une autre
   en CSS. Si .btn change là-bas, il faut la reporter ici. */
.wp-block-button {
  margin: 0;
}

.wp-block-button .wp-block-button__link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.95rem;
  padding: 14px var(--space-8);
  border-radius: var(--radius-md);
  border: none;
  transition: var(--transition);
  text-decoration: none;
  letter-spacing: 0.01em;
  background: var(--violet);
  color: var(--white);
  box-shadow: var(--shadow-violet);
}

.wp-block-button .wp-block-button__link:hover {
  background: var(--violet-dark);
  color: var(--white);
  transform: translateY(-2px);
  box-shadow: var(--shadow-violet-lg);
}

/* LE CONTENEUR NE DOIT RIEN DESSINER.

   La classe de variante atterrit sur le <div class="wp-block-button">, et
   composants.css l'y reconnaît : .btn-white y peignait un rectangle BLANC CARRÉ, et
   .btn-secondary une BORDURE navy carrée - tous deux derrière le vrai bouton, qui,
   lui, est arrondi. D'où les « coins carrés » et le survol carré.

   Le conteneur est donc neutralisé, et le composant reposé sur le lien. Toute nouvelle
   variante devra l'être aussi : c'est le prix du partage des noms de classes avec la
   maquette, et il est plus faible que celui d'un second vocabulaire. */
.wp-block-button.is-style-blanc,
.wp-block-button.is-style-secondaire {
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0;
}

/* Les variantes, sur le LIEN. */
.wp-block-button.is-style-blanc .wp-block-button__link {
  background: var(--white);
  color: var(--navy);
  box-shadow: var(--shadow-on-dark);
}

.wp-block-button.is-style-blanc .wp-block-button__link:hover {
  background: var(--off-white);
  color: var(--navy);
}

.wp-block-button.is-style-secondaire .wp-block-button__link {
  background: transparent;
  color: var(--navy);
  border: 2px solid var(--navy);
  box-shadow: none;
}

.wp-block-button.is-style-secondaire .wp-block-button__link:hover {
  background: var(--navy);
  color: var(--white);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lg);
}

/* SUR FOND SOMBRE, LE SURVOL S'INVERSE - ET IL FAUT LE DIRE ICI, PAS PLUS HAUT.
   La règle du survol clair juste au-dessus pèse (0,4,0), exactement comme celle qui
   vit en tête de fichier (« .section-dark .is-style-secondaire … :hover »). À égalité,
   c'est l'ordre du fichier qui tranche, et la règle claire venait après : au survol,
   le bouton se remplissait de NAVY SUR UNE SECTION NAVY et disparaissait. Mesuré dans
   le navigateur, pas déduit.

   On qualifie donc par « .wp-block-button » pour passer à (0,5,0), et on la pose après.
   Deux verrous plutôt qu'un : la spécificité gagne, l'ordre confirme. */
.section-dark .wp-block-button.is-style-secondaire .wp-block-button__link:hover,
.hero-page .wp-block-button.is-style-secondaire .wp-block-button__link:hover,
.cta-band .wp-block-button.is-style-secondaire .wp-block-button__link:hover,
.hero-home .wp-block-button.is-style-secondaire .wp-block-button__link:hover {
  background: var(--white);
  color: var(--navy);
  transform: translateY(-2px);
  box-shadow: var(--shadow-on-dark);
}

/* La flèche : elle est décorative, elle n'a donc rien à faire dans le texte que le
   rédacteur saisit. Le pseudo-élément la pose, et l'anime au survol comme .btn-arrow
   le fait dans la maquette.

   Mais .btn-arrow atterrit sur le CONTENEUR, et composants.css y voit une flèche à
   dessiner : une seconde flèche apparaissait donc SOUS le bouton, orpheline. On la
   coupe là, on la repose sur le lien. */
.wp-block-button.is-style-fleche::after {
  content: none;
}

.wp-block-button.is-style-fleche .wp-block-button__link::after {
  content: '→';
  transition: var(--transition);
}

.wp-block-button.is-style-fleche .wp-block-button__link:hover::after {
  transform: translateX(4px);
}

/* Sur fond sombre, le bouton secondaire s'inverse : la maquette le fait déjà pour
   .btn-secondary, mais son sélecteur vise le lien, pas le conteneur.

   LE CONTOUR EST BLANC PLEIN, ET NON --on-navy-border. Ce token vaut
   rgba(255,255,255,0.15) : c'est le filet d'un BORD DE PANNEAU, une séparation qu'on
   devine. Posé sur un bouton, il le faisait disparaître dans le navy - un bouton
   fantôme dont il ne restait que le libellé, là où la maquette pose un contour plein.
   L'écart ne se voyait dans aucun contrôle : comparer.py mesure des boîtes, pas des
   couleurs, et les deux rendus avaient exactement la même géométrie.

   Un bord de panneau se devine, un bouton s'annonce : ce ne sont pas les mêmes rôles,
   donc ce ne sont pas les mêmes tokens.

   Cette règle bat celle qui vise le LIEN (« .section-dark .is-style-secondaire
   .wp-block-button__link », plus haut) par sa spécificité - 4 classes contre 3. C'est
   elle qui décide, et c'est pour cela qu'elle doit porter la bonne valeur. */
.section-dark .wp-block-button.is-style-secondaire .wp-block-button__link,
.hero-page .wp-block-button.is-style-secondaire .wp-block-button__link,
.cta-band .wp-block-button.is-style-secondaire .wp-block-button__link,
.hero-home .wp-block-button.is-style-secondaire .wp-block-button__link {
  color: var(--white);
  border-color: var(--white);
}

/* --- Hero ---
   La seconde ligne du h1 est mise en valeur. La maquette employait
   <span class="hero-highlight"> ; Gutenberg ne le conserverait pas. <strong> est un
   format natif, il survit - et le h1 étant déjà en graisse 800, l'accentuation ne se
   voit pas : seule la couleur parle, exactement comme dans la maquette. */
.hero-home h1 strong {
  color: var(--on-navy-stat-violet);
  font-weight: inherit;
}

/* NE PAS neutraliser les marges du hero ici : « .hero-stats » porte un
   margin-top de --space-14 dans composants.css, et une règle de même spécificité
   posée ici l'écraserait (le pont est chargé après). Le filet des chiffres se
   collait alors aux boutons. La maquette gère ses marges, on la laisse faire. */

/* --- Grille des problèmes ---

   .is-style-verbatim était un <div> portant son texte et un <span class="pain-icon"> INLINE.
   En blocs, l'icône devient un paragraphe à part - Gutenberg ne conserve pas les
   <span> de son texte enrichi.

   ET C'EST LÀ LE PIÈGE. Mise en colonne flex, l'icône retire sa largeur au texte sur
   TOUTES les lignes, là où un span inline ne la retire que sur la PREMIÈRE. Une carte
   y gagnait une ligne entière, et dépassait ses voisines.

   float lui rend son comportement d'origine : le texte s'enroule autour, puis reprend
   toute la largeur. C'est exactement ce que faisait le <span>. */
/* Le verbatim FLOTTE son icône : le texte s'enroule autour, puis reprend toute la
   largeur - le comportement d'un <span> inline, que le bloc orgatypik/icone (un
   <img class="icone"> direct dans la citation) retrouve par ce flottement. La
   taille (26 px) tient dans une ligne de texte, sans lui en voler une seconde. */
.is-style-verbatim > .icone {
  float: left;
  margin: 0 var(--space-2) 0 0;
  width: 26px;
  height: 26px;
}

.is-style-verbatim > p {
  margin: 0;
}

/* .is-style-lien-carte est un lien dans la maquette. En bloc, c'est un paragraphe QUI CONTIENT
   le lien : le composant habille le paragraphe, le lien n'a plus qu'à hériter. */
p.is-style-lien-carte a,
p.is-style-lien-carte a:hover {
  color: inherit;
  text-decoration: none;
}

/* --- Étapes de méthode ---
   .is-style-numero-etape et .step-content étaient des <div>. En blocs, un paragraphe et un
   groupe. Le flex de .is-style-etape les met en ligne, il ne reste qu'à neutraliser les
   marges. */
/* L'ÉTIQUETTE - le libellé de durée (« Semaine 1-2 »).

   C'est un STYLE DE BLOC, enregistré dans functions.php : il apparaît dans le panneau
   « Styles » de l'inspecteur, le rédacteur le choisit d'un clic. C'est la différence
   entre un composant et un effet de bord.

   Il était un <strong> DANS le titre, que « .step-content h3 strong » transformait en
   pastille. Rien ne l'annonçait, et un second mot en gras dans ce titre donnait une
   seconde pastille. On ne peut pas designer ce qu'on ne peut pas désigner.

   Les valeurs sont celles de .step-tag dans la maquette, qui reste la référence. */
.is-style-etiquette {
  font-family: var(--font-mono);
  font-size: 0.65rem;
  font-weight: 600;
  color: var(--violet);
  background: var(--surface-tint-violet);
  padding: var(--space-1) 10px;
  border-radius: var(--radius-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Le groupe qui tient le titre et son étiquette sur une même ligne est en layout FLEX
   NATIF : WordPress en écrit lui-même le display, l'alignement et le gap. Rien ici. Ne
   reste que la marge du titre, que le flux ne pose plus. */
.step-head { margin-bottom: var(--space-3); }
.step-head h3 { margin: 0; }

/* --- Tuiles de valeur ---
   La boîte d'icône (.value-tile-icon) pose sa marge sous elle-même, comme dans la
   maquette ; l'icône est le bloc orgatypik/icone qu'elle contient. */
.value-tile-icon,
.value-tile-icon--lg { margin-bottom: var(--space-3); }

/* --- Témoignages et verbatim ---
   Tous deux SONT désormais des blocs Citation : <blockquote class="wp-block-quote
   is-style-…">, plus de groupe autour. Le témoignage porte le texte en <p> direct et
   l'attribution dans son <cite> ; le verbatim garde son icône flottée et son texte.
   La bordure et le retrait gauche viennent de la règle de carte, plus haut : elle est
   dans la même feuille, donc APRÈS le cœur, et l'emporte sans avoir à se répéter. */

/* --- Tarifs --- */
/* --- Tableau comparatif ---
   Le bloc Tableau rend <figure class="wp-block-table"><table>. La classe atterrit sur
   la FIGURE, alors que la maquette la pose sur le <table>. Ses sélecteurs descendants
   (.is-style-comparatif th, td…) continuent de fonctionner - un ancêtre les satisfait
   aussi bien. Seules les règles portées par .is-style-comparatif lui-même sont à
   redescendre. */
/* « margin: 0 » EMPORTAIT AUSSI LA MARGE HAUTE. Cette règle était là pour neutraliser
   les marges par défaut que WordPress met sur ses <figure> - et de spécificité (0,1,1),
   elle battait « .is-style-comparatif { margin-top: … } » (0,1,0), qui donne au tableau son
   air au-dessus. Le tableau collait donc au paragraphe qui le précède.

   On ne remet à zéro que ce qu'il faut : les marges latérales et basse. */
figure.is-style-comparatif {
  /* La marge haute est REPOSÉE ICI, et il le faut. Quand le tableau est le PREMIER
     enfant de son conteneur - c'est le cas sur l'accueil - WordPress lui écrit
     « :where(.is-layout-flow) > :first-child { margin-block-start: 0 } ». Cette règle
     pèse (0,1,0), exactement comme « .is-style-comparatif », et elle passe APRÈS dans la
     cascade : à égalité, l'ordre tranche, et elle gagnait. « figure.is-style-comparatif »
     pèse (0,1,1) : elle tient. */
  margin-right: 0;
  margin-bottom: 0;
  margin-left: 0;
}

figure.is-style-comparatif > table {
  width: 100%;
  border-collapse: collapse;
}

/* LE BLOC TABLEAU DESSINE SA PROPRE GRILLE.

   Son CSS pose « border: 1px solid » sur CHAQUE cellule. Il a la même spécificité que
   « .is-style-comparatif td » de la maquette, mais WordPress imprime les styles de blocs
   APRÈS nos feuilles : c'est lui qui gagne. Le tableau se retrouvait quadrillé, là où
   la maquette ne veut que des filets horizontaux et des coins arrondis.

   On coupe la grille, puis on repose le filet - avec la spécificité qu'il faut pour
   tenir. C'est une duplication, et elle est inévitable : on ne peut pas rendre à une
   règle une priorité qu'elle a perdue. */
figure.is-style-comparatif th,
figure.is-style-comparatif td {
  border: none;
}

figure.is-style-comparatif td {
  border-bottom: 1px solid var(--gray-200);
}

figure.is-style-comparatif tr:last-child td {
  border-bottom: none;
}

/* --- Accordéon (FAQ) ---
   Le bloc Détails de Gutenberg EST un <details>/<summary> natif : le même composant que
   la maquette, sans une ligne de JavaScript.

   MAIS SON summary NE PORTE AUCUNE CLASSE, et il ne peut pas en porter : le save() de
   core/details produit « <summary>texte</summary> », rien de plus. Y ajouter la classe
   .accordion-trigger de la maquette rend le bloc INVALIDE - mesuré dans l'éditeur.

   Cette règle ne faisait donc que tuer le triangle natif, et laissait le summary NU : ni
   padding, ni police, ni chevron. Les douze accordéons du site étaient des lignes de
   texte brutes. Elle porte désormais tout ce que .accordion-trigger portait, mais elle
   vise la STRUCTURE - la seule chose que Gutenberg garantisse. */
/* SURTOUT PAS « display: flex » avec un gap ici. Le gap se glisserait entre chaque
   fragment de texte enrichi : une question comme « Qu'est-ce que le <em>groupthink</em> ? »
   se scinde en trois éléments flex (avant, le <em>, après), et le gap ouvre un blanc
   avant et après le mot. Même leçon que .is-style-billes li. On laisse donc le texte
   couler en bloc, et on pose le chevron en ABSOLU à droite. */
details.is-style-accordeon > summary {
  position: relative;
  display: block;
  padding: var(--space-6) var(--space-8) var(--space-6) 0;
  cursor: pointer;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--navy);
  text-align: left;
  list-style: none;
}

details.is-style-accordeon > summary::-webkit-details-marker {
  display: none;
}

/* Le chevron. Un pseudo-élément : WordPress ne sait pas le dire, et c'est très bien -
   c'est exactement ce que le CSS doit garder. En absolu à droite, calé sur la première
   ligne (et non centré sur tout le summary, pour les questions à plusieurs lignes). */
details.is-style-accordeon > summary::after {
  content: '+';
  position: absolute;
  right: 0;
  top: var(--space-6);
  font-size: 1.4rem;
  font-weight: 300;
  line-height: 1;
  color: var(--violet);
  transition: var(--transition);
}

details.is-style-accordeon[open] > summary::after { transform: rotate(45deg); }

details.is-style-accordeon > *:not(summary) {
  margin-top: 0;
}

/* --- Note statistique ---
   Les deux chiffres reprennent les couleurs des barres du graphe Gallup : la prune du
   8 % France, l'émeraude du 70 %. La maquette les portait en
   <strong class="stat-inline-low|high"> ; Gutenberg ne garde pas la classe, mais il
   garde le <strong>. On les distingue donc par leur RANG.

   CONTRAINTE DE RÉDACTION, et elle n'est pas négociable : la phrase doit contenir
   EXACTEMENT DEUX <strong>, le 8 % puis le 70 %, dans cet ordre. Un troisième mot mis
   en gras casserait la correspondance avec le graphe.

   La taille de 1.2rem n'est pas esthétique : à 19,2 px gras, le texte est « large » au
   sens WCAG, le seuil tombe à 3:1, et la prune passe avec ses 3.72:1 sur --navy-mid.
   Réduite, elle échouerait. NE PAS LA RÉDUIRE. */
.stat-note p strong {
  font-size: 1.2rem;
}

.stat-note p strong:nth-of-type(1) {
  color: var(--on-navy-stat-plum);
}

.stat-note p strong:nth-of-type(2) {
  color: var(--on-navy-stat-high);
}

/* --- Pied de section --- */
/* Le bloc Boutons est un conteneur FLEX : il ne suit pas le text-align: center de la
   section qui le porte, et retombe à gauche. Il faut le centrer lui-même, partout où
   la maquette centre son bouton. */
.is-style-pied-de-section .wp-block-buttons,
.cta-band .wp-block-buttons {
  justify-content: center;
}

/* LA MAQUETTE ÉCRIT « .is-style-pied-de-section .btn { margin-top: --space-4 } ».

   Or un bouton Gutenberg n'est pas un .btn : c'est un .wp-block-buttons qui enveloppe
   un .wp-block-button__link. La règle ne trouvait donc plus personne, et le bouton se
   collait à la phrase qui le précède.

   C'est LE motif de tout ce fichier, et il vaut d'être retenu : une règle de la
   maquette qui nomme un ÉLÉMENT (a, div, .btn) survit au portage ; une règle qui nomme
   une STRUCTURE ne survit que si Gutenberg produit la même. Il ne la produit presque
   jamais. */
.is-style-pied-de-section .wp-block-buttons {
  margin-top: var(--space-4);
}

/* =============================================
   FORMULAIRES - ce que la maquette n'a pas
   ============================================= */

/* LE POT DE MIEL. Il doit être invisible à l'humain et VISIBLE au robot : un
   « display: none » ou un « type=hidden » seraient repérés par n'importe quel robot un
   peu sérieux, qui saurait alors ne pas le remplir. On le sort du cadre, sans le
   masquer. aria-hidden et tabindex=-1 le retirent du clavier et des lecteurs d'écran.

   C'est ce qui remplace un captcha - lequel serait un SERVICE TIERS : reCAPTCHA
   transmettrait l'adresse IP du visiteur à Google, et la politique de confidentialité
   affirme qu'aucune donnée ne quitte l'UE. */
.form-leurre {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Le retour au visiteur. Pas d'icône, pas de couleur seule : le texte dit ce qui se
   passe, et le rôle ARIA le fait annoncer par un lecteur d'écran. */
.form-succes,
.form-erreur {
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-md);
  border-left: 4px solid;
  font-size: 0.95rem;
}

/* --success et --error étaient des alias ORPHELINS : tokens.css les annonçait « consommés
   par les états de validation du formulaire », et aucun élément ne les portait - les
   modificateurs .form-hint--* avaient été retirés. Ils trouvent ici leur consommateur, et
   c'est le bon : un formulaire ALERTE, il ne catégorise pas. C'est exactement la
   distinction que la charte demande de faire avant d'employer un voyant. */
.form-succes {
  background: var(--off-white);
  border-color: var(--success);
  color: var(--success);
}

.form-erreur {
  background: var(--off-white);
  border-color: var(--error);
  color: var(--error);
}

/* Le champ fautif. Le rouge de la charte passe l'AA en TEXTE (5.19:1 sur blanc) : c'est
   le seul voyant qui le fasse, et il est ici à sa place. */
.form-group--erreur input,
.form-group--erreur select,
.form-group--erreur textarea {
  border-color: var(--error);
}

.form-group--erreur label { color: var(--error); }

/* =============================================
   MENTIONS LÉGALES - ce que Gutenberg ne sait pas dire
   ============================================= */

/* LE CHAMP JURIDIQUE MANQUANT. La maquette l'écrit <span class="legal-todo"> ; Gutenberg
   ne conserve aucun <span>. Il devient donc un <code> - qui est un format EN LIGNE natif,
   donc préservé à l'édition, et qui portait déjà la police monospace que la classe
   demandait. Il ne pouvait pas devenir un bloc : il est AU MILIEU d'une phrase
   (« RCS Toulouse [Numéro] - SIRET [14 chiffres] »), et un bloc l'aurait coupée en deux.

   Volontairement voyant : il signale un champ qu'il reste à renseigner. Les pages légales
   sont publiées (forme orgatypik EI) ; un champ encore voyant doit donc être traité. */
.legal-info code {
  font-family: var(--font-mono);
  font-size: 0.85em;
  font-weight: 600;
  color: var(--attention);
  background: var(--surface-attention);
  border-bottom: 1px dashed var(--attention);
  border-radius: var(--radius-sm);
  padding: 1px 6px;
}
